diff options
Diffstat (limited to 'plugins/AdvaImg/src/FreeImage/PluginPCX.cpp')
-rw-r--r-- | plugins/AdvaImg/src/FreeImage/PluginPCX.cpp | 659 |
1 files changed, 0 insertions, 659 deletions
diff --git a/plugins/AdvaImg/src/FreeImage/PluginPCX.cpp b/plugins/AdvaImg/src/FreeImage/PluginPCX.cpp deleted file mode 100644 index cd75629ddc..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginPCX.cpp +++ /dev/null @@ -1,659 +0,0 @@ -// ========================================================== -// PCX Loader -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Jani Kajala (janik@remedy.fi) -// - Markus Loibl (markus.loibl@epost.de) -// - Hervé Drolon (drolon@infonie.fr) -// - Juergen Riecker (j.riecker@gmx.de) -// -// 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 -// ---------------------------------------------------------- - -#define IO_BUF_SIZE 2048 - -// ---------------------------------------------------------- - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct tagPCXHEADER { - BYTE manufacturer; // Magic number (0x0A = ZSoft Z) - BYTE version; // Version 0 == 2.5 - // 2 == 2.8 with palette info - // 3 == 2.8 without palette info - // 5 == 3.0 with palette info - BYTE encoding; // Encoding: 0 = uncompressed, 1 = PCX rle compressed - BYTE bpp; // Bits per pixel per plane (only 1 or 8) - WORD window[4]; // left, upper, right,lower pixel coord. - WORD hdpi; // Horizontal resolution - WORD vdpi; // Vertical resolution - BYTE color_map[48]; // Colormap for 16-color images - BYTE reserved; - BYTE planes; // Number of planes (1, 3 or 4) - WORD bytes_per_line; // Bytes per row (always even) - WORD palette_info; // Palette information (1 = color or b&w; 2 = gray scale) - WORD h_screen_size; - WORD v_screen_size; - BYTE filler[54]; // Reserved filler -} PCXHEADER; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -// ========================================================== -// Internal functions -// ========================================================== - -static BOOL -pcx_validate(FreeImageIO *io, fi_handle handle) { - BYTE pcx_signature = 0x0A; - BYTE signature[4] = { 0, 0, 0, 0 }; - - if(io->read_proc(&signature, 1, 4, handle) != 4) { - return FALSE; - } - // magic number (0x0A = ZSoft Z) - if(signature[0] == pcx_signature) { - // version - if(signature[1] <= 5) { - // encoding - if((signature[2] == 0) || (signature[2] == 1)) { - // bits per pixel per plane - if((signature[3] == 1) || (signature[3] == 8)) { - return TRUE; - } - } - } - } - - return FALSE; -} - -static unsigned -readline(FreeImageIO &io, fi_handle handle, BYTE *buffer, unsigned length, BOOL rle, BYTE * ReadBuf, int * ReadPos) { - // -----------------------------------------------------------// - // Read either run-length encoded or normal image data // - // // - // THIS IS HOW RUNTIME LENGTH ENCODING WORKS IN PCX: // - // // - // 1) If the upper 2 bits of a byte are set, // - // the lower 6 bits specify the count for the next byte // - // // - // 2) If the upper 2 bits of the byte are clear, // - // the byte is actual data with a count of 1 // - // // - // Note that a scanline always has an even number of bytes // - // ------------------------------------------------------------- - - BYTE count = 0, value = 0; - unsigned written = 0; - - if (rle) { - // run-length encoded read - - while (length--) { - if (count == 0) { - if (*ReadPos >= IO_BUF_SIZE - 1 ) { - if (*ReadPos == IO_BUF_SIZE - 1) { - // we still have one BYTE, copy it to the start pos - - *ReadBuf = ReadBuf[IO_BUF_SIZE - 1]; - - io.read_proc(ReadBuf + 1, 1, IO_BUF_SIZE - 1, handle); - } else { - // read the complete buffer - - io.read_proc(ReadBuf, 1, IO_BUF_SIZE, handle); - } - - *ReadPos = 0; - } - - value = *(ReadBuf + (*ReadPos)++); - - if ((value & 0xC0) == 0xC0) { - count = value & 0x3F; - value = *(ReadBuf + (*ReadPos)++); - } else { - count = 1; - } - } - - count--; - - *(buffer + written++) = value; - } - - } else { - // normal read - - written = io.read_proc(buffer, length, 1, handle); - } - - return written; -} - -#ifdef FREEIMAGE_BIGENDIAN -static void -SwapHeader(PCXHEADER *header) { - SwapShort(&header->window[0]); - SwapShort(&header->window[1]); - SwapShort(&header->window[2]); - SwapShort(&header->window[3]); - SwapShort(&header->hdpi); - SwapShort(&header->vdpi); - SwapShort(&header->bytes_per_line); - SwapShort(&header->palette_info); - SwapShort(&header->h_screen_size); - SwapShort(&header->v_screen_size); -} -#endif - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -/*! - Returns the format string for the plugin. Each plugin, - both internal in the DLL and external in a .fip file, must have - a unique format string to be addressable. -*/ - -static const char * DLL_CALLCONV -Format() { - return "PCX"; -} - -/*! - Returns a description string for the plugin. Though a - description is not necessary per-se, - it is advised to return an unique string in order to tell the - user what type of bitmaps this plugin will read and/or write. -*/ - -static const char * DLL_CALLCONV -Description() { - return "Zsoft Paintbrush"; -} - -/*! - Returns a comma separated list of file - extensions indicating what files this plugin can open. The - list, being used by FreeImage_GetFIFFromFilename, is usually - used as a last resort in finding the type of the bitmap we - are dealing with. Best is to check the first few bytes on - the low-level bits level first and compare them with a known - signature . If this fails, FreeImage_GetFIFFromFilename can be - used. -*/ - -static const char * DLL_CALLCONV -Extension() { - return "pcx"; -} - -/*! - Returns an (optional) regular expression to help - software identifying a bitmap type. The - expression can be applied to the first few bytes (header) of - the bitmap. FreeImage is not capable of processing regular expression itself, - but FreeImageQt, the FreeImage Trolltech support library, can. If RegExpr - returns NULL, FreeImageQt will automatically bypass Trolltech's regular - expression support and use its internal functions to find the bitmap type. -*/ - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-pcx"; -} - -/*! - Validates a bitmap by reading the first few bytes - and comparing them with a known bitmap signature. - TRUE is returned if the bytes match the signature, FALSE otherwise. - The Validate function is used by using FreeImage_GetFileType. - - Note: a plugin can safely read data any data from the bitmap without seeking back - to the original entry point; the entry point is stored prior to calling this - function and restored after. - - Note: because of FreeImage's io redirection support, the header for the bitmap - must be on the start of the bitmap or at least on a known part in the bitmap. It is - forbidden to seek to the end of the bitmap or to a point relative to the end of a bitmap, - because the end of the bitmap is not always known. -*/ - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - return pcx_validate(io, handle); -} - -/*! - This function is used to 'ask' the plugin if it can write - a bitmap in a certain bitdepth. Different bitmap types have different - capabilities, for example not all formats allow writing in palettized mode. - This function is there provide an uniform interface to the plugin's - capabilities. SupportsExportDepth returns TRUE if the plugin support writing - in the asked bitdepth, or FALSE if it doesn't. The function also - returns FALSE if bitmap saving is not supported by the plugin at all. -*/ - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -/*! - Loads a bitmap into memory. On entry it is assumed that - the bitmap to be loaded is of the correct type. If the bitmap - is of an incorrect type, the plugin might not gracefully fail but - crash or enter an endless loop. It is also assumed that all - the bitmap data is available at one time. If the bitmap is not complete, - for example because it is being downloaded while loaded, the plugin - might also not gracefully fail. - - The Load function has the following parameters: - - The first parameter (FreeImageIO *io) is a structure providing - function pointers in order to make use of FreeImage's IO redirection. Using - FreeImage's file i/o functions instead of standard ones it is garantueed - that all bitmap types, both current and future ones, can be loaded from - memory, file cabinets, the internet and more. The second parameter (fi_handle handle) - is a companion of FreeImageIO and can be best compared with the standard FILE* type, - in a generalized form. - - The third parameter (int page) indicates wether we will be loading a certain page - in the bitmap or if we will load the default one. This parameter is only used if - the plugin supports multi-paged bitmaps, e.g. cabinet bitmaps that contain a series - of images or pages. If the plugin does support multi-paging, the page parameter - can contain either a number higher or equal to 0 to load a certain page, or -1 to - load the default page. If the plugin does not support multi-paging, - the page parameter is always -1. - - The fourth parameter (int flags) manipulates the load function to load a bitmap - in a certain way. Every plugin has a different flag parameter with different meanings. - - The last parameter (void *data) can contain a special data block used when - the file is read multi-paged. Because not every plugin supports multi-paging - not every plugin will use the data parameter and it will be set to NULL.However, - when the plugin does support multi-paging the parameter contains a pointer to a - block of data allocated by the Open function. -*/ - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - BYTE *bits; // Pointer to dib data - RGBQUAD *pal; // Pointer to dib palette - BYTE *line = NULL; // PCX raster line - BYTE *ReadBuf = NULL; // buffer; - BOOL bIsRLE; // True if the file is run-length encoded - - if(!handle) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - // check PCX identifier - - long start_pos = io->tell_proc(handle); - BOOL validated = pcx_validate(io, handle); - io->seek_proc(handle, start_pos, SEEK_SET); - if(!validated) { - throw FI_MSG_ERROR_MAGIC_NUMBER; - } - - // process the header - - PCXHEADER header; - - if(io->read_proc(&header, sizeof(PCXHEADER), 1, handle) != 1) { - throw FI_MSG_ERROR_PARSING; - } -#ifdef FREEIMAGE_BIGENDIAN - SwapHeader(&header); -#endif - - // allocate a new DIB - - unsigned width = header.window[2] - header.window[0] + 1; - unsigned height = header.window[3] - header.window[1] + 1; - unsigned bitcount = header.bpp * header.planes; - - if (bitcount == 24) { - dib = FreeImage_AllocateHeader(header_only, width, height, bitcount, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_AllocateHeader(header_only, width, height, bitcount); - } - - // if the dib couldn't be allocated, throw an error - - if (!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // metrics handling code - - FreeImage_SetDotsPerMeterX(dib, (unsigned) (((float)header.hdpi) / 0.0254000 + 0.5)); - FreeImage_SetDotsPerMeterY(dib, (unsigned) (((float)header.vdpi) / 0.0254000 + 0.5)); - - // Set up the palette if needed - // ---------------------------- - - switch(bitcount) { - case 1: - { - pal = FreeImage_GetPalette(dib); - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; - break; - } - - case 4: - { - pal = FreeImage_GetPalette(dib); - - BYTE *pColormap = &header.color_map[0]; - - for (int i = 0; i < 16; i++) { - pal[i].rgbRed = pColormap[0]; - pal[i].rgbGreen = pColormap[1]; - pal[i].rgbBlue = pColormap[2]; - pColormap += 3; - } - - break; - } - - case 8: - { - BYTE palette_id; - - io->seek_proc(handle, -769L, SEEK_END); - io->read_proc(&palette_id, 1, 1, handle); - - if (palette_id == 0x0C) { - BYTE *cmap = (BYTE*)malloc(768 * sizeof(BYTE)); - io->read_proc(cmap, 768, 1, handle); - - pal = FreeImage_GetPalette(dib); - BYTE *pColormap = &cmap[0]; - - for(int i = 0; i < 256; i++) { - pal[i].rgbRed = pColormap[0]; - pal[i].rgbGreen = pColormap[1]; - pal[i].rgbBlue = pColormap[2]; - pColormap += 3; - } - - free(cmap); - } - - // wrong palette ID, perhaps a gray scale is needed ? - - else if (header.palette_info == 2) { - pal = FreeImage_GetPalette(dib); - - for(int i = 0; i < 256; i++) { - pal[i].rgbRed = (BYTE)i; - pal[i].rgbGreen = (BYTE)i; - pal[i].rgbBlue = (BYTE)i; - } - } - - io->seek_proc(handle, (long)sizeof(PCXHEADER), SEEK_SET); - } - break; - } - - if(header_only) { - // header only mode - return dib; - } - - // calculate the line length for the PCX and the DIB - - // length of raster line in bytes - unsigned linelength = header.bytes_per_line * header.planes; - // length of DIB line (rounded to DWORD) in bytes - unsigned pitch = FreeImage_GetPitch(dib); - - // run-length encoding ? - - bIsRLE = (header.encoding == 1) ? TRUE : FALSE; - - // load image data - // --------------- - - line = (BYTE*)malloc(linelength * sizeof(BYTE)); - if(!line) throw FI_MSG_ERROR_MEMORY; - - ReadBuf = (BYTE*)malloc(IO_BUF_SIZE * sizeof(BYTE)); - if(!ReadBuf) throw FI_MSG_ERROR_MEMORY; - - bits = FreeImage_GetScanLine(dib, height - 1); - - int ReadPos = IO_BUF_SIZE; - - if ((header.planes == 1) && ((header.bpp == 1) || (header.bpp == 8))) { - BYTE skip; - unsigned written; - - for (unsigned y = 0; y < height; y++) { - written = readline(*io, handle, bits, linelength, bIsRLE, ReadBuf, &ReadPos); - - // skip trailing garbage at the end of the scanline - - for (unsigned count = written; count < linelength; count++) { - if (ReadPos < IO_BUF_SIZE) { - ReadPos++; - } else { - io->read_proc(&skip, sizeof(BYTE), 1, handle); - } - } - - bits -= pitch; - } - } else if ((header.planes == 4) && (header.bpp == 1)) { - BYTE bit, mask, skip; - unsigned index; - BYTE *buffer; - unsigned x, y, written; - - buffer = (BYTE*)malloc(width * sizeof(BYTE)); - if(!buffer) throw FI_MSG_ERROR_MEMORY; - - for (y = 0; y < height; y++) { - written = readline(*io, handle, line, linelength, bIsRLE, ReadBuf, &ReadPos); - - // build a nibble using the 4 planes - - memset(buffer, 0, width * sizeof(BYTE)); - - for(int plane = 0; plane < 4; plane++) { - bit = (BYTE)(1 << plane); - - for (x = 0; x < width; x++) { - index = (unsigned)((x / 8) + plane * header.bytes_per_line); - mask = (BYTE)(0x80 >> (x & 0x07)); - buffer[x] |= (line[index] & mask) ? bit : 0; - } - } - - // then write the DIB row - - for (x = 0; x < width / 2; x++) { - bits[x] = (buffer[2*x] << 4) | buffer[2*x+1]; - } - - // skip trailing garbage at the end of the scanline - - for (unsigned count = written; count < linelength; count++) { - if (ReadPos < IO_BUF_SIZE) { - ReadPos++; - } else { - io->read_proc(&skip, sizeof(BYTE), 1, handle); - } - } - - bits -= pitch; - } - - free(buffer); - - } else if((header.planes == 3) && (header.bpp == 8)) { - BYTE *pline; - - for (unsigned y = 0; y < height; y++) { - readline(*io, handle, line, linelength, bIsRLE, ReadBuf, &ReadPos); - - // convert the plane stream to BGR (RRRRGGGGBBBB -> BGRBGRBGRBGR) - // well, now with the FI_RGBA_x macros, on BIGENDIAN we convert to RGB - - pline = line; - unsigned x; - - for (x = 0; x < width; x++) { - bits[x * 3 + FI_RGBA_RED] = pline[x]; - } - pline += header.bytes_per_line; - - for (x = 0; x < width; x++) { - bits[x * 3 + FI_RGBA_GREEN] = pline[x]; - } - pline += header.bytes_per_line; - - for (x = 0; x < width; x++) { - bits[x * 3 + FI_RGBA_BLUE] = pline[x]; - } - pline += header.bytes_per_line; - - bits -= pitch; - } - } else { - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - - free(line); - free(ReadBuf); - - return dib; - - } catch (const char *text) { - // free allocated memory - - if (dib != NULL) { - FreeImage_Unload(dib); - } - if (line != NULL) { - free(line); - } - if (ReadBuf != NULL) { - free(ReadBuf); - } - - FreeImage_OutputMessageProc(s_format_id, text); - } - - return NULL; -} - -// ========================================================== -// Init -// ========================================================== - -/*! - Initialises the plugin. The first parameter (Plugin *plugin) - contains a pointer to a pre-allocated Plugin structure - wherein pointers to the available plugin functions - has to be stored. The second parameter (int format_id) is an identification - number that the plugin may use to show plugin specific warning messages - or other information to the user. The plugin number - is generated by FreeImage and can differ everytime the plugin is - initialised. - - If you want to create your own plugin you have to take some - rules into account. Plugin functions have to be compiled - __stdcall using the multithreaded c runtime libraries. Throwing - exceptions in plugin functions is allowed, as long as those exceptions - are being caught inside the same plugin. It is forbidden for a plugin - function to directly call FreeImage functions or to allocate memory - and pass it to the main DLL. Exception to this rule is the special file data - block that may be allocated the Open function. Allocating a FIBITMAP inside a - plugin can be using the function allocate_proc in the FreeImage structure, - which will allocate the memory using the DLL's c runtime library. -*/ - -void DLL_CALLCONV -InitPCX(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 = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - 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; -} |