summaryrefslogtreecommitdiff
path: root/plugins/AdvaImg/src/FreeImage/PluginICO.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/AdvaImg/src/FreeImage/PluginICO.cpp')
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginICO.cpp824
1 files changed, 0 insertions, 824 deletions
diff --git a/plugins/AdvaImg/src/FreeImage/PluginICO.cpp b/plugins/AdvaImg/src/FreeImage/PluginICO.cpp
deleted file mode 100644
index 5c4673e4de..0000000000
--- a/plugins/AdvaImg/src/FreeImage/PluginICO.cpp
+++ /dev/null
@@ -1,824 +0,0 @@
-// ==========================================================
-// ICO Loader and Writer
-//
-// Design and implementation by
-// - Floris van den Berg (flvdberg@wxs.nl)
-// - Hervé Drolon (drolon@infonie.fr)
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-#include "FreeImage.h"
-#include "Utilities.h"
-
-// ----------------------------------------------------------
-// Constants + headers
-// ----------------------------------------------------------
-
-#ifdef _WIN32
-#pragma pack(push, 1)
-#else
-#pragma pack(1)
-#endif
-
-// These next two structs represent how the icon information is stored
-// in an ICO file.
-
-typedef struct tagICONHEADER {
- WORD idReserved; // reserved
- WORD idType; // resource type (1 for icons)
- WORD idCount; // how many images?
-} ICONHEADER;
-
-typedef struct tagICONDIRECTORYENTRY {
- BYTE bWidth; // width of the image
- BYTE bHeight; // height of the image (times 2)
- BYTE bColorCount; // number of colors in image (0 if >=8bpp)
- BYTE bReserved; // reserved
- WORD wPlanes; // color Planes
- WORD wBitCount; // bits per pixel
- DWORD dwBytesInRes; // how many bytes in this resource?
- DWORD dwImageOffset; // where in the file is this image
-} ICONDIRENTRY;
-
-#ifdef _WIN32
-#pragma pack(pop)
-#else
-#pragma pack()
-#endif
-
-// ==========================================================
-// Static helpers
-// ==========================================================
-
-/** How wide, in bytes, would this many bits be, DWORD aligned ?
-*/
-static int
-WidthBytes(int bits) {
- return ((((bits) + 31)>>5)<<2);
-}
-
-/** Calculates the size of a single icon image
-@return Returns the size for that image
-*/
-static DWORD
-CalculateImageSize(FIBITMAP* icon_dib) {
- DWORD dwNumBytes = 0;
-
- unsigned colors = FreeImage_GetColorsUsed(icon_dib);
- unsigned width = FreeImage_GetWidth(icon_dib);
- unsigned height = FreeImage_GetHeight(icon_dib);
- unsigned pitch = FreeImage_GetPitch(icon_dib);
-
- dwNumBytes = sizeof( BITMAPINFOHEADER ); // header
- dwNumBytes += colors * sizeof(RGBQUAD); // palette
- dwNumBytes += height * pitch; // XOR mask
- dwNumBytes += height * WidthBytes(width); // AND mask
-
- return dwNumBytes;
-}
-
-/** Calculates the file offset for an icon image
-@return Returns the file offset for that image
-*/
-static DWORD
-CalculateImageOffset(std::vector<FIBITMAP*>& vPages, int nIndex ) {
- DWORD dwSize;
-
- // calculate the ICO header size
- dwSize = sizeof(ICONHEADER);
- // add the ICONDIRENTRY's
- dwSize += (DWORD)( vPages.size() * sizeof(ICONDIRENTRY) );
- // add the sizes of the previous images
- for(int k = 0; k < nIndex; k++) {
- FIBITMAP *icon_dib = (FIBITMAP*)vPages[k];
- dwSize += CalculateImageSize(icon_dib);
- }
-
- return dwSize;
-}
-
-/**
-Vista icon support
-@return Returns TRUE if the bitmap data is stored in PNG format
-*/
-static BOOL
-IsPNG(FreeImageIO *io, fi_handle handle) {
- BYTE png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
- BYTE signature[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
- long tell = io->tell_proc(handle);
- io->read_proc(&signature, 1, 8, handle);
- BOOL bIsPNG = (memcmp(png_signature, signature, 8) == 0);
- io->seek_proc(handle, tell, SEEK_SET);
-
- return bIsPNG;
-}
-
-#ifdef FREEIMAGE_BIGENDIAN
-static void
-SwapInfoHeader(BITMAPINFOHEADER *header) {
- SwapLong(&header->biSize);
- SwapLong((DWORD *)&header->biWidth);
- SwapLong((DWORD *)&header->biHeight);
- SwapShort(&header->biPlanes);
- SwapShort(&header->biBitCount);
- SwapLong(&header->biCompression);
- SwapLong(&header->biSizeImage);
- SwapLong((DWORD *)&header->biXPelsPerMeter);
- SwapLong((DWORD *)&header->biYPelsPerMeter);
- SwapLong(&header->biClrUsed);
- SwapLong(&header->biClrImportant);
-}
-
-static void
-SwapIconHeader(ICONHEADER *header) {
- SwapShort(&header->idReserved);
- SwapShort(&header->idType);
- SwapShort(&header->idCount);
-}
-
-static void
-SwapIconDirEntries(ICONDIRENTRY *ent, int num) {
- while(num) {
- SwapShort(&ent->wPlanes);
- SwapShort(&ent->wBitCount);
- SwapLong(&ent->dwBytesInRes);
- SwapLong(&ent->dwImageOffset);
- num--;
- ent++;
- }
-}
-#endif
-
-// ==========================================================
-// Plugin Interface
-// ==========================================================
-
-static int s_format_id;
-
-// ==========================================================
-// Plugin Implementation
-// ==========================================================
-
-static const char * DLL_CALLCONV
-Format() {
- return "ICO";
-}
-
-static const char * DLL_CALLCONV
-Description() {
- return "Windows Icon";
-}
-
-static const char * DLL_CALLCONV
-Extension() {
- return "ico";
-}
-
-static const char * DLL_CALLCONV
-RegExpr() {
- return NULL;
-}
-
-static const char * DLL_CALLCONV
-MimeType() {
- return "image/vnd.microsoft.icon";
-}
-
-static BOOL DLL_CALLCONV
-Validate(FreeImageIO *io, fi_handle handle) {
- ICONHEADER icon_header;
-
- io->read_proc(&icon_header, sizeof(ICONHEADER), 1, handle);
-#ifdef FREEIMAGE_BIGENDIAN
- SwapIconHeader(&icon_header);
-#endif
-
- return ((icon_header.idReserved == 0) && (icon_header.idType == 1) && (icon_header.idCount > 0));
-}
-
-static BOOL DLL_CALLCONV
-SupportsExportDepth(int depth) {
- return (
- (depth == 1) ||
- (depth == 4) ||
- (depth == 8) ||
- (depth == 16) ||
- (depth == 24) ||
- (depth == 32)
- );
-}
-
-static BOOL DLL_CALLCONV
-SupportsExportType(FREE_IMAGE_TYPE type) {
- return (type == FIT_BITMAP) ? TRUE : FALSE;
-}
-
-static BOOL DLL_CALLCONV
-SupportsNoPixels() {
- return TRUE;
-}
-
-// ----------------------------------------------------------
-
-static void * DLL_CALLCONV
-Open(FreeImageIO *io, fi_handle handle, BOOL read) {
- // Allocate memory for the header structure
- ICONHEADER *lpIH = (ICONHEADER*)malloc(sizeof(ICONHEADER));
- if(lpIH == NULL) {
- return NULL;
- }
-
- if (read) {
- // Read in the header
- io->read_proc(lpIH, 1, sizeof(ICONHEADER), handle);
-#ifdef FREEIMAGE_BIGENDIAN
- SwapIconHeader(lpIH);
-#endif
-
- if(!(lpIH->idReserved == 0) || !(lpIH->idType == 1)) {
- // Not an ICO file
- free(lpIH);
- return NULL;
- }
- }
- else {
- // Fill the header
- lpIH->idReserved = 0;
- lpIH->idType = 1;
- lpIH->idCount = 0;
- }
-
- return lpIH;
-}
-
-static void DLL_CALLCONV
-Close(FreeImageIO *io, fi_handle handle, void *data) {
- // free the header structure
- ICONHEADER *lpIH = (ICONHEADER*)data;
- free(lpIH);
-}
-
-// ----------------------------------------------------------
-
-static int DLL_CALLCONV
-PageCount(FreeImageIO *io, fi_handle handle, void *data) {
- ICONHEADER *lpIH = (ICONHEADER*)data;
-
- if(lpIH) {
- return lpIH->idCount;
- }
- return 1;
-}
-
-// ----------------------------------------------------------
-
-static FIBITMAP*
-LoadStandardIcon(FreeImageIO *io, fi_handle handle, int flags, BOOL header_only) {
- FIBITMAP *dib = NULL;
-
- // load the BITMAPINFOHEADER
- BITMAPINFOHEADER bmih;
- io->read_proc(&bmih, sizeof(BITMAPINFOHEADER), 1, handle);
-#ifdef FREEIMAGE_BIGENDIAN
- SwapInfoHeader(&bmih);
-#endif
-
- // allocate the bitmap
- int width = bmih.biWidth;
- int height = bmih.biHeight / 2; // height == xor + and mask
- unsigned bit_count = bmih.biBitCount;
- unsigned line = CalculateLine(width, bit_count);
- unsigned pitch = CalculatePitch(line);
-
- // allocate memory for one icon
-
- dib = FreeImage_AllocateHeader(header_only, width, height, bit_count);
-
- if (dib == NULL) {
- return NULL;
- }
-
- if( bmih.biBitCount <= 8 ) {
- // read the palette data
- io->read_proc(FreeImage_GetPalette(dib), CalculateUsedPaletteEntries(bit_count) * sizeof(RGBQUAD), 1, handle);
-#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
- RGBQUAD *pal = FreeImage_GetPalette(dib);
- for(unsigned i = 0; i < CalculateUsedPaletteEntries(bit_count); i++) {
- INPLACESWAP(pal[i].rgbRed, pal[i].rgbBlue);
- }
-#endif
- }
-
- if(header_only) {
- // header only mode
- return dib;
- }
-
- // read the icon
- io->read_proc(FreeImage_GetBits(dib), height * pitch, 1, handle);
-
-#ifdef FREEIMAGE_BIGENDIAN
- if (bit_count == 16) {
- for(int y = 0; y < height; y++) {
- WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y);
- for(int x = 0; x < width; x++) {
- SwapShort(pixel);
- pixel++;
- }
- }
- }
-#endif
-#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
- if (bit_count == 24 || bit_count == 32) {
- for(int y = 0; y < height; y++) {
- BYTE *pixel = FreeImage_GetScanLine(dib, y);
- for(int x = 0; x < width; x++) {
- INPLACESWAP(pixel[0], pixel[2]);
- pixel += (bit_count>>3);
- }
- }
- }
-#endif
- // bitmap has been loaded successfully!
-
- // convert to 32bpp and generate an alpha channel
- // apply the AND mask only if the image is not 32 bpp
- if(((flags & ICO_MAKEALPHA) == ICO_MAKEALPHA) && (bit_count < 32)) {
- FIBITMAP *dib32 = FreeImage_ConvertTo32Bits(dib);
- FreeImage_Unload(dib);
-
- if (dib32 == NULL) {
- return NULL;
- }
-
- int width_and = WidthBytes(width);
- BYTE *line_and = (BYTE *)malloc(width_and);
-
- if( line_and == NULL ) {
- FreeImage_Unload(dib32);
- return NULL;
- }
-
- //loop through each line of the AND-mask generating the alpha channel, invert XOR-mask
- for(int y = 0; y < height; y++) {
- RGBQUAD *quad = (RGBQUAD *)FreeImage_GetScanLine(dib32, y);
- io->read_proc(line_and, width_and, 1, handle);
- for(int x = 0; x < width; x++) {
- quad->rgbReserved = (line_and[x>>3] & (0x80 >> (x & 0x07))) != 0 ? 0 : 0xFF;
- if( quad->rgbReserved == 0 ) {
- quad->rgbBlue ^= 0xFF;
- quad->rgbGreen ^= 0xFF;
- quad->rgbRed ^= 0xFF;
- }
- quad++;
- }
- }
- free(line_and);
-
- return dib32;
- }
-
- return dib;
-}
-
-static FIBITMAP * DLL_CALLCONV
-Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
- if (page == -1) {
- page = 0;
- }
-
- BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
-
- if (handle != NULL) {
- FIBITMAP *dib = NULL;
-
- // get the icon header
- ICONHEADER *icon_header = (ICONHEADER*)data;
-
- if (icon_header) {
- // load the icon descriptions
- ICONDIRENTRY *icon_list = (ICONDIRENTRY*)malloc(icon_header->idCount * sizeof(ICONDIRENTRY));
- if(icon_list == NULL) {
- return NULL;
- }
- io->seek_proc(handle, sizeof(ICONHEADER), SEEK_SET);
- io->read_proc(icon_list, icon_header->idCount * sizeof(ICONDIRENTRY), 1, handle);
-#ifdef FREEIMAGE_BIGENDIAN
- SwapIconDirEntries(icon_list, icon_header->idCount);
-#endif
-
- // load the requested icon
- if (page < icon_header->idCount) {
- // seek to the start of the bitmap data for the icon
- io->seek_proc(handle, icon_list[page].dwImageOffset, SEEK_SET);
-
- if( IsPNG(io, handle) ) {
- // Vista icon support
- // see http://blogs.msdn.com/b/oldnewthing/archive/2010/10/22/10079192.aspx
- dib = FreeImage_LoadFromHandle(FIF_PNG, io, handle, header_only ? FIF_LOAD_NOPIXELS : PNG_DEFAULT);
- }
- else {
- // standard icon support
- // see http://msdn.microsoft.com/en-us/library/ms997538.aspx
- // see http://blogs.msdn.com/b/oldnewthing/archive/2010/10/18/10077133.aspx
- dib = LoadStandardIcon(io, handle, flags, header_only);
- }
-
- free(icon_list);
-
- return dib;
-
- } else {
- free(icon_list);
- FreeImage_OutputMessageProc(s_format_id, "Page doesn't exist");
- }
- } else {
- FreeImage_OutputMessageProc(s_format_id, "File is not an ICO file");
- }
- }
-
- return NULL;
-}
-
-// ----------------------------------------------------------
-
-static BOOL
-SaveStandardIcon(FreeImageIO *io, FIBITMAP *dib, fi_handle handle) {
- BITMAPINFOHEADER *bmih = NULL;
-
- // write the BITMAPINFOHEADER
- bmih = FreeImage_GetInfoHeader(dib);
- bmih->biHeight *= 2; // height == xor + and mask
-#ifdef FREEIMAGE_BIGENDIAN
- SwapInfoHeader(bmih);
-#endif
- io->write_proc(bmih, sizeof(BITMAPINFOHEADER), 1, handle);
-#ifdef FREEIMAGE_BIGENDIAN
- SwapInfoHeader(bmih);
-#endif
- bmih->biHeight /= 2;
-
- // write the palette data
- if (FreeImage_GetPalette(dib) != NULL) {
- RGBQUAD *pal = FreeImage_GetPalette(dib);
- FILE_BGRA bgra;
- for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++) {
- bgra.b = pal[i].rgbBlue;
- bgra.g = pal[i].rgbGreen;
- bgra.r = pal[i].rgbRed;
- bgra.a = pal[i].rgbReserved;
- io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle);
- }
- }
-
- // write the bits
- int width = bmih->biWidth;
- int height = bmih->biHeight;
- unsigned bit_count = bmih->biBitCount;
- unsigned line = CalculateLine(width, bit_count);
- unsigned pitch = CalculatePitch(line);
- int size_xor = height * pitch;
- int size_and = height * WidthBytes(width);
-
- // XOR mask
-#ifdef FREEIMAGE_BIGENDIAN
- if (bit_count == 16) {
- WORD pixel;
- for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
- BYTE *line = FreeImage_GetScanLine(dib, y);
- for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
- pixel = ((WORD *)line)[x];
- SwapShort(&pixel);
- if (io->write_proc(&pixel, sizeof(WORD), 1, handle) != 1)
- return FALSE;
- }
- }
- } else
-#endif
-#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
- if (bit_count == 24) {
- FILE_BGR bgr;
- for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
- BYTE *line = FreeImage_GetScanLine(dib, y);
- for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
- RGBTRIPLE *triple = ((RGBTRIPLE *)line)+x;
- bgr.b = triple->rgbtBlue;
- bgr.g = triple->rgbtGreen;
- bgr.r = triple->rgbtRed;
- if (io->write_proc(&bgr, sizeof(FILE_BGR), 1, handle) != 1)
- return FALSE;
- }
- }
- } else if (bit_count == 32) {
- FILE_BGRA bgra;
- for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
- BYTE *line = FreeImage_GetScanLine(dib, y);
- for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
- RGBQUAD *quad = ((RGBQUAD *)line)+x;
- bgra.b = quad->rgbBlue;
- bgra.g = quad->rgbGreen;
- bgra.r = quad->rgbRed;
- bgra.a = quad->rgbReserved;
- if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1)
- return FALSE;
- }
- }
- } else
-#endif
-#if defined(FREEIMAGE_BIGENDIAN) || FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
- {
-#endif
- BYTE *xor_mask = FreeImage_GetBits(dib);
- io->write_proc(xor_mask, size_xor, 1, handle);
-#if defined(FREEIMAGE_BIGENDIAN) || FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
- }
-#endif
- // AND mask
- BYTE *and_mask = (BYTE*)malloc(size_and);
- if(!and_mask) {
- return FALSE;
- }
-
- if(FreeImage_IsTransparent(dib)) {
-
- if(bit_count == 32) {
- // create the AND mask from the alpha channel
-
- int width_and = WidthBytes(width);
- BYTE *and_bits = and_mask;
-
- // clear the mask
- memset(and_mask, 0, size_and);
-
- for(int y = 0; y < height; y++) {
- RGBQUAD *bits = (RGBQUAD*)FreeImage_GetScanLine(dib, y);
-
- for(int x = 0; x < width; x++) {
- if(bits[x].rgbReserved != 0xFF) {
- // set any transparent color to full transparency
- and_bits[x >> 3] |= (0x80 >> (x & 0x7));
- }
- }
-
- and_bits += width_and;
- }
- }
- else if(bit_count <= 8) {
- // create the AND mask from the transparency table
-
- BYTE *trns = FreeImage_GetTransparencyTable(dib);
-
- int width_and = WidthBytes(width);
- BYTE *and_bits = and_mask;
-
- // clear the mask
- memset(and_mask, 0, size_and);
-
- switch(FreeImage_GetBPP(dib)) {
- case 1:
- {
- for(int y = 0; y < height; y++) {
- BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y);
- for(int x = 0; x < width; x++) {
- // get pixel at (x, y)
- BYTE index = (bits[x >> 3] & (0x80 >> (x & 0x07))) != 0;
- if(trns[index] != 0xFF) {
- // set any transparent color to full transparency
- and_bits[x >> 3] |= (0x80 >> (x & 0x7));
- }
- }
- and_bits += width_and;
- }
- }
- break;
-
- case 4:
- {
- for(int y = 0; y < height; y++) {
- BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y);
- for(int x = 0; x < width; x++) {
- // get pixel at (x, y)
- BYTE shift = (BYTE)((1 - x % 2) << 2);
- BYTE index = (bits[x >> 1] & (0x0F << shift)) >> shift;
- if(trns[index] != 0xFF) {
- // set any transparent color to full transparency
- and_bits[x >> 3] |= (0x80 >> (x & 0x7));
- }
- }
- and_bits += width_and;
- }
- }
- break;
-
- case 8:
- {
- for(int y = 0; y < height; y++) {
- BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y);
- for(int x = 0; x < width; x++) {
- // get pixel at (x, y)
- BYTE index = bits[x];
- if(trns[index] != 0xFF) {
- // set any transparent color to full transparency
- and_bits[x >> 3] |= (0x80 >> (x & 0x7));
- }
- }
- and_bits += width_and;
- }
- }
- break;
-
- }
- }
- }
- else {
- // empty AND mask
- memset(and_mask, 0, size_and);
- }
-
- io->write_proc(and_mask, size_and, 1, handle);
- free(and_mask);
-
- return TRUE;
-}
-
-static BOOL DLL_CALLCONV
-Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
- ICONHEADER *icon_header = NULL;
- std::vector<FIBITMAP*> vPages;
- int k;
-
- if(!dib || !handle || !data) {
- return FALSE;
- }
-
- // check format limits
- unsigned w = FreeImage_GetWidth(dib);
- unsigned h = FreeImage_GetHeight(dib);
- if((w < 16) || (w > 256) || (h < 16) || (h > 256) || (w != h)) {
- FreeImage_OutputMessageProc(s_format_id, "Unsupported icon size: width x height = %d x %d", w, h);
- return FALSE;
- }
-
- if (page == -1) {
- page = 0;
- }
-
- // get the icon header
- icon_header = (ICONHEADER*)data;
-
- try {
- FIBITMAP *icon_dib = NULL;
-
- // load all icons
- for(k = 0; k < icon_header->idCount; k++) {
- icon_dib = Load(io, handle, k, flags, data);
- if(!icon_dib) {
- throw FI_MSG_ERROR_DIB_MEMORY;
- }
- vPages.push_back(icon_dib);
- }
-
- // add the page
- icon_dib = FreeImage_Clone(dib);
- vPages.push_back(icon_dib);
- icon_header->idCount++;
-
- // write the header
- io->seek_proc(handle, 0, SEEK_SET);
-#ifdef FREEIMAGE_BIGENDIAN
- SwapIconHeader(icon_header);
-#endif
- io->write_proc(icon_header, sizeof(ICONHEADER), 1, handle);
-#ifdef FREEIMAGE_BIGENDIAN
- SwapIconHeader(icon_header);
-#endif
-
- // write all icons
- // ...
-
- // save the icon descriptions
-
- ICONDIRENTRY *icon_list = (ICONDIRENTRY *)malloc(icon_header->idCount * sizeof(ICONDIRENTRY));
- if(!icon_list) {
- throw FI_MSG_ERROR_MEMORY;
- }
- memset(icon_list, 0, icon_header->idCount * sizeof(ICONDIRENTRY));
-
- for(k = 0; k < icon_header->idCount; k++) {
- icon_dib = (FIBITMAP*)vPages[k];
-
- // convert internal format to ICONDIRENTRY
- // take into account Vista icons whose size is 256x256
- const BITMAPINFOHEADER *bmih = FreeImage_GetInfoHeader(icon_dib);
- icon_list[k].bWidth = (bmih->biWidth > 255) ? 0 : (BYTE)bmih->biWidth;
- icon_list[k].bHeight = (bmih->biHeight > 255) ? 0 : (BYTE)bmih->biHeight;
- icon_list[k].bReserved = 0;
- icon_list[k].wPlanes = bmih->biPlanes;
- icon_list[k].wBitCount = bmih->biBitCount;
- if( (icon_list[k].wPlanes * icon_list[k].wBitCount) >= 8 ) {
- icon_list[k].bColorCount = 0;
- } else {
- icon_list[k].bColorCount = (BYTE)(1 << (icon_list[k].wPlanes * icon_list[k].wBitCount));
- }
- // initial guess (correct only for standard icons)
- icon_list[k].dwBytesInRes = CalculateImageSize(icon_dib);
- icon_list[k].dwImageOffset = CalculateImageOffset(vPages, k);
- }
-
- // make a room for icon dir entries, until later update
- const long directory_start = io->tell_proc(handle);
- io->write_proc(icon_list, sizeof(ICONDIRENTRY) * icon_header->idCount, 1, handle);
-
- // write the image bits for each image
-
- DWORD dwImageOffset = (DWORD)io->tell_proc(handle);
-
- for(k = 0; k < icon_header->idCount; k++) {
- icon_dib = (FIBITMAP*)vPages[k];
-
- if((icon_list[k].bWidth == 0) && (icon_list[k].bHeight == 0)) {
- // Vista icon support
- FreeImage_SaveToHandle(FIF_PNG, icon_dib, io, handle, PNG_DEFAULT);
- }
- else {
- // standard icon support
- // see http://msdn.microsoft.com/en-us/library/ms997538.aspx
- SaveStandardIcon(io, icon_dib, handle);
- }
-
- // update ICONDIRENTRY members
- DWORD dwBytesInRes = (DWORD)io->tell_proc(handle) - dwImageOffset;
- icon_list[k].dwImageOffset = dwImageOffset;
- icon_list[k].dwBytesInRes = dwBytesInRes;
- dwImageOffset += dwBytesInRes;
- }
-
- // update the icon descriptions
- const long current_pos = io->tell_proc(handle);
- io->seek_proc(handle, directory_start, SEEK_SET);
-#ifdef FREEIMAGE_BIGENDIAN
- SwapIconDirEntries(icon_list, icon_header->idCount);
-#endif
- io->write_proc(icon_list, sizeof(ICONDIRENTRY) * icon_header->idCount, 1, handle);
- io->seek_proc(handle, current_pos, SEEK_SET);
-
- free(icon_list);
-
- // free the vector class
- for(k = 0; k < icon_header->idCount; k++) {
- icon_dib = (FIBITMAP*)vPages[k];
- FreeImage_Unload(icon_dib);
- }
-
- return TRUE;
-
- } catch(const char *text) {
- // free the vector class
- for(size_t k = 0; k < vPages.size(); k++) {
- FIBITMAP *icon_dib = (FIBITMAP*)vPages[k];
- FreeImage_Unload(icon_dib);
- }
- FreeImage_OutputMessageProc(s_format_id, text);
- return FALSE;
- }
-}
-
-// ==========================================================
-// Init
-// ==========================================================
-
-void DLL_CALLCONV
-InitICO(Plugin *plugin, int format_id) {
- s_format_id = format_id;
-
- plugin->format_proc = Format;
- plugin->description_proc = Description;
- plugin->extension_proc = Extension;
- plugin->regexpr_proc = RegExpr;
- plugin->open_proc = Open;
- plugin->close_proc = Close;
- plugin->pagecount_proc = PageCount;
- plugin->pagecapability_proc = NULL;
- plugin->load_proc = Load;
- plugin->save_proc = Save;
- plugin->validate_proc = Validate;
- plugin->mime_proc = MimeType;
- plugin->supports_export_bpp_proc = SupportsExportDepth;
- plugin->supports_export_type_proc = SupportsExportType;
- plugin->supports_icc_profiles_proc = NULL;
- plugin->supports_no_pixels_proc = SupportsNoPixels;
-}