/src/graphicsmagick/coders/mac.c
Line | Count | Source |
1 | | /* |
2 | | % Copyright (C) 2010-2025 GraphicsMagick Group |
3 | | % SPDX-License-Identifier: MIT |
4 | | % |
5 | | % This program is covered by multiple licenses, which are described in |
6 | | % Copyright.txt. You should have received a copy of Copyright.txt with this |
7 | | % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. |
8 | | % |
9 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
10 | | % % |
11 | | % % |
12 | | % M M AAA CCC % |
13 | | % MM MM A A C % |
14 | | % M M M AAAAA C % |
15 | | % M M A A C % |
16 | | % M M A A CCC % |
17 | | % % |
18 | | % Read MAC: MacPaint Image Format. % |
19 | | % % |
20 | | % % |
21 | | % Software Design % |
22 | | % Jaroslav Fojtik % |
23 | | % 2010 % |
24 | | % % |
25 | | % % |
26 | | % % |
27 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
28 | | % |
29 | | % |
30 | | */ |
31 | | |
32 | | /* |
33 | | Include declarations. |
34 | | */ |
35 | | #include "magick/studio.h" |
36 | | #include "magick/blob.h" |
37 | | #include "magick/colormap.h" |
38 | | #include "magick/constitute.h" |
39 | | #include "magick/log.h" |
40 | | #include "magick/magick.h" |
41 | | #include "magick/monitor.h" |
42 | | #include "magick/pixel_cache.h" |
43 | | #include "magick/utility.h" |
44 | | #include "magick/static.h" |
45 | | |
46 | | |
47 | | /* |
48 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
49 | | % % |
50 | | % % |
51 | | % % |
52 | | % R e a d M A C I m a g e % |
53 | | % % |
54 | | % % |
55 | | % % |
56 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
57 | | % |
58 | | % Method ReadMACImage reads an MAC image file and returns it. It |
59 | | % allocates the memory necessary for the new Image structure and returns a |
60 | | % pointer to the new image. |
61 | | % |
62 | | % The format of the ReadMACImage method is: |
63 | | % |
64 | | % Image *ReadMACImage(const ImageInfo *image_info,ExceptionInfo *exception) |
65 | | % |
66 | | % A description of each parameter follows: |
67 | | % |
68 | | % o image: Method ReadMACImage returns a pointer to the image after |
69 | | % reading. A null image is returned if there is a memory shortage or if |
70 | | % the image cannot be read. |
71 | | % |
72 | | % o image_info: Specifies a pointer to a ImageInfo structure. |
73 | | % |
74 | | % o exception: return any errors or warnings in this structure. |
75 | | % |
76 | | % |
77 | | */ |
78 | | static Image *ReadMACImage(const ImageInfo *image_info,ExceptionInfo *exception) |
79 | 287 | { |
80 | 287 | Image *image; |
81 | 287 | unsigned int y; |
82 | 287 | unsigned char x8, rep, b; |
83 | 287 | size_t ldblk; |
84 | 287 | unsigned char *BImgBuff = NULL; |
85 | 287 | unsigned char *DataPtr; |
86 | 287 | unsigned int status; |
87 | 287 | const PixelPacket *q; |
88 | | |
89 | | /* Open image file. */ |
90 | 287 | assert(image_info != (const ImageInfo *) NULL); |
91 | 287 | assert(image_info->signature == MagickSignature); |
92 | 287 | assert(exception != (ExceptionInfo *) NULL); |
93 | 287 | assert(exception->signature == MagickSignature); |
94 | 287 | image = AllocateImage(image_info); |
95 | 287 | status = OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
96 | 287 | if (status == False) |
97 | 287 | ThrowReaderException(FileOpenError,UnableToOpenFile,image); |
98 | | |
99 | | /* Read MAC image. */ |
100 | 287 | ldblk = ReadBlobLSBShort(image); |
101 | 287 | if ((ldblk & 0xFF)!=0) |
102 | 271 | ThrowReaderException(CorruptImageError,ImproperImageHeader,image); |
103 | | |
104 | 271 | if (ldblk==0) /* ???? don't know why */ |
105 | 226 | SeekBlob(image,0x200,SEEK_SET); |
106 | 45 | else |
107 | 45 | SeekBlob(image,0x280,SEEK_SET); |
108 | | |
109 | 271 | image->columns = 576; |
110 | 271 | image->rows = 720; |
111 | 271 | image->depth = 1; |
112 | 271 | image->colors = 1l << image->depth; |
113 | | |
114 | 271 | if (!AllocateImageColormap(image,image->colors)) goto NoMemory; |
115 | | |
116 | | /* If ping is true, then only set image size and colors without reading any image data. */ |
117 | 271 | if (image_info->ping) goto DONE_READING; |
118 | | |
119 | | /* ----- Load RLE compressed raster ----- */ |
120 | 271 | ldblk = (MagickArraySize(image->depth,image->columns)) /8; |
121 | 271 | BImgBuff = MagickAllocateResourceLimitedMemory(unsigned char *,ldblk); |
122 | 271 | if (BImgBuff==NULL) |
123 | 0 | NoMemory: |
124 | 271 | ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); |
125 | | |
126 | 271 | DataPtr = BImgBuff; |
127 | 271 | x8=0; y=0; |
128 | | |
129 | 1.30M | while (y<image->rows) |
130 | 1.30M | { |
131 | 1.30M | rep = ReadBlobByte(image); |
132 | 1.30M | if(EOFBlob(image)) break; |
133 | | |
134 | 1.30M | if ( rep>=128 || rep<= 0) |
135 | 1.29M | { |
136 | 1.29M | b = ~ReadBlobByte(image);; |
137 | | |
138 | 1.29M | rep = ~rep + 2; |
139 | 5.39M | while (rep>0) |
140 | 4.09M | { |
141 | 4.09M | *DataPtr++ = b; |
142 | 4.09M | x8++; |
143 | 4.09M | rep--; |
144 | 4.09M | if(x8>=ldblk) |
145 | 56.6k | { |
146 | 56.6k | x8=0; |
147 | | |
148 | 56.6k | q = SetImagePixels(image,0,y,image->columns,1); |
149 | 56.6k | if (q == (PixelPacket *)NULL) break; |
150 | 56.6k | (void)ImportImagePixelArea(image,GrayQuantum,1,BImgBuff,NULL,0); |
151 | 56.6k | if (!SyncImagePixels(image)) break; |
152 | | |
153 | 56.6k | DataPtr = BImgBuff; |
154 | 56.6k | y++; |
155 | 56.6k | if ( y >= image->rows ) |
156 | 23 | { |
157 | 23 | break; |
158 | 23 | } |
159 | 56.6k | } |
160 | 4.09M | } |
161 | 1.29M | } |
162 | 12.7k | else |
163 | 12.7k | { |
164 | 12.7k | rep++; |
165 | 722k | while ( rep > 0 ) |
166 | 709k | { |
167 | 709k | b = ~ReadBlobByte(image); |
168 | 709k | *DataPtr++ = b; |
169 | 709k | x8++; |
170 | 709k | rep--; |
171 | 709k | if ( x8>=ldblk ) |
172 | 10.0k | { |
173 | 10.0k | x8=0; |
174 | | |
175 | 10.0k | q = SetImagePixels(image,0,y,image->columns,1); |
176 | 10.0k | if (q == (PixelPacket *)NULL) break; |
177 | 10.0k | (void)ImportImagePixelArea(image,GrayQuantum,1,BImgBuff,NULL,0); |
178 | 10.0k | if (!SyncImagePixels(image)) break; |
179 | | |
180 | 10.0k | DataPtr = BImgBuff; |
181 | 10.0k | y++; |
182 | 10.0k | if ( y >= image->rows ) |
183 | 7 | { |
184 | 7 | break; |
185 | 7 | } |
186 | 10.0k | } |
187 | 709k | } |
188 | 12.7k | } |
189 | 1.30M | } |
190 | 271 | if (BImgBuff!=NULL) |
191 | 271 | MagickFreeResourceLimitedMemory(unsigned char *,BImgBuff); |
192 | 271 | if (EOFBlob(image)) |
193 | 244 | ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,image->filename); |
194 | | |
195 | 271 | DONE_READING: |
196 | 271 | CloseBlob(image); |
197 | 271 | StopTimer(&image->timer); |
198 | 271 | return(image); |
199 | 271 | } |
200 | | |
201 | | |
202 | | /* |
203 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
204 | | % % |
205 | | % % |
206 | | % % |
207 | | % R e g i s t e r M A C I m a g e % |
208 | | % % |
209 | | % % |
210 | | % % |
211 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
212 | | % |
213 | | % Method RegisterMACImage adds attributes for the MAC image format to |
214 | | % the list of supported formats. The attributes include the image format |
215 | | % tag, a method to read and/or write the format, whether the format |
216 | | % supports the saving of more than one frame to the same file or blob, |
217 | | % whether the format supports native in-memory I/O, and a brief |
218 | | % description of the format. |
219 | | % |
220 | | % The format of the RegisterMACImage method is: |
221 | | % |
222 | | % RegisterMACImage(void) |
223 | | */ |
224 | | ModuleExport void RegisterMACImage(void) |
225 | 1 | { |
226 | 1 | MagickInfo *entry; |
227 | | |
228 | 1 | entry=SetMagickInfo("MAC"); |
229 | 1 | entry->decoder = (DecoderHandler)ReadMACImage; |
230 | 1 | entry->description="Mac Paint"; |
231 | 1 | entry->seekable_stream = True; |
232 | 1 | entry->module="MAC"; |
233 | 1 | (void) RegisterMagickInfo(entry); |
234 | 1 | } |
235 | | |
236 | | /* |
237 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
238 | | % % |
239 | | % % |
240 | | % % |
241 | | % U n r e g i s t e r M A C I m a g e % |
242 | | % % |
243 | | % % |
244 | | % % |
245 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
246 | | % |
247 | | % Method UnregisterMACImage removes format registrations made by the |
248 | | % MAC module from the list of supported formats. |
249 | | % |
250 | | % The format of the UnregisterMACImage method is: |
251 | | % |
252 | | % UnregisterMACImage(void) |
253 | | % |
254 | | */ |
255 | | ModuleExport void UnregisterMACImage(void) |
256 | 0 | { |
257 | 0 | (void) UnregisterMagickInfo("MAC"); |
258 | 0 | } |