Files
haiku-beta6/src/kits/interface/Bitmap.cpp
T

1726 lines
45 KiB
C++
Raw Normal View History

//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, OpenBeOS
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: Bitmap.cpp
// Author: Ingo Weinhold ([email protected])
// Description: BBitmap objects represent off-screen windows that
// contain bitmap data.
//------------------------------------------------------------------------------
#include <algobase.h>
#include <limits.h>
#include <new>
#include <stdlib.h>
#include <Bitmap.h>
#include <InterfaceDefs.h>
#include <Locker.h>
#include <OS.h>
enum {
NOT_IMPLEMENTED = B_ERROR,
};
// TODO: system palette -- hard-coded for now, when the app server is ready
// we should use system_colors() or BScreen::ColorMap().
const rgb_color kSystemPalette[] = {
{ 0, 0, 0, 255 }, { 8, 8, 8, 255 }, { 16, 16, 16, 255 },
{ 24, 24, 24, 255 }, { 32, 32, 32, 255 }, { 40, 40, 40, 255 },
{ 48, 48, 48, 255 }, { 56, 56, 56, 255 }, { 64, 64, 64, 255 },
{ 72, 72, 72, 255 }, { 80, 80, 80, 255 }, { 88, 88, 88, 255 },
{ 96, 96, 96, 255 }, { 104, 104, 104, 255 }, { 112, 112, 112, 255 },
{ 120, 120, 120, 255 }, { 128, 128, 128, 255 }, { 136, 136, 136, 255 },
{ 144, 144, 144, 255 }, { 152, 152, 152, 255 }, { 160, 160, 160, 255 },
{ 168, 168, 168, 255 }, { 176, 176, 176, 255 }, { 184, 184, 184, 255 },
{ 192, 192, 192, 255 }, { 200, 200, 200, 255 }, { 208, 208, 208, 255 },
{ 216, 216, 216, 255 }, { 224, 224, 224, 255 }, { 232, 232, 232, 255 },
{ 240, 240, 240, 255 }, { 248, 248, 248, 255 }, { 0, 0, 255, 255 },
{ 0, 0, 229, 255 }, { 0, 0, 204, 255 }, { 0, 0, 179, 255 },
{ 0, 0, 154, 255 }, { 0, 0, 129, 255 }, { 0, 0, 105, 255 },
{ 0, 0, 80, 255 }, { 0, 0, 55, 255 }, { 0, 0, 30, 255 },
{ 255, 0, 0, 255 }, { 228, 0, 0, 255 }, { 203, 0, 0, 255 },
{ 178, 0, 0, 255 }, { 153, 0, 0, 255 }, { 128, 0, 0, 255 },
{ 105, 0, 0, 255 }, { 80, 0, 0, 255 }, { 55, 0, 0, 255 },
{ 30, 0, 0, 255 }, { 0, 255, 0, 255 }, { 0, 228, 0, 255 },
{ 0, 203, 0, 255 }, { 0, 178, 0, 255 }, { 0, 153, 0, 255 },
{ 0, 128, 0, 255 }, { 0, 105, 0, 255 }, { 0, 80, 0, 255 },
{ 0, 55, 0, 255 }, { 0, 30, 0, 255 }, { 0, 152, 51, 255 },
{ 255, 255, 255, 255 }, { 203, 255, 255, 255 }, { 203, 255, 203, 255 },
{ 203, 255, 152, 255 }, { 203, 255, 102, 255 }, { 203, 255, 51, 255 },
{ 203, 255, 0, 255 }, { 152, 255, 255, 255 }, { 152, 255, 203, 255 },
{ 152, 255, 152, 255 }, { 152, 255, 102, 255 }, { 152, 255, 51, 255 },
{ 152, 255, 0, 255 }, { 102, 255, 255, 255 }, { 102, 255, 203, 255 },
{ 102, 255, 152, 255 }, { 102, 255, 102, 255 }, { 102, 255, 51, 255 },
{ 102, 255, 0, 255 }, { 51, 255, 255, 255 }, { 51, 255, 203, 255 },
{ 51, 255, 152, 255 }, { 51, 255, 102, 255 }, { 51, 255, 51, 255 },
{ 51, 255, 0, 255 }, { 255, 152, 255, 255 }, { 255, 152, 203, 255 },
{ 255, 152, 152, 255 }, { 255, 152, 102, 255 }, { 255, 152, 51, 255 },
{ 255, 152, 0, 255 }, { 0, 102, 255, 255 }, { 0, 102, 203, 255 },
{ 203, 203, 255, 255 }, { 203, 203, 203, 255 }, { 203, 203, 152, 255 },
{ 203, 203, 102, 255 }, { 203, 203, 51, 255 }, { 203, 203, 0, 255 },
{ 152, 203, 255, 255 }, { 152, 203, 203, 255 }, { 152, 203, 152, 255 },
{ 152, 203, 102, 255 }, { 152, 203, 51, 255 }, { 152, 203, 0, 255 },
{ 102, 203, 255, 255 }, { 102, 203, 203, 255 }, { 102, 203, 152, 255 },
{ 102, 203, 102, 255 }, { 102, 203, 51, 255 }, { 102, 203, 0, 255 },
{ 51, 203, 255, 255 }, { 51, 203, 203, 255 }, { 51, 203, 152, 255 },
{ 51, 203, 102, 255 }, { 51, 203, 51, 255 }, { 51, 203, 0, 255 },
{ 255, 102, 255, 255 }, { 255, 102, 203, 255 }, { 255, 102, 152, 255 },
{ 255, 102, 102, 255 }, { 255, 102, 51, 255 }, { 255, 102, 0, 255 },
{ 0, 102, 152, 255 }, { 0, 102, 102, 255 }, { 203, 152, 255, 255 },
{ 203, 152, 203, 255 }, { 203, 152, 152, 255 }, { 203, 152, 102, 255 },
{ 203, 152, 51, 255 }, { 203, 152, 0, 255 }, { 152, 152, 255, 255 },
{ 152, 152, 203, 255 }, { 152, 152, 152, 255 }, { 152, 152, 102, 255 },
{ 152, 152, 51, 255 }, { 152, 152, 0, 255 }, { 102, 152, 255, 255 },
{ 102, 152, 203, 255 }, { 102, 152, 152, 255 }, { 102, 152, 102, 255 },
{ 102, 152, 51, 255 }, { 102, 152, 0, 255 }, { 51, 152, 255, 255 },
{ 51, 152, 203, 255 }, { 51, 152, 152, 255 }, { 51, 152, 102, 255 },
{ 51, 152, 51, 255 }, { 51, 152, 0, 255 }, { 230, 134, 0, 255 },
{ 255, 51, 203, 255 }, { 255, 51, 152, 255 }, { 255, 51, 102, 255 },
{ 255, 51, 51, 255 }, { 255, 51, 0, 255 }, { 0, 102, 51, 255 },
{ 0, 102, 0, 255 }, { 203, 102, 255, 255 }, { 203, 102, 203, 255 },
{ 203, 102, 152, 255 }, { 203, 102, 102, 255 }, { 203, 102, 51, 255 },
{ 203, 102, 0, 255 }, { 152, 102, 255, 255 }, { 152, 102, 203, 255 },
{ 152, 102, 152, 255 }, { 152, 102, 102, 255 }, { 152, 102, 51, 255 },
{ 152, 102, 0, 255 }, { 102, 102, 255, 255 }, { 102, 102, 203, 255 },
{ 102, 102, 152, 255 }, { 102, 102, 102, 255 }, { 102, 102, 51, 255 },
{ 102, 102, 0, 255 }, { 51, 102, 255, 255 }, { 51, 102, 203, 255 },
{ 51, 102, 152, 255 }, { 51, 102, 102, 255 }, { 51, 102, 51, 255 },
{ 51, 102, 0, 255 }, { 255, 0, 255, 255 }, { 255, 0, 203, 255 },
{ 255, 0, 152, 255 }, { 255, 0, 102, 255 }, { 255, 0, 51, 255 },
{ 255, 175, 19, 255 }, { 0, 51, 255, 255 }, { 0, 51, 203, 255 },
{ 203, 51, 255, 255 }, { 203, 51, 203, 255 }, { 203, 51, 152, 255 },
{ 203, 51, 102, 255 }, { 203, 51, 51, 255 }, { 203, 51, 0, 255 },
{ 152, 51, 255, 255 }, { 152, 51, 203, 255 }, { 152, 51, 152, 255 },
{ 152, 51, 102, 255 }, { 152, 51, 51, 255 }, { 152, 51, 0, 255 },
{ 102, 51, 255, 255 }, { 102, 51, 203, 255 }, { 102, 51, 152, 255 },
{ 102, 51, 102, 255 }, { 102, 51, 51, 255 }, { 102, 51, 0, 255 },
{ 51, 51, 255, 255 }, { 51, 51, 203, 255 }, { 51, 51, 152, 255 },
{ 51, 51, 102, 255 }, { 51, 51, 51, 255 }, { 51, 51, 0, 255 },
{ 255, 203, 102, 255 }, { 255, 203, 152, 255 }, { 255, 203, 203, 255 },
{ 255, 203, 255, 255 }, { 0, 51, 152, 255 }, { 0, 51, 102, 255 },
{ 0, 51, 51, 255 }, { 0, 51, 0, 255 }, { 203, 0, 255, 255 },
{ 203, 0, 203, 255 }, { 203, 0, 152, 255 }, { 203, 0, 102, 255 },
{ 203, 0, 51, 255 }, { 255, 227, 70, 255 }, { 152, 0, 255, 255 },
{ 152, 0, 203, 255 }, { 152, 0, 152, 255 }, { 152, 0, 102, 255 },
{ 152, 0, 51, 255 }, { 152, 0, 0, 255 }, { 102, 0, 255, 255 },
{ 102, 0, 203, 255 }, { 102, 0, 152, 255 }, { 102, 0, 102, 255 },
{ 102, 0, 51, 255 }, { 102, 0, 0, 255 }, { 51, 0, 255, 255 },
{ 51, 0, 203, 255 }, { 51, 0, 152, 255 }, { 51, 0, 102, 255 },
{ 51, 0, 51, 255 }, { 51, 0, 0, 255 }, { 255, 203, 51, 255 },
{ 255, 203, 0, 255 }, { 255, 255, 0, 255 }, { 255, 255, 51, 255 },
{ 255, 255, 102, 255 }, { 255, 255, 152, 255 }, { 255, 255, 203, 255 },
{ 255, 255, 255, 255 }
};
// is_supported
static inline
bool
is_supported(color_space colorSpace)
{
bool result = false;
switch (colorSpace) {
// supported
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:
case B_RGB16_BIG: case B_RGB15_BIG: case B_RGBA15_BIG:
case B_CMAP8: case B_GRAY8: case B_GRAY1:
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:
case B_LAB24: case B_LAB32: case B_LABA32:
case B_HSI24: case B_HSI32: case B_HSIA32:
case B_HSV24: case B_HSV32: case B_HSVA32:
case B_HLS24: case B_HLS32: case B_HLSA32:
case B_CMY24: case B_CMY32: case B_CMYA32: case B_CMYK32:
result = true;
break;
// unsupported
case B_NO_COLOR_SPACE:
case B_YUV9: case B_YUV12:
break;
}
return result;
}
// get_raw_bytes_per_row
static inline
int32
get_raw_bytes_per_row(color_space colorSpace, int32 width)
{
int32 bpr = 0;
switch (colorSpace) {
// supported
case B_RGB32: case B_RGBA32:
case B_RGB32_BIG: case B_RGBA32_BIG:
case B_UVL32: case B_UVLA32:
case B_LAB32: case B_LABA32:
case B_HSI32: case B_HSIA32:
case B_HSV32: case B_HSVA32:
case B_HLS32: case B_HLSA32:
case B_CMY32: case B_CMYA32: case B_CMYK32:
bpr = 4 * width;
break;
case B_RGB24: case B_RGB24_BIG:
case B_UVL24: case B_LAB24: case B_HSI24:
case B_HSV24: case B_HLS24: case B_CMY24:
bpr = 3 * width;
break;
case B_RGB16: case B_RGB15: case B_RGBA15:
case B_RGB16_BIG: case B_RGB15_BIG: case B_RGBA15_BIG:
bpr = 2 * width;
break;
case B_CMAP8: case B_GRAY8:
bpr = width;
break;
case B_GRAY1:
bpr = (width + 7) / 8;
break;
case B_YCbCr422: case B_YUV422:
bpr = (width + 3) / 4 * 8;
break;
case B_YCbCr411: case B_YUV411:
bpr = (width + 3) / 4 * 6;
break;
case B_YCbCr444: case B_YUV444:
bpr = (width + 3) / 4 * 12;
break;
case B_YCbCr420: case B_YUV420:
bpr = (width + 3) / 4 * 6;
break;
// unsupported
case B_NO_COLOR_SPACE:
case B_YUV9: case B_YUV12:
break;
}
return bpr;
}
// get_bytes_per_row
static inline
int32
get_bytes_per_row(color_space colorSpace, int32 width)
{
int32 bpr = get_raw_bytes_per_row(colorSpace, width);
// align to int32
bpr = (bpr + 3) & 0x7ffffffc;
return bpr;
}
// brightness_for
static inline
uint8
brightness_for(uint8 red, uint8 green, uint8 blue)
{
// brightness = 0.301 * red + 0.586 * green + 0.113 * blue
// we use for performance reasons:
// brightness = (308 * red + 600 * green + 116 * blue) / 1024
return uint8((308 * red + 600 * green + 116 * blue) / 1024);
}
// color_distance
static inline
unsigned
color_distance(uint8 red1, uint8 green1, uint8 blue1,
uint8 red2, uint8 green2, uint8 blue2)
{
// euklidian distance (its square actually)
int rd = (int)red1 - (int)red2;
int gd = (int)green1 - (int)green2;
int bd = (int)blue1 - (int)blue2;
// return rd * rd + gd * gd + bd * bd;
// distance according to psycho-visual tests
int rmean = ((int)red1 + (int)red2) / 2;
return (((512 + rmean) * rd * rd) >> 8)
+ 4 * gd * gd
+ (((767 - rmean) * bd * bd) >> 8);
}
// bit_mask, inverse_bit_mask
static inline int32 bit_mask(int32 bit) { return (1 << bit); }
static inline int32 inverse_bit_mask(int32 bit) { return ~bit_mask(bit); }
//////////////////////
// PaletteConverter //
//////////////////////
namespace BPrivate {
// helper class for palette color <-> linear color conversion
class PaletteConverter {
public:
PaletteConverter();
PaletteConverter(const rgb_color *palette);
PaletteConverter(const color_map *colorMap);
~PaletteConverter();
status_t SetTo(const rgb_color *palette);
status_t SetTo(const color_map *colorMap);
status_t InitCheck() const;
inline uint8 IndexForRGB15(uint16 rgb) const;
inline uint8 IndexForRGB15(uint8 red, uint8 green, uint8 blue) const;
inline uint8 IndexForRGB16(uint16 rgb) const;
inline uint8 IndexForRGB16(uint8 red, uint8 green, uint8 blue) const;
inline uint8 IndexForRGB24(uint32 rgb) const;
inline uint8 IndexForRGB24(uint8 red, uint8 green, uint8 blue) const;
inline uint8 IndexForGray(uint8 gray) const;
inline const rgb_color &RGBColorForIndex(uint8 index) const;
inline uint16 RGB15ColorForIndex(uint8 index) const;
inline uint16 RGB16ColorForIndex(uint8 index) const;
inline uint32 RGB24ColorForIndex(uint8 index) const;
inline void RGB24ColorForIndex(uint8 index, uint8 &red, uint8 &green,
uint8 &blue) const;
inline uint8 GrayColorForIndex(uint8 index) const;
private:
const color_map *fColorMap;
color_map *fOwnColorMap;
status_t fCStatus;
};
} // namespace BPrivate
using BPrivate::PaletteConverter;
// constructor
PaletteConverter::PaletteConverter()
: fColorMap(NULL),
fOwnColorMap(NULL),
fCStatus(B_NO_INIT)
{
}
// constructor
PaletteConverter::PaletteConverter(const rgb_color *palette)
: fColorMap(NULL),
fOwnColorMap(NULL),
fCStatus(B_NO_INIT)
{
SetTo(palette);
}
// constructor
PaletteConverter::PaletteConverter(const color_map *colorMap)
: fColorMap(NULL),
fOwnColorMap(NULL),
fCStatus(B_NO_INIT)
{
SetTo(colorMap);
}
// destructor
PaletteConverter::~PaletteConverter()
{
delete fOwnColorMap;
}
// SetTo
status_t
PaletteConverter::SetTo(const rgb_color *palette)
{
// cleanup
SetTo((const color_map*)NULL);
status_t error = (palette ? B_OK : B_BAD_VALUE);
// alloc color map
if (error == B_OK) {
fOwnColorMap = new(nothrow) color_map;
if (fOwnColorMap == NULL)
error = B_NO_MEMORY;
}
// init color map
if (error == B_OK) {
fColorMap = fOwnColorMap;
// init color list
memcpy(fOwnColorMap->color_list, palette, sizeof(rgb_color) * 256);
// init index map
for (int32 color = 0; color < 32768; color++) {
// get components
uint8 red = (color & 0x7c00) >> 7;
uint8 green = (color & 0x3e0) >> 2;
uint8 blue = (color & 0x1f) << 3;
red |= red >> 5;
green |= green >> 5;
blue |= blue >> 5;
// find closest color
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;
}
// no need to init inversion map
}
fCStatus = error;
return error;
}
// SetTo
status_t
PaletteConverter::SetTo(const color_map *colorMap)
{
// cleanup
if (fOwnColorMap) {
delete fOwnColorMap;
fOwnColorMap = NULL;
}
// set
fColorMap = colorMap;
fCStatus = (fColorMap ? B_OK : B_BAD_VALUE);
return fCStatus;
}
// InitCheck
status_t
PaletteConverter::InitCheck() const
{
return fCStatus;
}
// IndexForRGB15
inline
uint8
PaletteConverter::IndexForRGB15(uint16 rgb) const
{
return fColorMap->index_map[rgb];
}
// IndexForRGB15
inline
uint8
PaletteConverter::IndexForRGB15(uint8 red, uint8 green, uint8 blue) const
{
// the 5 least significant bits are used
return fColorMap->index_map[(red << 10) | (green << 5) | blue];
}
// IndexForRGB16
inline
uint8
PaletteConverter::IndexForRGB16(uint16 rgb) const
{
return fColorMap->index_map[(rgb >> 1) & 0x7fe0 | rgb & 0x1f];
}
// IndexForRGB16
inline
uint8
PaletteConverter::IndexForRGB16(uint8 red, uint8 green, uint8 blue) const
{
// the 5 (for red, blue) / 6 (for green) least significant bits are used
return fColorMap->index_map[(red << 10) | ((green & 0x3e) << 4) | blue];
}
// IndexForRGB24
inline
uint8
PaletteConverter::IndexForRGB24(uint32 rgb) const
{
return fColorMap->index_map[((rgb & 0xf8000000) >> 17)
| ((rgb & 0xf80000) >> 14)
| ((rgb & 0xf800) >> 11)];
}
// IndexForRGB24
inline
uint8
PaletteConverter::IndexForRGB24(uint8 red, uint8 green, uint8 blue) const
{
return fColorMap->index_map[((red & 0xf8) << 7)
| ((green & 0xf8) << 2)
| (blue >> 3)];
}
// IndexForGray
inline
uint8
PaletteConverter::IndexForGray(uint8 gray) const
{
return IndexForRGB24(gray, gray, gray);
}
// RGBColorForIndex
inline
const rgb_color &
PaletteConverter::RGBColorForIndex(uint8 index) const
{
return fColorMap->color_list[index];
}
// RGB15ColorForIndex
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);
}
// RGB16ColorForIndex
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);
}
// RGB24ColorForIndex
inline
uint32
PaletteConverter::RGB24ColorForIndex(uint8 index) const
{
const rgb_color &color = fColorMap->color_list[index];
return (color.red << 24) | (color.green << 16) | (color.blue >> 8);
}
// RGB24ColorForIndex
inline
void
PaletteConverter::RGB24ColorForIndex(uint8 index, uint8 &red, uint8 &green,
uint8 &blue) const
{
const rgb_color &color = fColorMap->color_list[index];
red = color.red;
green = color.green;
blue = color.blue;
}
// GrayColorForIndex
inline
uint8
PaletteConverter::GrayColorForIndex(uint8 index) const
{
const rgb_color &color = fColorMap->color_list[index];
return brightness_for(color.red, color.green, color.blue);
}
// TODO: Remove these and palette_converter() when BScreen is available.
static BLocker gPaletteConverterLock;
static PaletteConverter gPaletteConverter;
// palette_converter
static
const PaletteConverter*
palette_converter()
{
if (gPaletteConverterLock.Lock()) {
if (gPaletteConverter.InitCheck() != B_OK)
gPaletteConverter.SetTo(kSystemPalette);
gPaletteConverterLock.Unlock();
}
return &gPaletteConverter;
}
/////////////
// BBitmap //
/////////////
// constructor
BBitmap::BBitmap(BRect bounds, uint32 flags, color_space colorSpace,
int32 bytesPerRow, screen_id screenID)
: fBasePtr(NULL),
fSize(0),
fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1),
fBytesPerRow(0),
fWindow(NULL),
fServerToken(-1),
fToken(-1),
fArea(-1),
fOrigArea(-1),
fFlags(0),
fInitError(B_NO_INIT)
{
InitObject(bounds, colorSpace, flags, bytesPerRow, screenID);
}
// constructor
BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews,
bool needsContiguous)
: fBasePtr(NULL),
fSize(0),
fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1),
fBytesPerRow(0),
fWindow(NULL),
fServerToken(-1),
fToken(-1),
fArea(-1),
fOrigArea(-1),
fFlags(0),
fInitError(B_NO_INIT)
{
int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0)
| (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0);
InitObject(bounds, colorSpace, flags, B_ANY_BYTES_PER_ROW,
B_MAIN_SCREEN_ID);
}
// constructor
BBitmap::BBitmap(const BBitmap *source, bool acceptsViews,
bool needsContiguous)
: fBasePtr(NULL),
fSize(0),
fColorSpace(B_NO_COLOR_SPACE),
fBounds(0, 0, -1, -1),
fBytesPerRow(0),
fWindow(NULL),
fServerToken(-1),
fToken(-1),
fArea(-1),
fOrigArea(-1),
fFlags(0),
fInitError(B_NO_INIT)
{
if (source && source->IsValid()) {
int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0)
| (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0);
InitObject(source->Bounds(), source->ColorSpace(), flags,
source->BytesPerRow(), B_MAIN_SCREEN_ID);
if (InitCheck() == B_OK)
memcpy(Bits(), source->Bits(), BytesPerRow());
}
}
// destructor
BBitmap::~BBitmap()
{
if (fBasePtr)
free(fBasePtr);
}
// unarchiving constructor
BBitmap::BBitmap(BMessage *data)
{
}
// Instantiate
BArchivable *
BBitmap::Instantiate(BMessage *data)
{
return NULL; // not implemented
}
// Archive
status_t
BBitmap::Archive(BMessage *data, bool deep) const
{
return NOT_IMPLEMENTED;
}
// InitCheck
status_t
BBitmap::InitCheck() const
{
return fInitError;
}
// IsValid
bool
BBitmap::IsValid() const
{
return (InitCheck() == B_OK);
}
// LockBits
status_t
BBitmap::LockBits(uint32 *state)
{
return NOT_IMPLEMENTED;
}
// UnlockBits
void
BBitmap::UnlockBits()
{
}
// Area
area_id
BBitmap::Area() const
{
return NOT_IMPLEMENTED;
}
// Bits
void *
BBitmap::Bits() const
{
return fBasePtr;
}
// BitsLength
int32
BBitmap::BitsLength() const
{
return fSize;
}
// BytesPerRow
int32
BBitmap::BytesPerRow() const
{
return fBytesPerRow;
}
// ColorSpace
color_space
BBitmap::ColorSpace() const
{
return fColorSpace;
}
// Bounds
BRect
BBitmap::Bounds() const
{
return fBounds;
}
struct rgb32_pixel {
uint8 blue;
uint8 green;
uint8 red;
uint8 alpha;
};
struct rgb32_big_pixel {
uint8 red;
uint8 green;
uint8 blue;
uint8 alpha;
};
struct rgb24_pixel {
uint8 blue;
uint8 green;
uint8 red;
};
struct rgb24_big_pixel {
uint8 red;
uint8 green;
uint8 blue;
};
struct rgb16_pixel {
uint8 gb; // G[2:0],B[4:0]
uint8 rg; // 16: R[4:0],G[5:3]
// 15: -[0],R[4:0],G[4:3]
};
struct rgb16_big_pixel {
uint8 rg; // 16: R[4:0],G[5:3]
// 15: -[0],R[4:0],G[4:3]
uint8 gb; // G[2:0],B[4:0]
};
struct rgb_color_value {
uint8 red;
uint8 green;
uint8 blue;
};
typedef uint8 gray_color_value;
// BaseReader
template<typename _PixelType>
struct BaseReader {
typedef _PixelType pixel_t;
BaseReader(const void *data) : pixels((const pixel_t*)data) {}
inline void SetTo(const void *data) { pixels = (const pixel_t*)data; }
inline void NextRow(int32 skip)
{
pixels = (const pixel_t*)((const char*)pixels + skip);
}
const pixel_t *pixels;
};
// RGB24Reader
template<typename _PixelType>
struct RGB24Reader : public BaseReader<_PixelType> {
typedef rgb_color_value preferred_color_value_t;
RGB24Reader(const void *data) : BaseReader<_PixelType>(data) {}
inline void Read(rgb_color_value &color)
{
const pixel_t &pixel = *pixels;
color.red = pixel.red;
color.green = pixel.green;
color.blue = pixel.blue;
pixels++;
}
inline void Read(gray_color_value &gray)
{
rgb_color_value color;
Read(color);
gray = brightness_for(color.red, color.green, color.blue);
}
};
// RGB16Reader
template<typename _PixelType>
struct RGB16Reader : public BaseReader<_PixelType> {
typedef rgb_color_value preferred_color_value_t;
RGB16Reader(const void *data) : BaseReader<_PixelType>(data) {}
inline void Read(rgb_color_value &color)
{
// rg: R[4:0],G[5:3]
// gb: G[2:0],B[4:0]
const pixel_t &pixel = *pixels;
color.red = pixel.rg & 0xf8;
color.green = ((pixel.rg & 0x07) << 5) & ((pixel.gb & 0xe0) >> 3);
color.blue = (pixel.gb & 0x1f) << 3;
color.red |= color.red >> 5;
color.green |= color.green >> 6;
color.blue |= color.blue >> 5;
pixels++;
}
inline void Read(gray_color_value &gray)
{
rgb_color_value color;
Read(color);
gray = brightness_for(color.red, color.green, color.blue);
}
};
// RGB15Reader
template<typename _PixelType>
struct RGB15Reader : public BaseReader<_PixelType> {
typedef rgb_color_value preferred_color_value_t;
RGB15Reader(const void *data) : BaseReader<_PixelType>(data) {}
inline void Read(rgb_color_value &color)
{
// rg: -[0],R[4:0],G[4:3]
// gb: G[2:0],B[4:0]
const pixel_t &pixel = *pixels;
color.red = (pixel.rg & 0x7c) << 1;
color.green = ((pixel.rg & 0x03) << 6) & ((pixel.gb & 0xe0) >> 2);
color.blue = (pixel.gb & 0x1f) << 3;
color.red |= color.red >> 5;
color.green |= color.green >> 5;
color.blue |= color.blue >> 5;
pixels++;
}
inline void Read(gray_color_value &gray)
{
rgb_color_value color;
Read(color);
gray = brightness_for(color.red, color.green, color.blue);
}
};
// CMAP8Reader
struct CMAP8Reader : public BaseReader<uint8> {
typedef rgb_color_value preferred_color_value_t;
CMAP8Reader(const void *data, const PaletteConverter &converter)
: BaseReader<uint8>(data), converter(converter) {}
inline void Read(rgb_color_value &color)
{
converter.RGB24ColorForIndex(*pixels, color.red, color.green,
color.blue);
pixels++;
}
inline void Read(gray_color_value &gray)
{
gray = converter.GrayColorForIndex(*pixels);
pixels++;
}
const PaletteConverter &converter;
};
// Gray8Reader
struct Gray8Reader : public BaseReader<uint8> {
typedef gray_color_value preferred_color_value_t;
Gray8Reader(const void *data) : BaseReader<uint8>(data) {}
inline void Read(rgb_color_value &color)
{
color.red = color.green = color.blue = *pixels;
pixels++;
}
inline void Read(gray_color_value &gray)
{
gray = *pixels;
pixels++;
}
};
// Gray1Reader
struct Gray1Reader : public BaseReader<uint8> {
typedef gray_color_value preferred_color_value_t;
Gray1Reader(const void *data) : BaseReader<uint8>(data), bit(7) {}
inline void SetTo(const void *data)
{
pixels = (const pixel_t*)data;
bit = 7;
}
inline void NextRow(int32 skip)
{
if (bit == 7)
pixels = (const pixel_t*)((const char*)pixels + skip);
else {
pixels = (const pixel_t*)((const char*)pixels + skip + 1);
bit = 7;
}
}
inline void Read(rgb_color_value &color)
{
if (*pixels & bit_mask(bit))
color.red = color.green = color.blue = 255;
else
color.red = color.green = color.blue = 0;
bit--;
if (bit == -1) {
pixels++;
bit = 7;
}
}
inline void Read(gray_color_value &gray)
{
if (*pixels & bit_mask(bit))
gray = 255;
else
gray = 0;
bit--;
if (bit == -1) {
pixels++;
bit = 7;
}
}
int32 bit;
};
// BaseWriter
template<typename _PixelType>
struct BaseWriter {
typedef _PixelType pixel_t;
BaseWriter(void *data) : pixels((pixel_t*)data) {}
inline void SetTo(void *data) { pixels = (pixel_t*)data; }
pixel_t *pixels;
};
// RGB32Writer
template<typename _PixelType>
struct RGB32Writer : public BaseWriter<_PixelType> {
typedef rgb_color_value preferred_color_value_t;
RGB32Writer(void *data) : BaseWriter<_PixelType>(data) {}
inline void Write(const rgb_color_value &color)
{
pixel_t &pixel = *pixels;
pixel.red = color.red;
pixel.green = color.green;
pixel.blue = color.blue;
pixel.alpha = 255;
pixels++;
}
inline void Write(const gray_color_value &gray)
{
pixel_t &pixel = *pixels;
pixel.red = gray;
pixel.green = gray;
pixel.blue = gray;
pixel.alpha = 255;
pixels++;
}
};
// RGB24Writer
template<typename _PixelType>
struct RGB24Writer : public BaseWriter<_PixelType> {
typedef rgb_color_value preferred_color_value_t;
RGB24Writer(void *data) : BaseWriter<_PixelType>(data) {}
inline void Write(const rgb_color_value &color)
{
pixel_t &pixel = *pixels;
pixel.red = color.red;
pixel.green = color.green;
pixel.blue = color.blue;
pixels++;
}
inline void Write(const gray_color_value &gray)
{
pixel_t &pixel = *pixels;
pixel.red = gray;
pixel.green = gray;
pixel.blue = gray;
pixels++;
}
};
// RGB16Writer
template<typename _PixelType>
struct RGB16Writer : public BaseWriter<_PixelType> {
typedef rgb_color_value preferred_color_value_t;
RGB16Writer(void *data) : BaseWriter<_PixelType>(data) {}
inline void Write(const rgb_color_value &color)
{
// rg: R[4:0],G[5:3]
// gb: G[2:0],B[4:0]
pixel_t &pixel = *pixels;
pixel.rg = (color.red & 0xf8) | (color.green >> 5);
pixel.gb = ((color.green & 0x1c) << 3) | (color.blue >> 3);
pixels++;
}
inline void Write(const gray_color_value &gray)
{
pixel_t &pixel = *pixels;
pixel.rg = (gray & 0xf8) | (gray >> 5);
pixel.gb = ((gray & 0x1c) << 3) | (gray >> 3);
pixels++;
}
};
// RGB15Writer
template<typename _PixelType>
struct RGB15Writer : public BaseWriter<_PixelType> {
typedef rgb_color_value preferred_color_value_t;
RGB15Writer(void *data) : BaseWriter<_PixelType>(data) {}
inline void Write(const rgb_color_value &color)
{
// rg: -[0],R[4:0],G[4:3]
// gb: G[2:0],B[4:0]
pixel_t &pixel = *pixels;
pixel.rg = ((color.red & 0xf8) >> 1) | (color.green >> 6);
pixel.gb = ((color.green & 0x38) << 2) | (color.blue >> 3);
pixels++;
}
inline void Write(const gray_color_value &gray)
{
pixel_t &pixel = *pixels;
pixel.rg = ((gray & 0xf8) >> 1) | (gray >> 6);
pixel.gb = ((gray & 0x38) << 2) | (gray >> 3);
pixels++;
}
};
// CMAP8Writer
struct CMAP8Writer : public BaseWriter<uint8> {
typedef rgb_color_value preferred_color_value_t;
CMAP8Writer(void *data, const PaletteConverter &converter)
: BaseWriter<uint8>(data), converter(converter) {}
inline void Write(const rgb_color_value &color)
{
*pixels = converter.IndexForRGB24(color.red, color.green, color.blue);
pixels++;
}
inline void Write(const gray_color_value &gray)
{
*pixels = converter.IndexForGray(gray);
pixels++;
}
const PaletteConverter &converter;
};
// Gray8Writer
struct Gray8Writer : public BaseWriter<uint8> {
typedef gray_color_value preferred_color_value_t;
Gray8Writer(void *data) : BaseWriter<uint8>(data) {}
inline void Write(const rgb_color_value &color)
{
*pixels = brightness_for(color.red, color.green, color.blue);
pixels++;
}
inline void Write(const gray_color_value &gray)
{
*pixels = gray;
pixels++;
}
};
// Gray1Writer
struct Gray1Writer : public BaseWriter<uint8> {
typedef gray_color_value preferred_color_value_t;
Gray1Writer(void *data) : BaseWriter<uint8>(data), bit(7) {}
inline void SetTo(void *data) { pixels = (pixel_t*)data; bit = 7; }
inline void Write(const gray_color_value &gray)
{
*pixels = (*pixels & inverse_bit_mask(bit))
| (gray & 0x80) >> (7 - bit);
bit--;
if (bit == -1) {
pixels++;
bit = 7;
}
}
inline void Write(const rgb_color_value &color)
{
Write(brightness_for(color.red, color.green, color.blue));
}
int32 bit;
};
// set_bits_worker
template<typename Reader, typename Writer, typename color_value_t>
static
status_t
set_bits_worker(const void *inData, int32 inLength, int32 inBPR,
int32 inRowSkip, void *outData, int32 outLength,
int32 outOffset, int32 outBPR, int32 rawOutBPR,
Reader _reader, Writer _writer)
{
status_t error = B_OK;
Reader reader(_reader);
Writer writer(_writer);
reader.SetTo(inData);
writer.SetTo((char*)outData + outOffset);
const char *inEnd = (const char*)inData + inLength
- sizeof(Reader::pixel_t);
const char *inLastRow = (const char*)inData + inLength
- (inBPR - inRowSkip);
const char *outEnd = (const char*)outData + outLength
- sizeof(Writer::pixel_t);
char *outRow = (char*)outData + outOffset - outOffset % outBPR;
const char *outRowEnd = outRow + rawOutBPR - sizeof(Writer::pixel_t);
while ((const char*)reader.pixels <= inEnd
&& (const char*)writer.pixels <= outEnd) {
// process one row
if ((const char*)reader.pixels <= inLastRow) {
// at least a complete row left
while ((const char*)writer.pixels <= outRowEnd) {
color_value_t color;
reader.Read(color);
writer.Write(color);
}
} else {
// no complete row left
// but maybe the complete end of the first row
while ((const char*)reader.pixels <= inEnd
&& (const char*)writer.pixels <= outRowEnd) {
color_value_t color;
reader.Read(color);
writer.Write(color);
}
}
// must be here, not in the if-branch (end of first row)
outRow += outBPR;
outRowEnd += outBPR;
reader.NextRow(inRowSkip);
writer.SetTo(outRow);
}
return error;
}
// set_bits_worker_gray1
template<typename Reader, typename Writer, typename color_value_t>
static
status_t
set_bits_worker_gray1(const void *inData, int32 inLength, int32 inBPR,
int32 inRowSkip, void *outData, int32 outLength,
int32 outOffset, int32 outBPR, int32 width,
Reader _reader, Writer _writer)
{
status_t error = B_OK;
Reader reader(_reader);
Writer writer(_writer);
reader.SetTo(inData);
writer.SetTo((char*)outData + outOffset);
const char *inEnd = (const char*)inData + inLength
- sizeof(Reader::pixel_t);
const char *inLastRow = (const char*)inData + inLength
- (inBPR - inRowSkip);
const char *outEnd = (const char*)outData + outLength - outBPR;
char *outRow = (char*)outData + outOffset - outOffset % outBPR;
int32 x = max(0L, width - ((char*)outData + outOffset - outRow) * 8) - 1;
while ((const char*)reader.pixels <= inEnd
&& (const char*)writer.pixels <= outEnd) {
// process one row
if ((const char*)reader.pixels <= inLastRow) {
// at least a complete row left
while (x >= 0) {
color_value_t color;
reader.Read(color);
writer.Write(color);
x--;
}
} else {
// no complete row left
// but maybe the complete end of the first row
while ((const char*)reader.pixels <= inEnd && x >= 0) {
color_value_t color;
reader.Read(color);
writer.Write(color);
x--;
}
}
// must be here, not in the if-branch (end of first row)
x = width - 1;
outRow += outBPR;
reader.NextRow(inRowSkip);
writer.SetTo(outRow);
}
return error;
}
// set_bits
template<typename Reader>
static
status_t
set_bits(const void *inData, int32 inLength, int32 inBPR, int32 inRowSkip,
void *outData, int32 outLength, int32 outOffset, int32 outBPR,
int32 rawOutBPR, color_space outColorSpace, int32 width,
Reader reader, const PaletteConverter &paletteConverter)
{
status_t error = B_OK;
switch (outColorSpace) {
// supported
case B_RGB32: case B_RGBA32:
{
typedef RGB32Writer<rgb32_pixel> Writer;
typedef typename Reader::preferred_color_value_t color_value_t;
error = set_bits_worker<Reader, Writer, color_value_t>(
inData, inLength, inBPR, inRowSkip, outData, outLength,
outOffset, outBPR, rawOutBPR, reader, Writer(outData));
break;
}
case B_RGB32_BIG: case B_RGBA32_BIG:
{
typedef RGB32Writer<rgb32_big_pixel> Writer;
typedef typename Reader::preferred_color_value_t color_value_t;
error = set_bits_worker<Reader, Writer, color_value_t>(
inData, inLength, inBPR, inRowSkip, outData, outLength,
outOffset, outBPR, rawOutBPR, reader, Writer(outData));
break;
}
case B_RGB24:
{
typedef RGB24Writer<rgb24_pixel> Writer;
typedef typename Reader::preferred_color_value_t color_value_t;
error = set_bits_worker<Reader, Writer, color_value_t>(
inData, inLength, inBPR, inRowSkip, outData, outLength,
outOffset, outBPR, rawOutBPR, reader, Writer(outData));
break;
}
case B_RGB24_BIG:
{
typedef RGB24Writer<rgb24_big_pixel> Writer;
typedef typename Reader::preferred_color_value_t color_value_t;
error = set_bits_worker<Reader, Writer, color_value_t>(
inData, inLength, inBPR, inRowSkip, outData, outLength,
outOffset, outBPR, rawOutBPR, reader, Writer(outData));
break;
}
case B_RGB16:
{
typedef RGB16Writer<rgb16_pixel> Writer;
typedef typename Reader::preferred_color_value_t color_value_t;
error = set_bits_worker<Reader, Writer, color_value_t>(
inData, inLength, inBPR, inRowSkip, outData, outLength,
outOffset, outBPR, rawOutBPR, reader, Writer(outData));
break;
}
case B_RGB16_BIG:
{
typedef RGB16Writer<rgb16_big_pixel> Writer;
typedef typename Reader::preferred_color_value_t color_value_t;
error = set_bits_worker<Reader, Writer, color_value_t>(
inData, inLength, inBPR, inRowSkip, outData, outLength,
outOffset, outBPR, rawOutBPR, reader, Writer(outData));
break;
}
case B_RGB15: case B_RGBA15:
{
typedef RGB15Writer<rgb16_pixel> Writer;
typedef typename Reader::preferred_color_value_t color_value_t;
error = set_bits_worker<Reader, Writer, color_value_t>(
inData, inLength, inBPR, inRowSkip, outData, outLength,
outOffset, outBPR, rawOutBPR, reader, Writer(outData));
break;
}
case B_RGB15_BIG: case B_RGBA15_BIG:
{
typedef RGB15Writer<rgb16_big_pixel> Writer;
typedef typename Reader::preferred_color_value_t color_value_t;
error = set_bits_worker<Reader, Writer, color_value_t>(
inData, inLength, inBPR, inRowSkip, outData, outLength,
outOffset, outBPR, rawOutBPR, reader, Writer(outData));
break;
}
case B_CMAP8:
{
typedef CMAP8Writer Writer;
typedef typename Reader::preferred_color_value_t color_value_t;
error = set_bits_worker<Reader, Writer, color_value_t>(
inData, inLength, inBPR, inRowSkip, outData, outLength,
outOffset, outBPR, rawOutBPR, reader,
Writer(outData, paletteConverter));
break;
}
case B_GRAY8:
{
typedef Gray8Writer Writer;
typedef gray_color_value color_value_t;
error = set_bits_worker<Reader, Writer, color_value_t>(
inData, inLength, inBPR, inRowSkip, outData, outLength,
outOffset, outBPR, rawOutBPR, reader, Writer(outData));
break;
}
case B_GRAY1:
{
typedef Gray1Writer Writer;
typedef gray_color_value color_value_t;
error = set_bits_worker_gray1<Reader, Writer, color_value_t>(
inData, inLength, inBPR, inRowSkip, outData, outLength,
outOffset, outBPR, width, reader, Writer(outData));
break;
}
// unsupported
case B_NO_COLOR_SPACE:
case B_YUV9: case B_YUV12:
case B_UVL32: case B_UVLA32:
case B_LAB32: case B_LABA32:
case B_HSI32: case B_HSIA32:
case B_HSV32: case B_HSVA32:
case B_HLS32: case B_HLSA32:
case B_CMY32: case B_CMYA32: case B_CMYK32:
case B_UVL24: case B_LAB24: case B_HSI24:
case B_HSV24: case B_HLS24: case B_CMY24:
case B_YCbCr422: case B_YUV422:
case B_YCbCr411: case B_YUV411:
case B_YCbCr444: case B_YUV444:
case B_YCbCr420: case B_YUV420:
default:
error = B_BAD_VALUE;
break;
}
return error;
}
// SetBits
void
BBitmap::SetBits(const void *data, int32 length, int32 offset,
color_space colorSpace)
{
status_t error = (InitCheck() == B_OK ? B_OK : B_NO_INIT);
// check params
if (error == B_OK && (data == NULL || offset > fSize || length < 0))
error = B_BAD_VALUE;
int32 width = 0;
if (error == B_OK)
width = fBounds.IntegerWidth() + 1;
int32 inBPR = -1;
// tweaks to mimic R5 behavior
if (error == B_OK) {
// B_RGB32 means actually unpadded B_RGB24_BIG
if (colorSpace == B_RGB32) {
colorSpace = B_RGB24_BIG;
inBPR = width * 3;
// If in color space is B_CMAP8, but the bitmap's is another one,
// ignore source data row padding.
} else if (colorSpace == B_CMAP8 && fColorSpace != B_CMAP8)
inBPR = width;
}
// call the sane method, which does the actual work
if (error == B_OK)
error = ImportBits(data, length, inBPR, offset, colorSpace);
}
// ImportBits
status_t
BBitmap::ImportBits(const void *data, int32 length, int32 bpr, int32 offset,
color_space colorSpace)
{
status_t error = (InitCheck() == B_OK ? B_OK : B_NO_INIT);
// check params
if (error == B_OK && (data == NULL || offset > fSize || length < 0))
error = B_BAD_VALUE;
// get BPR
int32 width = 0;
int32 inRowSkip = 0;
if (error == B_OK) {
width = fBounds.IntegerWidth() + 1;
if (bpr < 0)
bpr = get_bytes_per_row(colorSpace, width);
inRowSkip = bpr - get_raw_bytes_per_row(colorSpace, width);
if (inRowSkip < 0)
error = B_BAD_VALUE;
}
if (error != B_OK) {
// catch error case
} else if (colorSpace == fColorSpace && bpr == fBytesPerRow) {
length = min(length, fSize - offset);
memcpy((char*)fBasePtr + offset, data, length);
} else {
// TODO: Retrieve color map from BScreen, when available:
// PaletteConverter paletteConverter(BScreen().ColorMap());
const PaletteConverter &paletteConverter = *palette_converter();
int32 rawOutBPR = get_raw_bytes_per_row(fColorSpace, width);
switch (colorSpace) {
// supported
case B_RGB32: case B_RGBA32:
{
typedef RGB24Reader<rgb32_pixel> Reader;
error = set_bits<Reader>(data, length, bpr, inRowSkip,
fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
fColorSpace, width, Reader(data), paletteConverter);
break;
}
case B_RGB32_BIG: case B_RGBA32_BIG:
{
typedef RGB24Reader<rgb32_big_pixel> Reader;
error = set_bits<Reader>(data, length, bpr, inRowSkip,
fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
fColorSpace, width, Reader(data), paletteConverter);
break;
}
case B_RGB24:
{
typedef RGB24Reader<rgb24_pixel> Reader;
error = set_bits<Reader>(data, length, bpr, inRowSkip,
fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
fColorSpace, width, Reader(data), paletteConverter);
break;
}
case B_RGB24_BIG:
{
typedef RGB24Reader<rgb24_big_pixel> Reader;
error = set_bits<Reader>(data, length, bpr, inRowSkip,
fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
fColorSpace, width, Reader(data), paletteConverter);
break;
}
case B_RGB16:
{
typedef RGB16Reader<rgb16_pixel> Reader;
error = set_bits<Reader>(data, length, bpr, inRowSkip,
fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
fColorSpace, width, Reader(data), paletteConverter);
break;
}
case B_RGB16_BIG:
{
typedef RGB16Reader<rgb16_big_pixel> Reader;
error = set_bits<Reader>(data, length, bpr, inRowSkip,
fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
fColorSpace, width, Reader(data), paletteConverter);
break;
}
case B_RGB15: case B_RGBA15:
{
typedef RGB15Reader<rgb16_pixel> Reader;
error = set_bits<Reader>(data, length, bpr, inRowSkip,
fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
fColorSpace, width, Reader(data), paletteConverter);
break;
}
case B_RGB15_BIG: case B_RGBA15_BIG:
{
typedef RGB15Reader<rgb16_big_pixel> Reader;
error = set_bits<Reader>(data, length, bpr, inRowSkip,
fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
fColorSpace, width, Reader(data), paletteConverter);
break;
}
case B_CMAP8:
{
typedef CMAP8Reader Reader;
error = set_bits<Reader>(data, length, bpr, inRowSkip,
fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
fColorSpace, width, Reader(data, paletteConverter),
paletteConverter);
break;
}
case B_GRAY8:
{
typedef Gray8Reader Reader;
error = set_bits<Reader>(data, length, bpr, inRowSkip,
fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
fColorSpace, width, Reader(data), paletteConverter);
break;
}
case B_GRAY1:
{
typedef Gray1Reader Reader;
error = set_bits<Reader>(data, length, bpr, inRowSkip,
fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
fColorSpace, width, Reader(data), paletteConverter);
break;
}
// unsupported
case B_NO_COLOR_SPACE:
case B_YUV9: case B_YUV12:
case B_UVL32: case B_UVLA32:
case B_LAB32: case B_LABA32:
case B_HSI32: case B_HSIA32:
case B_HSV32: case B_HSVA32:
case B_HLS32: case B_HLSA32:
case B_CMY32: case B_CMYA32: case B_CMYK32:
case B_UVL24: case B_LAB24: case B_HSI24:
case B_HSV24: case B_HLS24: case B_CMY24:
case B_YCbCr422: case B_YUV422:
case B_YCbCr411: case B_YUV411:
case B_YCbCr444: case B_YUV444:
case B_YCbCr420: case B_YUV420:
default:
error = B_BAD_VALUE;
break;
}
}
return error;
}
// ImportBits
status_t
BBitmap::ImportBits(const BBitmap *bitmap)
{
status_t error = (InitCheck() == B_OK ? B_OK : B_NO_INIT);
// check param
if (error == B_OK && bitmap == NULL)
error = B_BAD_VALUE;
if (error == B_OK && bitmap->InitCheck() != B_OK)
error = B_BAD_VALUE;
if (error == B_OK && bitmap->Bounds() != fBounds)
error = B_BAD_VALUE;
// set bits
if (error == B_OK) {
error = ImportBits(bitmap->Bits(), bitmap->BitsLength(),
bitmap->BytesPerRow(), 0, bitmap->ColorSpace());
}
return error;
}
// GetOverlayRestrictions
status_t
BBitmap::GetOverlayRestrictions(overlay_restrictions *restrictions) const
{
return NOT_IMPLEMENTED;
}
// AddChild
void
BBitmap::AddChild(BView *view)
{
}
// RemoveChild
bool
BBitmap::RemoveChild(BView *view)
{
return false; // not implemented
}
// CountChildren
int32
BBitmap::CountChildren() const
{
return 0; // not implemented
}
// ChildAt
BView *
BBitmap::ChildAt(int32 index) const
{
return NULL; // not implemented
}
// FindView
BView *
BBitmap::FindView(const char *viewName) const
{
return NULL; // not implemented
}
// FindView
BView *
BBitmap::FindView(BPoint point) const
{
return NULL; // not implemented
}
// Lock
bool
BBitmap::Lock()
{
return false; // not implemented
}
// Unlock
void
BBitmap::Unlock()
{
}
// IsLocked
bool
BBitmap::IsLocked() const
{
return false; // not implemented
}
// Perform
status_t
BBitmap::Perform(perform_code d, void *arg)
{
return NOT_IMPLEMENTED;
}
// FBC
void BBitmap::_ReservedBitmap1() {}
void BBitmap::_ReservedBitmap2() {}
void BBitmap::_ReservedBitmap3() {}
// copy constructor
BBitmap::BBitmap(const BBitmap &)
{
}
// =
BBitmap &
BBitmap::operator=(const BBitmap &)
{
return *this;
}
// get_shared_pointer
char *
BBitmap::get_shared_pointer() const
{
return NULL; // not implemented
}
// get_server_token
int32
BBitmap::get_server_token() const
{
return -1; // not implemented
}
// InitObject
void
BBitmap::InitObject(BRect bounds, color_space colorSpace, uint32 flags,
int32 bytesPerRow, screen_id screenID)
{
// clean up
if (fBasePtr) {
free(fBasePtr);
fBasePtr = NULL;
}
// check params
status_t error = B_OK;
if (!bounds.IsValid() || !is_supported(colorSpace))
error = B_BAD_VALUE;
if (error == B_OK) {
int32 bpr = get_bytes_per_row(colorSpace, bounds.IntegerWidth() + 1);
if (bytesPerRow < 0)
bytesPerRow = bpr;
else if (bytesPerRow < bpr)
error = B_BAD_VALUE;
}
// allocate the bitmap buffer
if (error == B_OK) {
int32 size = bytesPerRow * (bounds.IntegerHeight() + 1);
fBasePtr = malloc(size);
if (fBasePtr) {
fSize = size;
fColorSpace = colorSpace;
fBounds = bounds;
fBytesPerRow = bytesPerRow;
fWindow = NULL;
fServerToken = -1;
fToken = -1;
fArea = -1;
fOrigArea = -1;
fFlags = flags;
} else
error = B_NO_MEMORY;
}
fInitError = error;
}
// AssertPtr
void
BBitmap::AssertPtr()
{
}