/src/FreeImage/Source/FreeImage/PluginCUT.cpp
C++ | 240 lines | 151 code | 50 blank | 39 comment | 28 complexity | cafb02db2dfdb001b0e775b93b2ac552 MD5 | raw file
1// ========================================================== 2// CUT Loader 3// 4// Design and implementation by 5// - Floris van den Berg (flvdberg@wxs.nl) 6// 7// This file is part of FreeImage 3 8// 9// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY 10// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES 11// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE 12// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED 13// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT 14// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY 15// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL 16// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER 17// THIS DISCLAIMER. 18// 19// Use at your own risk! 20// ========================================================== 21 22#include "FreeImage.h" 23#include "Utilities.h" 24 25// ---------------------------------------------------------- 26// Constants + headers 27// ---------------------------------------------------------- 28 29#ifdef _WIN32 30#pragma pack(push, 1) 31#else 32#pragma pack(1) 33#endif 34 35typedef struct tagCUTHEADER { 36 WORD width; 37 WORD height; 38 LONG dummy; 39} CUTHEADER; 40 41#ifdef _WIN32 42#pragma pack(pop) 43#else 44#pragma pack() 45#endif 46 47// ========================================================== 48// Plugin Interface 49// ========================================================== 50 51static int s_format_id; 52 53// ========================================================== 54// Plugin Implementation 55// ========================================================== 56 57static const char * DLL_CALLCONV 58Format() { 59 return "CUT"; 60} 61 62static const char * DLL_CALLCONV 63Description() { 64 return "Dr. Halo"; 65} 66 67static const char * DLL_CALLCONV 68Extension() { 69 return "cut"; 70} 71 72static const char * DLL_CALLCONV 73RegExpr() { 74 return NULL; 75} 76 77static const char * DLL_CALLCONV 78MimeType() { 79 return "image/x-cut"; 80} 81 82static BOOL DLL_CALLCONV 83Validate(FreeImageIO *io, fi_handle handle) { 84 return FALSE; 85} 86 87static BOOL DLL_CALLCONV 88SupportsExportDepth(int depth) { 89 return FALSE; 90} 91 92static BOOL DLL_CALLCONV 93SupportsExportType(FREE_IMAGE_TYPE type) { 94 return FALSE; 95} 96 97static BOOL DLL_CALLCONV 98SupportsNoPixels() { 99 return TRUE; 100} 101 102// ---------------------------------------------------------- 103 104static FIBITMAP * DLL_CALLCONV 105Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { 106 FIBITMAP *dib = NULL; 107 108 if(!handle) { 109 return NULL; 110 } 111 112 try { 113 CUTHEADER header; 114 115 BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; 116 117 // read the cut header 118 119 if(io->read_proc(&header, 1, sizeof(CUTHEADER), handle) != sizeof(CUTHEADER)) { 120 throw FI_MSG_ERROR_PARSING; 121 } 122 123#ifdef FREEIMAGE_BIGENDIAN 124 SwapShort((WORD *)&header.width); 125 SwapShort((WORD *)&header.height); 126#endif 127 128 if ((header.width == 0) || (header.height == 0)) { 129 return NULL; 130 } 131 132 // allocate a new bitmap 133 134 dib = FreeImage_AllocateHeader(header_only, header.width, header.height, 8); 135 136 if (dib == NULL) { 137 throw FI_MSG_ERROR_DIB_MEMORY; 138 } 139 140 // stuff it with a palette 141 142 RGBQUAD *palette = FreeImage_GetPalette(dib); 143 144 for (int j = 0; j < 256; ++j) { 145 palette[j].rgbBlue = palette[j].rgbGreen = palette[j].rgbRed = (BYTE)j; 146 } 147 148 if(header_only) { 149 // header only mode 150 return dib; 151 } 152 153 // unpack the RLE bitmap bits 154 155 BYTE *bits = FreeImage_GetScanLine(dib, header.height - 1); 156 157 unsigned i = 0, k = 0; 158 unsigned pitch = FreeImage_GetPitch(dib); 159 unsigned size = header.width * header.height; 160 BYTE count = 0, run = 0; 161 162 while (i < size) { 163 if(io->read_proc(&count, 1, sizeof(BYTE), handle) != 1) { 164 throw FI_MSG_ERROR_PARSING; 165 } 166 167 if (count == 0) { 168 k = 0; 169 bits -= pitch; 170 171 // paint shop pro adds two useless bytes here... 172 173 io->read_proc(&count, 1, sizeof(BYTE), handle); 174 io->read_proc(&count, 1, sizeof(BYTE), handle); 175 176 continue; 177 } 178 179 if (count & 0x80) { 180 count &= ~(0x80); 181 182 if(io->read_proc(&run, 1, sizeof(BYTE), handle) != 1) { 183 throw FI_MSG_ERROR_PARSING; 184 } 185 186 if(k + count <= header.width) { 187 memset(bits + k, run, count); 188 } else { 189 throw FI_MSG_ERROR_PARSING; 190 } 191 } else { 192 if(k + count <= header.width) { 193 if(io->read_proc(&bits[k], count, sizeof(BYTE), handle) != 1) { 194 throw FI_MSG_ERROR_PARSING; 195 } 196 } else { 197 throw FI_MSG_ERROR_PARSING; 198 } 199 } 200 201 k += count; 202 i += count; 203 } 204 205 return dib; 206 207 } catch(const char* text) { 208 if(dib) { 209 FreeImage_Unload(dib); 210 } 211 FreeImage_OutputMessageProc(s_format_id, text); 212 return NULL; 213 } 214} 215 216// ========================================================== 217// Init 218// ========================================================== 219 220void DLL_CALLCONV 221InitCUT(Plugin *plugin, int format_id) { 222 s_format_id = format_id; 223 224 plugin->format_proc = Format; 225 plugin->description_proc = Description; 226 plugin->extension_proc = Extension; 227 plugin->regexpr_proc = RegExpr; 228 plugin->open_proc = NULL; 229 plugin->close_proc = NULL; 230 plugin->pagecount_proc = NULL; 231 plugin->pagecapability_proc = NULL; 232 plugin->load_proc = Load; 233 plugin->save_proc = NULL; 234 plugin->validate_proc = Validate; 235 plugin->mime_proc = MimeType; 236 plugin->supports_export_bpp_proc = SupportsExportDepth; 237 plugin->supports_export_type_proc = SupportsExportType; 238 plugin->supports_icc_profiles_proc = NULL; 239 plugin->supports_no_pixels_proc = SupportsNoPixels; 240}