interface: add colorspaces support for RGB48 and RGBA64
these colorspaces are packed as RGB or RGBA, not BGR or BGRA. RGB48_BIG and RGBA64 only differ in the endianess of the channel the 2-byte value. this is a big difference with RGB24_BIG and RGBA32_BIG, in which case _BIG means the order is RGB (BGR) and not BGR (BGRA). BGR48, BGRA64 could indeed be added, if needed. I chose 0x11 and 0x12 arbitrarily, but given the order of channels 0x1011 and 0x1012 might make more sense. This would mean using another bit for "real" bigendian colorspaces. Only the color conversion to 32-bits is implemented. Tested with the RAWTranslator modified to output 16bpp with success. Found some references in enum AVPixelFormat in libavutil/pixfmt.h. Change-Id: I4b023dec85d01f1e63e1b053139e5bb5d263a0e0 Reviewed-on: https://review.haiku-os.org/c/haiku/+/4468 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
parent
c1432f757f
commit
bb187c91d8
@ -149,6 +149,8 @@ typedef enum {
|
||||
B_NO_COLOR_SPACE = 0x0000,
|
||||
|
||||
// linear color space (little endian)
|
||||
B_RGBA64 = 0x2012, // RGBA RGBA 16:16:16:16
|
||||
B_RGB48 = 0x0011, // RGB RGB 16:16:16
|
||||
B_RGB32 = 0x0008, // BGR- -RGB 8:8:8:8
|
||||
B_RGBA32 = 0x2008, // BGRA ARGB 8:8:8:8
|
||||
B_RGB24 = 0x0003, // BGR RGB 8:8:8
|
||||
@ -160,6 +162,8 @@ typedef enum {
|
||||
B_GRAY1 = 0x0001, // Each bit represents a single pixel
|
||||
|
||||
// linear color space (big endian)
|
||||
B_RGBA64_BIG = 0x3012, // RGBA RGBA 16:16:16:16
|
||||
B_RGB48_BIG = 0x1011, // RGB RGB 16:16:16
|
||||
B_RGB32_BIG = 0x1008, // -RGB BGR- 8:8:8:8
|
||||
B_RGBA32_BIG = 0x3008, // ARGB BGRA 8:8:8:8
|
||||
B_RGB24_BIG = 0x1003, // RGB BGR 8:8:8
|
||||
@ -168,6 +172,8 @@ typedef enum {
|
||||
B_RGBA15_BIG = 0x3010, // ARGB BGRA 5:5:5:1
|
||||
|
||||
// linear color space (little endian, for completeness)
|
||||
B_RGBA64_LITTLE = B_RGBA64,
|
||||
B_RGB48_LITTLE = B_RGB48,
|
||||
B_RGB32_LITTLE = B_RGB32,
|
||||
B_RGBA32_LITTLE = B_RGBA32,
|
||||
B_RGB24_LITTLE = B_RGB24,
|
||||
|
@ -179,6 +179,12 @@ get_raw_bytes_per_row(color_space colorSpace, int32 width)
|
||||
int32 bpr = 0;
|
||||
switch (colorSpace) {
|
||||
// supported
|
||||
case B_RGBA64: case B_RGBA64_BIG:
|
||||
bpr = 8 * width;
|
||||
break;
|
||||
case B_RGB48: case B_RGB48_BIG:
|
||||
bpr = 6 * width;
|
||||
break;
|
||||
case B_RGB32: case B_RGBA32:
|
||||
case B_RGB32_BIG: case B_RGBA32_BIG:
|
||||
case B_UVL32: case B_UVLA32:
|
||||
|
@ -57,6 +57,14 @@ get_pixel_size_for(color_space space, size_t *pixelChunk, size_t *rowAlignment,
|
||||
int32 pixPerChunk = 0;
|
||||
switch (space) {
|
||||
// supported
|
||||
case B_RGBA64: case B_RGBA64_BIG:
|
||||
bytesPerPixel = 8;
|
||||
pixPerChunk = 2;
|
||||
break;
|
||||
case B_RGB48: case B_RGB48_BIG:
|
||||
bytesPerPixel = 6;
|
||||
pixPerChunk = 2;
|
||||
break;
|
||||
case B_RGB32: case B_RGBA32:
|
||||
case B_RGB32_BIG: case B_RGBA32_BIG:
|
||||
case B_UVL32: case B_UVLA32:
|
||||
@ -150,6 +158,8 @@ bitmaps_support_space(color_space space, uint32 *supportFlags)
|
||||
bool result = false;
|
||||
switch (space) {
|
||||
// supported
|
||||
case B_RGBA64: case B_RGBA64_BIG:
|
||||
case B_RGB48: case B_RGB48_BIG:
|
||||
case B_RGB32: case B_RGBA32: case B_RGB24:
|
||||
case B_RGB32_BIG: case B_RGBA32_BIG: case B_RGB24_BIG:
|
||||
case B_RGB16: case B_RGB15: case B_RGBA15:
|
||||
|
@ -87,6 +87,12 @@ get_raw_bytes_per_row(color_space colorSpace, int32 width)
|
||||
int32 bpr = 0;
|
||||
switch (colorSpace) {
|
||||
// supported
|
||||
case B_RGBA64: case B_RGBA64_BIG:
|
||||
bpr = 8 * width;
|
||||
break;
|
||||
case B_RGB48: case B_RGB48_BIG:
|
||||
bpr = 6 * width;
|
||||
break;
|
||||
case B_RGB32: case B_RGBA32:
|
||||
case B_RGB32_BIG: case B_RGBA32_BIG:
|
||||
case B_UVL32: case B_UVLA32:
|
||||
|
@ -491,9 +491,20 @@ PaletteConverter::_InitializeDefaultNoAppServer()
|
||||
|
||||
|
||||
typedef uint32 (readFunc)(const uint8 **source, int32 index);
|
||||
typedef uint64 (read64Func)(const uint16 **source, int32 index);
|
||||
typedef void (writeFunc)(uint8 **dest, uint8 *data, int32 index);
|
||||
|
||||
|
||||
uint64
|
||||
ReadRGB48(const uint16 **source, int32 index)
|
||||
{
|
||||
uint64 result = (*source)[0] | ((uint64)((*source)[1]) << 16)
|
||||
| ((uint64)((*source)[2]) << 32);
|
||||
*source += 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WriteRGB24(uint8 **dest, uint8 *data, int32 index)
|
||||
{
|
||||
@ -573,6 +584,145 @@ ReadCMAP8(const uint8 **source, int32 index)
|
||||
}
|
||||
|
||||
|
||||
template<typename srcByte, typename dstByte>
|
||||
status_t
|
||||
ConvertBits64To32(const srcByte *srcBits, dstByte *dstBits, int32 srcBitsLength,
|
||||
int32 dstBitsLength, int32 redShift, int32 greenShift, int32 blueShift,
|
||||
int32 alphaShift, int32 alphaBits, uint32 redMask, uint32 greenMask,
|
||||
uint32 blueMask, uint32 alphaMask, int32 srcBytesPerRow,
|
||||
int32 dstBytesPerRow, int32 srcBitsPerPixel, int32 dstBitsPerPixel,
|
||||
color_space srcColorSpace, color_space dstColorSpace, BPoint srcOffset,
|
||||
BPoint dstOffset, int32 width, int32 height, bool srcSwap, bool dstSwap,
|
||||
read64Func *srcFunc, writeFunc *dstFunc)
|
||||
{
|
||||
uint8* srcBitsEnd = (uint8*)srcBits + srcBitsLength;
|
||||
uint8* dstBitsEnd = (uint8*)dstBits + dstBitsLength;
|
||||
|
||||
int32 srcBitsPerRow = srcBytesPerRow << 3;
|
||||
int32 dstBitsPerRow = dstBytesPerRow << 3;
|
||||
|
||||
// Advance the buffers to reach their offsets
|
||||
int32 srcOffsetX = (int32)srcOffset.x;
|
||||
int32 dstOffsetX = (int32)dstOffset.x;
|
||||
int32 srcOffsetY = (int32)srcOffset.y;
|
||||
int32 dstOffsetY = (int32)dstOffset.y;
|
||||
if (srcOffsetX < 0) {
|
||||
dstOffsetX -= srcOffsetX;
|
||||
srcOffsetX = 0;
|
||||
}
|
||||
if (srcOffsetY < 0) {
|
||||
dstOffsetY -= srcOffsetY;
|
||||
height += srcOffsetY;
|
||||
srcOffsetY = 0;
|
||||
}
|
||||
if (dstOffsetX < 0) {
|
||||
srcOffsetX -= dstOffsetX;
|
||||
dstOffsetX = 0;
|
||||
}
|
||||
if (dstOffsetY < 0) {
|
||||
srcOffsetY -= dstOffsetY;
|
||||
height += dstOffsetY;
|
||||
dstOffsetY = 0;
|
||||
}
|
||||
|
||||
srcBits = (srcByte*)((uint8*)srcBits + ((srcOffsetY * srcBitsPerRow
|
||||
+ srcOffsetX * srcBitsPerPixel) >> 3));
|
||||
dstBits = (dstByte*)((uint8*)dstBits + ((dstOffsetY * dstBitsPerRow
|
||||
+ dstOffsetX * dstBitsPerPixel) >> 3));
|
||||
|
||||
// Ensure that the width fits
|
||||
int32 srcWidth = (srcBitsPerRow - srcOffsetX * srcBitsPerPixel)
|
||||
/ srcBitsPerPixel;
|
||||
if (srcWidth < width)
|
||||
width = srcWidth;
|
||||
|
||||
int32 dstWidth = (dstBitsPerRow - dstOffsetX * dstBitsPerPixel)
|
||||
/ dstBitsPerPixel;
|
||||
if (dstWidth < width)
|
||||
width = dstWidth;
|
||||
|
||||
if (width < 0)
|
||||
return B_OK;
|
||||
|
||||
int32 srcLinePad = (srcBitsPerRow - width * srcBitsPerPixel + 7) >> 3;
|
||||
int32 dstLinePad = (dstBitsPerRow - width * dstBitsPerPixel + 7) >> 3;
|
||||
uint64 result;
|
||||
uint64 source;
|
||||
|
||||
// srcSwap, means the lower bits come first
|
||||
if (srcSwap) {
|
||||
redShift -= 8;
|
||||
greenShift -= 8;
|
||||
blueShift -= 8;
|
||||
alphaShift -= 8;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < height; i++) {
|
||||
for (int32 j = 0; j < width; j++) {
|
||||
if ((uint8 *)srcBits + sizeof(srcByte) > srcBitsEnd
|
||||
|| (uint8 *)dstBits + sizeof(dstByte) > dstBitsEnd)
|
||||
return B_OK;
|
||||
|
||||
if (srcFunc)
|
||||
source = srcFunc((const uint16 **)&srcBits, srcOffsetX++);
|
||||
else {
|
||||
source = *srcBits;
|
||||
srcBits++;
|
||||
}
|
||||
|
||||
if (redShift > 0)
|
||||
result = ((source >> redShift) & redMask);
|
||||
else if (redShift < 0)
|
||||
result = ((source << -redShift) & redMask);
|
||||
else
|
||||
result = source & redMask;
|
||||
|
||||
if (greenShift > 0)
|
||||
result |= ((source >> greenShift) & greenMask);
|
||||
else if (greenShift < 0)
|
||||
result |= ((source << -greenShift) & greenMask);
|
||||
else
|
||||
result |= source & greenMask;
|
||||
|
||||
if (blueShift > 0)
|
||||
result |= ((source >> blueShift) & blueMask);
|
||||
else if (blueShift < 0)
|
||||
result |= ((source << -blueShift) & blueMask);
|
||||
else
|
||||
result |= source & blueMask;
|
||||
|
||||
if (alphaBits > 0) {
|
||||
if (alphaShift > 0)
|
||||
result |= ((source >> alphaShift) & alphaMask);
|
||||
else if (alphaShift < 0)
|
||||
result |= ((source << -alphaShift) & alphaMask);
|
||||
else
|
||||
result |= source & alphaMask;
|
||||
|
||||
// if we only had one alpha bit we want it to be 0/255
|
||||
if (alphaBits == 1 && result & alphaMask)
|
||||
result |= alphaMask;
|
||||
} else
|
||||
result |= alphaMask;
|
||||
|
||||
if (dstFunc)
|
||||
dstFunc((uint8 **)&dstBits, (uint8 *)&result, dstOffsetX++);
|
||||
else {
|
||||
*dstBits = result;
|
||||
dstBits++;
|
||||
}
|
||||
}
|
||||
|
||||
srcBits = (srcByte*)((uint8*)srcBits + srcLinePad);
|
||||
dstBits = (dstByte*)((uint8*)dstBits + dstLinePad);
|
||||
dstOffsetX -= width;
|
||||
srcOffsetX -= width;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
template<typename srcByte, typename dstByte>
|
||||
status_t
|
||||
ConvertBits(const srcByte *srcBits, dstByte *dstBits, int32 srcBitsLength,
|
||||
@ -614,10 +764,10 @@ ConvertBits(const srcByte *srcBits, dstByte *dstBits, int32 srcBitsLength,
|
||||
dstOffsetY = 0;
|
||||
}
|
||||
|
||||
srcBits = (srcByte*)((uint8*)srcBits + ((srcOffsetY * srcBitsPerRow + srcOffsetX
|
||||
* srcBitsPerPixel) >> 3));
|
||||
dstBits = (dstByte*)((uint8*)dstBits + ((dstOffsetY * dstBitsPerRow + dstOffsetX
|
||||
* dstBitsPerPixel) >> 3));
|
||||
srcBits = (srcByte*)((uint8*)srcBits + ((srcOffsetY * srcBitsPerRow
|
||||
+ srcOffsetX * srcBitsPerPixel) >> 3));
|
||||
dstBits = (dstByte*)((uint8*)dstBits + ((dstOffsetY * dstBitsPerRow
|
||||
+ dstOffsetX * dstBitsPerPixel) >> 3));
|
||||
|
||||
// Ensure that the width fits
|
||||
int32 srcWidth = (srcBitsPerRow - srcOffsetX * srcBitsPerPixel)
|
||||
@ -738,6 +888,64 @@ ConvertBits(const srcByte *srcBits, dstByte *dstBits, int32 srcBitsLength,
|
||||
}
|
||||
|
||||
|
||||
template<typename srcByte>
|
||||
status_t
|
||||
ConvertBits64(const srcByte *srcBits, void *dstBits, int32 srcBitsLength,
|
||||
int32 dstBitsLength, int32 redShift, int32 greenShift, int32 blueShift,
|
||||
int32 alphaShift, int32 alphaBits, int32 srcBytesPerRow,
|
||||
int32 dstBytesPerRow, int32 srcBitsPerPixel, color_space srcColorSpace,
|
||||
color_space dstColorSpace, BPoint srcOffset, BPoint dstOffset, int32 width,
|
||||
int32 height, bool srcSwap, read64Func *srcFunc)
|
||||
{
|
||||
switch (dstColorSpace) {
|
||||
case B_RGBA32:
|
||||
ConvertBits64To32(srcBits, (uint32 *)dstBits, srcBitsLength,
|
||||
dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8,
|
||||
alphaShift - 32, alphaBits, 0x00ff0000, 0x0000ff00, 0x000000ff,
|
||||
0xff000000, srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel,
|
||||
32, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
|
||||
height, srcSwap, false, srcFunc, NULL);
|
||||
break;
|
||||
|
||||
case B_RGBA32_BIG:
|
||||
ConvertBits64To32(srcBits, (uint32 *)dstBits, srcBitsLength,
|
||||
dstBitsLength, redShift - 16, greenShift - 24, blueShift - 32,
|
||||
alphaShift - 8, alphaBits, 0x0000ff00, 0x00ff0000, 0xff000000,
|
||||
0x00000ff, srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32,
|
||||
srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
|
||||
height, srcSwap, false, srcFunc, NULL);
|
||||
break;
|
||||
|
||||
/* Note: we set the unused alpha to 255 here. This is because BeOS
|
||||
uses the unused alpha for B_OP_ALPHA even though it should
|
||||
not care about it. */
|
||||
case B_RGB32:
|
||||
ConvertBits64To32(srcBits, (uint32 *)dstBits, srcBitsLength,
|
||||
dstBitsLength, redShift - 24, greenShift - 32, blueShift - 16,
|
||||
0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000,
|
||||
srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32,
|
||||
srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
|
||||
height, srcSwap, false, srcFunc, NULL);
|
||||
break;
|
||||
|
||||
case B_RGB32_BIG:
|
||||
ConvertBits64To32(srcBits, (uint32 *)dstBits, srcBitsLength,
|
||||
dstBitsLength, redShift - 16, greenShift - 24, blueShift - 32,
|
||||
0, 0, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff,
|
||||
srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32,
|
||||
srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
|
||||
height, srcSwap, false, srcFunc, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
return B_BAD_VALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
template<typename srcByte>
|
||||
status_t
|
||||
ConvertBits(const srcByte *srcBits, void *dstBits, int32 srcBitsLength,
|
||||
@ -927,6 +1135,22 @@ ConvertBits(const void *srcBits, void *dstBits, int32 srcBitsLength,
|
||||
return B_BAD_VALUE;
|
||||
|
||||
switch (srcColorSpace) {
|
||||
case B_RGBA64:
|
||||
case B_RGBA64_BIG:
|
||||
return ConvertBits64((const uint64 *)srcBits, dstBits,
|
||||
srcBitsLength, dstBitsLength, 16, 32, 48, 64, 16,
|
||||
srcBytesPerRow, dstBytesPerRow, 64, srcColorSpace,
|
||||
dstColorSpace, srcOffset, dstOffset, width, height,
|
||||
srcColorSpace == B_RGBA64_BIG, NULL);
|
||||
|
||||
case B_RGB48:
|
||||
case B_RGB48_BIG:
|
||||
return ConvertBits64((const uint16 *)srcBits, dstBits,
|
||||
srcBitsLength, dstBitsLength, 16, 32, 48, 0, 0, srcBytesPerRow,
|
||||
dstBytesPerRow, 48, srcColorSpace, dstColorSpace, srcOffset,
|
||||
dstOffset, width, height, srcColorSpace == B_RGB48_BIG,
|
||||
ReadRGB48);
|
||||
|
||||
case B_RGBA32:
|
||||
return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength,
|
||||
dstBitsLength, 24, 16, 8, 32, 8, srcBytesPerRow,
|
||||
|
@ -97,6 +97,14 @@ get_pixel_size_for(color_space space, size_t *pixelChunk, size_t *rowAlignment,
|
||||
int32 pixPerChunk = 0;
|
||||
switch (space) {
|
||||
// supported
|
||||
case B_RGBA64: case B_RGBA64_BIG:
|
||||
bytesPerPixel = 8;
|
||||
pixPerChunk = 2;
|
||||
break;
|
||||
case B_RGB48: case B_RGB48_BIG:
|
||||
bytesPerPixel = 6;
|
||||
pixPerChunk = 2;
|
||||
break;
|
||||
case B_RGB32: case B_RGBA32:
|
||||
case B_RGB32_BIG: case B_RGBA32_BIG:
|
||||
case B_UVL32: case B_UVLA32:
|
||||
@ -217,6 +225,8 @@ bitmaps_support_space(color_space space, uint32 *supportFlags)
|
||||
break;
|
||||
|
||||
// supported, but cannot draw
|
||||
case B_RGBA64: case B_RGBA64_BIG:
|
||||
case B_RGB48: case B_RGB48_BIG:
|
||||
case B_YCbCr422: case B_YCbCr411: case B_YCbCr444: case B_YCbCr420:
|
||||
case B_YUV422: case B_YUV411: case B_YUV444: case B_YUV420:
|
||||
case B_UVL24: case B_UVL32: case B_UVLA32:
|
||||
|
@ -35,6 +35,12 @@ get_bytes_per_row(color_space colorSpace, int32 width)
|
||||
int32 bpr = 0;
|
||||
switch (colorSpace) {
|
||||
// supported
|
||||
case B_RGBA64: case B_RGBA64_BIG:
|
||||
bpr = 8 * width;
|
||||
break;
|
||||
case B_RGB48: case B_RGB48_BIG:
|
||||
bpr = 6 * width;
|
||||
break;
|
||||
case B_RGB32: case B_RGBA32:
|
||||
case B_RGB32_BIG: case B_RGBA32_BIG:
|
||||
case B_UVL32: case B_UVLA32:
|
||||
@ -98,6 +104,11 @@ void TBBitmapTester::BBitmap1()
|
||||
BRect bounds;
|
||||
color_space space;
|
||||
} testCases[] = {
|
||||
{ BRect(0, 0, 39, 9), B_RGBA64 },
|
||||
{ BRect(0, 0, 39, 9), B_RGBA64_BIG },
|
||||
{ BRect(0, 0, 39, 9), B_RGB48 },
|
||||
{ BRect(0, 0, 39, 9), B_RGB48_BIG },
|
||||
|
||||
{ BRect(0, 0, 39, 9), B_RGB32 },
|
||||
{ BRect(0, 0, 39, 9), B_RGBA32 },
|
||||
{ BRect(0, 0, 39, 9), B_RGB32_BIG },
|
||||
|
Loading…
Reference in New Issue
Block a user