/src/imagemagick/coders/rle.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
3 | | % % |
4 | | % % |
5 | | % % |
6 | | % RRRR L EEEEE % |
7 | | % R R L E % |
8 | | % RRRR L EEE % |
9 | | % R R L E % |
10 | | % R R LLLLL EEEEE % |
11 | | % % |
12 | | % % |
13 | | % Read URT RLE Image Format % |
14 | | % % |
15 | | % Software Design % |
16 | | % Cristy % |
17 | | % July 1992 % |
18 | | % % |
19 | | % % |
20 | | % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization % |
21 | | % dedicated to making software imaging solutions freely available. % |
22 | | % % |
23 | | % You may not use this file except in compliance with the License. You may % |
24 | | % obtain a copy of the License at % |
25 | | % % |
26 | | % https://imagemagick.org/script/license.php % |
27 | | % % |
28 | | % Unless required by applicable law or agreed to in writing, software % |
29 | | % distributed under the License is distributed on an "AS IS" BASIS, % |
30 | | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
31 | | % See the License for the specific language governing permissions and % |
32 | | % limitations under the License. % |
33 | | % % |
34 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
35 | | % |
36 | | % |
37 | | */ |
38 | | |
39 | | /* |
40 | | Include declarations. |
41 | | */ |
42 | | #include "MagickCore/studio.h" |
43 | | #include "MagickCore/blob.h" |
44 | | #include "MagickCore/blob-private.h" |
45 | | #include "MagickCore/cache.h" |
46 | | #include "MagickCore/colormap.h" |
47 | | #include "MagickCore/colormap-private.h" |
48 | | #include "MagickCore/exception.h" |
49 | | #include "MagickCore/exception-private.h" |
50 | | #include "MagickCore/image.h" |
51 | | #include "MagickCore/image-private.h" |
52 | | #include "MagickCore/list.h" |
53 | | #include "MagickCore/magick.h" |
54 | | #include "MagickCore/memory_.h" |
55 | | #include "MagickCore/monitor.h" |
56 | | #include "MagickCore/monitor-private.h" |
57 | | #include "MagickCore/pixel-accessor.h" |
58 | | #include "MagickCore/pixel.h" |
59 | | #include "MagickCore/property.h" |
60 | | #include "MagickCore/quantum-private.h" |
61 | | #include "MagickCore/static.h" |
62 | | #include "MagickCore/string_.h" |
63 | | #include "MagickCore/module.h" |
64 | | |
65 | | /* |
66 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
67 | | % % |
68 | | % % |
69 | | % % |
70 | | % I s R L E % |
71 | | % % |
72 | | % % |
73 | | % % |
74 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
75 | | % |
76 | | % IsRLE() returns MagickTrue if the image format type, identified by the |
77 | | % magick string, is RLE. |
78 | | % |
79 | | % The format of the ReadRLEImage method is: |
80 | | % |
81 | | % MagickBooleanType IsRLE(const unsigned char *magick,const size_t length) |
82 | | % |
83 | | % A description of each parameter follows: |
84 | | % |
85 | | % o magick: compare image format pattern against these bytes. |
86 | | % |
87 | | % o length: Specifies the length of the magick string. |
88 | | % |
89 | | % |
90 | | */ |
91 | | static MagickBooleanType IsRLE(const unsigned char *magick,const size_t length) |
92 | 0 | { |
93 | 0 | if (length < 2) |
94 | 0 | return(MagickFalse); |
95 | 0 | if (memcmp(magick,"\122\314",2) == 0) |
96 | 0 | return(MagickTrue); |
97 | 0 | return(MagickFalse); |
98 | 0 | } |
99 | | |
100 | | /* |
101 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
102 | | % % |
103 | | % % |
104 | | % % |
105 | | % R e a d R L E I m a g e % |
106 | | % % |
107 | | % % |
108 | | % % |
109 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
110 | | % |
111 | | % ReadRLEImage() reads a run-length encoded Utah Raster Toolkit |
112 | | % image file and returns it. It allocates the memory necessary for the new |
113 | | % Image structure and returns a pointer to the new image. |
114 | | % |
115 | | % The format of the ReadRLEImage method is: |
116 | | % |
117 | | % Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception) |
118 | | % |
119 | | % A description of each parameter follows: |
120 | | % |
121 | | % o image_info: the image info. |
122 | | % |
123 | | % o exception: return any errors or warnings in this structure. |
124 | | % |
125 | | % |
126 | | */ |
127 | | static Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception) |
128 | 2.63k | { |
129 | 27.3k | #define SkipLinesOp 0x01 |
130 | 3.71k | #define SetColorOp 0x02 |
131 | 6.10k | #define SkipPixelsOp 0x03 |
132 | 2.82k | #define ByteDataOp 0x05 |
133 | 3.26k | #define RunDataOp 0x06 |
134 | 134k | #define EOFOp 0x07 |
135 | 2.63k | #define ThrowRLEException(exception,message) \ |
136 | 1.91k | { \ |
137 | 1.91k | if (colormap != (unsigned char *) NULL) \ |
138 | 1.91k | colormap=(unsigned char *) RelinquishMagickMemory(colormap); \ |
139 | 1.91k | if (pixel_info != (MemoryInfo *) NULL) \ |
140 | 1.91k | pixel_info=RelinquishVirtualMemory(pixel_info); \ |
141 | 1.91k | ThrowReaderException((exception),(message)); \ |
142 | 0 | } |
143 | | |
144 | 2.63k | char |
145 | 2.63k | magick[12]; |
146 | | |
147 | 2.63k | Image |
148 | 2.63k | *image; |
149 | | |
150 | 2.63k | int |
151 | 2.63k | opcode, |
152 | 2.63k | operand; |
153 | | |
154 | 2.63k | MagickStatusType |
155 | 2.63k | flags, |
156 | 2.63k | status; |
157 | | |
158 | 2.63k | MagickSizeType |
159 | 2.63k | number_pixels; |
160 | | |
161 | 2.63k | MemoryInfo |
162 | 2.63k | *pixel_info; |
163 | | |
164 | 2.63k | Quantum |
165 | 2.63k | index, |
166 | 2.63k | *q; |
167 | | |
168 | 2.63k | size_t |
169 | 2.63k | bits_per_pixel, |
170 | 2.63k | map_length, |
171 | 2.63k | number_colormaps, |
172 | 2.63k | number_planes, |
173 | 2.63k | number_planes_filled, |
174 | 2.63k | one, |
175 | 2.63k | pixel_info_length; |
176 | | |
177 | 2.63k | ssize_t |
178 | 2.63k | count, |
179 | 2.63k | i, |
180 | 2.63k | offset, |
181 | 2.63k | x, |
182 | 2.63k | y; |
183 | | |
184 | 2.63k | unsigned char |
185 | 2.63k | background_color[256] = { 0 }, |
186 | 2.63k | *colormap, |
187 | 2.63k | *p, |
188 | 2.63k | pixel, |
189 | 2.63k | plane, |
190 | 2.63k | *pixels; |
191 | | |
192 | | /* |
193 | | Open image file. |
194 | | */ |
195 | 2.63k | assert(image_info != (const ImageInfo *) NULL); |
196 | 2.63k | assert(image_info->signature == MagickCoreSignature); |
197 | 2.63k | assert(exception != (ExceptionInfo *) NULL); |
198 | 2.63k | assert(exception->signature == MagickCoreSignature); |
199 | 2.63k | if (IsEventLogging() != MagickFalse) |
200 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", |
201 | 0 | image_info->filename); |
202 | 2.63k | image=AcquireImage(image_info,exception); |
203 | 2.63k | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
204 | 2.63k | if (status == MagickFalse) |
205 | 0 | return(DestroyImageList(image)); |
206 | | /* |
207 | | Determine if this a RLE file. |
208 | | */ |
209 | 2.63k | colormap=(unsigned char *) NULL; |
210 | 2.63k | pixel_info=(MemoryInfo *) NULL; |
211 | 2.63k | count=ReadBlob(image,2,(unsigned char *) magick); |
212 | 2.63k | if ((count != 2) || (memcmp(magick,"\122\314",2) != 0)) |
213 | 2.58k | ThrowRLEException(CorruptImageError,"ImproperImageHeader"); |
214 | 2.58k | do |
215 | 5.18k | { |
216 | | /* |
217 | | Read image header. |
218 | | */ |
219 | 5.18k | image->page.x=(ssize_t) ReadBlobLSBShort(image); |
220 | 5.18k | image->page.y=(ssize_t) ReadBlobLSBShort(image); |
221 | 5.18k | image->columns=ReadBlobLSBShort(image); |
222 | 5.18k | image->rows=ReadBlobLSBShort(image); |
223 | 5.18k | flags=(MagickStatusType) ReadBlobByte(image); |
224 | 5.18k | image->alpha_trait=flags & 0x04 ? BlendPixelTrait : UndefinedPixelTrait; |
225 | 5.18k | number_planes=(size_t) ReadBlobByte(image); |
226 | 5.18k | bits_per_pixel=(size_t) ReadBlobByte(image); |
227 | 5.18k | number_colormaps=(size_t) ReadBlobByte(image); |
228 | 5.18k | map_length=(unsigned char) ReadBlobByte(image); |
229 | 5.18k | if (map_length >= 22) |
230 | 5.05k | ThrowRLEException(CorruptImageError,"ImproperImageHeader"); |
231 | 5.05k | if (EOFBlob(image) != MagickFalse) |
232 | 5.05k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
233 | 5.05k | one=1; |
234 | 5.05k | map_length=one << map_length; |
235 | 5.05k | if ((number_planes == 0) || (number_planes == 2) || ((flags & 0x04) && |
236 | 5.03k | ((number_planes <= 2) || number_planes > 254)) || (bits_per_pixel != 8)) |
237 | 5.00k | ThrowRLEException(CorruptImageError,"ImproperImageHeader"); |
238 | 5.00k | if (number_planes > 4) |
239 | 4.99k | ThrowRLEException(CorruptImageError,"ImproperImageHeader"); |
240 | 4.99k | if ((image->columns == 0) || (image->columns >= 32768) || |
241 | 4.99k | (image->rows == 0) || (image->rows >= 32768)) |
242 | 4.96k | ThrowRLEException(CorruptImageError,"ImproperImageHeader"); |
243 | 4.96k | if (flags & 0x02) |
244 | 1.81k | { |
245 | | /* |
246 | | No background color-- initialize to black. |
247 | | */ |
248 | 5.79k | for (i=0; i < (ssize_t) number_planes; i++) |
249 | 3.98k | background_color[i]=0; |
250 | 1.81k | (void) ReadBlobByte(image); |
251 | 1.81k | } |
252 | 3.15k | else |
253 | 3.15k | { |
254 | | /* |
255 | | Initialize background color. |
256 | | */ |
257 | 3.15k | p=background_color; |
258 | 7.05k | for (i=0; i < (ssize_t) number_planes; i++) |
259 | 3.90k | *p++=(unsigned char) ReadBlobByte(image); |
260 | 3.15k | } |
261 | 4.96k | if ((number_planes & 0x01) == 0) |
262 | 356 | (void) ReadBlobByte(image); |
263 | 4.96k | if (EOFBlob(image) != MagickFalse) |
264 | 4.91k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
265 | 4.91k | if (image->alpha_trait != UndefinedPixelTrait) |
266 | 793 | number_planes++; |
267 | 4.91k | number_pixels=(MagickSizeType) image->columns*image->rows; |
268 | 4.91k | if ((GetBlobSize(image) == 0) || ((((MagickSizeType) number_pixels* |
269 | 4.91k | number_planes*bits_per_pixel/8)/GetBlobSize(image)) > 254)) |
270 | 32 | ThrowRLEException(CorruptImageError,"InsufficientImageDataInFile") |
271 | 4.88k | if (((MagickSizeType) number_colormaps*map_length) > GetBlobSize(image)) |
272 | 58 | ThrowRLEException(CorruptImageError,"InsufficientImageDataInFile") |
273 | 4.82k | if (number_colormaps != 0) |
274 | 2.10k | { |
275 | | /* |
276 | | Read image colormaps. |
277 | | */ |
278 | 2.10k | colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps, |
279 | 2.10k | 3*map_length*sizeof(*colormap)); |
280 | 2.10k | if (colormap == (unsigned char *) NULL) |
281 | 2.10k | ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed"); |
282 | 2.10k | (void) memset(colormap,0,number_colormaps*3*map_length* |
283 | 2.10k | sizeof(*colormap)); |
284 | 2.10k | p=colormap; |
285 | 18.5k | for (i=0; i < (ssize_t) number_colormaps; i++) |
286 | 55.8k | for (x=0; x < (ssize_t) map_length; x++) |
287 | 39.4k | { |
288 | 39.4k | *p++=(unsigned char) ScaleQuantumToChar(ScaleShortToQuantum( |
289 | 39.4k | ReadBlobLSBShort(image))); |
290 | 39.4k | if (EOFBlob(image) != MagickFalse) |
291 | 39.3k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
292 | 39.3k | } |
293 | 2.10k | } |
294 | 4.71k | if ((flags & 0x08) != 0) |
295 | 779 | { |
296 | 779 | char |
297 | 779 | *comment; |
298 | | |
299 | 779 | size_t |
300 | 779 | length; |
301 | | |
302 | | /* |
303 | | Read image comment. |
304 | | */ |
305 | 779 | length=ReadBlobLSBShort(image); |
306 | 779 | if (length != 0) |
307 | 588 | { |
308 | 588 | comment=(char *) AcquireQuantumMemory(length,sizeof(*comment)); |
309 | 588 | if (comment == (char *) NULL) |
310 | 588 | ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed"); |
311 | 588 | count=ReadBlob(image,length-1,(unsigned char *) comment); |
312 | 588 | if (count != (ssize_t) (length-1)) |
313 | 45 | { |
314 | 45 | comment=DestroyString(comment); |
315 | 45 | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
316 | 0 | } |
317 | 543 | comment[length-1]='\0'; |
318 | 543 | (void) SetImageProperty(image,"comment",comment,exception); |
319 | 543 | comment=DestroyString(comment); |
320 | 543 | if ((length & 0x01) == 0) |
321 | 137 | (void) ReadBlobByte(image); |
322 | 543 | } |
323 | 779 | } |
324 | 4.66k | if (EOFBlob(image) != MagickFalse) |
325 | 4.64k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
326 | 4.64k | if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) |
327 | 0 | if (image->scene >= (image_info->scene+image_info->number_scenes-1)) |
328 | 0 | break; |
329 | 4.64k | status=SetImageExtent(image,image->columns,image->rows,exception); |
330 | 4.64k | if (status == MagickFalse) |
331 | 84 | { |
332 | 84 | if (colormap != (unsigned char *) NULL) |
333 | 27 | colormap=(unsigned char *) RelinquishMagickMemory(colormap); |
334 | 84 | if (pixel_info != (MemoryInfo *) NULL) |
335 | 0 | pixel_info=RelinquishVirtualMemory(pixel_info); |
336 | 84 | return(DestroyImageList(image)); |
337 | 84 | } |
338 | | /* |
339 | | Allocate RLE pixels. |
340 | | */ |
341 | 4.55k | number_planes_filled=(number_planes % 2 == 0) ? number_planes : |
342 | 4.55k | number_planes+1; |
343 | 4.55k | if (HeapOverflowSanityCheckGetSize(number_planes_filled, |
344 | 4.55k | (size_t) number_pixels,(size_t *) NULL) != MagickFalse) |
345 | 4.55k | ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed"); |
346 | 4.55k | pixel_info=AcquireVirtualMemory(image->columns,image->rows* |
347 | 4.55k | MagickMax(number_planes_filled,4)*sizeof(*pixels)); |
348 | 4.55k | if (pixel_info == (MemoryInfo *) NULL) |
349 | 4.55k | ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed"); |
350 | 4.55k | pixel_info_length=image->columns*image->rows* |
351 | 4.55k | MagickMax(number_planes_filled,4); |
352 | 4.55k | pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); |
353 | 4.55k | (void) memset(pixels,0,pixel_info_length); |
354 | 4.55k | if ((flags & 0x01) && !(flags & 0x02)) |
355 | 1.57k | { |
356 | 1.57k | ssize_t |
357 | 1.57k | j; |
358 | | |
359 | | /* |
360 | | Set background color. |
361 | | */ |
362 | 1.57k | p=pixels; |
363 | 40.9M | for (i=0; i < (ssize_t) number_pixels; i++) |
364 | 40.9M | { |
365 | 40.9M | if ((image->alpha_trait & BlendPixelTrait) == 0) |
366 | 83.0M | for (j=0; j < (ssize_t) number_planes; j++) |
367 | 42.1M | *p++=background_color[j]; |
368 | 50.1k | else |
369 | 50.1k | { |
370 | 209k | for (j=0; j < (ssize_t) (number_planes-1); j++) |
371 | 159k | *p++=background_color[j]; |
372 | 50.1k | *p++=0; /* initialize matte channel */ |
373 | 50.1k | } |
374 | 40.9M | } |
375 | 1.57k | } |
376 | | /* |
377 | | Read runlength-encoded image. |
378 | | */ |
379 | 4.55k | plane=0; |
380 | 4.55k | x=0; |
381 | 4.55k | y=0; |
382 | 4.55k | opcode=ReadBlobByte(image); |
383 | 4.55k | if (opcode == EOF) |
384 | 112 | { |
385 | 112 | if (number_colormaps != 0) |
386 | 14 | colormap=(unsigned char *) RelinquishMagickMemory(colormap); |
387 | 112 | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
388 | 0 | } |
389 | 4.44k | do |
390 | 135k | { |
391 | 135k | switch (opcode & 0x3f) |
392 | 135k | { |
393 | 27.3k | case SkipLinesOp: |
394 | 27.3k | { |
395 | 27.3k | operand=ReadBlobByte(image); |
396 | 27.3k | if (operand == EOF) |
397 | 27.3k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
398 | 27.3k | if (opcode & 0x40) |
399 | 22.1k | { |
400 | 22.1k | operand=ReadBlobLSBSignedShort(image); |
401 | 22.1k | if (operand == EOF) |
402 | 22.1k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
403 | 22.1k | } |
404 | 27.3k | x=0; |
405 | 27.3k | y+=operand; |
406 | 27.3k | break; |
407 | 27.3k | } |
408 | 3.71k | case SetColorOp: |
409 | 3.71k | { |
410 | 3.71k | operand=ReadBlobByte(image); |
411 | 3.71k | if (operand == EOF) |
412 | 3.69k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
413 | 3.69k | plane=(unsigned char) operand; |
414 | 3.69k | if (plane == 255) |
415 | 296 | plane=(unsigned char) (number_planes-1); |
416 | 3.69k | x=0; |
417 | 3.69k | break; |
418 | 3.71k | } |
419 | 6.10k | case SkipPixelsOp: |
420 | 6.10k | { |
421 | 6.10k | operand=ReadBlobByte(image); |
422 | 6.10k | if (operand == EOF) |
423 | 6.08k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
424 | 6.08k | if (opcode & 0x40) |
425 | 3.96k | { |
426 | 3.96k | operand=ReadBlobLSBSignedShort(image); |
427 | 3.96k | if (operand == EOF) |
428 | 3.96k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
429 | 3.96k | } |
430 | 6.08k | x+=operand; |
431 | 6.08k | break; |
432 | 6.08k | } |
433 | 2.82k | case ByteDataOp: |
434 | 2.82k | { |
435 | 2.82k | operand=ReadBlobByte(image); |
436 | 2.82k | if (operand == EOF) |
437 | 2.80k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
438 | 2.80k | if (opcode & 0x40) |
439 | 1.65k | { |
440 | 1.65k | operand=ReadBlobLSBSignedShort(image); |
441 | 1.65k | if (operand == EOF) |
442 | 1.64k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
443 | 1.64k | } |
444 | 2.80k | offset=(ssize_t) ((((ssize_t) image->rows-y-1)*(ssize_t) |
445 | 2.80k | image->columns*(ssize_t) number_planes)+x*(ssize_t) |
446 | 2.80k | number_planes+plane); |
447 | 2.80k | operand++; |
448 | 2.80k | if ((offset < 0) || |
449 | 2.80k | ((size_t) (offset+operand*(ssize_t) number_planes) > pixel_info_length)) |
450 | 2.59k | ThrowRLEException(CorruptImageError,"UnableToReadImageData"); |
451 | 2.59k | p=pixels+offset; |
452 | 478k | for (i=0; i < (ssize_t) operand; i++) |
453 | 475k | { |
454 | 475k | pixel=(unsigned char) ReadBlobByte(image); |
455 | 475k | if ((y < (ssize_t) image->rows) && |
456 | 475k | ((x+i) < (ssize_t) image->columns)) |
457 | 118k | *p=pixel; |
458 | 475k | p+=(ptrdiff_t) number_planes; |
459 | 475k | } |
460 | 2.59k | if (operand & 0x01) |
461 | 1.29k | (void) ReadBlobByte(image); |
462 | 2.59k | x+=operand; |
463 | 2.59k | break; |
464 | 2.80k | } |
465 | 3.26k | case RunDataOp: |
466 | 3.26k | { |
467 | 3.26k | operand=ReadBlobByte(image); |
468 | 3.26k | if (operand == EOF) |
469 | 3.25k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
470 | 3.25k | if (opcode & 0x40) |
471 | 1.69k | { |
472 | 1.69k | operand=ReadBlobLSBSignedShort(image); |
473 | 1.69k | if (operand == EOF) |
474 | 1.68k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
475 | 1.68k | } |
476 | 3.24k | pixel=(unsigned char) ReadBlobByte(image); |
477 | 3.24k | (void) ReadBlobByte(image); |
478 | 3.24k | offset=(((ssize_t) image->rows-y-1)*(ssize_t) image->columns* |
479 | 3.24k | (ssize_t) number_planes)+x*(ssize_t) number_planes+plane; |
480 | 3.24k | operand++; |
481 | 3.24k | if ((offset < 0) || |
482 | 3.24k | ((size_t) (offset+operand*(ssize_t) number_planes) > pixel_info_length)) |
483 | 3.03k | ThrowRLEException(CorruptImageError,"UnableToReadImageData"); |
484 | 3.03k | p=pixels+offset; |
485 | 9.14M | for (i=0; i < (ssize_t) operand; i++) |
486 | 9.14M | { |
487 | 9.14M | if ((y < (ssize_t) image->rows) && |
488 | 9.14M | ((x+i) < (ssize_t) image->columns)) |
489 | 506k | *p=pixel; |
490 | 9.14M | p+=(ptrdiff_t) number_planes; |
491 | 9.14M | } |
492 | 3.03k | x+=operand; |
493 | 3.03k | break; |
494 | 3.24k | } |
495 | 92.3k | default: |
496 | 92.3k | break; |
497 | 135k | } |
498 | 135k | opcode=ReadBlobByte(image); |
499 | 135k | if (opcode == EOF) |
500 | 134k | ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile"); |
501 | 134k | } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF)); |
502 | 3.25k | if (number_colormaps != 0) |
503 | 1.66k | { |
504 | 1.66k | MagickStatusType |
505 | 1.66k | mask; |
506 | | |
507 | | /* |
508 | | Apply colormap affineation to image. |
509 | | */ |
510 | 1.66k | mask=(MagickStatusType) (map_length-1); |
511 | 1.66k | p=pixels; |
512 | 1.66k | x=(ssize_t) number_planes; |
513 | 1.66k | if (number_colormaps == 1) |
514 | 32.6M | for (i=0; i < (ssize_t) number_pixels; i++) |
515 | 32.6M | { |
516 | 32.6M | ValidateColormapValue(image,(ssize_t) (*p & mask),&index,exception); |
517 | 32.6M | *p=colormap[(ssize_t) index]; |
518 | 32.6M | p++; |
519 | 32.6M | } |
520 | 363 | else |
521 | 363 | if ((number_planes >= 3) && (number_colormaps >= 3)) |
522 | 578k | for (i=0; i < (ssize_t) number_pixels; i++) |
523 | 2.38M | for (x=0; x < (ssize_t) number_planes; x++) |
524 | 1.80M | { |
525 | 1.80M | ValidateColormapValue(image,x*(ssize_t) map_length+ |
526 | 1.80M | (*p & mask),&index,exception); |
527 | 1.80M | *p=colormap[(ssize_t) index]; |
528 | 1.80M | p++; |
529 | 1.80M | } |
530 | 1.66k | if ((i < (ssize_t) number_pixels) || (x < (ssize_t) number_planes)) |
531 | 1.64k | ThrowRLEException(CorruptImageError,"UnableToReadImageData"); |
532 | 1.64k | } |
533 | | /* |
534 | | Initialize image structure. |
535 | | */ |
536 | 3.23k | if (number_planes >= 3) |
537 | 707 | { |
538 | | /* |
539 | | Convert raster image to DirectClass pixel packets. |
540 | | */ |
541 | 707 | p=pixels; |
542 | 39.1k | for (y=0; y < (ssize_t) image->rows; y++) |
543 | 38.4k | { |
544 | 38.4k | q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); |
545 | 38.4k | if (q == (Quantum *) NULL) |
546 | 0 | break; |
547 | 2.02M | for (x=0; x < (ssize_t) image->columns; x++) |
548 | 1.98M | { |
549 | 1.98M | SetPixelRed(image,ScaleCharToQuantum(*p++),q); |
550 | 1.98M | SetPixelGreen(image,ScaleCharToQuantum(*p++),q); |
551 | 1.98M | SetPixelBlue(image,ScaleCharToQuantum(*p++),q); |
552 | 1.98M | if (image->alpha_trait != UndefinedPixelTrait) |
553 | 448k | SetPixelAlpha(image,ScaleCharToQuantum(*p++),q); |
554 | 1.98M | q+=(ptrdiff_t) GetPixelChannels(image); |
555 | 1.98M | } |
556 | 38.4k | if (SyncAuthenticPixels(image,exception) == MagickFalse) |
557 | 0 | break; |
558 | 38.4k | if (image->previous == (Image *) NULL) |
559 | 22.1k | { |
560 | 22.1k | status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, |
561 | 22.1k | image->rows); |
562 | 22.1k | if (status == MagickFalse) |
563 | 0 | break; |
564 | 22.1k | } |
565 | 38.4k | } |
566 | 707 | } |
567 | 2.53k | else |
568 | 2.53k | { |
569 | | /* |
570 | | Create colormap. |
571 | | */ |
572 | 2.53k | if (number_colormaps == 0) |
573 | 1.09k | map_length=256; |
574 | 2.53k | if (AcquireImageColormap(image,map_length,exception) == MagickFalse) |
575 | 2.53k | ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed"); |
576 | 2.53k | p=colormap; |
577 | 2.53k | if (number_colormaps == 1) |
578 | 10.9k | for (i=0; i < (ssize_t) image->colors; i++) |
579 | 9.70k | { |
580 | | /* |
581 | | Pseudocolor. |
582 | | */ |
583 | 9.70k | image->colormap[i].red=(MagickRealType) |
584 | 9.70k | ScaleCharToQuantum((unsigned char) i); |
585 | 9.70k | image->colormap[i].green=(MagickRealType) |
586 | 9.70k | ScaleCharToQuantum((unsigned char) i); |
587 | 9.70k | image->colormap[i].blue=(MagickRealType) |
588 | 9.70k | ScaleCharToQuantum((unsigned char) i); |
589 | 9.70k | } |
590 | 1.30k | else |
591 | 1.30k | if (number_colormaps > 1) |
592 | 1.02k | for (i=0; i < (ssize_t) image->colors; i++) |
593 | 810 | { |
594 | 810 | image->colormap[i].red=(MagickRealType) |
595 | 810 | ScaleCharToQuantum(*p); |
596 | 810 | image->colormap[i].green=(MagickRealType) |
597 | 810 | ScaleCharToQuantum(*(p+map_length)); |
598 | 810 | image->colormap[i].blue=(MagickRealType) |
599 | 810 | ScaleCharToQuantum(*(p+map_length*2)); |
600 | 810 | p++; |
601 | 810 | } |
602 | 2.53k | p=pixels; |
603 | 2.53k | if ((image->alpha_trait & BlendPixelTrait) == 0) |
604 | 2.53k | { |
605 | | /* |
606 | | Convert raster image to PseudoClass pixel packets. |
607 | | */ |
608 | 333k | for (y=0; y < (ssize_t) image->rows; y++) |
609 | 330k | { |
610 | 330k | q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); |
611 | 330k | if (q == (Quantum *) NULL) |
612 | 0 | break; |
613 | 46.5M | for (x=0; x < (ssize_t) image->columns; x++) |
614 | 46.2M | { |
615 | 46.2M | SetPixelIndex(image,(Quantum) *p++,q); |
616 | 46.2M | q+=(ptrdiff_t) GetPixelChannels(image); |
617 | 46.2M | } |
618 | 330k | if (SyncAuthenticPixels(image,exception) == MagickFalse) |
619 | 0 | break; |
620 | 330k | if (image->previous == (Image *) NULL) |
621 | 116k | { |
622 | 116k | status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) |
623 | 116k | y,image->rows); |
624 | 116k | if (status == MagickFalse) |
625 | 0 | break; |
626 | 116k | } |
627 | 330k | } |
628 | 2.53k | (void) SyncImage(image,exception); |
629 | 2.53k | } |
630 | 0 | else |
631 | 0 | { |
632 | | /* |
633 | | Image has a matte channel-- promote to DirectClass. |
634 | | */ |
635 | 0 | for (y=0; y < (ssize_t) image->rows; y++) |
636 | 0 | { |
637 | 0 | q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); |
638 | 0 | if (q == (Quantum *) NULL) |
639 | 0 | break; |
640 | 0 | for (x=0; x < (ssize_t) image->columns; x++) |
641 | 0 | { |
642 | 0 | ValidateColormapValue(image,(ssize_t) *p++,&index,exception); |
643 | 0 | SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t) |
644 | 0 | index].red),q); |
645 | 0 | ValidateColormapValue(image,(ssize_t) *p++,&index,exception); |
646 | 0 | SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t) |
647 | 0 | index].green),q); |
648 | 0 | ValidateColormapValue(image,(ssize_t) *p++,&index,exception); |
649 | 0 | SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t) |
650 | 0 | index].blue),q); |
651 | 0 | SetPixelAlpha(image,ScaleCharToQuantum(*p++),q); |
652 | 0 | q+=(ptrdiff_t) GetPixelChannels(image); |
653 | 0 | } |
654 | 0 | if (x < (ssize_t) image->columns) |
655 | 0 | break; |
656 | 0 | if (SyncAuthenticPixels(image,exception) == MagickFalse) |
657 | 0 | break; |
658 | 0 | if (image->previous == (Image *) NULL) |
659 | 0 | { |
660 | 0 | status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) |
661 | 0 | y,image->rows); |
662 | 0 | if (status == MagickFalse) |
663 | 0 | break; |
664 | 0 | } |
665 | 0 | } |
666 | 0 | image->colormap=(PixelInfo *) RelinquishMagickMemory( |
667 | 0 | image->colormap); |
668 | 0 | image->storage_class=DirectClass; |
669 | 0 | image->colors=0; |
670 | 0 | } |
671 | 2.53k | } |
672 | 3.23k | if (colormap != (unsigned char *) NULL) |
673 | 1.64k | colormap=(unsigned char *) RelinquishMagickMemory(colormap); |
674 | 3.23k | pixel_info=RelinquishVirtualMemory(pixel_info); |
675 | 3.23k | if (EOFBlob(image) != MagickFalse) |
676 | 0 | { |
677 | 0 | ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", |
678 | 0 | image->filename); |
679 | 0 | break; |
680 | 0 | } |
681 | | /* |
682 | | Proceed to next image. |
683 | | */ |
684 | 3.23k | if (image_info->number_scenes != 0) |
685 | 55 | if (image->scene >= (image_info->scene+image_info->number_scenes-1)) |
686 | 1 | break; |
687 | 3.23k | (void) ReadBlobByte(image); |
688 | 3.23k | count=ReadBlob(image,2,(unsigned char *) magick); |
689 | 3.23k | if ((count != 0) && (memcmp(magick,"\122\314",2) == 0)) |
690 | 2.60k | { |
691 | | /* |
692 | | Allocate next image structure. |
693 | | */ |
694 | 2.60k | AcquireNextImage(image_info,image,exception); |
695 | 2.60k | if (GetNextImageInList(image) == (Image *) NULL) |
696 | 0 | { |
697 | 0 | status=MagickFalse; |
698 | 0 | break; |
699 | 0 | } |
700 | 2.60k | image=SyncNextImageInList(image); |
701 | 2.60k | status=SetImageProgress(image,LoadImagesTag,TellBlob(image), |
702 | 2.60k | GetBlobSize(image)); |
703 | 2.60k | if (status == MagickFalse) |
704 | 0 | break; |
705 | 2.60k | } |
706 | 3.23k | } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0)); |
707 | 639 | if (colormap != (unsigned char *) NULL) |
708 | 0 | colormap=(unsigned char *) RelinquishMagickMemory(colormap); |
709 | 639 | if (CloseBlob(image) == MagickFalse) |
710 | 0 | status=MagickFalse; |
711 | 639 | if (status == MagickFalse) |
712 | 0 | return(DestroyImageList(image)); |
713 | 639 | return(GetFirstImageInList(image)); |
714 | 639 | } |
715 | | |
716 | | /* |
717 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
718 | | % % |
719 | | % % |
720 | | % % |
721 | | % R e g i s t e r R L E I m a g e % |
722 | | % % |
723 | | % % |
724 | | % % |
725 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
726 | | % |
727 | | % RegisterRLEImage() adds attributes for the RLE image format to |
728 | | % the list of supported formats. The attributes include the image format |
729 | | % tag, a method to read and/or write the format, whether the format |
730 | | % supports the saving of more than one frame to the same file or blob, |
731 | | % whether the format supports native in-memory I/O, and a brief |
732 | | % description of the format. |
733 | | % |
734 | | % The format of the RegisterRLEImage method is: |
735 | | % |
736 | | % size_t RegisterRLEImage(void) |
737 | | % |
738 | | */ |
739 | | ModuleExport size_t RegisterRLEImage(void) |
740 | 10 | { |
741 | 10 | MagickInfo |
742 | 10 | *entry; |
743 | | |
744 | 10 | entry=AcquireMagickInfo("RLE","RLE","Utah Run length encoded image"); |
745 | 10 | entry->decoder=(DecodeImageHandler *) ReadRLEImage; |
746 | 10 | entry->magick=(IsImageFormatHandler *) IsRLE; |
747 | 10 | entry->flags|=CoderDecoderSeekableStreamFlag; |
748 | 10 | entry->flags^=CoderAdjoinFlag; |
749 | 10 | (void) RegisterMagickInfo(entry); |
750 | 10 | return(MagickImageCoderSignature); |
751 | 10 | } |
752 | | |
753 | | /* |
754 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
755 | | % % |
756 | | % % |
757 | | % % |
758 | | % U n r e g i s t e r R L E I m a g e % |
759 | | % % |
760 | | % % |
761 | | % % |
762 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
763 | | % |
764 | | % UnregisterRLEImage() removes format registrations made by the |
765 | | % RLE module from the list of supported formats. |
766 | | % |
767 | | % The format of the UnregisterRLEImage method is: |
768 | | % |
769 | | % UnregisterRLEImage(void) |
770 | | % |
771 | | */ |
772 | | ModuleExport void UnregisterRLEImage(void) |
773 | 0 | { |
774 | 0 | (void) UnregisterMagickInfo("RLE"); |
775 | 0 | } |