mirror of
https://github.com/GerbilSoft/rom-properties.git
synced 2025-06-18 19:45:41 -04:00
[librptexture] ICO: Select the best icon image.
First, the image size is checked. If either width or height are larger than the previously-selected image, this image is picked. Otherwise, if the size is identical (both width and height), and bitcount is higher, then the image is selected. TODO: Better non-square icon handling? (Use "largest area"?)
This commit is contained in:
parent
fbdeae25a5
commit
1caf44d15e
@ -220,11 +220,95 @@ int ICOPrivate::loadIconDirectory_Win3(void)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Picking the first icon for now.
|
||||
// TODO: Pick the largest, then highest color depth.
|
||||
pBestIcon = &iconDirectory[0];
|
||||
pIconHeader = &iconBitmapHeaders[0];
|
||||
return 0;
|
||||
// Go through the icon bitmap headers and figure out the "best" one.
|
||||
unsigned int width_best = 0, height_best = 0, bitcount_best = 0;
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
// Get the width, height, and color depth from this bitmap header.
|
||||
const IconBitmapHeader_t *const p = &iconBitmapHeaders[i];
|
||||
unsigned int width, height, bitcount;
|
||||
|
||||
switch (p->size) {
|
||||
default:
|
||||
// Not supported...
|
||||
continue;
|
||||
|
||||
case BITMAPCOREHEADER_SIZE:
|
||||
if (le32_to_cpu(p->bch.bcPlanes) > 1) {
|
||||
// Cannot handle planar bitmaps.
|
||||
continue;
|
||||
}
|
||||
width = le16_to_cpu(p->bch.bcWidth);
|
||||
height = le16_to_cpu(p->bch.bcHeight) / 2;
|
||||
bitcount = le16_to_cpu(p->bch.bcBitCount);
|
||||
break;
|
||||
|
||||
case BITMAPINFOHEADER_SIZE:
|
||||
case BITMAPV2INFOHEADER_SIZE:
|
||||
case BITMAPV3INFOHEADER_SIZE:
|
||||
case BITMAPV4HEADER_SIZE:
|
||||
case BITMAPV5HEADER_SIZE:
|
||||
if (le32_to_cpu(p->bih.biPlanes) > 1) {
|
||||
// Cannot handle planar bitmaps.
|
||||
continue;
|
||||
}
|
||||
width = le32_to_cpu(p->bih.biWidth);
|
||||
height = le32_to_cpu(p->bih.biHeight) / 2;
|
||||
bitcount = le16_to_cpu(p->bih.biBitCount);
|
||||
break;
|
||||
|
||||
case 0x474E5089: // "\x89PNG"
|
||||
switch (p->png.ihdr.data.color_type) {
|
||||
default:
|
||||
// Not supported...
|
||||
continue;
|
||||
|
||||
case PNG_COLOR_TYPE_PALETTE:
|
||||
bitcount = p->png.ihdr.data.bit_depth;
|
||||
break;
|
||||
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
// Handling as if it's RGB.
|
||||
bitcount = p->png.ihdr.data.bit_depth * 3;
|
||||
break;
|
||||
|
||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
// Handling as if it's ARGB.
|
||||
bitcount = p->png.ihdr.data.bit_depth * 4;
|
||||
break;
|
||||
}
|
||||
|
||||
width = be32_to_cpu(p->png.ihdr.data.width);
|
||||
height = be32_to_cpu(p->png.ihdr.data.height);
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if the image is larger.
|
||||
// TODO: Non-square icon handling.
|
||||
bool icon_is_better = false;
|
||||
if (width > width_best || height > height_best) {
|
||||
// Image is larger.
|
||||
icon_is_better = true;
|
||||
} else if (width == width_best && height == height_best) {
|
||||
// Image is the same size.
|
||||
if (bitcount > bitcount_best) {
|
||||
// Color depth is higher.
|
||||
icon_is_better = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (icon_is_better) {
|
||||
// This icon is better.
|
||||
pBestIcon = &iconDirectory[i];
|
||||
pIconHeader = p;
|
||||
width_best = width;
|
||||
height_best = height;
|
||||
bitcount_best = bitcount;
|
||||
}
|
||||
}
|
||||
|
||||
return (pBestIcon) ? 0 : -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,6 +153,22 @@ typedef enum {
|
||||
|
||||
/** PNG chunks (TODO: Combine with librpbase/tests/bmp.h?) **/
|
||||
|
||||
/* These describe the color_type field in png_info. */
|
||||
/* color type masks */
|
||||
#define PNG_COLOR_MASK_PALETTE 1
|
||||
#define PNG_COLOR_MASK_COLOR 2
|
||||
#define PNG_COLOR_MASK_ALPHA 4
|
||||
|
||||
/* color types. Note that not all combinations are legal */
|
||||
#define PNG_COLOR_TYPE_GRAY 0
|
||||
#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
|
||||
#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR)
|
||||
#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
|
||||
#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
|
||||
/* aliases */
|
||||
#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA
|
||||
#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA
|
||||
|
||||
/**
|
||||
* PNG IHDR chunk
|
||||
*/
|
||||
@ -169,7 +185,9 @@ typedef struct RP_PACKED _PNG_IHDR_t {
|
||||
ASSERT_STRUCT(PNG_IHDR_t, 13);
|
||||
#pragma pack()
|
||||
|
||||
// PNG IHDR struct, with length, name, and CRC32.
|
||||
/**
|
||||
* PNG IHDR struct, with length, name, and CRC32.
|
||||
*/
|
||||
#pragma pack(1)
|
||||
typedef struct RP_PACKED _PNG_IHDR_full_t {
|
||||
uint32_t chunk_size; // BE32
|
||||
|
Loading…
Reference in New Issue
Block a user