A few more bitmap icon updates, edge cases.

* Support downscaling icons to a size smaller than the source.
* For > 4x icon scaling do a scale4x followed by a bilinear scale.

Note that I tried to do a combination of scale2x/scale3x with bilinear scaling
and the results were worse than scale2x/scale3x with down scaling.

The 24x24 icon case looks pretty bad either using bilinear or scale2x followed
by a downscale because I am currently upscaling the 16x16 icon in Deskbar (we
didn't up until now support bitmap icon downscaling so I had no choice). It
might be a better idea to downscale the 32x32 version instead.

Note that all of the above has to do with bitmap icons ONLY and none of it
applies to HVIF icons that scale beautifully without these tricks.
This commit is contained in:
John Scipione
2013-03-04 12:56:12 -05:00
parent b09c265cb4
commit afecfa9ca8
+26 -29
View File
@@ -641,43 +641,29 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height,
uint32 dstWidth = result->Bounds().IntegerWidth() + 1;
uint32 dstHeight = result->Bounds().IntegerHeight() + 1;
if (dstWidth < width || dstHeight < height) {
// TODO: implement down scaling
return B_ERROR;
}
uint8* dst = (uint8*)result->Bits();
uint32 dstBPR = result->BytesPerRow();
// check for integer multiple scale
if (dstWidth == 2 * width && dstHeight == 2 * height) {
// scale2x
// check for downscaling or integer multiple scaling
if (dstWidth < width || dstHeight < height
|| dstWidth == 2 * width && dstHeight == 2 * height
|| dstWidth == 3 * width && dstHeight == 3 * height
|| dstWidth == 4 * width && dstHeight == 4 * height) {
BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1),
result->ColorSpace());
converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8);
uint8* convertedBits = (uint8*)converted->Bits();
int32 convertedBPR = converted->BytesPerRow();
scale2x(convertedBits, dst, width, height, convertedBPR, dstBPR);
delete converted;
return B_OK;
} else if (dstWidth == 3 * width && dstHeight == 3 * height) {
// scale3x
BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1),
result->ColorSpace());
converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8);
uint8* convertedBits = (uint8*)converted->Bits();
int32 convertedBPR = converted->BytesPerRow();
scale3x(convertedBits, dst, width, height, convertedBPR, dstBPR);
delete converted;
return B_OK;
} else if (dstWidth == 4 * width && dstHeight == 4 * height) {
// scale4x
BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1),
result->ColorSpace());
converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8);
uint8* convertedBits = (uint8*)converted->Bits();
int32 convertedBPR = converted->BytesPerRow();
scale4x(convertedBits, dst, width, height, convertedBPR, dstBPR);
if (dstWidth < width || dstHeight < height)
scale_down(convertedBits, dst, width, height, dstWidth, dstHeight);
else if (dstWidth == 2 * width && dstHeight == 2 * height)
scale2x(convertedBits, dst, width, height, convertedBPR, dstBPR);
else if (dstWidth == 3 * width && dstHeight == 3 * height)
scale3x(convertedBits, dst, width, height, convertedBPR, dstBPR);
else if (dstWidth == 4 * width && dstHeight == 4 * height)
scale4x(convertedBits, dst, width, height, convertedBPR, dstBPR);
delete converted;
return B_OK;
}
@@ -741,6 +727,17 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height,
scale4x(dst, tempBits, width, height, dstBPR, tempBPR);
scale_down(tempBits, dst, width * 3, height * 3, dstWidth, dstHeight);
delete temp;
} else if (dstWidth > 4 * width && dstHeight > 4 * height) {
// scale4x then bilinear
BBitmap* temp = new BBitmap(BRect(0, 0, width * 4 - 1, height * 4 - 1),
result->ColorSpace());
uint8* tempBits = (uint8*)temp->Bits();
uint32 tempBPR = temp->BytesPerRow();
scale4x(dst, tempBits, width, height, dstBPR, tempBPR);
result->ImportBits(tempBits, height * tempBPR, tempBPR, 0,
temp->ColorSpace());
scale_bilinear(dst, width, height, dstWidth, dstHeight, dstBPR);
delete temp;
} else {
// fall back to bilinear scaling
scale_bilinear(dst, width, height, dstWidth, dstHeight, dstBPR);