blob: 11d5ad544c416a57ae78d0c96f294cb7cbe2078d [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% %
cristyb56bb242014-11-25 17:12:48 +000020% Copyright 1999-2015 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);
120 assert(image_info->signature == MagickSignature);
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 == MagickSignature);
126 if (LocaleNCompare(image_info->filename,"data:",5) == 0)
127 return(ReadInlineImage(image_info,image_info->filename,exception));
cristy9950d572011-10-01 18:22:35 +0000128 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000129 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
130 if (status == MagickFalse)
131 {
132 image=DestroyImageList(image);
133 return((Image *) NULL);
134 }
135 quantum=MagickMin((size_t) GetBlobSize(image),MagickMaxBufferExtent);
cristydd8fc832014-06-02 11:00:18 +0000136 if (quantum == 0)
137 quantum=MagickMaxBufferExtent;
cristy3ed852e2009-09-05 21:47:34 +0000138 inline_image=(unsigned char *) AcquireQuantumMemory(quantum,
139 sizeof(*inline_image));
cristy564a5692012-01-20 23:56:26 +0000140 count=0;
cristy3ed852e2009-09-05 21:47:34 +0000141 for (i=0; inline_image != (unsigned char *) NULL; i+=count)
142 {
143 count=(ssize_t) ReadBlob(image,quantum,inline_image+i);
144 if (count <= 0)
145 {
146 count=0;
147 if (errno != EINTR)
148 break;
149 }
cristy9c66d8c2012-08-10 11:05:36 +0000150 if (~((size_t) i) < (quantum+1))
cristy3ed852e2009-09-05 21:47:34 +0000151 {
152 inline_image=(unsigned char *) RelinquishMagickMemory(inline_image);
153 break;
154 }
cristy3ff1f542015-02-10 22:37:51 +0000155 inline_image=(unsigned char *) ResizeQuantumMemory(inline_image,i+count+
156 quantum+1,sizeof(*inline_image));
cristy3ed852e2009-09-05 21:47:34 +0000157 }
158 if (inline_image == (unsigned char *) NULL)
159 {
160 (void) ThrowMagickException(exception,GetMagickModule(),
161 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
162 return((Image *) NULL);
163 }
164 inline_image[i+count]='\0';
165 image=DestroyImageList(image);
166 image=ReadInlineImage(image_info,(char *) inline_image,exception);
167 inline_image=(unsigned char *) RelinquishMagickMemory(inline_image);
168 return(image);
169}
170
171/*
172%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173% %
174% %
175% %
176% R e g i s t e r I N L I N E I m a g e %
177% %
178% %
179% %
180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181%
182% RegisterINLINEImage() adds attributes for the INLINE image format to
183% the list of supported formats. The attributes include the image format
184% tag, a method to read and/or write the format, whether the format
185% supports the saving of more than one frame to the same file or blob,
186% whether the format supports native in-memory I/O, and a brief
187% description of the format.
188%
189% The format of the RegisterINLINEImage method is:
190%
cristybb503372010-05-27 20:51:26 +0000191% size_t RegisterINLINEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000192%
193*/
cristybb503372010-05-27 20:51:26 +0000194ModuleExport size_t RegisterINLINEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000195{
196 MagickInfo
197 *entry;
198
199 entry=SetMagickInfo("INLINE");
200 entry->decoder=(DecodeImageHandler *) ReadINLINEImage;
cristy12bcd3d2015-01-28 00:54:23 +0000201 entry->encoder=(EncodeImageHandler *) WriteINLINEImage;
cristy009d7392010-07-25 22:08:41 +0000202 entry->format_type=ImplicitFormatType;
cristy3ed852e2009-09-05 21:47:34 +0000203 entry->description=ConstantString("Base64-encoded inline images");
204 entry->module=ConstantString("INLINE");
205 (void) RegisterMagickInfo(entry);
206 return(MagickImageCoderSignature);
207}
208
209/*
210%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
211% %
212% %
213% %
214% U n r e g i s t e r I N L I N E I m a g e %
215% %
216% %
217% %
218%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219%
220% UnregisterINLINEImage() removes format registrations made by the
221% INLINE module from the list of supported formats.
222%
223% The format of the UnregisterINLINEImage method is:
224%
225% UnregisterINLINEImage(void)
226%
227*/
228ModuleExport void UnregisterINLINEImage(void)
229{
230 (void) UnregisterMagickInfo("INLINE");
231}
cristy12bcd3d2015-01-28 00:54:23 +0000232
233/*
234%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235% %
236% %
237% %
238% W r i t e I N L I N E I m a g e %
239% %
240% %
241% %
242%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
243%
244% WriteINLINEImage() writes an image to a file in INLINE format (Base64).
245%
246% The format of the WriteINLINEImage method is:
247%
248% MagickBooleanType WriteINLINEImage(const ImageInfo *image_info,
249% Image *image,ExceptionInfo *exception)
250%
251% A description of each parameter follows.
252%
253% o image_info: the image info.
254%
255% o image: The image.
256%
257% o exception: return any errors or warnings in this structure.
258%
259*/
260static MagickBooleanType WriteINLINEImage(const ImageInfo *image_info,
261 Image *image,ExceptionInfo *exception)
262{
263 char
264 *base64,
265 message[MaxTextExtent];
266
267 const MagickInfo
268 *magick_info;
269
cristy642e14e2015-01-28 12:17:08 +0000270 Image
271 *write_image;
272
cristy12bcd3d2015-01-28 00:54:23 +0000273 ImageInfo
274 *write_info;
275
276 MagickBooleanType
277 status;
278
279 size_t
280 blob_length,
281 encode_length;
282
283 unsigned char
284 *blob;
285
286 /*
287 Convert image to base64-encoding.
288 */
289 assert(image_info != (const ImageInfo *) NULL);
290 assert(image_info->signature == MagickSignature);
291 assert(image != (Image *) NULL);
292 assert(image->signature == MagickSignature);
293 if (image->debug != MagickFalse)
294 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy642e14e2015-01-28 12:17:08 +0000295 write_info=CloneImageInfo(image_info);
296 (void) SetImageInfo(write_info,1,exception);
297 if (LocaleCompare(write_info->magick,"INLINE") == 0)
298 (void) CopyMagickString(write_info->magick,image->magick,MaxTextExtent);
299 magick_info=GetMagickInfo(write_info->magick,exception);
300 if ((magick_info == (const MagickInfo *) NULL) ||
301 (GetMagickMimeType(magick_info) == (const char *) NULL))
302 ThrowWriterException(CorruptImageError,"ImageTypeNotSupported");
303 (void) CopyMagickString(image->filename,write_info->filename,MaxTextExtent);
cristy12bcd3d2015-01-28 00:54:23 +0000304 blob_length=2048;
cristy642e14e2015-01-28 12:17:08 +0000305 write_image=CloneImage(image,0,0,MagickTrue,exception);
306 if (write_image == (Image *) NULL)
307 {
308 write_info=DestroyImageInfo(write_info);
309 return(MagickTrue);
310 }
311 blob=(unsigned char *) ImageToBlob(write_info,write_image,&blob_length,
312 exception);
313 write_image=DestroyImage(write_image);
314 write_info=DestroyImageInfo(write_info);
cristy12bcd3d2015-01-28 00:54:23 +0000315 if (blob == (unsigned char *) NULL)
316 return(MagickFalse);
317 encode_length=0;
318 base64=Base64Encode(blob,blob_length,&encode_length);
319 blob=(unsigned char *) RelinquishMagickMemory(blob);
320 if (base64 == (char *) NULL)
321 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
cristy3d149f32015-01-29 13:00:56 +0000322 /*
323 Write base64-encoded image.
324 */
cristy12bcd3d2015-01-28 00:54:23 +0000325 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy12bcd3d2015-01-28 00:54:23 +0000326 if (status == MagickFalse)
cristy3d149f32015-01-29 13:00:56 +0000327 {
328 base64=DestroyString(base64);
329 return(status);
330 }
cristy12bcd3d2015-01-28 00:54:23 +0000331 (void) FormatLocaleString(message,MaxTextExtent,"data:%s;base64,",
332 GetMagickMimeType(magick_info));
333 (void) WriteBlobString(image,message);
334 (void) WriteBlobString(image,base64);
335 base64=DestroyString(base64);
336 return(MagickTrue);
337}