1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % IIIII N N L IIIII N N EEEEE %
7 % I NN N L I NN N E %
8 % I N N N L I N N N EEE %
9 % I N NN L I N NN E %
10 % IIIII N N LLLLL IIIII N N EEEEE %
11 % %
12 % %
13 % Read Inline Images %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2016 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 % http://www.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/blob-private.h"
45 #include "MagickCore/client.h"
46 #include "MagickCore/constitute.h"
47 #include "MagickCore/display.h"
48 #include "MagickCore/exception.h"
49 #include "MagickCore/exception-private.h"
50 #include "MagickCore/image.h"
51 #include "MagickCore/image-private.h"
52 #include "MagickCore/list.h"
53 #include "MagickCore/magick.h"
54 #include "MagickCore/memory_.h"
55 #include "MagickCore/option.h"
56 #include "MagickCore/quantum-private.h"
57 #include "MagickCore/static.h"
58 #include "MagickCore/string_.h"
59 #include "MagickCore/module.h"
60 #include "MagickCore/utility.h"
61 #include "MagickCore/xwindow.h"
62 #include "MagickCore/xwindow-private.h"
63
64 /*
65 Forward declarations.
66 */
67 static MagickBooleanType
68 WriteINLINEImage(const ImageInfo *,Image *,ExceptionInfo *);
69
70 /*
71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 % %
73 % %
74 % %
75 % R e a d I N L I N E I m a g e %
76 % %
77 % %
78 % %
79 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80 %
81 % ReadINLINEImage() reads base64-encoded inlines images.
82 %
83 % The format of the ReadINLINEImage method is:
84 %
85 % Image *ReadINLINEImage(const ImageInfo *image_info,
86 % ExceptionInfo *exception)
87 %
88 % A description of each parameter follows:
89 %
90 % o image_info: the image info.
91 %
92 % o exception: return any errors or warnings in this structure.
93 %
94 */
ReadINLINEImage(const ImageInfo * image_info,ExceptionInfo * exception)95 static Image *ReadINLINEImage(const ImageInfo *image_info,
96 ExceptionInfo *exception)
97 {
98 Image
99 *image;
100
101 MagickBooleanType
102 status;
103
104 register size_t
105 i;
106
107 size_t
108 quantum;
109
110 ssize_t
111 count;
112
113 unsigned char
114 *inline_image;
115
116 /*
117 Open image file.
118 */
119 assert(image_info != (const ImageInfo *) NULL);
120 assert(image_info->signature == MagickCoreSignature);
121 if (image_info->debug != MagickFalse)
122 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
123 image_info->filename);
124 assert(exception != (ExceptionInfo *) NULL);
125 assert(exception->signature == MagickCoreSignature);
126 if (LocaleCompare(image_info->magick,"DATA") == 0)
127 {
128 char
129 *filename;
130
131 Image
132 *data_image;
133
134 filename=AcquireString("data:");
135 (void) ConcatenateMagickString(filename,image_info->filename,
136 MagickPathExtent);
137 data_image=ReadInlineImage(image_info,filename,exception);
138 filename=DestroyString(filename);
139 return(data_image);
140 }
141 image=AcquireImage(image_info,exception);
142 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
143 if (status == MagickFalse)
144 {
145 image=DestroyImageList(image);
146 return((Image *) NULL);
147 }
148 quantum=MagickMin((size_t) GetBlobSize(image),MagickMaxBufferExtent);
149 if (quantum == 0)
150 quantum=MagickMaxBufferExtent;
151 inline_image=(unsigned char *) AcquireQuantumMemory(quantum,
152 sizeof(*inline_image));
153 count=0;
154 for (i=0; inline_image != (unsigned char *) NULL; i+=count)
155 {
156 count=(ssize_t) ReadBlob(image,quantum,inline_image+i);
157 if (count <= 0)
158 {
159 count=0;
160 if (errno != EINTR)
161 break;
162 }
163 if (~((size_t) i) < (quantum+1))
164 {
165 inline_image=(unsigned char *) RelinquishMagickMemory(inline_image);
166 break;
167 }
168 inline_image=(unsigned char *) ResizeQuantumMemory(inline_image,i+count+
169 quantum+1,sizeof(*inline_image));
170 }
171 if (inline_image == (unsigned char *) NULL)
172 {
173 (void) ThrowMagickException(exception,GetMagickModule(),
174 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
175 return((Image *) NULL);
176 }
177 inline_image[i+count]='\0';
178 image=DestroyImageList(image);
179 image=ReadInlineImage(image_info,(char *) inline_image,exception);
180 inline_image=(unsigned char *) RelinquishMagickMemory(inline_image);
181 return(image);
182 }
183
184 /*
185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186 % %
187 % %
188 % %
189 % R e g i s t e r I N L I N E I m a g e %
190 % %
191 % %
192 % %
193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194 %
195 % RegisterINLINEImage() adds attributes for the INLINE image format to
196 % the list of supported formats. The attributes include the image format
197 % tag, a method to read and/or write the format, whether the format
198 % supports the saving of more than one frame to the same file or blob,
199 % whether the format supports native in-memory I/O, and a brief
200 % description of the format.
201 %
202 % The format of the RegisterINLINEImage method is:
203 %
204 % size_t RegisterINLINEImage(void)
205 %
206 */
RegisterINLINEImage(void)207 ModuleExport size_t RegisterINLINEImage(void)
208 {
209 MagickInfo
210 *entry;
211
212 entry=AcquireMagickInfo("DATA","INLINE","Base64-encoded inline images");
213 entry->decoder=(DecodeImageHandler *) ReadINLINEImage;
214 entry->encoder=(EncodeImageHandler *) WriteINLINEImage;
215 entry->format_type=ImplicitFormatType;
216 (void) RegisterMagickInfo(entry);
217 entry=AcquireMagickInfo("INLINE","INLINE","Base64-encoded inline images");
218 entry->decoder=(DecodeImageHandler *) ReadINLINEImage;
219 entry->encoder=(EncodeImageHandler *) WriteINLINEImage;
220 entry->format_type=ImplicitFormatType;
221 (void) RegisterMagickInfo(entry);
222 return(MagickImageCoderSignature);
223 }
224
225 /*
226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227 % %
228 % %
229 % %
230 % U n r e g i s t e r I N L I N E I m a g e %
231 % %
232 % %
233 % %
234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235 %
236 % UnregisterINLINEImage() removes format registrations made by the
237 % INLINE module from the list of supported formats.
238 %
239 % The format of the UnregisterINLINEImage method is:
240 %
241 % UnregisterINLINEImage(void)
242 %
243 */
UnregisterINLINEImage(void)244 ModuleExport void UnregisterINLINEImage(void)
245 {
246 (void) UnregisterMagickInfo("INLINE");
247 (void) UnregisterMagickInfo("DATA");
248 }
249
250 /*
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252 % %
253 % %
254 % %
255 % W r i t e I N L I N E I m a g e %
256 % %
257 % %
258 % %
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 %
261 % WriteINLINEImage() writes an image to a file in INLINE format (Base64).
262 %
263 % The format of the WriteINLINEImage method is:
264 %
265 % MagickBooleanType WriteINLINEImage(const ImageInfo *image_info,
266 % Image *image,ExceptionInfo *exception)
267 %
268 % A description of each parameter follows.
269 %
270 % o image_info: the image info.
271 %
272 % o image: The image.
273 %
274 % o exception: return any errors or warnings in this structure.
275 %
276 */
WriteINLINEImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)277 static MagickBooleanType WriteINLINEImage(const ImageInfo *image_info,
278 Image *image,ExceptionInfo *exception)
279 {
280 char
281 *base64,
282 message[MagickPathExtent];
283
284 const MagickInfo
285 *magick_info;
286
287 Image
288 *write_image;
289
290 ImageInfo
291 *write_info;
292
293 MagickBooleanType
294 status;
295
296 size_t
297 blob_length,
298 encode_length;
299
300 unsigned char
301 *blob;
302
303 /*
304 Convert image to base64-encoding.
305 */
306 assert(image_info != (const ImageInfo *) NULL);
307 assert(image_info->signature == MagickCoreSignature);
308 assert(image != (Image *) NULL);
309 assert(image->signature == MagickCoreSignature);
310 if (image->debug != MagickFalse)
311 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
312 write_info=CloneImageInfo(image_info);
313 (void) SetImageInfo(write_info,1,exception);
314 if (LocaleCompare(write_info->magick,"INLINE") == 0)
315 (void) CopyMagickString(write_info->magick,image->magick,MagickPathExtent);
316 magick_info=GetMagickInfo(write_info->magick,exception);
317 if ((magick_info == (const MagickInfo *) NULL) ||
318 (GetMagickMimeType(magick_info) == (const char *) NULL))
319 ThrowWriterException(CorruptImageError,"ImageTypeNotSupported");
320 (void) CopyMagickString(image->filename,write_info->filename,
321 MagickPathExtent);
322 blob_length=2048;
323 write_image=CloneImage(image,0,0,MagickTrue,exception);
324 if (write_image == (Image *) NULL)
325 {
326 write_info=DestroyImageInfo(write_info);
327 return(MagickTrue);
328 }
329 blob=(unsigned char *) ImageToBlob(write_info,write_image,&blob_length,
330 exception);
331 write_image=DestroyImage(write_image);
332 write_info=DestroyImageInfo(write_info);
333 if (blob == (unsigned char *) NULL)
334 return(MagickFalse);
335 encode_length=0;
336 base64=Base64Encode(blob,blob_length,&encode_length);
337 blob=(unsigned char *) RelinquishMagickMemory(blob);
338 if (base64 == (char *) NULL)
339 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
340 /*
341 Write base64-encoded image.
342 */
343 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
344 if (status == MagickFalse)
345 {
346 base64=DestroyString(base64);
347 return(status);
348 }
349 (void) FormatLocaleString(message,MagickPathExtent,"data:%s;base64,",
350 GetMagickMimeType(magick_info));
351 (void) WriteBlobString(image,message);
352 (void) WriteBlobString(image,base64);
353 base64=DestroyString(base64);
354 return(MagickTrue);
355 }
356