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*/ 67static 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*/ 95static 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*/ 207ModuleExport 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*/ 244ModuleExport 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*/ 277static 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