#include "IcoFormat.h" #include #include #include #include "Format/ico.h" namespace sp { namespace image { ICONDIRENTRY* findLargestImage(ICONDIRENTRY *ent, uint16_t size) { uint32_t idx = 0, lgsz = 0, sz; for (int i = 0; i < size; i++) { sz = ent[i].width * ent[i].height; if (sz > lgsz) { lgsz = sz; idx = i; } } return ent + idx; } bool IcoFormat::decode(Image& img, const unsigned char *data, unsigned size) { uint8_t *pixels; PixelFormat format; ICONDIRENTRY *ent; ICONDIRENTRY *largest; uint16_t type; uint16_t num_ent; type = system::ltoh16(data + 2); num_ent = system::ltoh16(data + 4); // Type: 1 = ICO, 2 = CUR if (type != 0x0001 || num_ent < 1) { return false; } // Allocate ICONDIRENT for all images in the file. ent = (ICONDIRENTRY *) malloc(sizeof(ICONDIRENTRY) * num_ent); if (!ent) { return false; } for (int i = 0; i < num_ent; i++) { unsigned int p = 6 + (i * ICONDIRENTRY_SIZE); ent[i].width = data[p + 0]; ent[i].height = data[p + 1]; ent[i].num_colors = data[p + 2]; ent[i].color_planes = data[p + 4]; ent[i].bpp = data[p + 6]; ent[i].size = system::ltoh32(data + p + 8); ent[i].offset = system::ltoh32(data + p + 12); } // Find Largest image largest = findLargestImage(ent, num_ent); if (largest->bpp == 32) { format = PixelFormat::PF_BGRA; } else { format = PixelFormat::PF_BGR; } // NOTE: plus 40 bytes here to skip over the DIB header. img.create(largest->width, largest->height, data + largest->offset + 40, format); free(ent); return true; } }} // namespace sp::image