1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % AAA RRRR TTTTT %
7 % A A R R T %
8 % AAAAA RRRR T %
9 % A A R R T %
10 % A A R R T %
11 % %
12 % %
13 % Support PFS: 1st Publisher Clip Art Format %
14 % %
15 % Software Design %
16 % 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/attribute.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/color-private.h"
48 #include "MagickCore/colormap.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/colorspace-private.h"
51 #include "MagickCore/exception.h"
52 #include "MagickCore/exception-private.h"
53 #include "MagickCore/image.h"
54 #include "MagickCore/image-private.h"
55 #include "MagickCore/list.h"
56 #include "MagickCore/magick.h"
57 #include "MagickCore/memory_.h"
58 #include "MagickCore/monitor.h"
59 #include "MagickCore/monitor-private.h"
60 #include "MagickCore/quantum-private.h"
61 #include "MagickCore/static.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/module.h"
64
65 /*
66 Forward declarations.
67 */
68 static MagickBooleanType
69 WriteARTImage(const ImageInfo *,Image *,ExceptionInfo *);
70
71 /*
72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 % %
74 % %
75 % %
76 % R e a d A R T I m a g e %
77 % %
78 % %
79 % %
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81 %
82 % ReadARTImage() reads an image of raw bits in LSB order and returns it.
83 % It allocates the memory necessary for the new Image structure and returns
84 % a pointer to the new image.
85 %
86 % The format of the ReadARTImage method is:
87 %
88 % Image *ReadARTImage(const ImageInfo *image_info,
89 % ExceptionInfo *exception)
90 %
91 % A description of each parameter follows:
92 %
93 % o image_info: the image info.
94 %
95 % o exception: return any errors or warnings in this structure.
96 %
97 */
ReadARTImage(const ImageInfo * image_info,ExceptionInfo * exception)98 static Image *ReadARTImage(const ImageInfo *image_info,ExceptionInfo *exception)
99 {
100 Image
101 *image;
102
103 QuantumInfo
104 *quantum_info;
105
106 MagickBooleanType
107 status;
108
109 size_t
110 length;
111
112 ssize_t
113 count,
114 y;
115
116 unsigned char
117 *pixels;
118
119 /*
120 Open image file.
121 */
122 assert(image_info != (const ImageInfo *) NULL);
123 assert(image_info->signature == MagickCoreSignature);
124 if (image_info->debug != MagickFalse)
125 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
126 image_info->filename);
127 assert(exception != (ExceptionInfo *) NULL);
128 assert(exception->signature == MagickCoreSignature);
129 image=AcquireImage(image_info,exception);
130 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
131 if (status == MagickFalse)
132 {
133 image=DestroyImageList(image);
134 return((Image *) NULL);
135 }
136 image->depth=1;
137 image->endian=MSBEndian;
138 (void) ReadBlobLSBShort(image);
139 image->columns=(size_t) ReadBlobLSBShort(image);
140 (void) ReadBlobLSBShort(image);
141 image->rows=(size_t) ReadBlobLSBShort(image);
142 if ((image->columns == 0) || (image->rows == 0))
143 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
144 if (image_info->ping != MagickFalse)
145 {
146 (void) CloseBlob(image);
147 return(GetFirstImageInList(image));
148 }
149 status=SetImageExtent(image,image->columns,image->rows,exception);
150 if (status == MagickFalse)
151 return(DestroyImageList(image));
152 /*
153 Convert bi-level image to pixel packets.
154 */
155 SetImageColorspace(image,GRAYColorspace,exception);
156 quantum_info=AcquireQuantumInfo(image_info,image);
157 if (quantum_info == (QuantumInfo *) NULL)
158 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
159 length=GetQuantumExtent(image,quantum_info,GrayQuantum);
160 pixels=GetQuantumPixels(quantum_info);
161 for (y=0; y < (ssize_t) image->rows; y++)
162 {
163 const void
164 *stream;
165
166 Quantum
167 *magick_restrict q;
168
169 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
170 if (q == (Quantum *) NULL)
171 break;
172 stream=ReadBlobStream(image,length,pixels,&count);
173 if (count != (ssize_t) length)
174 break;
175 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
176 GrayQuantum,(unsigned char *) stream,exception);
177 stream=ReadBlobStream(image,(size_t) (-(ssize_t) length) & 0x01,pixels,
178 &count);
179 if (SyncAuthenticPixels(image,exception) == MagickFalse)
180 break;
181 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
182 break;
183 }
184 SetQuantumImageType(image,GrayQuantum);
185 quantum_info=DestroyQuantumInfo(quantum_info);
186 if (y < (ssize_t) image->rows)
187 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
188 if (EOFBlob(image) != MagickFalse)
189 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
190 image->filename);
191 (void) CloseBlob(image);
192 return(GetFirstImageInList(image));
193 }
194
195 /*
196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197 % %
198 % %
199 % %
200 % R e g i s t e r A R T I m a g e %
201 % %
202 % %
203 % %
204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
205 %
206 % RegisterARTImage() adds attributes for the ART image format to
207 % the list of supported formats. The attributes include the image format
208 % tag, a method to read and/or write the format, whether the format
209 % supports the saving of more than one frame to the same file or blob,
210 % whether the format supports native in-memory I/O, and a brief
211 % description of the format.
212 %
213 % The format of the RegisterARTImage method is:
214 %
215 % size_t RegisterARTImage(void)
216 %
217 */
RegisterARTImage(void)218 ModuleExport size_t RegisterARTImage(void)
219 {
220 MagickInfo
221 *entry;
222
223 entry=AcquireMagickInfo("ART","ART","PFS: 1st Publisher Clip Art");
224 entry->decoder=(DecodeImageHandler *) ReadARTImage;
225 entry->encoder=(EncodeImageHandler *) WriteARTImage;
226 entry->flags|=CoderRawSupportFlag;
227 entry->flags^=CoderAdjoinFlag;
228 (void) RegisterMagickInfo(entry);
229 return(MagickImageCoderSignature);
230 }
231
232 /*
233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234 % %
235 % %
236 % %
237 % U n r e g i s t e r A R T I m a g e %
238 % %
239 % %
240 % %
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 %
243 % UnregisterARTImage() removes format registrations made by the
244 % ART module from the list of supported formats.
245 %
246 % The format of the UnregisterARTImage method is:
247 %
248 % UnregisterARTImage(void)
249 %
250 */
UnregisterARTImage(void)251 ModuleExport void UnregisterARTImage(void)
252 {
253 (void) UnregisterMagickInfo("ART");
254 }
255
256 /*
257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258 % %
259 % %
260 % %
261 % W r i t e A R T I m a g e %
262 % %
263 % %
264 % %
265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266 %
267 % WriteARTImage() writes an image of raw bits in LSB order to a file.
268 %
269 % The format of the WriteARTImage method is:
270 %
271 % MagickBooleanType WriteARTImage(const ImageInfo *image_info,
272 % Image *image,ExceptionInfo *exception)
273 %
274 % A description of each parameter follows.
275 %
276 % o image_info: the image info.
277 %
278 % o image: The image.
279 %
280 % o exception: return any errors or warnings in this structure.
281 %
282 */
WriteARTImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)283 static MagickBooleanType WriteARTImage(const ImageInfo *image_info,Image *image,
284 ExceptionInfo *exception)
285 {
286 MagickBooleanType
287 status;
288
289 QuantumInfo
290 *quantum_info;
291
292 const Quantum
293 *p;
294
295 size_t
296 length;
297
298 ssize_t
299 count,
300 y;
301
302 unsigned char
303 *pixels;
304
305 /*
306 Open output image file.
307 */
308 assert(image_info != (const ImageInfo *) NULL);
309 assert(image_info->signature == MagickCoreSignature);
310 assert(image != (Image *) NULL);
311 assert(image->signature == MagickCoreSignature);
312 if (image->debug != MagickFalse)
313 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
314 assert(exception != (ExceptionInfo *) NULL);
315 assert(exception->signature == MagickCoreSignature);
316 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
317 if (status == MagickFalse)
318 return(status);
319 if ((image->columns > 65535UL) || (image->rows > 65535UL))
320 ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
321 (void) TransformImageColorspace(image,sRGBColorspace,exception);
322 (void) SetImageType(image,BilevelType,exception);
323 image->endian=MSBEndian;
324 image->depth=1;
325 (void) WriteBlobLSBShort(image,0);
326 (void) WriteBlobLSBShort(image,(unsigned short) image->columns);
327 (void) WriteBlobLSBShort(image,0);
328 (void) WriteBlobLSBShort(image,(unsigned short) image->rows);
329 quantum_info=AcquireQuantumInfo(image_info,image);
330 if (quantum_info == (QuantumInfo *) NULL)
331 ThrowWriterException(ImageError,"MemoryAllocationFailed");
332 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
333 for (y=0; y < (ssize_t) image->rows; y++)
334 {
335 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
336 if (p == (const Quantum *) NULL)
337 break;
338 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
339 GrayQuantum,pixels,exception);
340 count=WriteBlob(image,length,pixels);
341 if (count != (ssize_t) length)
342 break;
343 count=WriteBlob(image,(size_t) (-(ssize_t) length) & 0x01,pixels);
344 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
345 image->rows);
346 if (status == MagickFalse)
347 break;
348 }
349 quantum_info=DestroyQuantumInfo(quantum_info);
350 if (y < (ssize_t) image->rows)
351 ThrowWriterException(CorruptImageError,"UnableToWriteImageData");
352 (void) CloseBlob(image);
353 return(status);
354 }
355