/src/imagemagick/coders/cut.c
Line | Count | Source |
1 | | /* |
2 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
3 | | % % |
4 | | % % |
5 | | % CCC U U TTTTT % |
6 | | % C U U T % |
7 | | % C U U T % |
8 | | % C U U T % |
9 | | % CCC UUU T % |
10 | | % % |
11 | | % % |
12 | | % Read DR Halo Image Format % |
13 | | % % |
14 | | % Software Design % |
15 | | % Jaroslav Fojtik % |
16 | | % June 2000 % |
17 | | % % |
18 | | % % |
19 | | % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization % |
20 | | % dedicated to making software imaging solutions freely available. % |
21 | | % % |
22 | | % You may not use this file except in compliance with the License. You may % |
23 | | % obtain a copy of the License at % |
24 | | % % |
25 | | % https://imagemagick.org/license/ % |
26 | | % % |
27 | | % Unless required by applicable law or agreed to in writing, software % |
28 | | % distributed under the License is distributed on an "AS IS" BASIS, % |
29 | | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
30 | | % See the License for the specific language governing permissions and % |
31 | | % limitations under the License. % |
32 | | % % |
33 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
34 | | % |
35 | | % |
36 | | */ |
37 | | |
38 | | /* |
39 | | Include declarations. |
40 | | */ |
41 | | #include "MagickCore/studio.h" |
42 | | #include "MagickCore/attribute.h" |
43 | | #include "MagickCore/blob.h" |
44 | | #include "MagickCore/blob-private.h" |
45 | | #include "MagickCore/cache.h" |
46 | | #include "MagickCore/color.h" |
47 | | #include "MagickCore/color-private.h" |
48 | | #include "MagickCore/colormap.h" |
49 | | #include "MagickCore/colormap-private.h" |
50 | | #include "MagickCore/colorspace-private.h" |
51 | | #include "MagickCore/exception.h" |
52 | | #include "MagickCore/exception-private.h" |
53 | | #include "MagickCore/image.h" |
54 | | #include "MagickCore/image-private.h" |
55 | | #include "MagickCore/list.h" |
56 | | #include "MagickCore/magick.h" |
57 | | #include "MagickCore/memory_.h" |
58 | | #include "MagickCore/pixel-accessor.h" |
59 | | #include "MagickCore/policy.h" |
60 | | #include "MagickCore/policy-private.h" |
61 | | #include "MagickCore/quantum-private.h" |
62 | | #include "MagickCore/static.h" |
63 | | #include "MagickCore/string_.h" |
64 | | #include "MagickCore/module.h" |
65 | | #include "MagickCore/utility.h" |
66 | | #include "MagickCore/utility-private.h" |
67 | | #include "coders/coders-private.h" |
68 | | |
69 | | typedef struct |
70 | | { |
71 | | unsigned Width; |
72 | | unsigned Height; |
73 | | unsigned Reserved; |
74 | | } CUTHeader; |
75 | | |
76 | | typedef struct |
77 | | { |
78 | | char FileId[2]; |
79 | | unsigned Version; |
80 | | unsigned Size; |
81 | | char FileType; |
82 | | char SubType; |
83 | | unsigned BoardID; |
84 | | unsigned GraphicsMode; |
85 | | unsigned MaxIndex; |
86 | | unsigned MaxRed; |
87 | | unsigned MaxGreen; |
88 | | unsigned MaxBlue; |
89 | | char PaletteId[20]; |
90 | | } CUTPalHeader; |
91 | | |
92 | | |
93 | | static MagickBooleanType InsertRow(Image *image,ssize_t bpp,unsigned char *p, |
94 | | ssize_t y,ExceptionInfo *exception) |
95 | 45.0k | { |
96 | 45.0k | int |
97 | 45.0k | bit; |
98 | | |
99 | 45.0k | Quantum |
100 | 45.0k | index; |
101 | | |
102 | 45.0k | Quantum |
103 | 45.0k | *q; |
104 | | |
105 | 45.0k | ssize_t |
106 | 45.0k | x; |
107 | | |
108 | 45.0k | q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); |
109 | 45.0k | if (q == (Quantum *) NULL) |
110 | 0 | return(MagickFalse); |
111 | 45.0k | switch (bpp) |
112 | 45.0k | { |
113 | 16.3k | case 1: /* Convert bitmap scanline. */ |
114 | 16.3k | { |
115 | 3.00M | for (x=0; x < ((ssize_t) image->columns-7); x+=8) |
116 | 2.98M | { |
117 | 26.8M | for (bit=0; bit < 8; bit++) |
118 | 23.8M | { |
119 | 23.8M | index=(Quantum) ((*p) & (0x80 >> bit) ? 0x01 : 0x00); |
120 | 23.8M | SetPixelIndex(image,index,q); |
121 | 23.8M | if (index < image->colors) |
122 | 23.8M | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
123 | 23.8M | q+=(ptrdiff_t) GetPixelChannels(image); |
124 | 23.8M | } |
125 | 2.98M | p++; |
126 | 2.98M | } |
127 | 16.3k | if ((image->columns % 8) != 0) |
128 | 0 | { |
129 | 0 | for (bit=0; bit < (ssize_t) (image->columns % 8); bit++) |
130 | 0 | { |
131 | 0 | index=(Quantum) ((*p) & (0x80 >> bit) ? 0x01 : 0x00); |
132 | 0 | SetPixelIndex(image,index,q); |
133 | 0 | if (index < image->colors) |
134 | 0 | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
135 | 0 | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
136 | 0 | q+=(ptrdiff_t) GetPixelChannels(image); |
137 | 0 | } |
138 | 0 | p++; |
139 | 0 | } |
140 | 16.3k | break; |
141 | 0 | } |
142 | 0 | case 2: /* Convert PseudoColor scanline. */ |
143 | 0 | { |
144 | 0 | for (x=0; x < ((ssize_t) image->columns-3); x+=4) |
145 | 0 | { |
146 | 0 | index=(Quantum) ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception); |
147 | 0 | SetPixelIndex(image,index,q); |
148 | 0 | if (index < image->colors) |
149 | 0 | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
150 | 0 | q+=(ptrdiff_t) GetPixelChannels(image); |
151 | 0 | index=(Quantum) ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception); |
152 | 0 | SetPixelIndex(image,index,q); |
153 | 0 | if (index < image->colors) |
154 | 0 | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
155 | 0 | q+=(ptrdiff_t) GetPixelChannels(image); |
156 | 0 | index=(Quantum) ConstrainColormapIndex(image,(*p >> 2) & 0x3,exception); |
157 | 0 | SetPixelIndex(image,index,q); |
158 | 0 | if (index < image->colors) |
159 | 0 | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
160 | 0 | q+=(ptrdiff_t) GetPixelChannels(image); |
161 | 0 | index=(Quantum) ConstrainColormapIndex(image,(*p) & 0x3,exception); |
162 | 0 | SetPixelIndex(image,index,q); |
163 | 0 | if (index < image->colors) |
164 | 0 | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
165 | 0 | q+=(ptrdiff_t) GetPixelChannels(image); |
166 | 0 | p++; |
167 | 0 | } |
168 | 0 | if ((image->columns % 4) != 0) |
169 | 0 | { |
170 | 0 | index=(Quantum) ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception); |
171 | 0 | SetPixelIndex(image,index,q); |
172 | 0 | if (index < image->colors) |
173 | 0 | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
174 | 0 | q+=(ptrdiff_t) GetPixelChannels(image); |
175 | 0 | if ((image->columns % 4) > 1) |
176 | 0 | { |
177 | 0 | index=(Quantum) ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception); |
178 | 0 | SetPixelIndex(image,index,q); |
179 | 0 | if (index < image->colors) |
180 | 0 | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
181 | 0 | q+=(ptrdiff_t) GetPixelChannels(image); |
182 | 0 | if ((image->columns % 4) > 2) |
183 | 0 | { |
184 | 0 | index=(Quantum) ConstrainColormapIndex(image,(*p >> 2) & 0x3, |
185 | 0 | exception); |
186 | 0 | SetPixelIndex(image,index,q); |
187 | 0 | if (index < image->colors) |
188 | 0 | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) |
189 | 0 | index,q); |
190 | 0 | q+=(ptrdiff_t) GetPixelChannels(image); |
191 | 0 | } |
192 | 0 | } |
193 | 0 | p++; |
194 | 0 | } |
195 | 0 | break; |
196 | 0 | } |
197 | | |
198 | 10.7k | case 4: /* Convert PseudoColor scanline. */ |
199 | 10.7k | { |
200 | 6.50M | for (x=0; x < ((ssize_t) image->columns-1); x+=2) |
201 | 6.49M | { |
202 | 6.49M | index=(Quantum) ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception); |
203 | 6.49M | SetPixelIndex(image,index,q); |
204 | 6.49M | if (index < image->colors) |
205 | 6.49M | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
206 | 6.49M | q+=(ptrdiff_t) GetPixelChannels(image); |
207 | 6.49M | index=(Quantum) ConstrainColormapIndex(image,(*p) & 0x0f,exception); |
208 | 6.49M | SetPixelIndex(image,index,q); |
209 | 6.49M | if (index < image->colors) |
210 | 6.49M | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
211 | 6.49M | p++; |
212 | 6.49M | q+=(ptrdiff_t) GetPixelChannels(image); |
213 | 6.49M | } |
214 | 10.7k | if ((image->columns % 2) != 0) |
215 | 0 | { |
216 | 0 | index=(Quantum) ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception); |
217 | 0 | SetPixelIndex(image,index,q); |
218 | 0 | if (index < image->colors) |
219 | 0 | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
220 | 0 | p++; |
221 | 0 | q+=(ptrdiff_t) GetPixelChannels(image); |
222 | 0 | } |
223 | 10.7k | break; |
224 | 0 | } |
225 | 17.9k | case 8: /* Convert PseudoColor scanline. */ |
226 | 17.9k | { |
227 | 2.15M | for (x=0; x < (ssize_t) image->columns; x++) |
228 | 2.13M | { |
229 | 2.13M | index=(Quantum) ConstrainColormapIndex(image,*p,exception); |
230 | 2.13M | SetPixelIndex(image,index,q); |
231 | 2.13M | if (index < image->colors) |
232 | 2.13M | SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); |
233 | 2.13M | p++; |
234 | 2.13M | q+=(ptrdiff_t) GetPixelChannels(image); |
235 | 2.13M | } |
236 | 17.9k | } |
237 | 17.9k | break; |
238 | | |
239 | 0 | case 24: /* Convert DirectColor scanline. */ |
240 | 0 | for (x=0; x < (ssize_t) image->columns; x++) |
241 | 0 | { |
242 | 0 | SetPixelRed(image,ScaleCharToQuantum(*p++),q); |
243 | 0 | SetPixelGreen(image,ScaleCharToQuantum(*p++),q); |
244 | 0 | SetPixelBlue(image,ScaleCharToQuantum(*p++),q); |
245 | 0 | q+=(ptrdiff_t) GetPixelChannels(image); |
246 | 0 | } |
247 | 0 | break; |
248 | 45.0k | } |
249 | 45.0k | if (!SyncAuthenticPixels(image,exception)) |
250 | 0 | return(MagickFalse); |
251 | 45.0k | return(MagickTrue); |
252 | 45.0k | } |
253 | | |
254 | | /* |
255 | | Compute the number of colors in Grayed R[i]=G[i]=B[i] image |
256 | | */ |
257 | | static int GetCutColors(Image *image,ExceptionInfo *exception) |
258 | 172 | { |
259 | 172 | Quantum |
260 | 172 | intensity, |
261 | 172 | scale_intensity; |
262 | | |
263 | 172 | Quantum |
264 | 172 | *q; |
265 | | |
266 | 172 | ssize_t |
267 | 172 | x, |
268 | 172 | y; |
269 | | |
270 | 172 | intensity=0; |
271 | 172 | scale_intensity=ScaleCharToQuantum(16); |
272 | 17.6k | for (y=0; y < (ssize_t) image->rows; y++) |
273 | 17.5k | { |
274 | 17.5k | q=GetAuthenticPixels(image,0,y,image->columns,1,exception); |
275 | 17.5k | if (q == (Quantum *) NULL) |
276 | 0 | break; |
277 | 20.3M | for (x=0; x < (ssize_t) image->columns; x++) |
278 | 20.3M | { |
279 | 20.3M | if (intensity < GetPixelRed(image,q)) |
280 | 210 | intensity=GetPixelRed(image,q); |
281 | 20.3M | if (intensity >= scale_intensity) |
282 | 38 | return(255); |
283 | 20.3M | q+=(ptrdiff_t) GetPixelChannels(image); |
284 | 20.3M | } |
285 | 17.5k | } |
286 | 134 | if (intensity < ScaleCharToQuantum(2)) |
287 | 92 | return(2); |
288 | 42 | if (intensity < ScaleCharToQuantum(16)) |
289 | 42 | return(16); |
290 | 0 | return((int) intensity); |
291 | 42 | } |
292 | | |
293 | | /* |
294 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
295 | | % % |
296 | | % % |
297 | | % % |
298 | | % R e a d C U T I m a g e % |
299 | | % % |
300 | | % % |
301 | | % % |
302 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
303 | | % |
304 | | % ReadCUTImage() reads an CUT X image file and returns it. It |
305 | | % allocates the memory necessary for the new Image structure and returns a |
306 | | % pointer to the new image. |
307 | | % |
308 | | % The format of the ReadCUTImage method is: |
309 | | % |
310 | | % Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) |
311 | | % |
312 | | % A description of each parameter follows: |
313 | | % |
314 | | % o image_info: the image info. |
315 | | % |
316 | | % o exception: return any errors or warnings in this structure. |
317 | | % |
318 | | */ |
319 | | static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) |
320 | 641 | { |
321 | 641 | #define ThrowCUTReaderException(severity,tag) \ |
322 | 199 | { \ |
323 | 199 | if (palette != NULL) \ |
324 | 199 | palette=DestroyImage(palette); \ |
325 | 199 | if (clone_info != NULL) \ |
326 | 199 | clone_info=DestroyImageInfo(clone_info); \ |
327 | 199 | ThrowReaderException(severity,tag); \ |
328 | 0 | } |
329 | | |
330 | 641 | Image *image,*palette; |
331 | 641 | ImageInfo *clone_info; |
332 | 641 | MagickBooleanType status; |
333 | 641 | MagickBooleanType authorized; |
334 | | |
335 | 641 | MagickOffsetType |
336 | 641 | offset; |
337 | | |
338 | 641 | size_t EncodedByte; |
339 | 641 | unsigned char RunCount,RunValue,RunCountMasked; |
340 | 641 | CUTHeader Header; |
341 | 641 | CUTPalHeader PalHeader; |
342 | 641 | ssize_t depth; |
343 | 641 | ssize_t i,j; |
344 | 641 | ssize_t ldblk; |
345 | 641 | unsigned char *BImgBuff=NULL,*ptrB; |
346 | 641 | Quantum *q; |
347 | | |
348 | | /* |
349 | | Open image file. |
350 | | */ |
351 | 641 | assert(image_info != (const ImageInfo *) NULL); |
352 | 641 | assert(image_info->signature == MagickCoreSignature); |
353 | 641 | assert(exception != (ExceptionInfo *) NULL); |
354 | 641 | assert(exception->signature == MagickCoreSignature); |
355 | 641 | if (IsEventLogging() != MagickFalse) |
356 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", |
357 | 0 | image_info->filename); |
358 | 641 | image=AcquireImage(image_info,exception); |
359 | 641 | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
360 | 641 | if (status == MagickFalse) |
361 | 0 | { |
362 | 0 | image=DestroyImageList(image); |
363 | 0 | return((Image *) NULL); |
364 | 0 | } |
365 | | /* |
366 | | Read CUT image. |
367 | | */ |
368 | 641 | palette=NULL; |
369 | 641 | clone_info=NULL; |
370 | 641 | Header.Width=ReadBlobLSBShort(image); |
371 | 641 | Header.Height=ReadBlobLSBShort(image); |
372 | 641 | Header.Reserved=ReadBlobLSBShort(image); |
373 | | |
374 | 641 | if (Header.Width==0 || Header.Height==0 || Header.Reserved!=0) |
375 | 600 | CUT_KO: ThrowCUTReaderException(CorruptImageError,"ImproperImageHeader"); |
376 | | |
377 | | /*---This code checks first line of image---*/ |
378 | 600 | EncodedByte=ReadBlobLSBShort(image); |
379 | 600 | RunCount=(unsigned char) ReadBlobByte(image); |
380 | 600 | RunCountMasked=RunCount & 0x7F; |
381 | 600 | ldblk=0; |
382 | 24.3k | while((int) RunCountMasked!=0) /*end of line?*/ |
383 | 23.7k | { |
384 | 23.7k | i=1; |
385 | 23.7k | if((int) RunCount<0x80) i=(ssize_t) RunCountMasked; |
386 | 23.7k | offset=SeekBlob(image,TellBlob(image)+i,SEEK_SET); |
387 | 23.7k | if (offset < 0) |
388 | 23.7k | ThrowCUTReaderException(CorruptImageError,"ImproperImageHeader"); |
389 | 23.7k | if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data*/ |
390 | 23.7k | EncodedByte-=(size_t)(i+1); |
391 | 23.7k | ldblk+=(ssize_t) RunCountMasked; |
392 | | |
393 | 23.7k | RunCount=(unsigned char) ReadBlobByte(image); |
394 | 23.7k | if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data: unexpected eof in line*/ |
395 | 23.7k | RunCountMasked=RunCount & 0x7F; |
396 | 23.7k | } |
397 | 521 | if(EncodedByte!=1) goto CUT_KO; /*wrong data: size incorrect*/ |
398 | 481 | i=0; /*guess a number of bit planes*/ |
399 | 481 | if(ldblk==(int) Header.Width) i=8; |
400 | 481 | if(2*ldblk==(int) Header.Width) i=4; |
401 | 481 | if(8*ldblk==(int) Header.Width) i=1; |
402 | 481 | if(i==0) goto CUT_KO; /*wrong data: incorrect bit planes*/ |
403 | 442 | depth=i; |
404 | | |
405 | 442 | image->columns=Header.Width; |
406 | 442 | image->rows=Header.Height; |
407 | 442 | image->depth=8; |
408 | 442 | image->colors=(size_t) (GetQuantumRange((size_t) i)+1); |
409 | | |
410 | 442 | if (image_info->ping != MagickFalse) goto Finish; |
411 | 442 | status=SetImageExtent(image,image->columns,image->rows,exception); |
412 | 442 | if (status == MagickFalse) |
413 | 39 | return(DestroyImageList(image)); |
414 | | |
415 | | /* ----- Do something with palette ----- */ |
416 | 403 | if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette; |
417 | | |
418 | | |
419 | 403 | i=(ssize_t) strlen(clone_info->filename); |
420 | 403 | j=i; |
421 | 538 | while(--i>0) |
422 | 538 | { |
423 | 538 | if(clone_info->filename[i]=='.') |
424 | 45 | { |
425 | 45 | break; |
426 | 45 | } |
427 | 493 | if(clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' || |
428 | 493 | clone_info->filename[i]==':' ) |
429 | 358 | { |
430 | 358 | i=j; |
431 | 358 | break; |
432 | 358 | } |
433 | 493 | } |
434 | | |
435 | 403 | authorized=IsPathAuthorized(ReadPolicyRights,clone_info->filename); |
436 | 403 | if (authorized == MagickFalse) |
437 | 403 | ThrowCUTReaderException(PolicyError,"NotAuthorized"); |
438 | 403 | (void) CopyMagickString(clone_info->filename+i,".PAL",(size_t) |
439 | 403 | (MagickPathExtent-i)); |
440 | 403 | if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) |
441 | 403 | { |
442 | 403 | (void) CopyMagickString(clone_info->filename+i,".pal",(size_t) |
443 | 403 | (MagickPathExtent-i)); |
444 | 403 | if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) |
445 | 403 | { |
446 | 403 | authorized=IsPathAuthorized(ReadPolicyRights,clone_info->filename); |
447 | 403 | if (authorized == MagickFalse) |
448 | 403 | ThrowCUTReaderException(PolicyError,"NotAuthorized"); |
449 | 403 | clone_info->filename[i]='\0'; |
450 | 403 | authorized=IsPathAuthorized(ReadPolicyRights,clone_info->filename); |
451 | 403 | if (authorized == MagickFalse) |
452 | 403 | ThrowCUTReaderException(PolicyError,"NotAuthorized"); |
453 | 403 | if ((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) |
454 | 403 | { |
455 | 403 | clone_info=DestroyImageInfo(clone_info); |
456 | 403 | clone_info=NULL; |
457 | 403 | goto NoPalette; |
458 | 403 | } |
459 | 403 | } |
460 | 403 | } |
461 | | |
462 | 0 | if( (palette=AcquireImage(clone_info,exception))==NULL ) goto NoPalette; |
463 | 0 | status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception); |
464 | 0 | if (status == MagickFalse) |
465 | 0 | { |
466 | 0 | ErasePalette: |
467 | 0 | palette=DestroyImage(palette); |
468 | 0 | palette=NULL; |
469 | 0 | goto NoPalette; |
470 | 0 | } |
471 | | |
472 | | |
473 | 0 | if(palette!=NULL) |
474 | 0 | { |
475 | 0 | (void) ReadBlob(palette,2,(unsigned char *) PalHeader.FileId); |
476 | 0 | if(strncmp(PalHeader.FileId,"AH",2) != 0) goto ErasePalette; |
477 | 0 | PalHeader.Version=ReadBlobLSBShort(palette); |
478 | 0 | PalHeader.Size=ReadBlobLSBShort(palette); |
479 | 0 | PalHeader.FileType=(char) ReadBlobByte(palette); |
480 | 0 | PalHeader.SubType=(char) ReadBlobByte(palette); |
481 | 0 | PalHeader.BoardID=ReadBlobLSBShort(palette); |
482 | 0 | PalHeader.GraphicsMode=ReadBlobLSBShort(palette); |
483 | 0 | PalHeader.MaxIndex=ReadBlobLSBShort(palette); |
484 | 0 | PalHeader.MaxRed=ReadBlobLSBShort(palette); |
485 | 0 | PalHeader.MaxGreen=ReadBlobLSBShort(palette); |
486 | 0 | PalHeader.MaxBlue=ReadBlobLSBShort(palette); |
487 | 0 | (void) ReadBlob(palette,20,(unsigned char *) PalHeader.PaletteId); |
488 | 0 | if (EOFBlob(image)) |
489 | 0 | ThrowCUTReaderException(CorruptImageError,"UnexpectedEndOfFile"); |
490 | |
|
491 | 0 | if(PalHeader.MaxIndex<1) goto ErasePalette; |
492 | 0 | image->colors=PalHeader.MaxIndex+1; |
493 | 0 | if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) goto NoMemory; |
494 | | |
495 | 0 | if(PalHeader.MaxRed==0) PalHeader.MaxRed=(unsigned int) QuantumRange; /*avoid division by 0*/ |
496 | 0 | if(PalHeader.MaxGreen==0) PalHeader.MaxGreen=(unsigned int) QuantumRange; |
497 | 0 | if(PalHeader.MaxBlue==0) PalHeader.MaxBlue=(unsigned int) QuantumRange; |
498 | |
|
499 | 0 | for(i=0;i<=(int) PalHeader.MaxIndex;i++) |
500 | 0 | { /*this may be wrong- I don't know why is palette such strange*/ |
501 | 0 | j=(ssize_t) TellBlob(palette); |
502 | 0 | if((j % 512)>512-6) |
503 | 0 | { |
504 | 0 | j=((j / 512)+1)*512; |
505 | 0 | offset=SeekBlob(palette,j,SEEK_SET); |
506 | 0 | if (offset < 0) |
507 | 0 | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
508 | 0 | } |
509 | 0 | image->colormap[i].red=(Quantum) ReadBlobLSBShort(palette); |
510 | 0 | if (QuantumRange != (Quantum) PalHeader.MaxRed) |
511 | 0 | { |
512 | 0 | image->colormap[i].red=ClampToQuantum((image->colormap[i].red* |
513 | 0 | (double) QuantumRange+(PalHeader.MaxRed >> 1))/ |
514 | 0 | PalHeader.MaxRed); |
515 | 0 | } |
516 | 0 | image->colormap[i].green=(Quantum) ReadBlobLSBShort(palette); |
517 | 0 | if (QuantumRange != (Quantum) PalHeader.MaxGreen) |
518 | 0 | { |
519 | 0 | image->colormap[i].green=ClampToQuantum((image->colormap[i].green* |
520 | 0 | (double) QuantumRange+(PalHeader.MaxGreen >> 1))/ |
521 | 0 | PalHeader.MaxGreen); |
522 | 0 | } |
523 | 0 | image->colormap[i].blue=(Quantum) ReadBlobLSBShort(palette); |
524 | 0 | if (QuantumRange != (Quantum) PalHeader.MaxBlue) |
525 | 0 | { |
526 | 0 | image->colormap[i].blue=ClampToQuantum((image->colormap[i].blue* |
527 | 0 | (double) QuantumRange+(PalHeader.MaxBlue >> 1))/ |
528 | 0 | PalHeader.MaxBlue); |
529 | 0 | } |
530 | |
|
531 | 0 | } |
532 | 0 | if (EOFBlob(image)) |
533 | 0 | ThrowCUTReaderException(CorruptImageError,"UnexpectedEndOfFile"); |
534 | 0 | } |
535 | | |
536 | | |
537 | | |
538 | 403 | NoPalette: |
539 | 403 | if(palette==NULL) |
540 | 403 | { |
541 | | |
542 | 403 | image->colors=256; |
543 | 403 | if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) |
544 | 0 | { |
545 | 0 | NoMemory: |
546 | 0 | ThrowCUTReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
547 | 0 | } |
548 | | |
549 | 103k | for (i=0; i < (ssize_t)image->colors; i++) |
550 | 103k | { |
551 | 103k | image->colormap[i].red=ScaleCharToQuantum((unsigned char) i); |
552 | 103k | image->colormap[i].green=ScaleCharToQuantum((unsigned char) i); |
553 | 103k | image->colormap[i].blue=ScaleCharToQuantum((unsigned char) i); |
554 | 103k | } |
555 | 403 | } |
556 | | |
557 | | |
558 | | /* ----- Load RLE compressed raster ----- */ |
559 | 403 | BImgBuff=(unsigned char *) AcquireQuantumMemory((size_t) ldblk, |
560 | 403 | sizeof(*BImgBuff)); /*Ldblk was set in the check phase*/ |
561 | 403 | if(BImgBuff==NULL) goto NoMemory; |
562 | 403 | (void) memset(BImgBuff,0,(size_t) ldblk*sizeof(*BImgBuff)); |
563 | | |
564 | 403 | offset=SeekBlob(image,6 /*sizeof(Header)*/,SEEK_SET); |
565 | 403 | if (offset < 0) |
566 | 0 | { |
567 | 0 | if (palette != NULL) |
568 | 0 | palette=DestroyImage(palette); |
569 | 0 | if (clone_info != NULL) |
570 | 0 | clone_info=DestroyImageInfo(clone_info); |
571 | 0 | BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff); |
572 | 0 | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
573 | 0 | } |
574 | 45.4k | for (i=0; i < (int) Header.Height; i++) |
575 | 45.2k | { |
576 | 45.2k | EncodedByte=ReadBlobLSBShort(image); |
577 | | |
578 | 45.2k | ptrB=BImgBuff; |
579 | 45.2k | j=ldblk; |
580 | | |
581 | 45.2k | RunCount=(unsigned char) ReadBlobByte(image); |
582 | 45.2k | RunCountMasked=RunCount & 0x7F; |
583 | | |
584 | 53.8k | while ((int) RunCountMasked != 0) |
585 | 12.6k | { |
586 | 12.6k | if((ssize_t) RunCountMasked>j) |
587 | 8.22k | { /*Wrong Data*/ |
588 | 8.22k | RunCountMasked=(unsigned char) j; |
589 | 8.22k | if(j==0) |
590 | 3.84k | { |
591 | 3.84k | break; |
592 | 3.84k | } |
593 | 8.22k | } |
594 | | |
595 | 8.77k | if((int) RunCount>0x80) |
596 | 5.23k | { |
597 | 5.23k | RunValue=(unsigned char) ReadBlobByte(image); |
598 | 5.23k | (void) memset(ptrB,(int) RunValue,(size_t) RunCountMasked); |
599 | 5.23k | } |
600 | 3.53k | else { |
601 | 3.53k | (void) ReadBlob(image,(size_t) RunCountMasked,ptrB); |
602 | 3.53k | } |
603 | | |
604 | 8.77k | ptrB+=(int) RunCountMasked; |
605 | 8.77k | j-=(int) RunCountMasked; |
606 | | |
607 | 8.77k | if (EOFBlob(image) != MagickFalse) goto Finish; /* wrong data: unexpected eof in line */ |
608 | 8.54k | RunCount=(unsigned char) ReadBlobByte(image); |
609 | 8.54k | RunCountMasked=RunCount & 0x7F; |
610 | 8.54k | } |
611 | | |
612 | 45.0k | InsertRow(image,depth,BImgBuff,i,exception); |
613 | 45.0k | } |
614 | 172 | (void) SyncImage(image,exception); |
615 | | |
616 | | |
617 | | /* detect monochrome image */ |
618 | 172 | if (palette == (Image *) NULL) |
619 | 172 | { |
620 | | /* attempt to detect binary (black&white) images */ |
621 | 172 | if ((image->storage_class == PseudoClass) && |
622 | 172 | (IdentifyImageCoderGray(image,exception) != MagickFalse)) |
623 | 172 | { |
624 | 172 | if (GetCutColors(image,exception) == 2) |
625 | 92 | { |
626 | 23.6k | for (i=0; i < (ssize_t)image->colors; i++) |
627 | 23.5k | { |
628 | 23.5k | Quantum |
629 | 23.5k | sample; |
630 | | |
631 | 23.5k | sample=ScaleCharToQuantum((unsigned char) i); |
632 | 23.5k | if (image->colormap[i].red != (double) sample) goto Finish; |
633 | 23.5k | if (image->colormap[i].green != (double) sample) goto Finish; |
634 | 23.5k | if (image->colormap[i].blue != (double) sample) goto Finish; |
635 | 23.5k | } |
636 | | |
637 | 92 | image->colormap[1].red=image->colormap[1].green= |
638 | 92 | image->colormap[1].blue=QuantumRange; |
639 | 12.2k | for (i=0; i < (ssize_t)image->rows; i++) |
640 | 12.1k | { |
641 | 12.1k | q=QueueAuthenticPixels(image,0,i,image->columns,1,exception); |
642 | 12.1k | if (q == (Quantum *) NULL) |
643 | 0 | break; |
644 | 14.1M | for (j=0; j < (ssize_t)image->columns; j++) |
645 | 14.1M | { |
646 | 14.1M | if (GetPixelRed(image,q) == ScaleCharToQuantum(1)) |
647 | 6.95M | { |
648 | 6.95M | SetPixelRed(image,QuantumRange,q); |
649 | 6.95M | SetPixelGreen(image,QuantumRange,q); |
650 | 6.95M | SetPixelBlue(image,QuantumRange,q); |
651 | 6.95M | } |
652 | 14.1M | q+=(ptrdiff_t) GetPixelChannels(image); |
653 | 14.1M | } |
654 | 12.1k | if (SyncAuthenticPixels(image,exception) == MagickFalse) goto Finish; |
655 | 12.1k | } |
656 | 92 | } |
657 | 172 | } |
658 | 172 | } |
659 | | |
660 | 403 | Finish: |
661 | 403 | if (BImgBuff != NULL) |
662 | 403 | BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff); |
663 | 403 | if (palette != NULL) |
664 | 0 | palette=DestroyImage(palette); |
665 | 403 | if (clone_info != NULL) |
666 | 0 | clone_info=DestroyImageInfo(clone_info); |
667 | 403 | if (EOFBlob(image) != MagickFalse) |
668 | 236 | ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", |
669 | 403 | image->filename); |
670 | 403 | if (CloseBlob(image) == MagickFalse) |
671 | 0 | status=MagickFalse; |
672 | 403 | if (status == MagickFalse) |
673 | 0 | return(DestroyImageList(image)); |
674 | 403 | return(GetFirstImageInList(image)); |
675 | 403 | } |
676 | | |
677 | | /* |
678 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
679 | | % % |
680 | | % % |
681 | | % % |
682 | | % R e g i s t e r C U T I m a g e % |
683 | | % % |
684 | | % % |
685 | | % % |
686 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
687 | | % |
688 | | % RegisterCUTImage() adds attributes for the CUT image format to |
689 | | % the list of supported formats. The attributes include the image format |
690 | | % tag, a method to read and/or write the format, whether the format |
691 | | % supports the saving of more than one frame to the same file or blob, |
692 | | % whether the format supports native in-memory I/O, and a brief |
693 | | % description of the format. |
694 | | % |
695 | | % The format of the RegisterCUTImage method is: |
696 | | % |
697 | | % size_t RegisterCUTImage(void) |
698 | | % |
699 | | */ |
700 | | ModuleExport size_t RegisterCUTImage(void) |
701 | 9 | { |
702 | 9 | MagickInfo |
703 | 9 | *entry; |
704 | | |
705 | 9 | entry=AcquireMagickInfo("CUT","CUT","DR Halo"); |
706 | 9 | entry->decoder=(DecodeImageHandler *) ReadCUTImage; |
707 | 9 | entry->flags|=CoderDecoderSeekableStreamFlag; |
708 | 9 | (void) RegisterMagickInfo(entry); |
709 | 9 | return(MagickImageCoderSignature); |
710 | 9 | } |
711 | | |
712 | | /* |
713 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
714 | | % % |
715 | | % % |
716 | | % % |
717 | | % U n r e g i s t e r C U T I m a g e % |
718 | | % % |
719 | | % % |
720 | | % % |
721 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
722 | | % |
723 | | % UnregisterCUTImage() removes format registrations made by the |
724 | | % CUT module from the list of supported formats. |
725 | | % |
726 | | % The format of the UnregisterCUTImage method is: |
727 | | % |
728 | | % UnregisterCUTImage(void) |
729 | | % |
730 | | */ |
731 | | ModuleExport void UnregisterCUTImage(void) |
732 | 0 | { |
733 | 0 | (void) UnregisterMagickInfo("CUT"); |
734 | 0 | } |