📄 drawingtidbits.cpp
字号:
/***************************************************************************** * DrawingTidbits.cpp ***************************************************************************** * Copyright (C) 2001 the VideoLAN team * $Id$ * * Authors: Tony Castley <tcastley@mail.powerup.com.au> * Stephan Aßmus <stippi@yellowbites.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/#include <math.h>#include <Bitmap.h>#include <Debug.h>#include <Screen.h>#include "DrawingTidbits.h"// ShiftComponentinline ucharShiftComponent(uchar component, float percent){ // change the color by <percent>, make sure we aren't rounding // off significant bits if (percent >= 1) return (uchar)(component * (2 - percent)); else return (uchar)(255 - percent * (255 - component));}// ShiftColorrgb_colorShiftColor(rgb_color color, float percent){ rgb_color result = { ShiftComponent(color.red, percent), ShiftComponent(color.green, percent), ShiftComponent(color.blue, percent), 0 }; return result;}// CompareColorsstatic boolCompareColors(const rgb_color a, const rgb_color b){ return a.red == b.red && a.green == b.green && a.blue == b.blue && a.alpha == b.alpha;}// ==booloperator==(const rgb_color &a, const rgb_color &b){ return CompareColors(a, b);}// !=booloperator!=(const rgb_color &a, const rgb_color &b){ return !CompareColors(a, b);}// ReplaceColorvoidReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to){ ASSERT(bitmap->ColorSpace() == B_COLOR_8_BIT); // other color spaces not implemented yet BScreen screen(B_MAIN_SCREEN_ID); uint32 fromIndex = screen.IndexForColor(from); uint32 toIndex = screen.IndexForColor(to); uchar *bits = (uchar *)bitmap->Bits(); int32 bitsLength = bitmap->BitsLength(); for (int32 index = 0; index < bitsLength; index++) if (bits[index] == fromIndex) bits[index] = toIndex;}// ReplaceTransparentColorvoidReplaceTransparentColor(BBitmap *bitmap, rgb_color with){ ASSERT(bitmap->ColorSpace() == B_COLOR_8_BIT); // other color spaces not implemented yet BScreen screen(B_MAIN_SCREEN_ID); uint32 withIndex = screen.IndexForColor(with); uchar *bits = (uchar *)bitmap->Bits(); int32 bitsLength = bitmap->BitsLength(); for (int32 index = 0; index < bitsLength; index++) if (bits[index] == B_TRANSPARENT_8_BIT) bits[index] = withIndex;}// ycrcb_to_rgbinline voidycbcr_to_rgb( uint8 y, uint8 cb, uint8 cr, uint8& r, uint8& g, uint8& b){ r = (uint8)max_c( 0, min_c( 255, 1.164 * ( y - 16 ) + 1.596 * ( cr - 128 ) ) ); g = (uint8)max_c( 0, min_c( 255, 1.164 * ( y - 16 ) - 0.813 * ( cr - 128 ) - 0.391 * ( cb - 128 ) ) ); b = (uint8)max_c( 0, min_c( 255, 1.164 * ( y - 16 ) + 2.018 * ( cb - 128 ) ) );}// this function will not produce visually pleasing results!// we'd have to convert to Lab colorspace, do the mixing// and convert back to RGB - in an ideal world...//// mix_colorsinline voidmix_colors( uint8 ra, uint8 ga, uint8 ba, uint8 rb, uint8 gb, uint8 bb, uint8& r, uint8& g, uint8& b, float mixLevel ){ float mixA = ( 1.0 - mixLevel ); float mixB = mixLevel; r = (uint8)(mixA * ra + mixB * rb); g = (uint8)(mixA * ga + mixB * gb); b = (uint8)(mixA * ba + mixB * bb);}// the algorithm used is probably pretty slow, but it should be easy// to understand what's going on...//// scale_bitmapstatus_tscale_bitmap( BBitmap* bitmap, uint32 fromWidth, uint32 fromHeight ){ status_t status = B_BAD_VALUE; if ( bitmap && bitmap->IsValid() && ( bitmap->ColorSpace() == B_RGB32 || bitmap->ColorSpace() == B_RGBA32 ) ) { status = B_MISMATCHED_VALUES; // we only support upscaling as of now uint32 destWidth = bitmap->Bounds().IntegerWidth() + 1; uint32 destHeight = bitmap->Bounds().IntegerHeight() + 1; if ( fromWidth <= destWidth && fromHeight <= destHeight ) { status = B_OK; uint32 bpr = bitmap->BytesPerRow(); if ( fromWidth < destWidth ) { // scale horizontally uint8* src = (uint8*)bitmap->Bits(); uint8* p = new uint8[fromWidth * 4]; // temp buffer for ( uint32 y = 0; y < fromHeight; y++ ) { // copy valid pixels into temp buffer memcpy( p, src, fromWidth * 4 ); for ( uint32 x = 0; x < destWidth; x++ ) { // mix colors of left and right pixels and write it back // into the bitmap float xPos = ( (float)x / (float)destWidth ) * (float)fromWidth; uint32 leftIndex = (uint32)floorf( xPos ) * 4; uint32 rightIndex = (uint32)ceilf( xPos ) * 4; rgb_color left; left.red = p[leftIndex + 2]; left.green = p[leftIndex + 1]; left.blue = p[leftIndex + 0]; rgb_color right; right.red = p[rightIndex + 2]; right.green = p[rightIndex + 1]; right.blue = p[rightIndex + 0]; rgb_color mix; mix_colors( left.red, left.green, left.blue, right.red, right.green, right.blue, mix.red, mix.green, mix.blue, xPos - floorf( xPos ) ); uint32 destIndex = x * 4; src[destIndex + 2] = mix.red; src[destIndex + 1] = mix.green; src[destIndex + 0] = mix.blue; } src += bpr; } delete[] p; } if ( fromHeight < destHeight ) { // scale vertically uint8* src = (uint8*)bitmap->Bits(); uint8* p = new uint8[fromHeight * 3]; // temp buffer for ( uint32 x = 0; x < destWidth; x++ ) { // copy valid pixels into temp buffer for ( uint32 y = 0; y < fromHeight; y++ ) { uint32 destIndex = y * 3; uint32 srcIndex = x * 4 + y * bpr; p[destIndex + 0] = src[srcIndex + 0]; p[destIndex + 1] = src[srcIndex + 1]; p[destIndex + 2] = src[srcIndex + 2]; } // do the scaling for ( uint32 y = 0; y < destHeight; y++ ) { // mix colors of upper and lower pixels and write it back // into the bitmap float yPos = ( (float)y / (float)destHeight ) * (float)fromHeight; uint32 upperIndex = (uint32)floorf( yPos ) * 3; uint32 lowerIndex = (uint32)ceilf( yPos ) * 3; rgb_color upper; upper.red = p[upperIndex + 2]; upper.green = p[upperIndex + 1]; upper.blue = p[upperIndex + 0]; rgb_color lower; lower.red = p[lowerIndex + 2]; lower.green = p[lowerIndex + 1]; lower.blue = p[lowerIndex + 0]; rgb_color mix; mix_colors( upper.red, upper.green, upper.blue, lower.red, lower.green, lower.blue, mix.red, mix.green, mix.blue, yPos - floorf( yPos ) ); uint32 destIndex = x * 4 + y * bpr; src[destIndex + 2] = mix.red; src[destIndex + 1] = mix.green;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -