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