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
35 typedef 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
51 static int s_format_id;
52
53 // ==========================================================
54 // Plugin Implementation
55 // ==========================================================
56
57 static const char * DLL_CALLCONV
Format()58 Format() {
59 return "CUT";
60 }
61
62 static const char * DLL_CALLCONV
Description()63 Description() {
64 return "Dr. Halo";
65 }
66
67 static const char * DLL_CALLCONV
Extension()68 Extension() {
69 return "cut";
70 }
71
72 static const char * DLL_CALLCONV
RegExpr()73 RegExpr() {
74 return NULL;
75 }
76
77 static const char * DLL_CALLCONV
MimeType()78 MimeType() {
79 return "image/x-cut";
80 }
81
82 static BOOL DLL_CALLCONV
Validate(FreeImageIO * io,fi_handle handle)83 Validate(FreeImageIO *io, fi_handle handle) {
84 return FALSE;
85 }
86
87 static BOOL DLL_CALLCONV
SupportsExportDepth(int depth)88 SupportsExportDepth(int depth) {
89 return FALSE;
90 }
91
92 static BOOL DLL_CALLCONV
SupportsExportType(FREE_IMAGE_TYPE type)93 SupportsExportType(FREE_IMAGE_TYPE type) {
94 return FALSE;
95 }
96
97 static BOOL DLL_CALLCONV
SupportsNoPixels()98 SupportsNoPixels() {
99 return TRUE;
100 }
101
102 // ----------------------------------------------------------
103
104 static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO * io,fi_handle handle,int page,int flags,void * data)105 Load(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
220 void DLL_CALLCONV
InitCUT(Plugin * plugin,int format_id)221 InitCUT(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 }
241