1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                                                                             %
7%                            M   M   AAA    CCCC                              %
8%                            MM MM  A   A  C                                  %
9%                            M M M  AAAAA  C                                  %
10%                            M   M  A   A  C                                  %
11%                            M   M  A   A   CCCC                              %
12%                                                                             %
13%                                                                             %
14%                         Read MacPaint Image Format                          %
15%                                                                             %
16%                              Software Design                                %
17%                                   Cristy                                    %
18%                                 July 1992                                   %
19%                                                                             %
20%                                                                             %
21%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
22%  dedicated to making software imaging solutions freely available.           %
23%                                                                             %
24%  You may not use this file except in compliance with the License.  You may  %
25%  obtain a copy of the License at                                            %
26%                                                                             %
27%    http://www.imagemagick.org/script/license.php                            %
28%                                                                             %
29%  Unless required by applicable law or agreed to in writing, software        %
30%  distributed under the License is distributed on an "AS IS" BASIS,          %
31%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
32%  See the License for the specific language governing permissions and        %
33%  limitations under the License.                                             %
34%                                                                             %
35%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36%
37%
38*/
39
40/*
41  Include declarations.
42*/
43#include "MagickCore/studio.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/colormap.h"
48#include "MagickCore/colorspace.h"
49#include "MagickCore/exception.h"
50#include "MagickCore/exception-private.h"
51#include "MagickCore/image.h"
52#include "MagickCore/image-private.h"
53#include "MagickCore/list.h"
54#include "MagickCore/magick.h"
55#include "MagickCore/memory_.h"
56#include "MagickCore/monitor.h"
57#include "MagickCore/monitor-private.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%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
66%                                                                             %
67%                                                                             %
68%                                                                             %
69%   R e a d M A C I m a g e                                                   %
70%                                                                             %
71%                                                                             %
72%                                                                             %
73%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74%
75%  ReadMACImage() reads an MacPaint image file and returns it.  It
76%  allocates the memory necessary for the new Image structure and returns a
77%  pointer to the new image.
78%
79%  The format of the ReadMACImage method is:
80%
81%      Image *ReadMACImage(const ImageInfo *image_info,ExceptionInfo *exception)
82%
83%  A description of each parameter follows:
84%
85%    o image_info: the image info.
86%
87%    o exception: return any errors or warnings in this structure.
88%
89*/
90static Image *ReadMACImage(const ImageInfo *image_info,ExceptionInfo *exception)
91{
92  Image
93    *image;
94
95  MagickBooleanType
96    status;
97
98  register Quantum
99    *q;
100
101  register ssize_t
102    x;
103
104  register unsigned char
105    *p;
106
107  size_t
108    length;
109
110  ssize_t
111    offset,
112    y;
113
114  unsigned char
115    count,
116    bit,
117    byte,
118    *pixels;
119
120  /*
121    Open image file.
122  */
123  assert(image_info != (const ImageInfo *) NULL);
124  assert(image_info->signature == MagickCoreSignature);
125  if (image_info->debug != MagickFalse)
126    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
127      image_info->filename);
128  assert(exception != (ExceptionInfo *) NULL);
129  assert(exception->signature == MagickCoreSignature);
130  image=AcquireImage(image_info,exception);
131  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
132  if (status == MagickFalse)
133    {
134      image=DestroyImageList(image);
135      return((Image *) NULL);
136    }
137  /*
138    Read MAC X image.
139  */
140  length=ReadBlobLSBShort(image);
141  if ((length & 0xff) != 0)
142    ThrowReaderException(CorruptImageError,"CorruptImage");
143  for (x=0; x < (ssize_t) 638; x++)
144    if (ReadBlobByte(image) == EOF)
145      ThrowReaderException(CorruptImageError,"CorruptImage");
146  image->columns=576;
147  image->rows=720;
148  image->depth=1;
149  if (AcquireImageColormap(image,2,exception) == MagickFalse)
150    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
151  if (image_info->ping != MagickFalse)
152    {
153      (void) CloseBlob(image);
154      return(GetFirstImageInList(image));
155    }
156  status=SetImageExtent(image,image->columns,image->rows,exception);
157  if (status == MagickFalse)
158    return(DestroyImageList(image));
159  /*
160    Convert MAC raster image to pixel packets.
161  */
162  length=(image->columns+7)/8;
163  pixels=(unsigned char *) AcquireQuantumMemory(length+1,sizeof(*pixels));
164  if (pixels == (unsigned char *) NULL)
165    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
166  p=pixels;
167  offset=0;
168  for (y=0; y < (ssize_t) image->rows; )
169  {
170    count=(unsigned char) ReadBlobByte(image);
171    if (EOFBlob(image) != MagickFalse)
172      break;
173    if ((count <= 0) || (count >= 128))
174      {
175        byte=(unsigned char) (~ReadBlobByte(image));
176        count=(~count)+2;
177        while (count != 0)
178        {
179          *p++=byte;
180          offset++;
181          count--;
182          if (offset >= (ssize_t) length)
183            {
184              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
185              if (q == (Quantum *) NULL)
186                break;
187              p=pixels;
188              bit=0;
189              byte=0;
190              for (x=0; x < (ssize_t) image->columns; x++)
191              {
192                if (bit == 0)
193                  byte=(*p++);
194                SetPixelIndex(image,((byte & 0x80) != 0 ? 0x01 : 0x00),q);
195                bit++;
196                byte<<=1;
197                if (bit == 8)
198                  bit=0;
199                q+=GetPixelChannels(image);
200              }
201              if (SyncAuthenticPixels(image,exception) == MagickFalse)
202                break;
203              offset=0;
204              p=pixels;
205              y++;
206            }
207        }
208        continue;
209      }
210    count++;
211    while (count != 0)
212    {
213      byte=(unsigned char) (~ReadBlobByte(image));
214      *p++=byte;
215      offset++;
216      count--;
217      if (offset >= (ssize_t) length)
218        {
219          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
220          if (q == (Quantum *) NULL)
221            break;
222          p=pixels;
223          bit=0;
224          byte=0;
225          for (x=0; x < (ssize_t) image->columns; x++)
226          {
227            if (bit == 0)
228              byte=(*p++);
229            SetPixelIndex(image,((byte & 0x80) != 0 ? 0x01 : 0x00),q);
230            bit++;
231            byte<<=1;
232            if (bit == 8)
233              bit=0;
234            q+=GetPixelChannels(image);
235          }
236          if (SyncAuthenticPixels(image,exception) == MagickFalse)
237            break;
238          offset=0;
239          p=pixels;
240          y++;
241        }
242    }
243  }
244  pixels=(unsigned char *) RelinquishMagickMemory(pixels);
245  (void) SyncImage(image,exception);
246  (void) CloseBlob(image);
247  return(GetFirstImageInList(image));
248}
249
250/*
251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252%                                                                             %
253%                                                                             %
254%                                                                             %
255%   R e g i s t e r M A C I m a g e                                           %
256%                                                                             %
257%                                                                             %
258%                                                                             %
259%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260%
261%  RegisterMACImage() adds attributes for the MAC X image format to the list
262%  of supported formats.  The attributes include the image format tag, a
263%  method to read and/or write the format, whether the format supports the
264%  saving of more than one frame to the same file or blob, whether the format
265%  supports native in-memory I/O, and a brief description of the format.
266%
267%  The format of the RegisterMACImage method is:
268%
269%      size_t RegisterMACImage(void)
270%
271*/
272ModuleExport size_t RegisterMACImage(void)
273{
274  MagickInfo
275    *entry;
276
277  entry=AcquireMagickInfo("MAC","MAC","MAC Paint");
278  entry->decoder=(DecodeImageHandler *) ReadMACImage;
279  (void) RegisterMagickInfo(entry);
280  return(MagickImageCoderSignature);
281}
282
283/*
284%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
285%                                                                             %
286%                                                                             %
287%                                                                             %
288%   U n r e g i s t e r M A C I m a g e                                       %
289%                                                                             %
290%                                                                             %
291%                                                                             %
292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293%
294%  UnregisterMACImage() removes format registrations made by the
295%  MAC module from the list of supported formats.
296%
297%  The format of the UnregisterMACImage method is:
298%
299%      UnregisterMACImage(void)
300%
301*/
302ModuleExport void UnregisterMACImage(void)
303{
304  (void) UnregisterMagickInfo("MAC");
305}
306