blob: 093d1316a9af037df81e4d2fd2cceae4f0f0fd60 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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 %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 1992 %
18% %
19% %
Cristy7ce65e72015-12-12 18:03:16 -050020% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% 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*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/blob.h"
44#include "MagickCore/blob-private.h"
45#include "MagickCore/client.h"
cristy3f858f42012-01-07 00:03:25 +000046#include "MagickCore/constitute.h"
cristy4c08aed2011-07-01 19:47:50 +000047#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"
cristy3ed852e2009-09-05 21:47:34 +000063
64/*
cristy12bcd3d2015-01-28 00:54:23 +000065 Forward declarations.
66*/
67static MagickBooleanType
68 WriteINLINEImage(const ImageInfo *,Image *,ExceptionInfo *);
69
70/*
cristy3ed852e2009-09-05 21:47:34 +000071%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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*/
cristy3ed852e2009-09-05 21:47:34 +000095static 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
cristy3ed852e2009-09-05 21:47:34 +0000107 size_t
108 quantum;
109
cristyebc891a2011-04-24 23:04:16 +0000110 ssize_t
111 count;
112
cristy3ed852e2009-09-05 21:47:34 +0000113 unsigned char
114 *inline_image;
115
116 /*
117 Open image file.
118 */
119 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000120 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000121 if (image_info->debug != MagickFalse)
122 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
123 image_info->filename);
124 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000125 assert(exception->signature == MagickCoreSignature);
Cristy6ffac4f2015-08-23 10:55:57 -0400126 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 }
cristy9950d572011-10-01 18:22:35 +0000141 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000142 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);
cristydd8fc832014-06-02 11:00:18 +0000149 if (quantum == 0)
150 quantum=MagickMaxBufferExtent;
cristy3ed852e2009-09-05 21:47:34 +0000151 inline_image=(unsigned char *) AcquireQuantumMemory(quantum,
152 sizeof(*inline_image));
cristy564a5692012-01-20 23:56:26 +0000153 count=0;
cristy3ed852e2009-09-05 21:47:34 +0000154 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 }
cristy9c66d8c2012-08-10 11:05:36 +0000163 if (~((size_t) i) < (quantum+1))
cristy3ed852e2009-09-05 21:47:34 +0000164 {
165 inline_image=(unsigned char *) RelinquishMagickMemory(inline_image);
166 break;
167 }
cristy3ff1f542015-02-10 22:37:51 +0000168 inline_image=(unsigned char *) ResizeQuantumMemory(inline_image,i+count+
169 quantum+1,sizeof(*inline_image));
cristy3ed852e2009-09-05 21:47:34 +0000170 }
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%
cristybb503372010-05-27 20:51:26 +0000204% size_t RegisterINLINEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000205%
206*/
cristybb503372010-05-27 20:51:26 +0000207ModuleExport size_t RegisterINLINEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000208{
209 MagickInfo
210 *entry;
211
Cristy6ffac4f2015-08-23 10:55:57 -0400212 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);
dirk06b627a2015-04-06 18:59:17 +0000217 entry=AcquireMagickInfo("INLINE","INLINE","Base64-encoded inline images");
cristy3ed852e2009-09-05 21:47:34 +0000218 entry->decoder=(DecodeImageHandler *) ReadINLINEImage;
cristy12bcd3d2015-01-28 00:54:23 +0000219 entry->encoder=(EncodeImageHandler *) WriteINLINEImage;
cristy009d7392010-07-25 22:08:41 +0000220 entry->format_type=ImplicitFormatType;
cristy3ed852e2009-09-05 21:47:34 +0000221 (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*/
244ModuleExport void UnregisterINLINEImage(void)
245{
246 (void) UnregisterMagickInfo("INLINE");
Cristy6ffac4f2015-08-23 10:55:57 -0400247 (void) UnregisterMagickInfo("DATA");
cristy3ed852e2009-09-05 21:47:34 +0000248}
cristy12bcd3d2015-01-28 00:54:23 +0000249
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*/
277static MagickBooleanType WriteINLINEImage(const ImageInfo *image_info,
278 Image *image,ExceptionInfo *exception)
279{
280 char
281 *base64,
cristy151b66d2015-04-15 10:50:31 +0000282 message[MagickPathExtent];
cristy12bcd3d2015-01-28 00:54:23 +0000283
284 const MagickInfo
285 *magick_info;
286
cristy642e14e2015-01-28 12:17:08 +0000287 Image
288 *write_image;
289
cristy12bcd3d2015-01-28 00:54:23 +0000290 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);
cristye1c94d92015-06-28 12:16:33 +0000307 assert(image_info->signature == MagickCoreSignature);
cristy12bcd3d2015-01-28 00:54:23 +0000308 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000309 assert(image->signature == MagickCoreSignature);
cristy12bcd3d2015-01-28 00:54:23 +0000310 if (image->debug != MagickFalse)
311 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy642e14e2015-01-28 12:17:08 +0000312 write_info=CloneImageInfo(image_info);
313 (void) SetImageInfo(write_info,1,exception);
314 if (LocaleCompare(write_info->magick,"INLINE") == 0)
cristy151b66d2015-04-15 10:50:31 +0000315 (void) CopyMagickString(write_info->magick,image->magick,MagickPathExtent);
cristy642e14e2015-01-28 12:17:08 +0000316 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");
Cristy6ffac4f2015-08-23 10:55:57 -0400320 (void) CopyMagickString(image->filename,write_info->filename,
321 MagickPathExtent);
cristy12bcd3d2015-01-28 00:54:23 +0000322 blob_length=2048;
cristy642e14e2015-01-28 12:17:08 +0000323 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);
cristy12bcd3d2015-01-28 00:54:23 +0000333 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");
cristy3d149f32015-01-29 13:00:56 +0000340 /*
341 Write base64-encoded image.
342 */
cristy12bcd3d2015-01-28 00:54:23 +0000343 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy12bcd3d2015-01-28 00:54:23 +0000344 if (status == MagickFalse)
cristy3d149f32015-01-29 13:00:56 +0000345 {
346 base64=DestroyString(base64);
347 return(status);
348 }
cristy151b66d2015-04-15 10:50:31 +0000349 (void) FormatLocaleString(message,MagickPathExtent,"data:%s;base64,",
cristy12bcd3d2015-01-28 00:54:23 +0000350 GetMagickMimeType(magick_info));
351 (void) WriteBlobString(image,message);
352 (void) WriteBlobString(image,base64);
353 base64=DestroyString(base64);
354 return(MagickTrue);
355}