#include "ColorConversion.h"
#include <InterfaceDefs.h>
#include <Locker.h>
#include <Point.h>
#include <Palette.h>
#include <new>
#include <string.h>
#include <pthread.h>
using std::nothrow;
namespace BPrivate {
static inline
uint8
brightness_for(uint8 red, uint8 green, uint8 blue)
{
return uint8((308 * red + 600 * green + 116 * blue) / 1024);
}
static inline
unsigned
color_distance(uint8 red1, uint8 green1, uint8 blue1,
uint8 red2, uint8 green2, uint8 blue2)
{
int rd = (int)red1 - (int)red2;
int gd = (int)green1 - (int)green2;
int bd = (int)blue1 - (int)blue2;
int rmean = ((int)red1 + (int)red2) / 2;
return (((512 + rmean) * rd * rd) >> 8)
+ 4 * gd * gd
+ (((767 - rmean) * bd * bd) >> 8);
}
PaletteConverter::PaletteConverter()
: fColorMap(NULL),
fOwnColorMap(NULL),
fCStatus(B_NO_INIT)
{
}
PaletteConverter::PaletteConverter(const rgb_color *palette)
: fColorMap(NULL),
fOwnColorMap(NULL),
fCStatus(B_NO_INIT)
{
SetTo(palette);
}
PaletteConverter::PaletteConverter(const color_map *colorMap)
: fColorMap(NULL),
fOwnColorMap(NULL),
fCStatus(B_NO_INIT)
{
SetTo(colorMap);
}
PaletteConverter::~PaletteConverter()
{
delete fOwnColorMap;
}
status_t
PaletteConverter::SetTo(const rgb_color *palette)
{
SetTo((const color_map*)NULL);
status_t error = (palette ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
fOwnColorMap = new(nothrow) color_map;
if (fOwnColorMap == NULL)
error = B_NO_MEMORY;
}
if (error == B_OK) {
fColorMap = fOwnColorMap;
memcpy((void*)fOwnColorMap->color_list, palette, sizeof(rgb_color) * 256);
for (int32 color = 0; color < 32768; color++) {
uint8 red = (color & 0x7c00) >> 7;
uint8 green = (color & 0x3e0) >> 2;
uint8 blue = (color & 0x1f) << 3;
red |= red >> 5;
green |= green >> 5;
blue |= blue >> 5;
uint8 closestIndex = 0;
unsigned closestDistance = UINT_MAX;
for (int32 i = 0; i < 256; i++) {
const rgb_color &c = fOwnColorMap->color_list[i];
unsigned distance = color_distance(red, green, blue,
c.red, c.green, c.blue);
if (distance < closestDistance) {
closestIndex = i;
closestDistance = distance;
}
}
fOwnColorMap->index_map[color] = closestIndex;
}
}
fCStatus = error;
return error;
}
status_t
PaletteConverter::SetTo(const color_map *colorMap)
{
if (fOwnColorMap) {
delete fOwnColorMap;
fOwnColorMap = NULL;
}
fColorMap = colorMap;
fCStatus = (fColorMap ? B_OK : B_BAD_VALUE);
return fCStatus;
}
status_t
PaletteConverter::InitCheck() const
{
return fCStatus;
}
inline
uint8
PaletteConverter::IndexForRGB15(uint16 rgb) const
{
return fColorMap->index_map[rgb];
}
inline
uint8
PaletteConverter::IndexForRGB15(uint8 red, uint8 green, uint8 blue) const
{
return fColorMap->index_map[(red << 10) | (green << 5) | blue];
}
inline
uint8
PaletteConverter::IndexForRGB16(uint16 rgb) const
{
return fColorMap->index_map[((rgb >> 1) & 0x7fe0) | (rgb & 0x1f)];
}
inline
uint8
PaletteConverter::IndexForRGB16(uint8 red, uint8 green, uint8 blue) const
{
return fColorMap->index_map[(red << 10) | ((green & 0x3e) << 4) | blue];
}
inline
uint8
PaletteConverter::IndexForRGB24(uint32 rgb) const
{
return fColorMap->index_map[((rgb & 0xf8000000) >> 17)
| ((rgb & 0xf80000) >> 14)
| ((rgb & 0xf800) >> 11)];
}
inline
uint8
PaletteConverter::IndexForRGB24(uint8 red, uint8 green, uint8 blue) const
{
return fColorMap->index_map[((red & 0xf8) << 7)
| ((green & 0xf8) << 2)
| (blue >> 3)];
}
inline
uint8
PaletteConverter::IndexForRGBA32(uint32 rgba) const
{
if ((rgba & 0x000000ff) < 128)
return B_TRANSPARENT_MAGIC_CMAP8;
return IndexForRGB24(rgba);
}
inline
uint8
PaletteConverter::IndexForGray(uint8 gray) const
{
return IndexForRGB24(gray, gray, gray);
}
inline
const rgb_color &
PaletteConverter::RGBColorForIndex(uint8 index) const
{
return fColorMap->color_list[index];
}
inline
uint16
PaletteConverter::RGB15ColorForIndex(uint8 index) const
{
const rgb_color &color = fColorMap->color_list[index];
return ((color.red & 0xf8) << 7)
| ((color.green & 0xf8) << 2)
| (color.blue >> 3);
}
inline
uint16
PaletteConverter::RGB16ColorForIndex(uint8 index) const
{
const rgb_color &color = fColorMap->color_list[index];
return ((color.red & 0xf8) << 8)
| ((color.green & 0xfc) << 3)
| (color.blue >> 3);
}
inline
uint32
PaletteConverter::RGBA32ColorForIndex(uint8 index) const
{
const rgb_color &color = fColorMap->color_list[index];
return (color.red << 16) | (color.green << 8) | color.blue
| (color.alpha << 24);
}
inline
void
PaletteConverter::RGBA32ColorForIndex(uint8 index, uint8 &red, uint8 &green,
uint8 &blue, uint8 &alpha) const
{
const rgb_color &color = fColorMap->color_list[index];
red = color.red;
green = color.green;
blue = color.blue;
alpha = color.alpha;
}
inline
uint8
PaletteConverter::GrayColorForIndex(uint8 index) const
{
const rgb_color &color = fColorMap->color_list[index];
return brightness_for(color.red, color.green, color.blue);
}
static pthread_once_t sPaletteConverterInitOnce = PTHREAD_ONCE_INIT;
static PaletteConverter sPaletteConverter;
status_t
PaletteConverter::InitializeDefault(bool useServer)
{
if (sPaletteConverter.InitCheck() != B_OK) {
pthread_once(&sPaletteConverterInitOnce,
useServer
? &_InitializeDefaultAppServer
: &_InitializeDefaultNoAppServer);
}
return sPaletteConverter.InitCheck();
}
void
PaletteConverter::_InitializeDefaultAppServer()
{
sPaletteConverter.SetTo(system_colors());
}
void
PaletteConverter::_InitializeDefaultNoAppServer()
{
sPaletteConverter.SetTo(kSystemPalette);
}
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)
{
(*dest)[0] = data[0];
(*dest)[1] = data[1];
(*dest)[2] = data[2];
*dest += 3;
}
uint32
ReadRGB24(const uint8 **source, int32 index)
{
uint32 result = (*source)[0] | ((*source)[1] << 8) | ((*source)[2] << 16);
*source += 3;
return result;
}
void
WriteGray8(uint8 **dest, uint8 *data, int32 index)
{
**dest = (data[2] * 308 + data[1] * 600 + data[0] * 116) >> 10;
(*dest)++;
}
uint32
ReadGray8(const uint8 **source, int32 index)
{
uint32 result = **source;
(*source)++;
return result;
}
void
WriteGray1(uint8 **dest, uint8 *data, int32 index)
{
int32 shift = 7 - (index % 8);
**dest &= ~(0x01 << shift);
**dest |= (data[2] * 308 + data[1] * 600 + data[0] * 116) >> (17 - shift);
if (shift == 0)
(*dest)++;
}
uint32
ReadGray1(const uint8 **source, int32 index)
{
int32 shift = 7 - (index % 8);
uint32 result = ((**source >> shift) & 0x01) ? 0x00 : 0xFF;
if (shift == 0)
(*source)++;
return result;
}
void
WriteCMAP8(uint8 **dest, uint8 *data, int32 index)
{
**dest = sPaletteConverter.IndexForRGBA32(*(uint32 *)data);
(*dest)++;
}
uint32
ReadCMAP8(const uint8 **source, int32 index)
{
uint32 result = sPaletteConverter.RGBA32ColorForIndex(**source);
(*source)++;
return result;
}
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;
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));
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;
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 (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,
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,
readFunc *srcFunc, writeFunc *dstFunc)
{
uint8* srcBitsEnd = (uint8*)srcBits + srcBitsLength;
uint8* dstBitsEnd = (uint8*)dstBits + dstBitsLength;
int32 srcBitsPerRow = srcBytesPerRow << 3;
int32 dstBitsPerRow = dstBytesPerRow << 3;
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));
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;
if (srcColorSpace == dstColorSpace && srcBitsPerPixel % 8 == 0) {
int32 copyCount = (width * srcBitsPerPixel) >> 3;
for (int32 i = 0; i < height; i++) {
if (copyCount > srcBitsLength)
copyCount = srcBitsLength;
if (copyCount > dstBitsLength)
copyCount = dstBitsLength;
if (copyCount == 0)
break;
memcpy(dstBits, srcBits, copyCount);
srcBitsLength -= copyCount;
dstBitsLength -= copyCount;
srcBits = (srcByte*)((uint8*)srcBits + srcBytesPerRow);
dstBits = (dstByte*)((uint8*)dstBits + dstBytesPerRow);
if ((uint8 *)srcBits > srcBitsEnd || (uint8 *)dstBits > dstBitsEnd)
return B_OK;
}
return B_OK;
}
int32 srcLinePad = (srcBitsPerRow - width * srcBitsPerPixel + 7) >> 3;
int32 dstLinePad = (dstBitsPerRow - width * dstBitsPerPixel + 7) >> 3;
uint32 result;
uint32 source;
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 uint8 **)&srcBits, srcOffsetX++);
else {
source = *srcBits;
srcBits++;
}
if (srcSwap)
source = (source << 8) | (source >> 8);
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 (alphaBits == 1 && result & alphaMask)
result |= alphaMask;
} else
result |= alphaMask;
if (dstSwap)
result = (result << 8) | (result >> 8);
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>
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;
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,
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, readFunc *srcFunc)
{
switch (dstColorSpace) {
case B_RGBA32:
ConvertBits(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:
ConvertBits(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;
case B_RGB32:
ConvertBits(srcBits, (uint32 *)dstBits, srcBitsLength,
dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8,
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:
ConvertBits(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;
case B_RGB24:
ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength,
dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8,
0, 0, 0xff0000, 0x00ff00, 0x0000ff, 0x000000, srcBytesPerRow,
dstBytesPerRow, srcBitsPerPixel, 24, srcColorSpace,
dstColorSpace, srcOffset, dstOffset, width, height, srcSwap,
false, srcFunc, WriteRGB24);
break;
case B_RGB24_BIG:
ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength,
dstBitsLength, redShift - 8, greenShift - 16, blueShift - 24,
0, 0, 0x0000ff, 0x00ff00, 0xff0000, 0x000000, srcBytesPerRow,
dstBytesPerRow, srcBitsPerPixel, 24, srcColorSpace,
dstColorSpace, srcOffset, dstOffset, width, height, srcSwap,
false, srcFunc, WriteRGB24);
break;
case B_RGB16:
case B_RGB16_BIG:
ConvertBits(srcBits, (uint16 *)dstBits, srcBitsLength,
dstBitsLength, redShift - 16, greenShift - 11, blueShift - 5,
0, 0, 0xf800, 0x07e0, 0x001f, 0x0000, srcBytesPerRow,
dstBytesPerRow, srcBitsPerPixel, 16, srcColorSpace,
dstColorSpace, srcOffset, dstOffset, width, height, srcSwap,
dstColorSpace == B_RGB16_BIG, srcFunc, NULL);
break;
case B_RGBA15:
case B_RGBA15_BIG:
ConvertBits(srcBits, (uint16 *)dstBits, srcBitsLength,
dstBitsLength, redShift - 15, greenShift - 10, blueShift - 5,
alphaShift - 16, alphaBits, 0x7c00, 0x03e0, 0x001f, 0x8000,
srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 16,
srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
height, srcSwap, dstColorSpace == B_RGBA15_BIG, srcFunc, NULL);
break;
case B_RGB15:
case B_RGB15_BIG:
ConvertBits(srcBits, (uint16 *)dstBits, srcBitsLength,
dstBitsLength, redShift - 15, greenShift - 10, blueShift - 5,
0, 0, 0x7c00, 0x03e0, 0x001f, 0x0000, srcBytesPerRow,
dstBytesPerRow, srcBitsPerPixel, 16, srcColorSpace,
dstColorSpace, srcOffset, dstOffset, width, height, srcSwap,
dstColorSpace == B_RGB15_BIG, srcFunc, NULL);
break;
case B_GRAY8:
ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength,
dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8,
0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000,
srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 8,
srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
height, srcSwap, false, srcFunc, WriteGray8);
break;
case B_GRAY1:
ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength,
dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8,
0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000,
srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 1,
srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
height, srcSwap, false, srcFunc, WriteGray1);
break;
case B_CMAP8:
PaletteConverter::InitializeDefault();
ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength,
dstBitsLength, redShift - 32, greenShift - 24, blueShift - 16,
alphaShift - 8, alphaBits, 0xff000000, 0x00ff0000, 0x0000ff00,
0x000000ff, srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 8,
srcColorSpace, dstColorSpace, srcOffset, dstOffset,
width, height, srcSwap, false, srcFunc, WriteCMAP8);
break;
default:
return B_BAD_VALUE;
break;
}
return B_OK;
}
status_t
ConvertBits(const void *srcBits, void *dstBits, int32 srcBitsLength,
int32 dstBitsLength, int32 srcBytesPerRow, int32 dstBytesPerRow,
color_space srcColorSpace, color_space dstColorSpace, int32 width,
int32 height)
{
return ConvertBits(srcBits, dstBits, srcBitsLength, dstBitsLength,
srcBytesPerRow, dstBytesPerRow, srcColorSpace, dstColorSpace,
BPoint(0, 0), BPoint(0, 0), width, height);
}
status_t
ConvertBits(const void *srcBits, void *dstBits, int32 srcBitsLength,
int32 dstBitsLength, int32 srcBytesPerRow, int32 dstBytesPerRow,
color_space srcColorSpace, color_space dstColorSpace, BPoint srcOffset,
BPoint dstOffset, int32 width, int32 height)
{
if (!srcBits || !dstBits || srcBitsLength < 0 || dstBitsLength < 0
|| width < 0 || height < 0 || srcBytesPerRow < 0 || dstBytesPerRow < 0)
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,
dstBytesPerRow, 32, srcColorSpace, dstColorSpace, srcOffset,
dstOffset, width, height, false, NULL);
case B_RGBA32_BIG:
return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength,
dstBitsLength, 16, 24, 32, 8, 8, srcBytesPerRow,
dstBytesPerRow, 32, srcColorSpace, dstColorSpace, srcOffset,
dstOffset, width, height, false, NULL);
case B_RGB32:
return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength,
dstBitsLength, 24, 16, 8, 0, 0, srcBytesPerRow, dstBytesPerRow,
32, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
height, false, NULL);
case B_RGB32_BIG:
return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength,
dstBitsLength, 16, 24, 32, 0, 0, srcBytesPerRow,
dstBytesPerRow, 32, srcColorSpace, dstColorSpace, srcOffset,
dstOffset, width, height, false, NULL);
case B_RGB24:
return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength,
dstBitsLength, 24, 16, 8, 0, 0, srcBytesPerRow, dstBytesPerRow,
24, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
height, false, ReadRGB24);
case B_RGB24_BIG:
return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength,
dstBitsLength, 8, 16, 24, 0, 0, srcBytesPerRow, dstBytesPerRow,
24, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
height, false, ReadRGB24);
case B_RGB16:
case B_RGB16_BIG:
return ConvertBits((const uint16 *)srcBits, dstBits, srcBitsLength,
dstBitsLength, 16, 11, 5, 0, 0, srcBytesPerRow, dstBytesPerRow,
16, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
height, srcColorSpace == B_RGB16_BIG, NULL);
case B_RGBA15:
case B_RGBA15_BIG:
return ConvertBits((const uint16 *)srcBits, dstBits, srcBitsLength,
dstBitsLength, 15, 10, 5, 16, 1, srcBytesPerRow,
dstBytesPerRow, 16, srcColorSpace, dstColorSpace, srcOffset,
dstOffset, width, height, srcColorSpace == B_RGBA15_BIG, NULL);
case B_RGB15:
case B_RGB15_BIG:
return ConvertBits((const uint16 *)srcBits, dstBits, srcBitsLength,
dstBitsLength, 15, 10, 5, 0, 0, srcBytesPerRow, dstBytesPerRow,
16, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
height, srcColorSpace == B_RGB15_BIG, NULL);
case B_GRAY8:
return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength,
dstBitsLength, 8, 8, 8, 0, 0, srcBytesPerRow, dstBytesPerRow,
8, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
height, false, ReadGray8);
case B_GRAY1:
return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength,
dstBitsLength, 8, 8, 8, 0, 0, srcBytesPerRow, dstBytesPerRow,
1, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
height, false, ReadGray1);
case B_CMAP8:
PaletteConverter::InitializeDefault();
return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength,
dstBitsLength, 24, 16, 8, 32, 8, srcBytesPerRow,
dstBytesPerRow, 8, srcColorSpace, dstColorSpace, srcOffset,
dstOffset, width, height, false, ReadCMAP8);
default:
return B_BAD_VALUE;
}
return B_OK;
}
}