/src/graphicsmagick/coders/art.c
Line | Count | Source |
1 | | /* |
2 | | % Copyright (C) 2003-2025 GraphicsMagick Group |
3 | | % Copyright (C) 2002 ImageMagick Studio |
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 | | % AAA RRRR TTTTT % |
13 | | % A A R R T % |
14 | | % AAAAA RRRR T % |
15 | | % A A R R T % |
16 | | % A A R R T % |
17 | | % % |
18 | | % % |
19 | | % Read/Write PFS: 1st Publisher Image Format. % |
20 | | % % |
21 | | % % |
22 | | % Software Design % |
23 | | % Jaroslav Fojtik % |
24 | | % January 2001 - 2007 % |
25 | | % % |
26 | | % % |
27 | | % % |
28 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
29 | | % |
30 | | % |
31 | | */ |
32 | | |
33 | | /* |
34 | | Include declarations. |
35 | | */ |
36 | | #include "magick/studio.h" |
37 | | #include "magick/blob.h" |
38 | | #include "magick/colormap.h" |
39 | | #include "magick/constitute.h" |
40 | | #include "magick/log.h" |
41 | | #include "magick/magick.h" |
42 | | #include "magick/monitor.h" |
43 | | #include "magick/pixel_cache.h" |
44 | | #include "magick/utility.h" |
45 | | #include "magick/static.h" |
46 | | |
47 | | /* |
48 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
49 | | % % |
50 | | % % |
51 | | % % |
52 | | % R e a d A R T I m a g e % |
53 | | % % |
54 | | % % |
55 | | % % |
56 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
57 | | % |
58 | | % Method ReadARTImage reads an ART X 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 ReadARTImage method is: |
63 | | % |
64 | | % Image *ReadARTImage(const ImageInfo *image_info,ExceptionInfo *exception) |
65 | | % |
66 | | % A description of each parameter follows: |
67 | | % |
68 | | % o image: Method ReadARTImage 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 *ReadARTImage(const ImageInfo *image_info,ExceptionInfo *exception) |
79 | 328 | { |
80 | 328 | Image *image; |
81 | 328 | unsigned int i; |
82 | 328 | unsigned int width,height,dummy; |
83 | 328 | long ldblk; |
84 | 328 | unsigned char *BImgBuff=NULL; |
85 | 328 | unsigned char Padding; |
86 | 328 | unsigned int status; |
87 | 328 | const PixelPacket *q; |
88 | | |
89 | | /* |
90 | | Open image file. |
91 | | */ |
92 | 328 | assert(image_info != (const ImageInfo *) NULL); |
93 | 328 | assert(image_info->signature == MagickSignature); |
94 | 328 | assert(exception != (ExceptionInfo *) NULL); |
95 | 328 | assert(exception->signature == MagickSignature); |
96 | 328 | image=AllocateImage(image_info); |
97 | 328 | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
98 | 328 | if (status == False) |
99 | 328 | ThrowReaderException(FileOpenError,UnableToOpenFile,image); |
100 | | /* |
101 | | Read ART image. |
102 | | */ |
103 | 328 | dummy=ReadBlobLSBShort(image); |
104 | 328 | width=ReadBlobLSBShort(image); |
105 | 328 | dummy=ReadBlobLSBShort(image); |
106 | 328 | height=ReadBlobLSBShort(image); |
107 | | |
108 | 328 | ldblk=(long) (((size_t) width+7) / 8); |
109 | 328 | Padding=(unsigned char) ((-ldblk) & 0x01); |
110 | | |
111 | 328 | image->columns=width; |
112 | 328 | image->rows=height; |
113 | 328 | if(GetBlobSize(image)!=(magick_off_t) (8+((size_t)ldblk+Padding)*image->rows)) |
114 | 240 | ThrowReaderException(CorruptImageError,ImproperImageHeader,image); |
115 | 240 | if (CheckImagePixelLimits(image, exception) != MagickPass) |
116 | 209 | ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); |
117 | 209 | image->depth=1; |
118 | 209 | image->colors=1l << image->depth; |
119 | | |
120 | | /* printf("ART header checked OK %d,%d\n",image->colors,image->depth); */ |
121 | | |
122 | 209 | if (!AllocateImageColormap(image,image->colors)) goto NoMemory; |
123 | | |
124 | | /* If ping is true, then only set image size and colors without reading any image data. */ |
125 | 209 | if (image_info->ping) goto DONE_READING; |
126 | | |
127 | 209 | BImgBuff=MagickAllocateResourceLimitedMemory(unsigned char *,((size_t) ldblk)); /*Ldblk was set in the check phase*/ |
128 | 209 | if (BImgBuff==NULL) |
129 | 0 | NoMemory: |
130 | 209 | ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); |
131 | | |
132 | 63.7k | for (i=0; i < height; i++) |
133 | 63.5k | { |
134 | 63.5k | if (ReadBlob(image,(size_t)ldblk,(char *)BImgBuff) != (size_t)ldblk) |
135 | 0 | break; |
136 | 63.5k | if (ReadBlob(image,Padding,(char *)&dummy) != Padding) |
137 | 0 | break; |
138 | | |
139 | 63.5k | q=SetImagePixelsEx(image,0,i,image->columns,1,exception); |
140 | 63.5k | if (q == (PixelPacket *)NULL) break; |
141 | 63.5k | (void)ImportImagePixelArea(image,GrayQuantum,1,BImgBuff,NULL,0); |
142 | 63.5k | if (!SyncImagePixelsEx(image,exception)) break; |
143 | 63.5k | } |
144 | 209 | MagickFreeResourceLimitedMemory(unsigned char *,BImgBuff); |
145 | | |
146 | 209 | if (i != height) |
147 | 209 | ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); |
148 | | |
149 | 209 | DONE_READING: |
150 | 209 | CloseBlob(image); |
151 | 209 | StopTimer(&image->timer); |
152 | 209 | return(image); |
153 | 209 | } |
154 | | |
155 | | |
156 | | /* |
157 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
158 | | % % |
159 | | % % |
160 | | % % |
161 | | % W r i t e A R T I m a g e % |
162 | | % % |
163 | | % % |
164 | | % % |
165 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
166 | | % |
167 | | % Function WriteARTImage writes an ART image to a file. |
168 | | % |
169 | | % The format of the WriteARTImage method is: |
170 | | % |
171 | | % unsigned int WriteARTImage(const ImageInfo *image_info,Image *image) |
172 | | % |
173 | | % A description of each parameter follows. |
174 | | % |
175 | | % o status: Function WriteARTImage return True if the image is written. |
176 | | % False is returned is there is a memory shortage or if the image file |
177 | | % fails to write. |
178 | | % |
179 | | % o image_info: Specifies a pointer to a ImageInfo structure. |
180 | | % |
181 | | % o image: A pointer to an Image structure. |
182 | | % |
183 | | */ |
184 | | static MagickPassFail WriteARTImage(const ImageInfo *image_info,Image *image) |
185 | 209 | { |
186 | 209 | long y; |
187 | 209 | unsigned dummy = 0; |
188 | 209 | size_t DataSize; |
189 | 209 | unsigned int status; |
190 | 209 | unsigned char Padding; |
191 | 209 | int logging; |
192 | 209 | unsigned char *pixels; |
193 | | |
194 | | /* |
195 | | Open output image file. |
196 | | */ |
197 | 209 | assert(image_info != (const ImageInfo *) NULL); |
198 | 209 | assert(image_info->signature == MagickSignature); |
199 | 209 | assert(image != (Image *) NULL); |
200 | 209 | assert(image->signature == MagickSignature); |
201 | 209 | logging=LogMagickEvent(CoderEvent,GetMagickModule(),"enter ART"); |
202 | 209 | status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); |
203 | 209 | if (status == MagickFail) |
204 | 209 | ThrowWriterException(FileOpenError,UnableToOpenFile,image); |
205 | | |
206 | 209 | DataSize = (long)((image->columns+7) / 8); |
207 | 209 | Padding = (unsigned char)((-(long) DataSize) & 0x01); |
208 | | |
209 | 209 | pixels=MagickAllocateResourceLimitedMemory(unsigned char *,(size_t) (DataSize)); |
210 | 209 | if (pixels == (unsigned char *) NULL) |
211 | 209 | ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image); |
212 | | |
213 | | /* |
214 | | Write ART hader. |
215 | | */ |
216 | 209 | (void) WriteBlobLSBShort(image,0); |
217 | 209 | (void) WriteBlobLSBShort(image,image->columns); |
218 | 209 | (void) WriteBlobLSBShort(image,0); |
219 | 209 | (void) WriteBlobLSBShort(image,image->rows); |
220 | | |
221 | | /* |
222 | | Store image data. |
223 | | */ |
224 | 63.7k | for(y=0; y<(long)image->rows; y++) |
225 | 63.5k | { |
226 | 63.5k | if (AcquireImagePixels(image,0,y,image->columns,1,&image->exception) |
227 | 63.5k | == (const PixelPacket *) NULL) |
228 | 0 | { |
229 | 0 | status=MagickFail; |
230 | 0 | break; |
231 | 0 | } |
232 | 63.5k | if (ExportImagePixelArea(image,GrayQuantum,1,pixels,0,0) != MagickPass) |
233 | 0 | { |
234 | 0 | status=MagickFail; |
235 | 0 | break; |
236 | 0 | } |
237 | 63.5k | if (WriteBlob(image,DataSize,pixels) != DataSize) |
238 | 0 | { |
239 | 0 | status=MagickFail; |
240 | 0 | break; |
241 | 0 | } |
242 | 63.5k | if (WriteBlob(image,Padding,(char *)&dummy) != Padding) |
243 | 0 | { |
244 | 0 | status=MagickFail; |
245 | 0 | break; |
246 | 0 | } |
247 | 63.5k | } |
248 | | |
249 | 209 | status &= CloseBlob(image); |
250 | 209 | MagickFreeResourceLimitedMemory(unsigned char *,pixels); |
251 | | |
252 | 209 | if (logging) |
253 | 0 | (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return ART"); |
254 | | |
255 | 209 | return(status); |
256 | 209 | } |
257 | | |
258 | | |
259 | | /* |
260 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
261 | | % % |
262 | | % % |
263 | | % % |
264 | | % R e g i s t e r A R T I m a g e % |
265 | | % % |
266 | | % % |
267 | | % % |
268 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
269 | | % |
270 | | % Method RegisterARTImage adds attributes for the ART image format to |
271 | | % the list of supported formats. The attributes include the image format |
272 | | % tag, a method to read and/or write the format, whether the format |
273 | | % supports the saving of more than one frame to the same file or blob, |
274 | | % whether the format supports native in-memory I/O, and a brief |
275 | | % description of the format. |
276 | | % |
277 | | % The format of the RegisterARTImage method is: |
278 | | % |
279 | | % RegisterARTImage(void) |
280 | | % |
281 | | */ |
282 | | ModuleExport void RegisterARTImage(void) |
283 | 1 | { |
284 | 1 | MagickInfo |
285 | 1 | *entry; |
286 | | |
287 | 1 | entry=SetMagickInfo("ART"); |
288 | 1 | entry->decoder = (DecoderHandler)ReadARTImage; |
289 | 1 | entry->encoder = (EncoderHandler)WriteARTImage; |
290 | 1 | entry->description="PFS: 1st Publisher"; |
291 | 1 | entry->module="ART"; |
292 | 1 | entry->adjoin=False; |
293 | 1 | (void) RegisterMagickInfo(entry); |
294 | 1 | } |
295 | | |
296 | | /* |
297 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
298 | | % % |
299 | | % % |
300 | | % % |
301 | | % U n r e g i s t e r A R T I m a g e % |
302 | | % % |
303 | | % % |
304 | | % % |
305 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
306 | | % |
307 | | % Method UnregisterARTImage removes format registrations made by the |
308 | | % ART module from the list of supported formats. |
309 | | % |
310 | | % The format of the UnregisterARTImage method is: |
311 | | % |
312 | | % UnregisterARTImage(void) |
313 | | % |
314 | | */ |
315 | | ModuleExport void UnregisterARTImage(void) |
316 | 0 | { |
317 | 0 | (void) UnregisterMagickInfo("ART"); |
318 | 0 | } |