map.c revision fe676ee3a9cf43404bdc9ba8b27f597b5e4e28f7
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-2014 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,exception); 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),exception); 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 == (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,exception); 222 p++; 223 if (image->colors > 256) 224 { 225 index=ConstrainColormapIndex(image,((size_t) index << 8)+(*p), 226 exception); 227 p++; 228 } 229 SetPixelIndex(image,index,q); 230 SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q); 231 q+=GetPixelChannels(image); 232 } 233 if (SyncAuthenticPixels(image,exception) == MagickFalse) 234 break; 235 } 236 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 237 if (y < (ssize_t) image->rows) 238 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 239 image->filename); 240 (void) CloseBlob(image); 241 return(GetFirstImageInList(image)); 242} 243 244/* 245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 246% % 247% % 248% % 249% R e g i s t e r M A P I m a g e % 250% % 251% % 252% % 253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 254% 255% RegisterMAPImage() adds attributes for the MAP image format to 256% the list of supported formats. The attributes include the image format 257% tag, a method to read and/or write the format, whether the format 258% supports the saving of more than one frame to the same file or blob, 259% whether the format supports native in-memory I/O, and a brief 260% description of the format. 261% 262% The format of the RegisterMAPImage method is: 263% 264% size_t RegisterMAPImage(void) 265% 266*/ 267ModuleExport size_t RegisterMAPImage(void) 268{ 269 MagickInfo 270 *entry; 271 272 entry=SetMagickInfo("MAP"); 273 entry->decoder=(DecodeImageHandler *) ReadMAPImage; 274 entry->encoder=(EncodeImageHandler *) WriteMAPImage; 275 entry->adjoin=MagickFalse; 276 entry->format_type=ExplicitFormatType; 277 entry->raw=MagickTrue; 278 entry->endian_support=MagickTrue; 279 entry->description=ConstantString("Colormap intensities and indices"); 280 entry->module=ConstantString("MAP"); 281 (void) RegisterMagickInfo(entry); 282 return(MagickImageCoderSignature); 283} 284 285/* 286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 287% % 288% % 289% % 290% U n r e g i s t e r M A P I m a g e % 291% % 292% % 293% % 294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 295% 296% UnregisterMAPImage() removes format registrations made by the 297% MAP module from the list of supported formats. 298% 299% The format of the UnregisterMAPImage method is: 300% 301% UnregisterMAPImage(void) 302% 303*/ 304ModuleExport void UnregisterMAPImage(void) 305{ 306 (void) UnregisterMagickInfo("MAP"); 307} 308 309/* 310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 311% % 312% % 313% % 314% W r i t e M A P I m a g e % 315% % 316% % 317% % 318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 319% 320% WriteMAPImage() writes an image to a file as red, green, and blue 321% colormap bytes followed by the colormap indexes. 322% 323% The format of the WriteMAPImage method is: 324% 325% MagickBooleanType WriteMAPImage(const ImageInfo *image_info, 326% Image *image,ExceptionInfo *exception) 327% 328% A description of each parameter follows. 329% 330% o image_info: the image info. 331% 332% o image: The image. 333% 334% o exception: return any errors or warnings in this structure. 335% 336*/ 337static MagickBooleanType WriteMAPImage(const ImageInfo *image_info,Image *image, 338 ExceptionInfo *exception) 339{ 340 MagickBooleanType 341 status; 342 343 register const Quantum 344 *p; 345 346 register ssize_t 347 i, 348 x; 349 350 register unsigned char 351 *q; 352 353 size_t 354 depth, 355 packet_size; 356 357 ssize_t 358 y; 359 360 unsigned char 361 *colormap, 362 *pixels; 363 364 /* 365 Open output image file. 366 */ 367 assert(image_info != (const ImageInfo *) NULL); 368 assert(image_info->signature == MagickSignature); 369 assert(image != (Image *) NULL); 370 assert(image->signature == MagickSignature); 371 if (image->debug != MagickFalse) 372 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 373 assert(exception != (ExceptionInfo *) NULL); 374 assert(exception->signature == MagickSignature); 375 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 376 if (status == MagickFalse) 377 return(status); 378 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse) 379 (void) TransformImageColorspace(image,sRGBColorspace,exception); 380 /* 381 Allocate colormap. 382 */ 383 if (IsPaletteImage(image,exception) == MagickFalse) 384 (void) SetImageType(image,PaletteType,exception); 385 depth=GetImageQuantumDepth(image,MagickTrue); 386 packet_size=(size_t) (depth/8); 387 pixels=(unsigned char *) AcquireQuantumMemory(image->columns,packet_size* 388 sizeof(*pixels)); 389 packet_size=(size_t) (image->colors > 256 ? 6UL : 3UL); 390 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,packet_size* 391 sizeof(*colormap)); 392 if ((pixels == (unsigned char *) NULL) || 393 (colormap == (unsigned char *) NULL)) 394 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 395 /* 396 Write colormap to file. 397 */ 398 q=colormap; 399 if (image->depth <= 8) 400 for (i=0; i < (ssize_t) image->colors; i++) 401 { 402 *q++=(unsigned char) image->colormap[i].red; 403 *q++=(unsigned char) image->colormap[i].green; 404 *q++=(unsigned char) image->colormap[i].blue; 405 } 406 else 407 for (i=0; i < (ssize_t) image->colors; i++) 408 { 409 *q++=(unsigned char) ((size_t) image->colormap[i].red >> 8); 410 *q++=(unsigned char) image->colormap[i].red; 411 *q++=(unsigned char) ((size_t) image->colormap[i].green >> 8); 412 *q++=(unsigned char) image->colormap[i].green; 413 *q++=(unsigned char) ((size_t) image->colormap[i].blue >> 8); 414 *q++=(unsigned char) image->colormap[i].blue; 415 } 416 (void) WriteBlob(image,packet_size*image->colors,colormap); 417 colormap=(unsigned char *) RelinquishMagickMemory(colormap); 418 /* 419 Write image pixels to file. 420 */ 421 for (y=0; y < (ssize_t) image->rows; y++) 422 { 423 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 424 if (p == (const Quantum *) NULL) 425 break; 426 q=pixels; 427 for (x=0; x < (ssize_t) image->columns; x++) 428 { 429 if (image->colors > 256) 430 *q++=(unsigned char) ((size_t) GetPixelIndex(image,p) >> 8); 431 *q++=(unsigned char) GetPixelIndex(image,p); 432 p+=GetPixelChannels(image); 433 } 434 (void) WriteBlob(image,(size_t) (q-pixels),pixels); 435 } 436 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 437 (void) CloseBlob(image); 438 return(status); 439} 440