1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% AAA AAA IIIII % 7% A A A A I % 8% AAAAA AAAAA I % 9% A A A A I % 10% A A A A IIIII % 11% % 12% % 13% Read/Write AAI X Image Format % 14% % 15% Software Design % 16% Cristy % 17% July 1992 % 18% % 19% % 20% Copyright 1999-2016 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/blob.h" 44#include "MagickCore/blob-private.h" 45#include "MagickCore/cache.h" 46#include "MagickCore/colorspace.h" 47#include "MagickCore/colorspace-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.h" 58#include "MagickCore/pixel-accessor.h" 59#include "MagickCore/quantum-private.h" 60#include "MagickCore/static.h" 61#include "MagickCore/string_.h" 62#include "MagickCore/module.h" 63 64/* 65 Forward declarations. 66*/ 67static MagickBooleanType 68 WriteAAIImage(const ImageInfo *,Image *,ExceptionInfo *); 69 70/* 71%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 72% % 73% % 74% % 75% R e a d A A I I m a g e % 76% % 77% % 78% % 79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 80% 81% ReadAAIImage() reads an AAI Dune image file and returns it. It 82% allocates the memory necessary for the new Image structure and returns a 83% pointer to the new image. 84% 85% The format of the ReadAAIImage method is: 86% 87% Image *ReadAAIImage(const ImageInfo *image_info,ExceptionInfo *exception) 88% 89% A description of each parameter follows: 90% 91% o image_info: the image info. 92% 93% o exception: return any errors or warnings in this structure. 94% 95*/ 96static Image *ReadAAIImage(const ImageInfo *image_info,ExceptionInfo *exception) 97{ 98 Image 99 *image; 100 101 MagickBooleanType 102 status; 103 104 register ssize_t 105 x; 106 107 register Quantum 108 *q; 109 110 register unsigned char 111 *p; 112 113 size_t 114 height, 115 length, 116 width; 117 118 ssize_t 119 count, 120 y; 121 122 unsigned char 123 *pixels; 124 125 /* 126 Open image file. 127 */ 128 assert(image_info != (const ImageInfo *) NULL); 129 assert(image_info->signature == MagickCoreSignature); 130 if (image_info->debug != MagickFalse) 131 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 132 image_info->filename); 133 assert(exception != (ExceptionInfo *) NULL); 134 assert(exception->signature == MagickCoreSignature); 135 image=AcquireImage(image_info,exception); 136 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 137 if (status == MagickFalse) 138 { 139 image=DestroyImageList(image); 140 return((Image *) NULL); 141 } 142 /* 143 Read AAI Dune image. 144 */ 145 width=ReadBlobLSBLong(image); 146 height=ReadBlobLSBLong(image); 147 if (EOFBlob(image) != MagickFalse) 148 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 149 if ((width == 0UL) || (height == 0UL)) 150 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 151 do 152 { 153 /* 154 Convert AAI raster image to pixel packets. 155 */ 156 image->columns=width; 157 image->rows=height; 158 image->depth=8; 159 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) 160 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 161 break; 162 status=SetImageExtent(image,image->columns,image->rows,exception); 163 if (status == MagickFalse) 164 return(DestroyImageList(image)); 165 pixels=(unsigned char *) AcquireQuantumMemory(image->columns, 166 4*sizeof(*pixels)); 167 if (pixels == (unsigned char *) NULL) 168 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 169 length=(size_t) 4*image->columns; 170 for (y=0; y < (ssize_t) image->rows; y++) 171 { 172 count=ReadBlob(image,length,pixels); 173 if (count != (ssize_t) length) 174 ThrowReaderException(CorruptImageError,"UnableToReadImageData"); 175 p=pixels; 176 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 177 if (q == (Quantum *) NULL) 178 break; 179 for (x=0; x < (ssize_t) image->columns; x++) 180 { 181 SetPixelBlue(image,ScaleCharToQuantum(*p++),q); 182 SetPixelGreen(image,ScaleCharToQuantum(*p++),q); 183 SetPixelRed(image,ScaleCharToQuantum(*p++),q); 184 if (*p == 254) 185 *p=255; 186 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q); 187 if (GetPixelAlpha(image,q) != OpaqueAlpha) 188 image->alpha_trait=BlendPixelTrait; 189 q+=GetPixelChannels(image); 190 } 191 if (SyncAuthenticPixels(image,exception) == MagickFalse) 192 break; 193 if (image->previous == (Image *) NULL) 194 { 195 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 196 image->rows); 197 if (status == MagickFalse) 198 break; 199 } 200 } 201 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 202 if (EOFBlob(image) != MagickFalse) 203 { 204 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 205 image->filename); 206 break; 207 } 208 /* 209 Proceed to next image. 210 */ 211 if (image_info->number_scenes != 0) 212 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 213 break; 214 width=ReadBlobLSBLong(image); 215 height=ReadBlobLSBLong(image); 216 if ((width != 0UL) && (height != 0UL)) 217 { 218 /* 219 Allocate next image structure. 220 */ 221 AcquireNextImage(image_info,image,exception); 222 if (GetNextImageInList(image) == (Image *) NULL) 223 { 224 image=DestroyImageList(image); 225 return((Image *) NULL); 226 } 227 image=SyncNextImageInList(image); 228 status=SetImageProgress(image,LoadImagesTag,TellBlob(image), 229 GetBlobSize(image)); 230 if (status == MagickFalse) 231 break; 232 } 233 } while ((width != 0UL) && (height != 0UL)); 234 (void) CloseBlob(image); 235 return(GetFirstImageInList(image)); 236} 237 238/* 239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 240% % 241% % 242% % 243% R e g i s t e r A A I I m a g e % 244% % 245% % 246% % 247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 248% 249% RegisterAAIImage() adds attributes for the AAI Dune image format to the list 250% of supported formats. The attributes include the image format tag, a 251% method to read and/or write the format, whether the format supports the 252% saving of more than one frame to the same file or blob, whether the format 253% supports native in-memory I/O, and a brief description of the format. 254% 255% The format of the RegisterAAIImage method is: 256% 257% size_t RegisterAAIImage(void) 258% 259*/ 260ModuleExport size_t RegisterAAIImage(void) 261{ 262 MagickInfo 263 *entry; 264 265 entry=AcquireMagickInfo("AAI","AAI","AAI Dune image"); 266 entry->decoder=(DecodeImageHandler *) ReadAAIImage; 267 entry->encoder=(EncodeImageHandler *) WriteAAIImage; 268 (void) RegisterMagickInfo(entry); 269 return(MagickImageCoderSignature); 270} 271 272/* 273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 274% % 275% % 276% % 277% U n r e g i s t e r A A I I m a g e % 278% % 279% % 280% % 281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 282% 283% UnregisterAAIImage() removes format registrations made by the 284% AAI module from the list of supported formats. 285% 286% The format of the UnregisterAAIImage method is: 287% 288% UnregisterAAIImage(void) 289% 290*/ 291ModuleExport void UnregisterAAIImage(void) 292{ 293 (void) UnregisterMagickInfo("AAI"); 294} 295 296/* 297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 298% % 299% % 300% % 301% W r i t e A A I I m a g e % 302% % 303% % 304% % 305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 306% 307% WriteAAIImage() writes an image to a file in AAI Dune image format. 308% 309% The format of the WriteAAIImage method is: 310% 311% MagickBooleanType WriteAAIImage(const ImageInfo *image_info, 312% Image *image,ExceptionInfo *exception) 313% 314% A description of each parameter follows. 315% 316% o image_info: the image info. 317% 318% o image: The image. 319% 320% o exception: return any errors or warnings in this structure. 321% 322*/ 323static MagickBooleanType WriteAAIImage(const ImageInfo *image_info,Image *image, 324 ExceptionInfo *exception) 325{ 326 MagickBooleanType 327 status; 328 329 MagickOffsetType 330 scene; 331 332 register const Quantum 333 *magick_restrict p; 334 335 register ssize_t 336 x; 337 338 register unsigned char 339 *magick_restrict q; 340 341 ssize_t 342 count, 343 y; 344 345 unsigned char 346 *pixels; 347 348 /* 349 Open output image file. 350 */ 351 assert(image_info != (const ImageInfo *) NULL); 352 assert(image_info->signature == MagickCoreSignature); 353 assert(image != (Image *) NULL); 354 assert(image->signature == MagickCoreSignature); 355 if (image->debug != MagickFalse) 356 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 357 assert(exception != (ExceptionInfo *) NULL); 358 assert(exception->signature == MagickCoreSignature); 359 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 360 if (status == MagickFalse) 361 return(status); 362 scene=0; 363 do 364 { 365 /* 366 Write AAI header. 367 */ 368 (void) TransformImageColorspace(image,sRGBColorspace,exception); 369 (void) WriteBlobLSBLong(image,(unsigned int) image->columns); 370 (void) WriteBlobLSBLong(image,(unsigned int) image->rows); 371 /* 372 Allocate memory for pixels. 373 */ 374 pixels=(unsigned char *) AcquireQuantumMemory(image->columns, 375 4*sizeof(*pixels)); 376 if (pixels == (unsigned char *) NULL) 377 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 378 /* 379 Convert MIFF to AAI raster pixels. 380 */ 381 for (y=0; y < (ssize_t) image->rows; y++) 382 { 383 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 384 if (p == (const Quantum *) NULL) 385 break; 386 q=pixels; 387 for (x=0; x < (ssize_t) image->columns; x++) 388 { 389 *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); 390 *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); 391 *q++=ScaleQuantumToChar(GetPixelRed(image,p)); 392 *q=ScaleQuantumToChar((Quantum) (image->alpha_trait != 393 UndefinedPixelTrait ? GetPixelAlpha(image,p) : OpaqueAlpha)); 394 if (*q == 255) 395 *q=254; 396 p+=GetPixelChannels(image); 397 q++; 398 } 399 count=WriteBlob(image,(size_t) (q-pixels),pixels); 400 if (count != (ssize_t) (q-pixels)) 401 break; 402 if (image->previous == (Image *) NULL) 403 { 404 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 405 image->rows); 406 if (status == MagickFalse) 407 break; 408 } 409 } 410 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 411 if (GetNextImageInList(image) == (Image *) NULL) 412 break; 413 image=SyncNextImageInList(image); 414 status=SetImageProgress(image,SaveImagesTag,scene++, 415 GetImageListLength(image)); 416 if (status == MagickFalse) 417 break; 418 } while (image_info->adjoin != MagickFalse); 419 (void) CloseBlob(image); 420 return(MagickTrue); 421} 422