• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
64 static 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 */
IsMGK(const unsigned char * magick,const size_t length)93 static 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 */
ReadMGKImage(const ImageInfo * image_info,ExceptionInfo * exception)129 static 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 */
RegisterMGKImage(void)297 ModuleExport 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 */
UnregisterMGKImage(void)331 ModuleExport 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 */
WriteMGKImage(const ImageInfo * image_info,Image * image)362 static 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