X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fbeos%2FDrawingTidbits.cpp;h=362933f5efd189ed8670a19d94c99d1d19e3e5a2;hb=6ee1e193fd896ab9a4729fde14f009d9ce629815;hp=05aeb858bf0961926c8bcec7917064c4225af04a;hpb=3305b049e7f587b23359a1c9047fb5763d19c1dc;p=vlc diff --git a/modules/gui/beos/DrawingTidbits.cpp b/modules/gui/beos/DrawingTidbits.cpp index 05aeb858bf..362933f5ef 100644 --- a/modules/gui/beos/DrawingTidbits.cpp +++ b/modules/gui/beos/DrawingTidbits.cpp @@ -46,82 +46,82 @@ ShiftComponent(uchar component, float percent) rgb_color ShiftColor(rgb_color color, float percent) { - rgb_color result = { - ShiftComponent(color.red, percent), - ShiftComponent(color.green, percent), - ShiftComponent(color.blue, percent), - 0 - }; - - return result; + rgb_color result = { + ShiftComponent(color.red, percent), + ShiftComponent(color.green, percent), + ShiftComponent(color.blue, percent), + 0 + }; + + return result; } // CompareColors static bool CompareColors(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; + return a.red == b.red + && a.green == b.green + && a.blue == b.blue + && a.alpha == b.alpha; } // == bool operator==(const rgb_color &a, const rgb_color &b) { - return CompareColors(a, b); + return CompareColors(a, b); } // != bool operator!=(const rgb_color &a, const rgb_color &b) { - return !CompareColors(a, b); + return !CompareColors(a, b); } // ReplaceColor void ReplaceColor(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; + 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; } // ReplaceTransparentColor -void +void ReplaceTransparentColor(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; + 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_rgb inline void ycbcr_to_rgb( uint8 y, uint8 cb, uint8 cr, - uint8& r, uint8& g, uint8& b) + 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 ) ) ); + 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! @@ -131,14 +131,14 @@ ycbcr_to_rgb( uint8 y, uint8 cb, uint8 cr, // mix_colors inline void mix_colors( uint8 ra, uint8 ga, uint8 ba, - uint8 rb, uint8 gb, uint8 bb, - uint8& r, uint8& g, uint8& b, float mixLevel ) + 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); + 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 @@ -148,330 +148,330 @@ mix_colors( uint8 ra, uint8 ga, uint8 ba, status_t scale_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; - src[destIndex + 0] = mix.blue; - } - } - delete[] p; - } - } - } - return status; + 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; + src[destIndex + 0] = mix.blue; + } + } + delete[] p; + } + } + } + return status; } // convert_bitmap status_t convert_bitmap( BBitmap* inBitmap, BBitmap* outBitmap ) { - status_t status = B_BAD_VALUE; - // see that we got valid bitmaps - if ( inBitmap && inBitmap->IsValid() - && outBitmap && outBitmap->IsValid() ) - { - status = B_MISMATCHED_VALUES; - // see that bitmaps are compatible and that we support the conversion - if ( inBitmap->Bounds().Width() <= outBitmap->Bounds().Width() - && inBitmap->Bounds().Height() <= outBitmap->Bounds().Height() - && ( outBitmap->ColorSpace() == B_RGB32 - || outBitmap->ColorSpace() == B_RGBA32) ) - { - int32 width = inBitmap->Bounds().IntegerWidth() + 1; - int32 height = inBitmap->Bounds().IntegerHeight() + 1; - int32 srcBpr = inBitmap->BytesPerRow(); - int32 dstBpr = outBitmap->BytesPerRow(); - uint8* srcBits = (uint8*)inBitmap->Bits(); - uint8* dstBits = (uint8*)outBitmap->Bits(); - switch (inBitmap->ColorSpace()) - { - case B_YCbCr422: - // Y0[7:0] Cb0[7:0] Y1[7:0] Cr0[7:0] - // Y2[7:0] Cb2[7:0] Y3[7:0] Cr2[7:0] - for ( int32 y = 0; y < height; y++ ) - { - for ( int32 x = 0; x < width; x += 2 ) - { - int32 srcOffset = x * 2; - int32 dstOffset = x * 4; - ycbcr_to_rgb( srcBits[srcOffset + 0], - srcBits[srcOffset + 1], - srcBits[srcOffset + 3], - dstBits[dstOffset + 2], - dstBits[dstOffset + 1], - dstBits[dstOffset + 0] ); - ycbcr_to_rgb( srcBits[srcOffset + 2], - srcBits[srcOffset + 1], - srcBits[srcOffset + 3], - dstBits[dstOffset + 6], - dstBits[dstOffset + 5], - dstBits[dstOffset + 4] ); - // take care of alpha - dstBits[x * 4 + 3] = 255; - dstBits[x * 4 + 7] = 255; - } - srcBits += srcBpr; - dstBits += dstBpr; - } - status = B_OK; - break; - case B_YCbCr420: - // Non-interlaced only! - // Cb0 Y0 Y1 Cb2 Y2 Y3 on even scan lines ... - // Cr0 Y0 Y1 Cr2 Y2 Y3 on odd scan lines - status = B_ERROR; - break; - case B_YUV422: - // U0[7:0] Y0[7:0] V0[7:0] Y1[7:0] - // U2[7:0] Y2[7:0] V2[7:0] Y3[7:0] - status = B_ERROR; - break; - case B_RGB32: - case B_RGBA32: - memcpy( dstBits, srcBits, inBitmap->BitsLength() ); - status = B_OK; - break; - case B_RGB16: - // G[2:0],B[4:0] R[4:0],G[5:3] - for ( int32 y = 0; y < height; y ++ ) - { - for ( int32 x = 0; x < width; x++ ) - { - int32 srcOffset = x * 2; - int32 dstOffset = x * 4; - uint8 blue = srcBits[srcOffset + 0] & 0x1f; - uint8 green = ( srcBits[srcOffset + 0] >> 5 ) - | ( ( srcBits[srcOffset + 1] & 0x07 ) << 3 ); - uint8 red = srcBits[srcOffset + 1] & 0xf8; - // homogeneously scale each component to 8 bit - dstBits[dstOffset + 0] = (blue << 3) | (blue >> 2); - dstBits[dstOffset + 1] = (green << 2) | (green >> 4); - dstBits[dstOffset + 2] = red | (red >> 5); - } - srcBits += srcBpr; - dstBits += dstBpr; - } - status = B_OK; - break; - default: - status = B_MISMATCHED_VALUES; - break; - } - if ( status == B_OK ) - { - if ( width < outBitmap->Bounds().IntegerWidth() + 1 - || height < outBitmap->Bounds().IntegerHeight() + 1 ) - { - scale_bitmap( outBitmap, width, height ); - } - } - } - } - return status; + status_t status = B_BAD_VALUE; + // see that we got valid bitmaps + if ( inBitmap && inBitmap->IsValid() + && outBitmap && outBitmap->IsValid() ) + { + status = B_MISMATCHED_VALUES; + // see that bitmaps are compatible and that we support the conversion + if ( inBitmap->Bounds().Width() <= outBitmap->Bounds().Width() + && inBitmap->Bounds().Height() <= outBitmap->Bounds().Height() + && ( outBitmap->ColorSpace() == B_RGB32 + || outBitmap->ColorSpace() == B_RGBA32) ) + { + int32 width = inBitmap->Bounds().IntegerWidth() + 1; + int32 height = inBitmap->Bounds().IntegerHeight() + 1; + int32 srcBpr = inBitmap->BytesPerRow(); + int32 dstBpr = outBitmap->BytesPerRow(); + uint8* srcBits = (uint8*)inBitmap->Bits(); + uint8* dstBits = (uint8*)outBitmap->Bits(); + switch (inBitmap->ColorSpace()) + { + case B_YCbCr422: + // Y0[7:0] Cb0[7:0] Y1[7:0] Cr0[7:0] + // Y2[7:0] Cb2[7:0] Y3[7:0] Cr2[7:0] + for ( int32 y = 0; y < height; y++ ) + { + for ( int32 x = 0; x < width; x += 2 ) + { + int32 srcOffset = x * 2; + int32 dstOffset = x * 4; + ycbcr_to_rgb( srcBits[srcOffset + 0], + srcBits[srcOffset + 1], + srcBits[srcOffset + 3], + dstBits[dstOffset + 2], + dstBits[dstOffset + 1], + dstBits[dstOffset + 0] ); + ycbcr_to_rgb( srcBits[srcOffset + 2], + srcBits[srcOffset + 1], + srcBits[srcOffset + 3], + dstBits[dstOffset + 6], + dstBits[dstOffset + 5], + dstBits[dstOffset + 4] ); + // take care of alpha + dstBits[x * 4 + 3] = 255; + dstBits[x * 4 + 7] = 255; + } + srcBits += srcBpr; + dstBits += dstBpr; + } + status = B_OK; + break; + case B_YCbCr420: + // Non-interlaced only! + // Cb0 Y0 Y1 Cb2 Y2 Y3 on even scan lines ... + // Cr0 Y0 Y1 Cr2 Y2 Y3 on odd scan lines + status = B_ERROR; + break; + case B_YUV422: + // U0[7:0] Y0[7:0] V0[7:0] Y1[7:0] + // U2[7:0] Y2[7:0] V2[7:0] Y3[7:0] + status = B_ERROR; + break; + case B_RGB32: + case B_RGBA32: + memcpy( dstBits, srcBits, inBitmap->BitsLength() ); + status = B_OK; + break; + case B_RGB16: + // G[2:0],B[4:0] R[4:0],G[5:3] + for ( int32 y = 0; y < height; y ++ ) + { + for ( int32 x = 0; x < width; x++ ) + { + int32 srcOffset = x * 2; + int32 dstOffset = x * 4; + uint8 blue = srcBits[srcOffset + 0] & 0x1f; + uint8 green = ( srcBits[srcOffset + 0] >> 5 ) + | ( ( srcBits[srcOffset + 1] & 0x07 ) << 3 ); + uint8 red = srcBits[srcOffset + 1] & 0xf8; + // homogeneously scale each component to 8 bit + dstBits[dstOffset + 0] = (blue << 3) | (blue >> 2); + dstBits[dstOffset + 1] = (green << 2) | (green >> 4); + dstBits[dstOffset + 2] = red | (red >> 5); + } + srcBits += srcBpr; + dstBits += dstBpr; + } + status = B_OK; + break; + default: + status = B_MISMATCHED_VALUES; + break; + } + if ( status == B_OK ) + { + if ( width < outBitmap->Bounds().IntegerWidth() + 1 + || height < outBitmap->Bounds().IntegerHeight() + 1 ) + { + scale_bitmap( outBitmap, width, height ); + } + } + } + } + return status; } // clip_float inline uint8 clip_float(float value) { - if (value < 0) - value = 0; - if (value > 255) - value = 255; - return (uint8)value; + if (value < 0) + value = 0; + if (value > 255) + value = 255; + return (uint8)value; } // dim_bitmap status_t dim_bitmap(BBitmap* bitmap, rgb_color center, float dimLevel) { - status_t status = B_BAD_VALUE; - if (bitmap && bitmap->IsValid()) - { - switch (bitmap->ColorSpace()) - { - case B_CMAP8: - { - BScreen screen(B_MAIN_SCREEN_ID); - if (screen.IsValid()) - { - // iterate over each pixel, get the respective - // color from the screen object, find the distance - // to the "center" color and shorten the distance - // by "dimLevel" - int32 length = bitmap->BitsLength(); - uint8* bits = (uint8*)bitmap->Bits(); - for (int32 i = 0; i < length; i++) - { - // preserve transparent pixels - if (bits[i] != B_TRANSPARENT_MAGIC_CMAP8) - { - // get color for this index - rgb_color c = screen.ColorForIndex(bits[i]); - // red - float dist = (c.red - center.red) * dimLevel; - c.red = clip_float(center.red + dist); - // green - dist = (c.green - center.green) * dimLevel; - c.green = clip_float(center.green + dist); - // blue - dist = (c.blue - center.blue) * dimLevel; - c.blue = clip_float(center.blue + dist); - // write correct index of the dimmed color - // back into bitmap (and hope the match is close...) - bits[i] = screen.IndexForColor(c); - } - } - status = B_OK; - } - break; - } - case B_RGB32: - case B_RGBA32: - { - // iterate over each color component, find the distance - // to the "center" color and shorten the distance - // by "dimLevel" - uint8* bits = (uint8*)bitmap->Bits(); - int32 bpr = bitmap->BytesPerRow(); - int32 pixels = bitmap->Bounds().IntegerWidth() + 1; - int32 lines = bitmap->Bounds().IntegerHeight() + 1; - // iterate over color components - for (int32 y = 0; y < lines; y++) { - for (int32 x = 0; x < pixels; x++) { - int32 offset = 4 * x; // four bytes per pixel - // blue - float dist = (bits[offset + 0] - center.blue) * dimLevel; - bits[offset + 0] = clip_float(center.blue + dist); - // green - dist = (bits[offset + 1] - center.green) * dimLevel; - bits[offset + 1] = clip_float(center.green + dist); - // red - dist = (bits[offset + 2] - center.red) * dimLevel; - bits[offset + 2] = clip_float(center.red + dist); - // ignore alpha channel - } - // next line - bits += bpr; - } - status = B_OK; - break; - } - default: - status = B_ERROR; - break; - } - } - return status; + status_t status = B_BAD_VALUE; + if (bitmap && bitmap->IsValid()) + { + switch (bitmap->ColorSpace()) + { + case B_CMAP8: + { + BScreen screen(B_MAIN_SCREEN_ID); + if (screen.IsValid()) + { + // iterate over each pixel, get the respective + // color from the screen object, find the distance + // to the "center" color and shorten the distance + // by "dimLevel" + int32 length = bitmap->BitsLength(); + uint8* bits = (uint8*)bitmap->Bits(); + for (int32 i = 0; i < length; i++) + { + // preserve transparent pixels + if (bits[i] != B_TRANSPARENT_MAGIC_CMAP8) + { + // get color for this index + rgb_color c = screen.ColorForIndex(bits[i]); + // red + float dist = (c.red - center.red) * dimLevel; + c.red = clip_float(center.red + dist); + // green + dist = (c.green - center.green) * dimLevel; + c.green = clip_float(center.green + dist); + // blue + dist = (c.blue - center.blue) * dimLevel; + c.blue = clip_float(center.blue + dist); + // write correct index of the dimmed color + // back into bitmap (and hope the match is close...) + bits[i] = screen.IndexForColor(c); + } + } + status = B_OK; + } + break; + } + case B_RGB32: + case B_RGBA32: + { + // iterate over each color component, find the distance + // to the "center" color and shorten the distance + // by "dimLevel" + uint8* bits = (uint8*)bitmap->Bits(); + int32 bpr = bitmap->BytesPerRow(); + int32 pixels = bitmap->Bounds().IntegerWidth() + 1; + int32 lines = bitmap->Bounds().IntegerHeight() + 1; + // iterate over color components + for (int32 y = 0; y < lines; y++) { + for (int32 x = 0; x < pixels; x++) { + int32 offset = 4 * x; // four bytes per pixel + // blue + float dist = (bits[offset + 0] - center.blue) * dimLevel; + bits[offset + 0] = clip_float(center.blue + dist); + // green + dist = (bits[offset + 1] - center.green) * dimLevel; + bits[offset + 1] = clip_float(center.green + dist); + // red + dist = (bits[offset + 2] - center.red) * dimLevel; + bits[offset + 2] = clip_float(center.red + dist); + // ignore alpha channel + } + // next line + bits += bpr; + } + status = B_OK; + break; + } + default: + status = B_ERROR; + break; + } + } + return status; } // dimmed_color_cmap8 rgb_color dimmed_color_cmap8(rgb_color color, rgb_color center, float dimLevel) { - BScreen screen(B_MAIN_SCREEN_ID); - if (screen.IsValid()) - { - // red - float dist = (color.red - center.red) * dimLevel; - color.red = clip_float(center.red + dist); - // green - dist = (color.green - center.green) * dimLevel; - color.green = clip_float(center.green + dist); - // blue - dist = (color.blue - center.blue) * dimLevel; - color.blue = clip_float(center.blue + dist); - // get color index for dimmed color - int32 index = screen.IndexForColor(color); - // put color at index (closest match in palette - // to dimmed result) into returned color - color = screen.ColorForIndex(index); - } - return color; + BScreen screen(B_MAIN_SCREEN_ID); + if (screen.IsValid()) + { + // red + float dist = (color.red - center.red) * dimLevel; + color.red = clip_float(center.red + dist); + // green + dist = (color.green - center.green) * dimLevel; + color.green = clip_float(center.green + dist); + // blue + dist = (color.blue - center.blue) * dimLevel; + color.blue = clip_float(center.blue + dist); + // get color index for dimmed color + int32 index = screen.IndexForColor(color); + // put color at index (closest match in palette + // to dimmed result) into returned color + color = screen.ColorForIndex(index); + } + return color; }