map.c revision 3a37efd7ece979e9c63dc8f2f2d3816bab8b1156
1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% M M AAA PPPP % 7% MM MM A A P P % 8% M M M AAAAA PPPP % 9% M M A A P % 10% M M A A P % 11% % 12% % 13% Read/Write Image Colormaps As An Image File. % 14% % 15% Software Design % 16% John Cristy % 17% July 1992 % 18% % 19% % 20% Copyright 1999-2011 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% http://www.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/attribute.h" 44#include "MagickCore/blob.h" 45#include "MagickCore/blob-private.h" 46#include "MagickCore/cache.h" 47#include "MagickCore/color.h" 48#include "MagickCore/color-private.h" 49#include "MagickCore/colormap.h" 50#include "MagickCore/colormap-private.h" 51#include "MagickCore/colorspace.h" 52#include "MagickCore/colorspace-private.h" 53#include "MagickCore/exception.h" 54#include "MagickCore/exception-private.h" 55#include "MagickCore/histogram.h" 56#include "MagickCore/image.h" 57#include "MagickCore/image-private.h" 58#include "MagickCore/list.h" 59#include "MagickCore/magick.h" 60#include "MagickCore/memory_.h" 61#include "MagickCore/pixel-accessor.h" 62#include "MagickCore/quantum-private.h" 63#include "MagickCore/static.h" 64#include "MagickCore/statistic.h" 65#include "MagickCore/string_.h" 66#include "MagickCore/module.h" 67 68/* 69 Forward declarations. 70*/ 71static MagickBooleanType 72 WriteMAPImage(const ImageInfo *,Image *,ExceptionInfo *); 73 74/* 75%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 76% % 77% % 78% % 79% R e a d M A P I m a g e % 80% % 81% % 82% % 83%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 84% 85% ReadMAPImage() reads an image of raw RGB colormap and colormap index 86% bytes and returns it. It allocates the memory necessary for the new Image 87% structure and returns a pointer to the new image. 88% 89% The format of the ReadMAPImage method is: 90% 91% Image *ReadMAPImage(const ImageInfo *image_info,ExceptionInfo *exception) 92% 93% A description of each parameter follows: 94% 95% o image_info: the image info. 96% 97% o exception: return any errors or warnings in this structure. 98% 99*/ 100static Image *ReadMAPImage(const ImageInfo *image_info,ExceptionInfo *exception) 101{ 102 Image 103 *image; 104 105 MagickBooleanType 106 status; 107 108 Quantum 109 index; 110 111 register ssize_t 112 x; 113 114 register Quantum 115 *q; 116 117 register ssize_t 118 i; 119 120 register unsigned char 121 *p; 122 123 size_t 124 depth, 125 packet_size, 126 quantum; 127 128 ssize_t 129 count, 130 y; 131 132 unsigned char 133 *colormap, 134 *pixels; 135 136 /* 137 Open image file. 138 */ 139 assert(image_info != (const ImageInfo *) NULL); 140 assert(image_info->signature == MagickSignature); 141 if (image_info->debug != MagickFalse) 142 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 143 image_info->filename); 144 assert(exception != (ExceptionInfo *) NULL); 145 assert(exception->signature == MagickSignature); 146 image=AcquireImage(image_info); 147 if ((image->columns == 0) || (image->rows == 0)) 148 ThrowReaderException(OptionError,"MustSpecifyImageSize"); 149 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 150 if (status == MagickFalse) 151 { 152 image=DestroyImageList(image); 153 return((Image *) NULL); 154 } 155 /* 156 Initialize image structure. 157 */ 158 image->storage_class=PseudoClass; 159 status=AcquireImageColormap(image,(size_t) 160 (image->offset != 0 ? image->offset : 256)); 161 if (status == MagickFalse) 162 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 163 depth=GetImageQuantumDepth(image,MagickTrue); 164 packet_size=(size_t) (depth/8); 165 pixels=(unsigned char *) AcquireQuantumMemory(image->columns,packet_size* 166 sizeof(*pixels)); 167 packet_size=(size_t) (image->colors > 256 ? 6UL : 3UL); 168 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,packet_size* 169 sizeof(*colormap)); 170 if ((pixels == (unsigned char *) NULL) || 171 (colormap == (unsigned char *) NULL)) 172 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 173 /* 174 Read image colormap. 175 */ 176 count=ReadBlob(image,packet_size*image->colors,colormap); 177 if (count != (ssize_t) (packet_size*image->colors)) 178 ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); 179 p=colormap; 180 if (image->depth <= 8) 181 for (i=0; i < (ssize_t) image->colors; i++) 182 { 183 image->colormap[i].red=ScaleCharToQuantum(*p++); 184 image->colormap[i].green=ScaleCharToQuantum(*p++); 185 image->colormap[i].blue=ScaleCharToQuantum(*p++); 186 } 187 else 188 for (i=0; i < (ssize_t) image->colors; i++) 189 { 190 quantum=(*p++ << 8); 191 quantum|=(*p++); 192 image->colormap[i].red=(Quantum) quantum; 193 quantum=(*p++ << 8); 194 quantum|=(*p++); 195 image->colormap[i].green=(Quantum) quantum; 196 quantum=(*p++ << 8); 197 quantum|=(*p++); 198 image->colormap[i].blue=(Quantum) quantum; 199 } 200 colormap=(unsigned char *) RelinquishMagickMemory(colormap); 201 if (image_info->ping != MagickFalse) 202 { 203 (void) CloseBlob(image); 204 return(GetFirstImageInList(image)); 205 } 206 /* 207 Read image pixels. 208 */ 209 packet_size=(size_t) (depth/8); 210 for (y=0; y < (ssize_t) image->rows; y++) 211 { 212 p=pixels; 213 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 214 if (q == (const Quantum *) NULL) 215 break; 216 count=ReadBlob(image,(size_t) packet_size*image->columns,pixels); 217 if (count != (ssize_t) (packet_size*image->columns)) 218 break; 219 for (x=0; x < (ssize_t) image->columns; x++) 220 { 221 index=ConstrainColormapIndex(image,*p); 222 p++; 223 if (image->colors > 256) 224 { 225 index=ConstrainColormapIndex(image,((size_t) index << 8)+(*p)); 226 p++; 227 } 228 SetPixelIndex(image,index,q); 229 SetPixelPacket(image,image->colormap+(ssize_t) index,q); 230 q+=GetPixelChannels(image); 231 } 232 if (SyncAuthenticPixels(image,exception) == MagickFalse) 233 break; 234 } 235 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 236 if (y < (ssize_t) image->rows) 237 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 238 image->filename); 239 (void) CloseBlob(image); 240 return(GetFirstImageInList(image)); 241} 242 243/* 244%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 245% % 246% % 247% % 248% R e g i s t e r M A P I m a g e % 249% % 250% % 251% % 252%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 253% 254% RegisterMAPImage() adds attributes for the MAP image format to 255% the list of supported formats. The attributes include the image format 256% tag, a method to read and/or write the format, whether the format 257% supports the saving of more than one frame to the same file or blob, 258% whether the format supports native in-memory I/O, and a brief 259% description of the format. 260% 261% The format of the RegisterMAPImage method is: 262% 263% size_t RegisterMAPImage(void) 264% 265*/ 266ModuleExport size_t RegisterMAPImage(void) 267{ 268 MagickInfo 269 *entry; 270 271 entry=SetMagickInfo("MAP"); 272 entry->decoder=(DecodeImageHandler *) ReadMAPImage; 273 entry->encoder=(EncodeImageHandler *) WriteMAPImage; 274 entry->adjoin=MagickFalse; 275 entry->format_type=ExplicitFormatType; 276 entry->raw=MagickTrue; 277 entry->endian_support=MagickTrue; 278 entry->description=ConstantString("Colormap intensities and indices"); 279 entry->module=ConstantString("MAP"); 280 (void) RegisterMagickInfo(entry); 281 return(MagickImageCoderSignature); 282} 283 284/* 285%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 286% % 287% % 288% % 289% U n r e g i s t e r M A P I m a g e % 290% % 291% % 292% % 293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 294% 295% UnregisterMAPImage() removes format registrations made by the 296% MAP module from the list of supported formats. 297% 298% The format of the UnregisterMAPImage method is: 299% 300% UnregisterMAPImage(void) 301% 302*/ 303ModuleExport void UnregisterMAPImage(void) 304{ 305 (void) UnregisterMagickInfo("MAP"); 306} 307 308/* 309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 310% % 311% % 312% % 313% W r i t e M A P I m a g e % 314% % 315% % 316% % 317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 318% 319% WriteMAPImage() writes an image to a file as red, green, and blue 320% colormap bytes followed by the colormap indexes. 321% 322% The format of the WriteMAPImage method is: 323% 324% MagickBooleanType WriteMAPImage(const ImageInfo *image_info, 325% Image *image,ExceptionInfo *exception) 326% 327% A description of each parameter follows. 328% 329% o image_info: the image info. 330% 331% o image: The image. 332% 333% o exception: return any errors or warnings in this structure. 334% 335*/ 336static MagickBooleanType WriteMAPImage(const ImageInfo *image_info,Image *image, 337 ExceptionInfo *exception) 338{ 339 MagickBooleanType 340 status; 341 342 register const Quantum 343 *p; 344 345 register ssize_t 346 i, 347 x; 348 349 register unsigned char 350 *q; 351 352 size_t 353 depth, 354 packet_size; 355 356 ssize_t 357 y; 358 359 unsigned char 360 *colormap, 361 *pixels; 362 363 /* 364 Open output image file. 365 */ 366 assert(image_info != (const ImageInfo *) NULL); 367 assert(image_info->signature == MagickSignature); 368 assert(image != (Image *) NULL); 369 assert(image->signature == MagickSignature); 370 if (image->debug != MagickFalse) 371 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 372 assert(exception != (ExceptionInfo *) NULL); 373 assert(exception->signature == MagickSignature); 374 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 375 if (status == MagickFalse) 376 return(status); 377 if (IsRGBColorspace(image->colorspace) == MagickFalse) 378 (void) TransformImageColorspace(image,RGBColorspace); 379 /* 380 Allocate colormap. 381 */ 382 if (IsPaletteImage(image,exception) == MagickFalse) 383 (void) SetImageType(image,PaletteType); 384 depth=GetImageQuantumDepth(image,MagickTrue); 385 packet_size=(size_t) (depth/8); 386 pixels=(unsigned char *) AcquireQuantumMemory(image->columns,packet_size* 387 sizeof(*pixels)); 388 packet_size=(size_t) (image->colors > 256 ? 6UL : 3UL); 389 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,packet_size* 390 sizeof(*colormap)); 391 if ((pixels == (unsigned char *) NULL) || 392 (colormap == (unsigned char *) NULL)) 393 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 394 /* 395 Write colormap to file. 396 */ 397 q=colormap; 398 if (image->depth <= 8) 399 for (i=0; i < (ssize_t) image->colors; i++) 400 { 401 *q++=(unsigned char) image->colormap[i].red; 402 *q++=(unsigned char) image->colormap[i].green; 403 *q++=(unsigned char) image->colormap[i].blue; 404 } 405 else 406 for (i=0; i < (ssize_t) image->colors; i++) 407 { 408 *q++=(unsigned char) ((size_t) image->colormap[i].red >> 8); 409 *q++=(unsigned char) image->colormap[i].red; 410 *q++=(unsigned char) ((size_t) image->colormap[i].green >> 8); 411 *q++=(unsigned char) image->colormap[i].green; 412 *q++=(unsigned char) ((size_t) image->colormap[i].blue >> 8); 413 *q++=(unsigned char) image->colormap[i].blue; 414 } 415 (void) WriteBlob(image,packet_size*image->colors,colormap); 416 colormap=(unsigned char *) RelinquishMagickMemory(colormap); 417 /* 418 Write image pixels to file. 419 */ 420 for (y=0; y < (ssize_t) image->rows; y++) 421 { 422 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 423 if (p == (const Quantum *) NULL) 424 break; 425 q=pixels; 426 for (x=0; x < (ssize_t) image->columns; x++) 427 { 428 if (image->colors > 256) 429 *q++=(unsigned char) ((size_t) GetPixelIndex(image,p) >> 8); 430 *q++=(unsigned char) GetPixelIndex(image,p); 431 p+=GetPixelChannels(image); 432 } 433 (void) WriteBlob(image,(size_t) (q-pixels),pixels); 434 } 435 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 436 (void) CloseBlob(image); 437 return(status); 438} 439