* Added ConvertToCMAP8() bitmap variant.

* Put header guards in the system namespace.
* Cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27035 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-08-18 11:40:01 +00:00
parent d9b93b821a
commit 6e006912aa
2 changed files with 137 additions and 119 deletions

View File

@ -1,17 +1,17 @@
/*
* Copyright 2006-2008, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
*/
#ifndef _ICON_UTILS_H
#define _ICON_UTILS_H
#ifndef ICON_UTILS_H
#define ICON_UTILS_H
#include <Mime.h>
class BBitmap;
class BNode;
// This class is a little different from many other classes.
// You don't create an instance of it; you just call its various
// static member functions for utility-like operations.
@ -65,6 +65,8 @@ public:
// to make any sense).
static status_t ConvertFromCMAP8(BBitmap* source,
BBitmap* result);
static status_t ConvertToCMAP8(BBitmap* source,
BBitmap* result);
static status_t ConvertFromCMAP8(const uint8* data,
uint32 width, uint32 height,
@ -75,4 +77,4 @@ public:
uint32 bytesPerRow, BBitmap* result);
};
#endif // ICON_UTILS_H
#endif // _ICON_UTILS_H

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2007, Haiku. All rights reserved.
* Copyright 2006-2008, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -33,14 +33,79 @@ using namespace BPrivate::Icon;
using std::nothrow;
// GetIcon
static void
scale_bilinear(uint8* bits, int32 srcWidth, int32 srcHeight, int32 dstWidth,
int32 dstHeight, uint32 bpr)
{
// first pass: scale bottom to top
uint8* dst = bits + (dstHeight - 1) * bpr;
// offset to bottom left pixel in target size
for (int32 x = 0; x < srcWidth; x++) {
uint8* d = dst;
for (int32 y = dstHeight - 1; y >= 0; y--) {
int32 lineF = y * 256 * (srcHeight - 1) / (dstHeight - 1);
int32 lineI = lineF >> 8;
uint8 weight = (uint8)(lineF & 0xff);
uint8* s1 = bits + lineI * bpr + 4 * x;
if (weight == 0) {
d[0] = s1[0];
d[1] = s1[1];
d[2] = s1[2];
d[3] = s1[3];
} else {
uint8* s2 = s1 + bpr;
d[0] = (((s2[0] - s1[0]) * weight) + (s1[0] << 8)) >> 8;
d[1] = (((s2[1] - s1[1]) * weight) + (s1[1] << 8)) >> 8;
d[2] = (((s2[2] - s1[2]) * weight) + (s1[2] << 8)) >> 8;
d[3] = (((s2[3] - s1[3]) * weight) + (s1[3] << 8)) >> 8;
}
d -= bpr;
}
dst += 4;
}
// second pass: scale right to left
dst = bits + (dstWidth - 1) * 4;
// offset to top left pixel in target size
for (int32 y = 0; y < dstWidth; y++) {
uint8* d = dst;
for (int32 x = dstWidth - 1; x >= 0; x--) {
int32 columnF = x * 256 * (srcWidth - 1) / (dstWidth - 1);
int32 columnI = columnF >> 8;
uint8 weight = (uint8)(columnF & 0xff);
uint8* s1 = bits + y * bpr + 4 * columnI;
if (weight == 0) {
d[0] = s1[0];
d[1] = s1[1];
d[2] = s1[2];
d[3] = s1[3];
} else {
uint8* s2 = s1 + 4;
d[0] = (((s2[0] - s1[0]) * weight) + (s1[0] << 8)) >> 8;
d[1] = (((s2[1] - s1[1]) * weight) + (s1[1] << 8)) >> 8;
d[2] = (((s2[2] - s1[2]) * weight) + (s1[2] << 8)) >> 8;
d[3] = (((s2[3] - s1[3]) * weight) + (s1[3] << 8)) >> 8;
}
d -= 4;
}
dst += bpr;
}
}
// #pragma mark -
status_t
BIconUtils::GetIcon(BNode* node,
const char* vectorIconAttrName,
const char* smallIconAttrName,
const char* largeIconAttrName,
icon_size size,
BBitmap* result)
BIconUtils::GetIcon(BNode* node, const char* vectorIconAttrName,
const char* smallIconAttrName, const char* largeIconAttrName,
icon_size size, BBitmap* result)
{
if (!result || result->InitCheck())
return B_BAD_VALUE;
@ -62,24 +127,20 @@ BIconUtils::GetIcon(BNode* node,
else
size = B_MINI_ICON;
ret = GetCMAP8Icon(node,
smallIconAttrName,
largeIconAttrName,
size, result);
ret = GetCMAP8Icon(node, smallIconAttrName, largeIconAttrName,
size, result);
}
break;
case B_CMAP8:
// prefer old B_CMAP8 icons
ret = GetCMAP8Icon(node,
smallIconAttrName,
largeIconAttrName,
size, result);
ret = GetCMAP8Icon(node, smallIconAttrName, largeIconAttrName,
size, result);
if (ret < B_OK) {
// try to fallback to vector icon
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
BBitmap temp(result->Bounds(),
B_BITMAP_NO_SERVER_LINK, B_RGBA32);
BBitmap temp(result->Bounds(), B_BITMAP_NO_SERVER_LINK,
B_RGBA32);
#else
BBitmap temp(result->Bounds(), B_RGBA32);
#endif
@ -92,8 +153,8 @@ BIconUtils::GetIcon(BNode* node,
uint32 width = temp.Bounds().IntegerWidth() + 1;
uint32 height = temp.Bounds().IntegerHeight() + 1;
uint32 bytesPerRow = temp.BytesPerRow();
ret = ConvertToCMAP8((uint8*)temp.Bits(),
width, height, bytesPerRow, result);
ret = ConvertToCMAP8((uint8*)temp.Bits(), width, height,
bytesPerRow, result);
}
break;
default:
@ -104,12 +165,12 @@ BIconUtils::GetIcon(BNode* node,
return ret;
}
// #pragma mark -
// GetVectorIcon
status_t
BIconUtils::GetVectorIcon(BNode* node, const char* attrName,
BBitmap* result)
BIconUtils::GetVectorIcon(BNode* node, const char* attrName, BBitmap* result)
{
if (!node || node->InitCheck() < B_OK || !attrName)
return B_BAD_VALUE;
@ -154,10 +215,9 @@ printf("read: %lld, import: %lld\n", importTime - startTime, finishTime - import
return B_OK;
}
// GetVectorIcon
status_t
BIconUtils::GetVectorIcon(const uint8* buffer, size_t size,
BBitmap* result)
BIconUtils::GetVectorIcon(const uint8* buffer, size_t size, BBitmap* result)
{
if (!result)
return B_BAD_VALUE;
@ -211,14 +271,13 @@ BIconUtils::GetVectorIcon(const uint8* buffer, size_t size,
return ret;
}
// #pragma mark -
status_t
BIconUtils::GetCMAP8Icon(BNode* node,
const char* smallIconAttrName,
const char* largeIconAttrName,
icon_size size,
BBitmap* icon)
BIconUtils::GetCMAP8Icon(BNode* node, const char* smallIconAttrName,
const char* largeIconAttrName, icon_size size, BBitmap* icon)
{
// check parameters and initialization
if (!icon || icon->InitCheck() != B_OK
@ -279,7 +338,7 @@ BIconUtils::GetCMAP8Icon(BNode* node,
// read the attribute
if (ret == B_OK) {
bool tempBuffer = (icon->ColorSpace() != B_CMAP8
|| icon->Bounds() != bounds);
|| icon->Bounds() != bounds);
uint8* buffer = NULL;
ssize_t read;
if (tempBuffer) {
@ -288,12 +347,11 @@ BIconUtils::GetCMAP8Icon(BNode* node,
if (!buffer) {
ret = B_NO_MEMORY;
} else {
read = node->ReadAttr(attribute, attrType, 0, buffer,
attrSize);
read = node->ReadAttr(attribute, attrType, 0, buffer, attrSize);
}
} else {
read = node->ReadAttr(attribute, attrType, 0, icon->Bits(),
attrSize);
read = node->ReadAttr(attribute, attrType, 0, icon->Bits(),
attrSize);
}
if (ret == B_OK) {
if (read < 0)
@ -304,9 +362,8 @@ BIconUtils::GetCMAP8Icon(BNode* node,
if (tempBuffer) {
// other color space than stored in attribute
if (ret == B_OK) {
ret = ConvertFromCMAP8(buffer,
(uint32)size, (uint32)size,
(uint32)size, icon);
ret = ConvertFromCMAP8(buffer, (uint32)size, (uint32)size,
(uint32)size, icon);
}
delete[] buffer;
}
@ -314,21 +371,23 @@ BIconUtils::GetCMAP8Icon(BNode* node,
return ret;
}
// #pragma mark -
// ConvertFromCMAP8
status_t
BIconUtils::ConvertFromCMAP8(BBitmap* source, BBitmap* result)
{
if (!source)
if (source == NULL || source->ColorSpace() != B_CMAP8)
return B_BAD_VALUE;
status_t ret = source->InitCheck();
if (ret < B_OK)
return ret;
status_t status = source->InitCheck();
if (status < B_OK)
return status;
if (source->ColorSpace() != B_CMAP8)
return B_BAD_VALUE;
status = result->InitCheck();
if (status < B_OK)
return status;
uint8* src = (uint8*)source->Bits();
uint32 srcBPR = source->BytesPerRow();
@ -338,78 +397,34 @@ BIconUtils::ConvertFromCMAP8(BBitmap* source, BBitmap* result)
return ConvertFromCMAP8(src, width, height, srcBPR, result);
}
// scale_bilinear
static void
scale_bilinear(uint8* bits, int32 srcWidth, int32 srcHeight,
int32 dstWidth, int32 dstHeight, uint32 bpr)
status_t
BIconUtils::ConvertToCMAP8(BBitmap* source, BBitmap* result)
{
// first pass: scale bottom to top
if (source == NULL || source->ColorSpace() != B_RGBA32
|| result->ColorSpace() != B_CMAP8)
return B_BAD_VALUE;
uint8* dst = bits + (dstHeight - 1) * bpr;
// offset to bottom left pixel in target size
for (int32 x = 0; x < srcWidth; x++) {
uint8* d = dst;
for (int32 y = dstHeight - 1; y >= 0; y--) {
int32 lineF = y * 256 * (srcHeight - 1) / (dstHeight - 1);
int32 lineI = lineF >> 8;
uint8 weight = (uint8)(lineF & 0xff);
uint8* s1 = bits + lineI * bpr + 4 * x;
if (weight == 0) {
d[0] = s1[0];
d[1] = s1[1];
d[2] = s1[2];
d[3] = s1[3];
} else {
uint8* s2 = s1 + bpr;
d[0] = (((s2[0] - s1[0]) * weight) + (s1[0] << 8)) >> 8;
d[1] = (((s2[1] - s1[1]) * weight) + (s1[1] << 8)) >> 8;
d[2] = (((s2[2] - s1[2]) * weight) + (s1[2] << 8)) >> 8;
d[3] = (((s2[3] - s1[3]) * weight) + (s1[3] << 8)) >> 8;
}
status_t status = source->InitCheck();
if (status < B_OK)
return status;
d -= bpr;
}
dst += 4;
}
status = result->InitCheck();
if (status < B_OK)
return status;
// second pass: scale right to left
uint8* src = (uint8*)source->Bits();
uint32 srcBPR = source->BytesPerRow();
uint32 width = source->Bounds().IntegerWidth() + 1;
uint32 height = source->Bounds().IntegerHeight() + 1;
dst = bits + (dstWidth - 1) * 4;
// offset to top left pixel in target size
for (int32 y = 0; y < dstWidth; y++) {
uint8* d = dst;
for (int32 x = dstWidth - 1; x >= 0; x--) {
int32 columnF = x * 256 * (srcWidth - 1) / (dstWidth - 1);
int32 columnI = columnF >> 8;
uint8 weight = (uint8)(columnF & 0xff);
uint8* s1 = bits + y * bpr + 4 * columnI;
if (weight == 0) {
d[0] = s1[0];
d[1] = s1[1];
d[2] = s1[2];
d[3] = s1[3];
} else {
uint8* s2 = s1 + 4;
d[0] = (((s2[0] - s1[0]) * weight) + (s1[0] << 8)) >> 8;
d[1] = (((s2[1] - s1[1]) * weight) + (s1[1] << 8)) >> 8;
d[2] = (((s2[2] - s1[2]) * weight) + (s1[2] << 8)) >> 8;
d[3] = (((s2[3] - s1[3]) * weight) + (s1[3] << 8)) >> 8;
}
d -= 4;
}
dst += bpr;
}
return ConvertToCMAP8(src, width, height, srcBPR, result);
}
// ConvertFromCMAP8
status_t
BIconUtils::ConvertFromCMAP8(const uint8* src,
uint32 width, uint32 height, uint32 srcBPR,
BBitmap* result)
BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height,
uint32 srcBPR, BBitmap* result)
{
if (!src || !result || srcBPR == 0)
return B_BAD_VALUE;
@ -460,8 +475,8 @@ BIconUtils::ConvertFromCMAP8(const uint8* src,
if (dstWidth > width || dstHeight > height) {
// up scaling
scale_bilinear((uint8*)result->Bits(), width, height,
dstWidth, dstHeight, dstBPR);
scale_bilinear((uint8*)result->Bits(), width, height, dstWidth,
dstHeight, dstBPR);
}
return B_OK;
@ -469,11 +484,10 @@ BIconUtils::ConvertFromCMAP8(const uint8* src,
//#endif // __HAIKU__
}
// ConvertToCMAP8
status_t
BIconUtils::ConvertToCMAP8(const uint8* src,
uint32 width, uint32 height, uint32 srcBPR,
BBitmap* result)
BIconUtils::ConvertToCMAP8(const uint8* src, uint32 width, uint32 height,
uint32 srcBPR, BBitmap* result)
{
if (!src || !result || srcBPR == 0)
return B_BAD_VALUE;
@ -534,8 +548,10 @@ memset(result->Bits(), 255, result->BitsLength());
//#endif // __HAIKU__
}
// #pragma mark - forbidden
BIconUtils::BIconUtils() {}
BIconUtils::~BIconUtils() {}
BIconUtils::BIconUtils(const BIconUtils&) {}