1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                            V   V  IIIII  DDDD                               %
7%                            V   V    I    D   D                              %
8%                            V   V    I    D   D                              %
9%                             V V     I    D   D                              %
10%                              V    IIIII  DDDD                               %
11%                                                                             %
12%                                                                             %
13%             Return a Visual Image Directory for matching 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/property.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/geometry.h"
50#include "MagickCore/image.h"
51#include "MagickCore/image-private.h"
52#include "MagickCore/list.h"
53#include "MagickCore/log.h"
54#include "MagickCore/magick.h"
55#include "MagickCore/memory_.h"
56#include "MagickCore/monitor.h"
57#include "MagickCore/monitor-private.h"
58#include "MagickCore/montage.h"
59#include "MagickCore/quantum-private.h"
60#include "MagickCore/resize.h"
61#include "MagickCore/static.h"
62#include "MagickCore/string_.h"
63#include "MagickCore/module.h"
64#include "MagickCore/utility.h"
65
66/*
67  Forward declarations.
68*/
69static MagickBooleanType
70  WriteVIDImage(const ImageInfo *,Image *,ExceptionInfo *);
71
72/*
73%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74%                                                                             %
75%                                                                             %
76%                                                                             %
77%   R e a d V I D I m a g e                                                   %
78%                                                                             %
79%                                                                             %
80%                                                                             %
81%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82%
83%  ReadVIDImage reads one of more images and creates a Visual Image
84%  Directory file.  It allocates the memory necessary for the new Image
85%  structure and returns a pointer to the new image.
86%
87%  The format of the ReadVIDImage method is:
88%
89%      Image *ReadVIDImage(const ImageInfo *image_info,ExceptionInfo *exception)
90%
91%  A description of each parameter follows:
92%
93%    o image_info: the image info.
94%
95%    o exception: return any errors or warnings in this structure.
96%
97*/
98static Image *ReadVIDImage(const ImageInfo *image_info,ExceptionInfo *exception)
99{
100#define ClientName  "montage"
101
102  char
103    **filelist,
104    *label;
105
106  Image
107    *image,
108    *images,
109    *montage_image,
110    *next_image,
111    *thumbnail_image;
112
113  ImageInfo
114    *read_info;
115
116  int
117    number_files;
118
119  MagickBooleanType
120    status;
121
122  MontageInfo
123    *montage_info;
124
125  RectangleInfo
126    geometry;
127
128  register ssize_t
129    i;
130
131  /*
132    Expand the filename.
133  */
134  assert(image_info != (const ImageInfo *) NULL);
135  assert(image_info->signature == MagickCoreSignature);
136  if (image_info->debug != MagickFalse)
137    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
138      image_info->filename);
139  assert(exception != (ExceptionInfo *) NULL);
140  assert(exception->signature == MagickCoreSignature);
141  image=AcquireImage(image_info,exception);
142  filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
143  if (filelist == (char **) NULL)
144    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
145  filelist[0]=ConstantString(image_info->filename);
146  number_files=1;
147  status=ExpandFilenames(&number_files,&filelist);
148  if ((status == MagickFalse) || (number_files == 0))
149    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
150  image=DestroyImage(image);
151  /*
152    Read each image and convert them to a tile.
153  */
154  images=NewImageList();
155  read_info=CloneImageInfo(image_info);
156  SetImageInfoBlob(read_info,(void *) NULL,0);
157  (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
158    (void *) NULL);
159  if (read_info->size == (char *) NULL)
160    (void) CloneString(&read_info->size,DefaultTileGeometry);
161  for (i=0; i < (ssize_t) number_files; i++)
162  {
163    if (image_info->debug != MagickFalse)
164      (void) LogMagickEvent(CoderEvent,GetMagickModule(),"name: %s",
165        filelist[i]);
166    (void) CopyMagickString(read_info->filename,filelist[i],MagickPathExtent);
167    filelist[i]=DestroyString(filelist[i]);
168    *read_info->magick='\0';
169    next_image=ReadImage(read_info,exception);
170    CatchException(exception);
171    if (next_image == (Image *) NULL)
172      break;
173    label=InterpretImageProperties((ImageInfo *) image_info,next_image,
174      DefaultTileLabel,exception);
175    (void) SetImageProperty(next_image,"label",label,exception);
176    label=DestroyString(label);
177    if (image_info->debug != MagickFalse)
178      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
179        "geometry: %.20gx%.20g",(double) next_image->columns,(double)
180        next_image->rows);
181    SetGeometry(next_image,&geometry);
182    (void) ParseMetaGeometry(read_info->size,&geometry.x,&geometry.y,
183      &geometry.width,&geometry.height);
184    thumbnail_image=ThumbnailImage(next_image,geometry.width,geometry.height,
185      exception);
186    if (thumbnail_image != (Image *) NULL)
187      {
188        next_image=DestroyImage(next_image);
189        next_image=thumbnail_image;
190      }
191    if (image_info->debug != MagickFalse)
192      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
193        "thumbnail geometry: %.20gx%.20g",(double) next_image->columns,(double)
194        next_image->rows);
195    AppendImageToList(&images,next_image);
196    status=SetImageProgress(images,LoadImagesTag,i,number_files);
197    if (status == MagickFalse)
198      break;
199  }
200  read_info=DestroyImageInfo(read_info);
201  filelist=(char **) RelinquishMagickMemory(filelist);
202  if (images == (Image *) NULL)
203    ThrowReaderException(CorruptImageError,
204      "ImageFileDoesNotContainAnyImageData");
205  /*
206    Create the visual image directory.
207  */
208  montage_info=CloneMontageInfo(image_info,(MontageInfo *) NULL);
209  if (image_info->debug != MagickFalse)
210    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"creating montage");
211  montage_image=MontageImageList(image_info,montage_info,
212    GetFirstImageInList(images),exception);
213  montage_info=DestroyMontageInfo(montage_info);
214  images=DestroyImageList(images);
215  return(montage_image);
216}
217
218/*
219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220%                                                                             %
221%                                                                             %
222%                                                                             %
223%   R e g i s t e r V I D I m a g e                                           %
224%                                                                             %
225%                                                                             %
226%                                                                             %
227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228%
229%  RegisterVIDImage() adds attributes for the VID image format to
230%  the list of supported formats.  The attributes include the image format
231%  tag, a method to read and/or write the format, whether the format
232%  supports the saving of more than one frame to the same file or blob,
233%  whether the format supports native in-memory I/O, and a brief
234%  description of the format.
235%
236%  The format of the RegisterVIDImage method is:
237%
238%      size_t RegisterVIDImage(void)
239%
240*/
241ModuleExport size_t RegisterVIDImage(void)
242{
243  MagickInfo
244    *entry;
245
246  entry=AcquireMagickInfo("VID","VID","Visual Image Directory");
247  entry->decoder=(DecodeImageHandler *) ReadVIDImage;
248  entry->encoder=(EncodeImageHandler *) WriteVIDImage;
249  entry->format_type=ImplicitFormatType;
250  (void) RegisterMagickInfo(entry);
251  return(MagickImageCoderSignature);
252}
253
254/*
255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256%                                                                             %
257%                                                                             %
258%                                                                             %
259%   U n r e g i s t e r V I D I m a g e                                       %
260%                                                                             %
261%                                                                             %
262%                                                                             %
263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
264%
265%  UnregisterVIDImage() removes format registrations made by the
266%  VID module from the list of supported formats.
267%
268%  The format of the UnregisterVIDImage method is:
269%
270%      UnregisterVIDImage(void)
271%
272*/
273ModuleExport void UnregisterVIDImage(void)
274{
275  (void) UnregisterMagickInfo("VID");
276}
277
278/*
279%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280%                                                                             %
281%                                                                             %
282%                                                                             %
283%   W r i t e V I D I m a g e                                                 %
284%                                                                             %
285%                                                                             %
286%                                                                             %
287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288%
289%  WriteVIDImage() writes an image to a file in VID X image format.
290%
291%  The format of the WriteVIDImage method is:
292%
293%      MagickBooleanType WriteVIDImage(const ImageInfo *image_info,
294%        Image *image,ExceptionInfo *exception)
295%
296%  A description of each parameter follows.
297%
298%    o image_info: the image info.
299%
300%    o image:  The image.
301%
302%    o exception: return any errors or warnings in this structure.
303%
304*/
305static MagickBooleanType WriteVIDImage(const ImageInfo *image_info,Image *image,
306  ExceptionInfo *exception)
307{
308  Image
309    *montage_image;
310
311  ImageInfo
312    *write_info;
313
314  MagickBooleanType
315    status;
316
317  MontageInfo
318    *montage_info;
319
320  register Image
321    *p;
322
323  /*
324    Create the visual image directory.
325  */
326  for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
327    (void) SetImageProperty(p,"label",DefaultTileLabel,exception);
328  montage_info=CloneMontageInfo(image_info,(MontageInfo *) NULL);
329  montage_image=MontageImageList(image_info,montage_info,image,exception);
330  montage_info=DestroyMontageInfo(montage_info);
331  if (montage_image == (Image *) NULL)
332    return(MagickFalse);
333  (void) CopyMagickString(montage_image->filename,image_info->filename,
334    MagickPathExtent);
335  write_info=CloneImageInfo(image_info);
336  *write_info->magick='\0';
337  (void) SetImageInfo(write_info,1,exception);
338  if ((*write_info->magick == '\0') ||
339      (LocaleCompare(write_info->magick,"VID") == 0))
340    (void) FormatLocaleString(montage_image->filename,MagickPathExtent,
341      "miff:%s",write_info->filename);
342  status=WriteImage(write_info,montage_image,exception);
343  montage_image=DestroyImage(montage_image);
344  write_info=DestroyImageInfo(write_info);
345  return(status);
346}
347