* 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
+6 -4
View File
@@ -1,17 +1,17 @@
/* /*
* Copyright 2006-2008, Haiku. All rights reserved. * Copyright 2006-2008, Haiku. All rights reserved.
* Distributed under the terms of the MIT License. * 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> #include <Mime.h>
class BBitmap; class BBitmap;
class BNode; class BNode;
// This class is a little different from many other classes. // This class is a little different from many other classes.
// You don't create an instance of it; you just call its various // You don't create an instance of it; you just call its various
// static member functions for utility-like operations. // static member functions for utility-like operations.
@@ -65,6 +65,8 @@ public:
// to make any sense). // to make any sense).
static status_t ConvertFromCMAP8(BBitmap* source, static status_t ConvertFromCMAP8(BBitmap* source,
BBitmap* result); BBitmap* result);
static status_t ConvertToCMAP8(BBitmap* source,
BBitmap* result);
static status_t ConvertFromCMAP8(const uint8* data, static status_t ConvertFromCMAP8(const uint8* data,
uint32 width, uint32 height, uint32 width, uint32 height,
@@ -75,4 +77,4 @@ public:
uint32 bytesPerRow, BBitmap* result); uint32 bytesPerRow, BBitmap* result);
}; };
#endif // ICON_UTILS_H #endif // _ICON_UTILS_H
+131 -115
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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -33,14 +33,79 @@ using namespace BPrivate::Icon;
using std::nothrow; 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 status_t
BIconUtils::GetIcon(BNode* node, BIconUtils::GetIcon(BNode* node, const char* vectorIconAttrName,
const char* vectorIconAttrName, const char* smallIconAttrName, const char* largeIconAttrName,
const char* smallIconAttrName, icon_size size, BBitmap* result)
const char* largeIconAttrName,
icon_size size,
BBitmap* result)
{ {
if (!result || result->InitCheck()) if (!result || result->InitCheck())
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -62,24 +127,20 @@ BIconUtils::GetIcon(BNode* node,
else else
size = B_MINI_ICON; size = B_MINI_ICON;
ret = GetCMAP8Icon(node, ret = GetCMAP8Icon(node, smallIconAttrName, largeIconAttrName,
smallIconAttrName, size, result);
largeIconAttrName,
size, result);
} }
break; break;
case B_CMAP8: case B_CMAP8:
// prefer old B_CMAP8 icons // prefer old B_CMAP8 icons
ret = GetCMAP8Icon(node, ret = GetCMAP8Icon(node, smallIconAttrName, largeIconAttrName,
smallIconAttrName, size, result);
largeIconAttrName,
size, result);
if (ret < B_OK) { if (ret < B_OK) {
// try to fallback to vector icon // try to fallback to vector icon
#ifdef HAIKU_TARGET_PLATFORM_HAIKU #ifdef HAIKU_TARGET_PLATFORM_HAIKU
BBitmap temp(result->Bounds(), BBitmap temp(result->Bounds(), B_BITMAP_NO_SERVER_LINK,
B_BITMAP_NO_SERVER_LINK, B_RGBA32); B_RGBA32);
#else #else
BBitmap temp(result->Bounds(), B_RGBA32); BBitmap temp(result->Bounds(), B_RGBA32);
#endif #endif
@@ -92,8 +153,8 @@ BIconUtils::GetIcon(BNode* node,
uint32 width = temp.Bounds().IntegerWidth() + 1; uint32 width = temp.Bounds().IntegerWidth() + 1;
uint32 height = temp.Bounds().IntegerHeight() + 1; uint32 height = temp.Bounds().IntegerHeight() + 1;
uint32 bytesPerRow = temp.BytesPerRow(); uint32 bytesPerRow = temp.BytesPerRow();
ret = ConvertToCMAP8((uint8*)temp.Bits(), ret = ConvertToCMAP8((uint8*)temp.Bits(), width, height,
width, height, bytesPerRow, result); bytesPerRow, result);
} }
break; break;
default: default:
@@ -104,12 +165,12 @@ BIconUtils::GetIcon(BNode* node,
return ret; return ret;
} }
// #pragma mark - // #pragma mark -
// GetVectorIcon
status_t status_t
BIconUtils::GetVectorIcon(BNode* node, const char* attrName, BIconUtils::GetVectorIcon(BNode* node, const char* attrName, BBitmap* result)
BBitmap* result)
{ {
if (!node || node->InitCheck() < B_OK || !attrName) if (!node || node->InitCheck() < B_OK || !attrName)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -154,10 +215,9 @@ printf("read: %lld, import: %lld\n", importTime - startTime, finishTime - import
return B_OK; return B_OK;
} }
// GetVectorIcon
status_t status_t
BIconUtils::GetVectorIcon(const uint8* buffer, size_t size, BIconUtils::GetVectorIcon(const uint8* buffer, size_t size, BBitmap* result)
BBitmap* result)
{ {
if (!result) if (!result)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -211,14 +271,13 @@ BIconUtils::GetVectorIcon(const uint8* buffer, size_t size,
return ret; return ret;
} }
// #pragma mark - // #pragma mark -
status_t status_t
BIconUtils::GetCMAP8Icon(BNode* node, BIconUtils::GetCMAP8Icon(BNode* node, const char* smallIconAttrName,
const char* smallIconAttrName, const char* largeIconAttrName, icon_size size, BBitmap* icon)
const char* largeIconAttrName,
icon_size size,
BBitmap* icon)
{ {
// check parameters and initialization // check parameters and initialization
if (!icon || icon->InitCheck() != B_OK if (!icon || icon->InitCheck() != B_OK
@@ -279,7 +338,7 @@ BIconUtils::GetCMAP8Icon(BNode* node,
// read the attribute // read the attribute
if (ret == B_OK) { if (ret == B_OK) {
bool tempBuffer = (icon->ColorSpace() != B_CMAP8 bool tempBuffer = (icon->ColorSpace() != B_CMAP8
|| icon->Bounds() != bounds); || icon->Bounds() != bounds);
uint8* buffer = NULL; uint8* buffer = NULL;
ssize_t read; ssize_t read;
if (tempBuffer) { if (tempBuffer) {
@@ -288,12 +347,11 @@ BIconUtils::GetCMAP8Icon(BNode* node,
if (!buffer) { if (!buffer) {
ret = B_NO_MEMORY; ret = B_NO_MEMORY;
} else { } else {
read = node->ReadAttr(attribute, attrType, 0, buffer, read = node->ReadAttr(attribute, attrType, 0, buffer, attrSize);
attrSize);
} }
} else { } else {
read = node->ReadAttr(attribute, attrType, 0, icon->Bits(), read = node->ReadAttr(attribute, attrType, 0, icon->Bits(),
attrSize); attrSize);
} }
if (ret == B_OK) { if (ret == B_OK) {
if (read < 0) if (read < 0)
@@ -304,9 +362,8 @@ BIconUtils::GetCMAP8Icon(BNode* node,
if (tempBuffer) { if (tempBuffer) {
// other color space than stored in attribute // other color space than stored in attribute
if (ret == B_OK) { if (ret == B_OK) {
ret = ConvertFromCMAP8(buffer, ret = ConvertFromCMAP8(buffer, (uint32)size, (uint32)size,
(uint32)size, (uint32)size, (uint32)size, icon);
(uint32)size, icon);
} }
delete[] buffer; delete[] buffer;
} }
@@ -314,21 +371,23 @@ BIconUtils::GetCMAP8Icon(BNode* node,
return ret; return ret;
} }
// #pragma mark - // #pragma mark -
// ConvertFromCMAP8
status_t status_t
BIconUtils::ConvertFromCMAP8(BBitmap* source, BBitmap* result) BIconUtils::ConvertFromCMAP8(BBitmap* source, BBitmap* result)
{ {
if (!source) if (source == NULL || source->ColorSpace() != B_CMAP8)
return B_BAD_VALUE; return B_BAD_VALUE;
status_t ret = source->InitCheck(); status_t status = source->InitCheck();
if (ret < B_OK) if (status < B_OK)
return ret; return status;
if (source->ColorSpace() != B_CMAP8) status = result->InitCheck();
return B_BAD_VALUE; if (status < B_OK)
return status;
uint8* src = (uint8*)source->Bits(); uint8* src = (uint8*)source->Bits();
uint32 srcBPR = source->BytesPerRow(); uint32 srcBPR = source->BytesPerRow();
@@ -338,78 +397,34 @@ BIconUtils::ConvertFromCMAP8(BBitmap* source, BBitmap* result)
return ConvertFromCMAP8(src, width, height, srcBPR, result); return ConvertFromCMAP8(src, width, height, srcBPR, result);
} }
// scale_bilinear
static void status_t
scale_bilinear(uint8* bits, int32 srcWidth, int32 srcHeight, BIconUtils::ConvertToCMAP8(BBitmap* source, BBitmap* result)
int32 dstWidth, int32 dstHeight, uint32 bpr)
{ {
// 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; status_t status = source->InitCheck();
// offset to bottom left pixel in target size if (status < B_OK)
for (int32 x = 0; x < srcWidth; x++) { return status;
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; status = result->InitCheck();
} if (status < B_OK)
dst += 4; 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; return ConvertToCMAP8(src, width, height, srcBPR, result);
// 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;
}
} }
// ConvertFromCMAP8
status_t status_t
BIconUtils::ConvertFromCMAP8(const uint8* src, BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height,
uint32 width, uint32 height, uint32 srcBPR, uint32 srcBPR, BBitmap* result)
BBitmap* result)
{ {
if (!src || !result || srcBPR == 0) if (!src || !result || srcBPR == 0)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -460,8 +475,8 @@ BIconUtils::ConvertFromCMAP8(const uint8* src,
if (dstWidth > width || dstHeight > height) { if (dstWidth > width || dstHeight > height) {
// up scaling // up scaling
scale_bilinear((uint8*)result->Bits(), width, height, scale_bilinear((uint8*)result->Bits(), width, height, dstWidth,
dstWidth, dstHeight, dstBPR); dstHeight, dstBPR);
} }
return B_OK; return B_OK;
@@ -469,11 +484,10 @@ BIconUtils::ConvertFromCMAP8(const uint8* src,
//#endif // __HAIKU__ //#endif // __HAIKU__
} }
// ConvertToCMAP8
status_t status_t
BIconUtils::ConvertToCMAP8(const uint8* src, BIconUtils::ConvertToCMAP8(const uint8* src, uint32 width, uint32 height,
uint32 width, uint32 height, uint32 srcBPR, uint32 srcBPR, BBitmap* result)
BBitmap* result)
{ {
if (!src || !result || srcBPR == 0) if (!src || !result || srcBPR == 0)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -534,8 +548,10 @@ memset(result->Bits(), 255, result->BitsLength());
//#endif // __HAIKU__ //#endif // __HAIKU__
} }
// #pragma mark - forbidden // #pragma mark - forbidden
BIconUtils::BIconUtils() {} BIconUtils::BIconUtils() {}
BIconUtils::~BIconUtils() {} BIconUtils::~BIconUtils() {}
BIconUtils::BIconUtils(const BIconUtils&) {} BIconUtils::BIconUtils(const BIconUtils&) {}