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-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/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*/
64static 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*/
90ModuleExport 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*/
120ModuleExport 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*/
152static 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    magick[MagickPathExtent];
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  property=GetImageProperty(image,"exif:JPEGInterchangeFormatLength",exception);
190  if (property == (const char *) NULL)
191    ThrowWriterException(CoderError,"ImageDoesNotHaveAThumbnail");
192  length=(size_t) StringToLong(property);
193  (void) ResetMagickMemory(magick,0,sizeof(magick));
194  for (i=0; i < (ssize_t) length; i++)
195  {
196    magick[0]=magick[1];
197    magick[1]=magick[2];
198    magick[2]=GetStringInfoDatum(profile)[offset+i];
199    if (memcmp(magick,"\377\330\377",3) == 0)
200      break;
201  }
202  thumbnail_image=BlobToImage(image_info,GetStringInfoDatum(profile)+offset+i-2,
203    length,exception);
204  if (thumbnail_image == (Image *) NULL)
205    return(MagickFalse);
206  (void) SetImageType(thumbnail_image,thumbnail_image->alpha_trait ==
207    UndefinedPixelTrait ? TrueColorType : TrueColorAlphaType,exception);
208  (void) CopyMagickString(thumbnail_image->filename,image->filename,
209    MagickPathExtent);
210  write_info=CloneImageInfo(image_info);
211  *write_info->magick='\0';
212  (void) SetImageInfo(write_info,1,exception);
213  if ((*write_info->magick == '\0') ||
214      (LocaleCompare(write_info->magick,"THUMBNAIL") == 0))
215    (void) FormatLocaleString(thumbnail_image->filename,MagickPathExtent,
216      "miff:%s",write_info->filename);
217  status=WriteImage(write_info,thumbnail_image,exception);
218  thumbnail_image=DestroyImage(thumbnail_image);
219  write_info=DestroyImageInfo(write_info);
220  return(status);
221}
222