Removing unused code to reveal what's left to replace, so DrawingBits.h and .cpp can be removed as per the TODO comment in these files. Mentioned GPL code is here: http://vlc.sourcearchive.com/documentation/0.9.8a/DrawingTidbits_8cpp-source.html
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32333 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -21,309 +21,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
// ShiftComponent
|
|
||||||
inline uchar
|
|
||||||
ShiftComponent(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));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShiftColor
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReplaceTransparentColor
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ycrcb_to_rgb
|
|
||||||
inline void
|
|
||||||
ycbcr_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_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 )
|
|
||||||
{
|
|
||||||
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_bitmap
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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:
|
|
||||||
//printf("unkown colorspace: %ld\n", inBitmap->ColorSpace());
|
|
||||||
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
|
// clip_float
|
||||||
inline uint8
|
inline uint8
|
||||||
clip_float(float value)
|
clip_float(float value)
|
||||||
@@ -443,3 +140,4 @@ dimmed_color_cmap8(rgb_color color, rgb_color center, float dimLevel)
|
|||||||
}
|
}
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,44 +19,6 @@
|
|||||||
class BBitmap;
|
class BBitmap;
|
||||||
|
|
||||||
const rgb_color kBlack = { 0, 0, 0, 255 };
|
const rgb_color kBlack = { 0, 0, 0, 255 };
|
||||||
const rgb_color kWhite = { 255, 255, 255, 255 };
|
|
||||||
|
|
||||||
rgb_color ShiftColor(rgb_color , float );
|
|
||||||
|
|
||||||
inline rgb_color
|
|
||||||
Color(int32 r, int32 g, int32 b, int32 alpha = 255)
|
|
||||||
{
|
|
||||||
rgb_color result;
|
|
||||||
result.red = r;
|
|
||||||
result.green = g;
|
|
||||||
result.blue = b;
|
|
||||||
result.alpha = alpha;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float kDarkness = 1.06;
|
|
||||||
const float kDimLevel = 0.6;
|
|
||||||
|
|
||||||
void ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to);
|
|
||||||
void ReplaceTransparentColor(BBitmap *bitmap, rgb_color with);
|
|
||||||
|
|
||||||
// function can be used to scale the upper left part of
|
|
||||||
// a bitmap to fill the entire bitmap, ie fromWidth
|
|
||||||
// and fromHeight must be smaller or equal to the bitmaps size!
|
|
||||||
// only supported colorspaces are B_RGB32 and B_RGBA32
|
|
||||||
status_t scale_bitmap( BBitmap* bitmap,
|
|
||||||
uint32 fromWidth, uint32 fromHeight );
|
|
||||||
|
|
||||||
// bitmaps need to be the same size, or this function will fail
|
|
||||||
// currently supported conversions:
|
|
||||||
// B_YCbCr422 -> B_RGB32
|
|
||||||
// B_RGB32 -> B_RGB32
|
|
||||||
// B_RGB16 -> B_RGB32
|
|
||||||
// not yet implemented conversions:
|
|
||||||
// B_YCbCr420 -> B_RGB32
|
|
||||||
// B_YUV422 -> B_RGB32
|
|
||||||
status_t convert_bitmap(BBitmap* inBitmap, BBitmap* outBitmap);
|
|
||||||
|
|
||||||
// dims bitmap (in place) by finding the distance of
|
// dims bitmap (in place) by finding the distance of
|
||||||
// the color at each pixel to the provided "center" color
|
// the color at each pixel to the provided "center" color
|
||||||
|
|||||||
Reference in New Issue
Block a user