1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % TTTTT H H U U M M BBBB N N AAA IIIII L % 7 % T H H U U MM MM B B NN N A A I L % 8 % T HHHHH U U M M M BBBB N N N AAAAA I L % 9 % T H H U U M M B B N NN A A I L % 10 % T H H UUU M M BBBB N N A A IIIII LLLLL % 11 % % 12 % % 13 % Write EXIF Thumbnail To File. % 14 % % 15 % Software Design % 16 % Cristy % 17 % July 1992 % 18 % % 19 % % 20 % Copyright 1999-2019 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/constitute.h" 47 #include "MagickCore/exception.h" 48 #include "MagickCore/exception-private.h" 49 #include "MagickCore/magick.h" 50 #include "MagickCore/memory_.h" 51 #include "MagickCore/module.h" 52 #include "MagickCore/monitor.h" 53 #include "MagickCore/monitor-private.h" 54 #include "MagickCore/profile.h" 55 #include "MagickCore/property.h" 56 #include "MagickCore/quantum-private.h" 57 #include "MagickCore/static.h" 58 #include "MagickCore/string_.h" 59 #include "MagickCore/string-private.h" 60 61 /* 62 Forward declarations. 63 */ 64 static MagickBooleanType 65 WriteTHUMBNAILImage(const ImageInfo *,Image *,ExceptionInfo *); 66 67 /* 68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 69 % % 70 % % 71 % % 72 % R e g i s t e r T H U M B N A I L I m a g e % 73 % % 74 % % 75 % % 76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 77 % 78 % RegisterTHUMBNAILImage() adds attributes for the THUMBNAIL image format to 79 % the list of supported formats. The attributes include the image format 80 % tag, a method to read and/or write the format, whether the format 81 % supports the saving of more than one frame to the same file or blob, 82 % whether the format supports native in-memory I/O, and a brief 83 % description of the format. 84 % 85 % The format of the RegisterTHUMBNAILImage method is: 86 % 87 % size_t RegisterTHUMBNAILImage(void) 88 % 89 */ RegisterTHUMBNAILImage(void)90 ModuleExport size_t RegisterTHUMBNAILImage(void) 91 { 92 MagickInfo 93 *entry; 94 95 entry=AcquireMagickInfo("THUMBNAIL","THUMBNAIL","EXIF Profile Thumbnail"); 96 entry->encoder=(EncodeImageHandler *) WriteTHUMBNAILImage; 97 (void) RegisterMagickInfo(entry); 98 return(MagickImageCoderSignature); 99 } 100 101 /* 102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 103 % % 104 % % 105 % % 106 % U n r e g i s t e r T H U M B N A I L I m a g e % 107 % % 108 % % 109 % % 110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 111 % 112 % UnregisterTHUMBNAILImage() removes format registrations made by the 113 % THUMBNAIL module from the list of supported formats. 114 % 115 % The format of the UnregisterTHUMBNAILImage method is: 116 % 117 % UnregisterTHUMBNAILImage(void) 118 % 119 */ UnregisterTHUMBNAILImage(void)120 ModuleExport void UnregisterTHUMBNAILImage(void) 121 { 122 (void) UnregisterMagickInfo("THUMBNAIL"); 123 } 124 125 /* 126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 127 % % 128 % % 129 % % 130 % W r i t e T H U M B N A I L I m a g e % 131 % % 132 % % 133 % % 134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 135 % 136 % WriteTHUMBNAILImage() extracts the EXIF thumbnail image and writes it. 137 % 138 % The format of the WriteTHUMBNAILImage method is: 139 % 140 % MagickBooleanType WriteTHUMBNAILImage(const ImageInfo *image_info, 141 % Image *image,ExceptionInfo *exception) 142 % 143 % A description of each parameter follows. 144 % 145 % o image_info: the image info. 146 % 147 % o image: The image. 148 % 149 % o exception: return any errors or warnings in this structure. 150 % 151 */ WriteTHUMBNAILImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)152 static MagickBooleanType WriteTHUMBNAILImage(const ImageInfo *image_info, 153 Image *image,ExceptionInfo *exception) 154 { 155 const char 156 *property; 157 158 const StringInfo 159 *profile; 160 161 Image 162 *thumbnail_image; 163 164 ImageInfo 165 *write_info; 166 167 MagickBooleanType 168 status; 169 170 register ssize_t 171 i; 172 173 size_t 174 length; 175 176 ssize_t 177 offset; 178 179 unsigned char 180 *q; 181 182 profile=GetImageProfile(image,"exif"); 183 if (profile == (const StringInfo *) NULL) 184 ThrowWriterException(CoderError,"ImageDoesNotHaveAThumbnail"); 185 property=GetImageProperty(image,"exif:JPEGInterchangeFormat",exception); 186 if (property == (const char *) NULL) 187 ThrowWriterException(CoderError,"ImageDoesNotHaveAThumbnail"); 188 offset=(ssize_t) StringToLong(property); 189 if (offset < 0) 190 ThrowWriterException(CoderError,"ImageDoesNotHaveAThumbnail"); 191 property=GetImageProperty(image,"exif:JPEGInterchangeFormatLength",exception); 192 if (property == (const char *) NULL) 193 ThrowWriterException(CoderError,"ImageDoesNotHaveAThumbnail"); 194 length=(size_t) StringToLong(property); 195 q=GetStringInfoDatum(profile)+offset; 196 for (i=offset; i < (ssize_t) GetStringInfoLength(profile) - 3; i++) 197 { 198 if (memcmp(q,"\377\330\377",3) == 0) 199 break; 200 q++; 201 } 202 if ((q+length) > (GetStringInfoDatum(profile)+GetStringInfoLength(profile))) 203 ThrowWriterException(CoderError,"ImageDoesNotHaveAThumbnail"); 204 thumbnail_image=BlobToImage(image_info,q,length,exception); 205 if (thumbnail_image == (Image *) NULL) 206 return(MagickFalse); 207 (void) SetImageType(thumbnail_image,thumbnail_image->alpha_trait == 208 UndefinedPixelTrait ? TrueColorType : TrueColorAlphaType,exception); 209 (void) CopyMagickString(thumbnail_image->filename,image->filename, 210 MagickPathExtent); 211 write_info=CloneImageInfo(image_info); 212 *write_info->magick='\0'; 213 (void) SetImageInfo(write_info,1,exception); 214 if ((*write_info->magick == '\0') || 215 (LocaleCompare(write_info->magick,"THUMBNAIL") == 0)) 216 (void) FormatLocaleString(thumbnail_image->filename,MagickPathExtent, 217 "miff:%s",write_info->filename); 218 status=WriteImage(write_info,thumbnail_image,exception); 219 thumbnail_image=DestroyImage(thumbnail_image); 220 write_info=DestroyImageInfo(write_info); 221 return(status); 222 } 223