From 37d495fca3506f63e36ff49e8d67efc136e5079e Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 22 Oct 2020 17:07:42 +0200 Subject: [PATCH] Adding source/Graphics/Image/IcoFormat --- engine.build.lua | 1 + source/Graphics/Image/IcoFormat.cpp | 76 +++++++++++++++++++++++++++++ source/Graphics/Image/IcoFormat.h | 19 ++++++++ 3 files changed, 96 insertions(+) create mode 100644 source/Graphics/Image/IcoFormat.cpp create mode 100644 source/Graphics/Image/IcoFormat.h diff --git a/engine.build.lua b/engine.build.lua index 35a8e2a..64a7ecb 100644 --- a/engine.build.lua +++ b/engine.build.lua @@ -99,6 +99,7 @@ local graphics_module = Module("source/Graphics", { -- Image "Image.cpp", "ImageLoader.cpp", + "Image/IcoFormat.cpp", "OpenGL.cpp", "GL/glad.c", diff --git a/source/Graphics/Image/IcoFormat.cpp b/source/Graphics/Image/IcoFormat.cpp new file mode 100644 index 0000000..721a106 --- /dev/null +++ b/source/Graphics/Image/IcoFormat.cpp @@ -0,0 +1,76 @@ + +#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_32BGRA; + } else { + format = PixelFormat::PF_32BGR; + } + + // 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 diff --git a/source/Graphics/Image/IcoFormat.h b/source/Graphics/Image/IcoFormat.h new file mode 100644 index 0000000..bd8c729 --- /dev/null +++ b/source/Graphics/Image/IcoFormat.h @@ -0,0 +1,19 @@ + +#ifndef SPECTRE_GRAPHICS_IMAGE_ICOFORMAT_H +#define SPECTRE_GRAPHICS_IMAGE_ICOFORMAT_H + +#include + +namespace sp { +namespace image { + +class IcoFormat +{ +public : + + bool decode(Image& img, const unsigned char *data, unsigned size); +}; + +}} // namespace sp::image + +#endif /* SPECTRE_GRAPHICS_IMAGE_ICOFORMAT_H */