/src/freeimage-svn/FreeImage/trunk/Source/FreeImage/PluginCUT.cpp
Line | Count | Source (jump to first uncovered line) |
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 |
58 | 2 | Format() { |
59 | 2 | return "CUT"; |
60 | 2 | } |
61 | | |
62 | | static const char * DLL_CALLCONV |
63 | 0 | Description() { |
64 | 0 | return "Dr. Halo"; |
65 | 0 | } |
66 | | |
67 | | static const char * DLL_CALLCONV |
68 | 0 | Extension() { |
69 | 0 | return "cut"; |
70 | 0 | } |
71 | | |
72 | | static const char * DLL_CALLCONV |
73 | 0 | RegExpr() { |
74 | 0 | return NULL; |
75 | 0 | } |
76 | | |
77 | | static const char * DLL_CALLCONV |
78 | 0 | MimeType() { |
79 | 0 | return "image/x-cut"; |
80 | 0 | } |
81 | | |
82 | | static BOOL DLL_CALLCONV |
83 | 23.9k | Validate(FreeImageIO *io, fi_handle handle) { |
84 | 23.9k | return FALSE; |
85 | 23.9k | } |
86 | | |
87 | | static BOOL DLL_CALLCONV |
88 | 0 | SupportsExportDepth(int depth) { |
89 | 0 | return FALSE; |
90 | 0 | } |
91 | | |
92 | | static BOOL DLL_CALLCONV |
93 | 0 | SupportsExportType(FREE_IMAGE_TYPE type) { |
94 | 0 | return FALSE; |
95 | 0 | } |
96 | | |
97 | | static BOOL DLL_CALLCONV |
98 | 0 | SupportsNoPixels() { |
99 | 0 | return TRUE; |
100 | 0 | } |
101 | | |
102 | | // ---------------------------------------------------------- |
103 | | |
104 | | static FIBITMAP * DLL_CALLCONV |
105 | 0 | Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { |
106 | 0 | FIBITMAP *dib = NULL; |
107 | |
|
108 | 0 | if(!handle) { |
109 | 0 | return NULL; |
110 | 0 | } |
111 | | |
112 | 0 | try { |
113 | 0 | CUTHEADER header; |
114 | |
|
115 | 0 | BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; |
116 | | |
117 | | // read the cut header |
118 | |
|
119 | 0 | if(io->read_proc(&header, 1, sizeof(CUTHEADER), handle) != sizeof(CUTHEADER)) { |
120 | 0 | throw FI_MSG_ERROR_PARSING; |
121 | 0 | } |
122 | | |
123 | | #ifdef FREEIMAGE_BIGENDIAN |
124 | | SwapShort((WORD *)&header.width); |
125 | | SwapShort((WORD *)&header.height); |
126 | | #endif |
127 | | |
128 | 0 | if ((header.width == 0) || (header.height == 0)) { |
129 | 0 | return NULL; |
130 | 0 | } |
131 | | |
132 | | // allocate a new bitmap |
133 | | |
134 | 0 | dib = FreeImage_AllocateHeader(header_only, header.width, header.height, 8); |
135 | |
|
136 | 0 | if (dib == NULL) { |
137 | 0 | throw FI_MSG_ERROR_DIB_MEMORY; |
138 | 0 | } |
139 | | |
140 | | // stuff it with a palette |
141 | | |
142 | 0 | RGBQUAD *palette = FreeImage_GetPalette(dib); |
143 | |
|
144 | 0 | for (int j = 0; j < 256; ++j) { |
145 | 0 | palette[j].rgbBlue = palette[j].rgbGreen = palette[j].rgbRed = (BYTE)j; |
146 | 0 | } |
147 | | |
148 | 0 | if(header_only) { |
149 | | // header only mode |
150 | 0 | return dib; |
151 | 0 | } |
152 | | |
153 | | // unpack the RLE bitmap bits |
154 | | |
155 | 0 | BYTE *bits = FreeImage_GetScanLine(dib, header.height - 1); |
156 | |
|
157 | 0 | unsigned i = 0, k = 0; |
158 | 0 | unsigned pitch = FreeImage_GetPitch(dib); |
159 | 0 | unsigned size = header.width * header.height; |
160 | 0 | BYTE count = 0, run = 0; |
161 | |
|
162 | 0 | while (i < size) { |
163 | 0 | if(io->read_proc(&count, 1, sizeof(BYTE), handle) != 1) { |
164 | 0 | throw FI_MSG_ERROR_PARSING; |
165 | 0 | } |
166 | | |
167 | 0 | if (count == 0) { |
168 | 0 | k = 0; |
169 | 0 | bits -= pitch; |
170 | | |
171 | | // paint shop pro adds two useless bytes here... |
172 | |
|
173 | 0 | io->read_proc(&count, 1, sizeof(BYTE), handle); |
174 | 0 | io->read_proc(&count, 1, sizeof(BYTE), handle); |
175 | |
|
176 | 0 | continue; |
177 | 0 | } |
178 | | |
179 | 0 | if (count & 0x80) { |
180 | 0 | count &= ~(0x80); |
181 | |
|
182 | 0 | if(io->read_proc(&run, 1, sizeof(BYTE), handle) != 1) { |
183 | 0 | throw FI_MSG_ERROR_PARSING; |
184 | 0 | } |
185 | | |
186 | 0 | if(k + count <= header.width) { |
187 | 0 | memset(bits + k, run, count); |
188 | 0 | } else { |
189 | 0 | throw FI_MSG_ERROR_PARSING; |
190 | 0 | } |
191 | 0 | } else { |
192 | 0 | if(k + count <= header.width) { |
193 | 0 | if(io->read_proc(&bits[k], count, sizeof(BYTE), handle) != 1) { |
194 | 0 | throw FI_MSG_ERROR_PARSING; |
195 | 0 | } |
196 | 0 | } else { |
197 | 0 | throw FI_MSG_ERROR_PARSING; |
198 | 0 | } |
199 | 0 | } |
200 | | |
201 | 0 | k += count; |
202 | 0 | i += count; |
203 | 0 | } |
204 | | |
205 | 0 | return dib; |
206 | |
|
207 | 0 | } catch(const char* text) { |
208 | 0 | if(dib) { |
209 | 0 | FreeImage_Unload(dib); |
210 | 0 | } |
211 | 0 | FreeImage_OutputMessageProc(s_format_id, text); |
212 | 0 | return NULL; |
213 | 0 | } |
214 | 0 | } |
215 | | |
216 | | // ========================================================== |
217 | | // Init |
218 | | // ========================================================== |
219 | | |
220 | | void DLL_CALLCONV |
221 | 2 | InitCUT(Plugin *plugin, int format_id) { |
222 | 2 | s_format_id = format_id; |
223 | | |
224 | 2 | plugin->format_proc = Format; |
225 | 2 | plugin->description_proc = Description; |
226 | 2 | plugin->extension_proc = Extension; |
227 | 2 | plugin->regexpr_proc = RegExpr; |
228 | 2 | plugin->open_proc = NULL; |
229 | 2 | plugin->close_proc = NULL; |
230 | 2 | plugin->pagecount_proc = NULL; |
231 | 2 | plugin->pagecapability_proc = NULL; |
232 | 2 | plugin->load_proc = Load; |
233 | 2 | plugin->save_proc = NULL; |
234 | 2 | plugin->validate_proc = Validate; |
235 | 2 | plugin->mime_proc = MimeType; |
236 | 2 | plugin->supports_export_bpp_proc = SupportsExportDepth; |
237 | 2 | plugin->supports_export_type_proc = SupportsExportType; |
238 | 2 | plugin->supports_icc_profiles_proc = NULL; |
239 | 2 | plugin->supports_no_pixels_proc = SupportsNoPixels; |
240 | 2 | } |