2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read/Write Image Colormaps As An Image File. %
20 % Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "magick/studio.h"
43 #include "magick/attribute.h"
44 #include "magick/blob.h"
45 #include "magick/blob-private.h"
46 #include "magick/cache.h"
47 #include "magick/color.h"
48 #include "magick/color-private.h"
49 #include "magick/colormap.h"
50 #include "magick/colormap-private.h"
51 #include "magick/colorspace.h"
52 #include "magick/exception.h"
53 #include "magick/exception-private.h"
54 #include "magick/histogram.h"
55 #include "magick/image.h"
56 #include "magick/image-private.h"
57 #include "magick/list.h"
58 #include "magick/magick.h"
59 #include "magick/memory_.h"
60 #include "magick/quantum-private.h"
61 #include "magick/static.h"
62 #include "magick/statistic.h"
63 #include "magick/string_.h"
64 #include "magick/module.h"
69 static MagickBooleanType
70 WriteMAPImage(const ImageInfo *,Image *);
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 % R e a d M A P I m a g e %
81 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 % ReadMAPImage() reads an image of raw RGB colormap and colormap index
84 % bytes and returns it. It allocates the memory necessary for the new Image
85 % structure and returns a pointer to the new image.
87 % The format of the ReadMAPImage method is:
89 % Image *ReadMAPImage(const ImageInfo *image_info,ExceptionInfo *exception)
91 % A description of each parameter follows:
93 % o image_info: the image info.
95 % o exception: return any errors or warnings in this structure.
98 static Image *ReadMAPImage(const ImageInfo *image_info,ExceptionInfo *exception)
124 register unsigned char
144 assert(image_info != (const ImageInfo *) NULL);
145 assert(image_info->signature == MagickSignature);
146 if (image_info->debug != MagickFalse)
147 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
148 image_info->filename);
149 assert(exception != (ExceptionInfo *) NULL);
150 assert(exception->signature == MagickSignature);
151 image=AcquireImage(image_info);
152 if ((image->columns == 0) || (image->rows == 0))
153 ThrowReaderException(OptionError,"MustSpecifyImageSize");
154 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
155 if (status == MagickFalse)
157 image=DestroyImageList(image);
158 return((Image *) NULL);
161 Initialize image structure.
163 image->storage_class=PseudoClass;
164 status=AcquireImageColormap(image,(unsigned long)
165 (image->offset != 0 ? image->offset : 256));
166 if (status == MagickFalse)
167 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
168 depth=GetImageQuantumDepth(image,MagickTrue);
169 packet_size=(size_t) (depth/8);
170 pixels=(unsigned char *) AcquireQuantumMemory(image->columns,packet_size*
172 packet_size=(size_t) (image->colors > 256 ? 6UL : 3UL);
173 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,packet_size*
175 if ((pixels == (unsigned char *) NULL) ||
176 (colormap == (unsigned char *) NULL))
177 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
181 count=ReadBlob(image,packet_size*image->colors,colormap);
182 if (count != (ssize_t) (packet_size*image->colors))
183 ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
185 if (image->depth <= 8)
186 for (i=0; i < (long) image->colors; i++)
188 image->colormap[i].red=ScaleCharToQuantum(*p++);
189 image->colormap[i].green=ScaleCharToQuantum(*p++);
190 image->colormap[i].blue=ScaleCharToQuantum(*p++);
193 for (i=0; i < (long) image->colors; i++)
197 image->colormap[i].red=(Quantum) quantum;
200 image->colormap[i].green=(Quantum) quantum;
203 image->colormap[i].blue=(Quantum) quantum;
205 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
206 if (image_info->ping != MagickFalse)
208 (void) CloseBlob(image);
209 return(GetFirstImageInList(image));
214 packet_size=(size_t) (depth/8);
215 for (y=0; y < (long) image->rows; y++)
218 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
219 if (q == (PixelPacket *) NULL)
221 indexes=GetAuthenticIndexQueue(image);
222 count=ReadBlob(image,(size_t) packet_size*image->columns,pixels);
223 if (count != (ssize_t) (packet_size*image->columns))
225 for (x=0; x < (long) image->columns; x++)
227 index=ConstrainColormapIndex(image,*p);
229 if (image->colors > 256)
231 index=ConstrainColormapIndex(image,((unsigned long) index << 8)+(*p));
234 indexes[x]=(IndexPacket) index;
235 *q++=image->colormap[(long) index];
237 if (SyncAuthenticPixels(image,exception) == MagickFalse)
240 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
241 if (y < (long) image->rows)
242 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
244 (void) CloseBlob(image);
245 return(GetFirstImageInList(image));
249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 % R e g i s t e r M A P I m a g e %
257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
259 % RegisterMAPImage() adds attributes for the MAP image format to
260 % the list of supported formats. The attributes include the image format
261 % tag, a method to read and/or write the format, whether the format
262 % supports the saving of more than one frame to the same file or blob,
263 % whether the format supports native in-memory I/O, and a brief
264 % description of the format.
266 % The format of the RegisterMAPImage method is:
268 % unsigned long RegisterMAPImage(void)
271 ModuleExport unsigned long RegisterMAPImage(void)
276 entry=SetMagickInfo("MAP");
277 entry->decoder=(DecodeImageHandler *) ReadMAPImage;
278 entry->encoder=(EncodeImageHandler *) WriteMAPImage;
279 entry->adjoin=MagickFalse;
280 entry->format_type=ExplicitFormatType;
281 entry->raw=MagickTrue;
282 entry->endian_support=MagickTrue;
283 entry->description=ConstantString("Colormap intensities and indices");
284 entry->module=ConstantString("MAP");
285 (void) RegisterMagickInfo(entry);
286 return(MagickImageCoderSignature);
290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294 % U n r e g i s t e r M A P I m a g e %
298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300 % UnregisterMAPImage() removes format registrations made by the
301 % MAP module from the list of supported formats.
303 % The format of the UnregisterMAPImage method is:
305 % UnregisterMAPImage(void)
308 ModuleExport void UnregisterMAPImage(void)
310 (void) UnregisterMagickInfo("MAP");
314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318 % W r i t e M A P I m a g e %
322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
324 % WriteMAPImage() writes an image to a file as red, green, and blue
325 % colormap bytes followed by the colormap indexes.
327 % The format of the WriteMAPImage method is:
329 % MagickBooleanType WriteMAPImage(const ImageInfo *image_info,Image *image)
331 % A description of each parameter follows.
333 % o image_info: the image info.
335 % o image: The image.
339 static MagickBooleanType WriteMAPImage(const ImageInfo *image_info,Image *image)
347 register const IndexPacket
350 register const PixelPacket
357 register unsigned char
371 Open output image file.
373 assert(image_info != (const ImageInfo *) NULL);
374 assert(image_info->signature == MagickSignature);
375 assert(image != (Image *) NULL);
376 assert(image->signature == MagickSignature);
377 if (image->debug != MagickFalse)
378 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
379 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
380 if (status == MagickFalse)
382 if (image->colorspace != RGBColorspace)
383 (void) TransformImageColorspace(image,RGBColorspace);
387 if (IsPaletteImage(image,&image->exception) == MagickFalse)
388 (void) SetImageType(image,PaletteType);
389 depth=GetImageQuantumDepth(image,MagickTrue);
390 packet_size=(size_t) (depth/8);
391 pixels=(unsigned char *) AcquireQuantumMemory(image->columns,packet_size*
393 packet_size=(size_t) (image->colors > 256 ? 6UL : 3UL);
394 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,packet_size*
396 if ((pixels == (unsigned char *) NULL) ||
397 (colormap == (unsigned char *) NULL))
398 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
400 Write colormap to file.
403 if (image->depth <= 8)
404 for (i=0; i < (long) image->colors; i++)
406 *q++=(unsigned char) image->colormap[i].red;
407 *q++=(unsigned char) image->colormap[i].green;
408 *q++=(unsigned char) image->colormap[i].blue;
411 for (i=0; i < (long) image->colors; i++)
413 *q++=(unsigned char) ((unsigned long) image->colormap[i].red >> 8);
414 *q++=(unsigned char) image->colormap[i].red;
415 *q++=(unsigned char) ((unsigned long) image->colormap[i].green >> 8);
416 *q++=(unsigned char) image->colormap[i].green;
417 *q++=(unsigned char) ((unsigned long) image->colormap[i].blue >> 8);
418 *q++=(unsigned char) image->colormap[i].blue;
420 (void) WriteBlob(image,packet_size*image->colors,colormap);
421 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
423 Write image pixels to file.
425 for (y=0; y < (long) image->rows; y++)
427 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
428 if (p == (const PixelPacket *) NULL)
430 indexes=GetVirtualIndexQueue(image);
432 for (x=0; x < (long) image->columns; x++)
434 if (image->colors > 256)
435 *q++=(unsigned char) ((unsigned long) indexes[x] >> 8);
436 *q++=(unsigned char) indexes[x];
438 (void) WriteBlob(image,(size_t) (q-pixels),pixels);
440 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
441 (void) CloseBlob(image);