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