xtrn.c revision 06b627a07ff44e1ff93ef1288c9f428066ded10d
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                        X   X  TTTTT  RRRR   N   N                           %
7%                         X X     T    R   R  NN  N                           %
8%                          X      T    RRRR   N N N                           %
9%                         X X     T    R R    N  NN                           %
10%                        X   X    T    R  R   N   N                           %
11%                                                                             %
12%                                                                             %
13%                    ImageMagickObject BLOB Interface.                        %
14%                                                                             %
15%                              Software Design                                %
16%                             William Radcliffe                               %
17%                                 May 2001                                    %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2015 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%  This coder is a kind of backdoor used by the COM object that allows it to  %
38%  pass blobs back and forth using the coder interface. It simply encodes and %
39%  decodes the filename as a comma delimited string and extracts the info it  %
40%  needs. The five methods of passing images are:                             %
41%                                                                             %
42%     FILE   - same thing as filename so it should be a NOP                   %
43%     IMAGE  - passes an image and image info structure                       %
44%     BLOB   - passes binary blob containining the image                      %
45%     STREAM - passes pointers to stream hooks in and does the hooking        %
46%     ARRAY  - passes a pointer to a Win32 smart array and streams to it      %
47%                                                                             %
48%  Of all of these, the only one getting any real use at the moment is the    %
49%  ARRAY handler. It is the primary way that images are shuttled back and     %
50%  forth as blobs via COM since this is what VB and VBSCRIPT use internally   %
51%  for this purpose.                                                          %
52%
53%
54*/
55
56/*
57  Include declarations.
58*/
59#include "MagickCore/studio.h"
60#include "MagickCore/blob.h"
61#include "MagickCore/blob-private.h"
62#include "MagickCore/constitute.h"
63#include "MagickCore/delegate.h"
64#include "MagickCore/exception.h"
65#include "MagickCore/exception-private.h"
66#include "MagickCore/image.h"
67#include "MagickCore/image-private.h"
68#include "MagickCore/list.h"
69#include "MagickCore/MagickCore.h"
70#include "MagickCore/memory_.h"
71#include "MagickCore/string_.h"
72#if defined(_VISUALC_)
73#define WIN32_LEAN_AND_MEAN
74#define VC_EXTRALEAN
75#include <windows.h>
76#include <ole2.h>
77
78/*
79  Forward declarations.
80*/
81static MagickBooleanType
82  WriteXTRNImage(const ImageInfo *,Image *,ExceptionInfo *exception);
83#endif
84
85/*
86%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87%                                                                             %
88%                                                                             %
89%                                                                             %
90%   R e a d X T R N I m a g e                                                 %
91%                                                                             %
92%                                                                             %
93%                                                                             %
94%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95%
96%  ReadXTRNImage() reads a XTRN image file and returns it.  It
97%  allocates the memory necessary for the new Image structure and returns a
98%  pointer to the new image.
99%
100%  The format of the ReadXTRNImage method is:
101%
102%      Image *ReadXTRNImage(const ImageInfo *image_info,
103%        ExceptionInfo *exception)
104%
105%  A description of each parameter follows:
106%
107%    o image_info: Specifies a pointer to an ImageInfo structure.
108%
109%    o exception: return any errors or warnings in this structure.
110%
111*/
112#if defined(_VISUALC_)
113static Image *ReadXTRNImage(const ImageInfo *image_info,
114  ExceptionInfo *exception)
115{
116  Image
117    *image;
118
119  ImageInfo
120    *clone_info;
121
122  void
123    *param1,
124    *param2,
125    *param3;
126
127  param1 = param2 = param3 = (void *) NULL;
128  image = (Image *) NULL;
129  clone_info=CloneImageInfo(image_info);
130  if (clone_info->filename == NULL)
131    {
132      clone_info=DestroyImageInfo(clone_info);
133      ThrowReaderException(FileOpenWarning,"No filename specified");
134    }
135  if (LocaleCompare(image_info->magick,"XTRNFILE") == 0)
136    {
137      image=ReadImage(clone_info,exception);
138      CatchException(exception);
139    }
140  else if (LocaleCompare(image_info->magick,"XTRNIMAGE") == 0)
141    {
142      Image
143        **image_ptr;
144
145#ifdef ALL_IMAGEINFO
146      ImageInfo
147        **image_info_ptr;
148#endif
149
150      (void) sscanf(clone_info->filename,"%lx,%lx",&param1,&param2);
151      image_ptr=(Image **) param2;
152      if (*image_ptr != (Image *) NULL)
153        image=CloneImage(*image_ptr,0,0,MagickFalse,exception);
154#ifdef ALL_IMAGEINFO
155      image_info_ptr=(ImageInfo **) param1;
156      if (*image_info_ptr != (ImageInfo *) NULL)
157        image_info=*image_info_ptr;
158#endif
159    }
160  else if (LocaleCompare(image_info->magick,"XTRNBLOB") == 0)
161    {
162      char
163        **blob_data;
164
165      size_t
166        *blob_length;
167
168      char
169        filename[MaxTextExtent];
170
171      (void) sscanf(clone_info->filename,"%lx,%lx,%s",&param1,&param2,&filename);
172      blob_data=(char **) param1;
173      blob_length=(size_t *) param2;
174      image=BlobToImage(clone_info,*blob_data,*blob_length,exception);
175      CatchException(exception);
176    }
177  else if (LocaleCompare(image_info->magick,"XTRNARRAY") == 0)
178    {
179      char
180        *blob_data,
181        filename[MaxTextExtent];
182
183      HRESULT
184        hr;
185
186      long
187        lBoundl,
188        lBoundu;
189
190      SAFEARRAY
191        *pSafeArray;
192
193      size_t
194        blob_length;
195
196      *filename='\0';
197      (void) sscanf(clone_info->filename,"%lx,%s",&param1,&filename);
198      hr=S_OK;
199      pSafeArray=(SAFEARRAY *) param1;
200      if (pSafeArray)
201        {
202          hr = SafeArrayGetLBound(pSafeArray, 1, &lBoundl);
203          if (SUCCEEDED(hr))
204            {
205              hr = SafeArrayGetUBound(pSafeArray, 1, &lBoundu);
206              if (SUCCEEDED(hr))
207                {
208                  blob_length = lBoundu - lBoundl + 1;
209                  hr = SafeArrayAccessData(pSafeArray,(void**) &blob_data);
210                  if(SUCCEEDED(hr))
211                    {
212                      *clone_info->filename='\0';
213                      *clone_info->magick='\0';
214                      if (*filename != '\0')
215                        (void) CopyMagickString(clone_info->filename,filename,
216                          MaxTextExtent);
217                      image=BlobToImage(clone_info,blob_data,blob_length,
218                        exception);
219                      hr=SafeArrayUnaccessData(pSafeArray);
220                      CatchException(exception);
221                    }
222                }
223            }
224        }
225    }
226  clone_info=DestroyImageInfo(clone_info);
227  return(image);
228}
229#endif
230
231/*
232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233%                                                                             %
234%                                                                             %
235%                                                                             %
236%   R e g i s t e r X T R N I m a g e                                         %
237%                                                                             %
238%                                                                             %
239%                                                                             %
240%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241%
242%  RegisterXTRNImage() adds attributes for the XTRN image format to
243%  the list of supported formats.  The attributes include the image format
244%  tag, a method to read and/or write the format, whether the format
245%  supports the saving of more than one frame to the same file or blob,
246%  whether the format supports native in-memory I/O, and a brief
247%  description of the format.
248%
249%  The format of the RegisterXTRNImage method is:
250%
251%      size_t RegisterXTRNImage(void)
252%
253*/
254ModuleExport size_t RegisterXTRNImage(void)
255{
256  MagickInfo
257    *entry;
258
259  entry=AcquireMagickInfo("XTRN","XTRNFILE","External transfer of a file");
260#if defined(_VISUALC_)
261  entry->decoder=ReadXTRNImage;
262  entry->encoder=WriteXTRNImage;
263#endif
264  entry->flags^=CoderAdjoinFlag;
265  entry->flags|=CoderStealthFlag;
266  RegisterMagickInfo(entry);
267  entry=AcquireMagickInfo("XTRN","XTRNIMAGE",
268    "External transfer of a image in memory");
269#if defined(_VISUALC_)
270  entry->decoder=ReadXTRNImage;
271  entry->encoder=WriteXTRNImage;
272#endif
273  entry->flags^=CoderAdjoinFlag;
274  entry->flags|=CoderStealthFlag;
275  RegisterMagickInfo(entry);
276  entry=AcquireMagickInfo("XTRN","XTRNBLOB",
277    "IExternal transfer of a blob in memory");
278#if defined(_VISUALC_)
279  entry->decoder=ReadXTRNImage;
280  entry->encoder=WriteXTRNImage;
281#endif
282  entry->flags^=CoderAdjoinFlag;
283  entry->flags|=CoderStealthFlag;
284  RegisterMagickInfo(entry);
285  entry=AcquireMagickInfo("XTRN","XTRNARRAY",
286    "External transfer via a smart array interface");
287#if defined(_VISUALC_)
288  entry->decoder=ReadXTRNImage;
289  entry->encoder=WriteXTRNImage;
290#endif
291  entry->flags^=CoderAdjoinFlag;
292  entry->flags|=CoderStealthFlag;
293  RegisterMagickInfo(entry);
294  return(MagickImageCoderSignature);
295}
296
297/*
298%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299%                                                                             %
300%                                                                             %
301%                                                                             %
302%   U n r e g i s t e r X T R N I m a g e                                     %
303%                                                                             %
304%                                                                             %
305%                                                                             %
306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307%
308%  UnregisterXTRNImage() removes format registrations made by the
309%  XTRN module from the list of supported formats.
310%
311%  The format of the UnregisterXTRNImage method is:
312%
313%      UnregisterXTRNImage(void)
314%
315*/
316ModuleExport void UnregisterXTRNImage(void)
317{
318  UnregisterMagickInfo("XTRNFILE");
319  UnregisterMagickInfo("XTRNIMAGE");
320  UnregisterMagickInfo("XTRNBLOB");
321  UnregisterMagickInfo("XTRNARRAY");
322}
323
324/*
325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326%                                                                             %
327%                                                                             %
328%                                                                             %
329%   W r i t e X T R N I m a g e                                               %
330%                                                                             %
331%                                                                             %
332%                                                                             %
333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334%
335%  WriteXTRNImage() writes an image in the XTRN encoded image format.
336%  We use GIF because it is the only format that is compressed without
337%  requiring additional optional delegates (TIFF, ZIP, etc).
338%
339%  The format of the WriteXTRNImage method is:
340%
341%      MagickBooleanType WriteXTRNImage(const ImageInfo *image_info,
342%        Image *image,ExceptionInfo *exception)
343%
344%  A description of each parameter follows.
345%
346%    o image_info: Specifies a pointer to an ImageInfo structure.
347%
348%    o image:  A pointer to a Image structure.
349%
350%    o exception: return any errors or warnings in this structure.
351%
352*/
353
354#if defined(_VISUALC_)
355static size_t SafeArrayFifo(const Image *image,const void *data,
356  const size_t length)
357{
358  SAFEARRAYBOUND NewArrayBounds[1];  /* 1 Dimension */
359  size_t tlen=length;
360  SAFEARRAY *pSafeArray = (SAFEARRAY *)image->client_data;
361  if (pSafeArray != NULL)
362  {
363    long lBoundl, lBoundu, lCount;
364    HRESULT hr = S_OK;
365    /* First see how big the buffer currently is */
366    hr = SafeArrayGetLBound(pSafeArray, 1, &lBoundl);
367    if (FAILED(hr))
368      return MagickFalse;
369    hr = SafeArrayGetUBound(pSafeArray, 1, &lBoundu);
370    if (FAILED(hr))
371      return MagickFalse;
372    lCount = lBoundu - lBoundl + 1;
373
374    if (length>0)
375    {
376      unsigned char       *pReturnBuffer = NULL;
377      NewArrayBounds[0].lLbound = 0;   /* Start-Index 0 */
378      NewArrayBounds[0].cElements = (unsigned long) (length+lCount);  /* # Elemente */
379      hr = SafeArrayRedim(pSafeArray, NewArrayBounds);
380      if (FAILED(hr))
381        return 0;
382      hr = SafeArrayAccessData(pSafeArray, (void**)&pReturnBuffer);
383      if( FAILED(hr) )
384        return 0;
385      (void) memcpy(pReturnBuffer+lCount,(unsigned char *) data,length);
386      hr=SafeArrayUnaccessData(pSafeArray);
387      if(FAILED(hr))
388        return 0;
389    }
390    else
391    {
392      /* Adjust the length of the buffer to fit */
393    }
394  }
395  return(tlen);
396}
397#endif
398
399#if defined(_VISUALC_)
400static MagickBooleanType WriteXTRNImage(const ImageInfo *image_info,
401  Image *image,ExceptionInfo *exception)
402{
403  Image *
404    p;
405
406  ImageInfo
407    *clone_info;
408
409  int
410    scene;
411
412  MagickBooleanType
413    status;
414
415  void
416    *param1,
417    *param2,
418    *param3;
419
420  param1 = param2 = param3 = (void *) NULL;
421  status=MagickTrue;
422  if (LocaleCompare(image_info->magick,"XTRNFILE") == 0)
423    {
424      clone_info=CloneImageInfo(image_info);
425      *clone_info->magick='\0';
426      status=WriteImage(clone_info,image,exception);
427      if (status == MagickFalse)
428        CatchImageException(image);
429      clone_info=DestroyImageInfo(clone_info);
430    }
431  else if (LocaleCompare(image_info->magick,"XTRNIMAGE") == 0)
432    {
433      Image
434        **image_ptr;
435
436      ImageInfo
437        **image_info_ptr;
438
439      clone_info=CloneImageInfo(image_info);
440      if (clone_info->filename[0])
441        {
442          (void) sscanf(clone_info->filename,"%lx,%lx",&param1,&param2);
443          image_info_ptr=(ImageInfo **) param1;
444          image_ptr=(Image **) param2;
445          if ((image_info_ptr != (ImageInfo **) NULL) &&
446              (image_ptr != (Image **) NULL))
447            {
448              *image_ptr=CloneImage(image,0,0,MagickFalse,exception);
449              *image_info_ptr=clone_info;
450            }
451        }
452    }
453  else if (LocaleCompare(image_info->magick,"XTRNBLOB") == 0)
454    {
455      char
456        **blob_data;
457
458      size_t
459        *blob_length;
460
461      char
462        filename[MaxTextExtent];
463
464      clone_info=CloneImageInfo(image_info);
465      if (clone_info->filename[0])
466        {
467          (void) sscanf(clone_info->filename,"%lx,%lx,%s",
468            &param1,&param2,&filename);
469
470          blob_data=(char **) param1;
471          blob_length=(size_t *) param2;
472          scene = 0;
473          (void) CopyMagickString(clone_info->filename,filename,MaxTextExtent);
474          for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
475          {
476            (void) CopyMagickString(p->filename,filename,MaxTextExtent);
477            p->scene=scene++;
478          }
479          SetImageInfo(clone_info,1,exception);
480          (void) CopyMagickString(image->magick,clone_info->magick,
481            MaxTextExtent);
482          if (*blob_length == 0)
483            *blob_length=8192;
484          *blob_data=(char *) ImageToBlob(clone_info,image,blob_length,
485            exception);
486          if (*blob_data == NULL)
487            status=MagickFalse;
488          if (status == MagickFalse)
489            CatchImageException(image);
490        }
491      clone_info=DestroyImageInfo(clone_info);
492    }
493  else if (LocaleCompare(image_info->magick,"XTRNARRAY") == 0)
494    {
495      char
496        filename[MaxTextExtent];
497
498      size_t
499        blob_length;
500
501      unsigned char
502        *blob_data;
503
504      clone_info=CloneImageInfo(image_info);
505      if (*clone_info->filename != '\0')
506        {
507          (void) sscanf(clone_info->filename,"%lx,%s",&param1,&filename);
508          image->client_data=param1;
509          scene=0;
510          (void) CopyMagickString(clone_info->filename,filename,MaxTextExtent);
511          for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
512          {
513            (void) CopyMagickString(p->filename,filename,MaxTextExtent);
514            p->scene=scene++;
515          }
516          SetImageInfo(clone_info,1,exception);
517          (void) CopyMagickString(image->magick,clone_info->magick,
518            MaxTextExtent);
519          blob_data=ImageToBlob(clone_info,image,&blob_length,
520            exception);
521          if (blob_data == (unsigned char *) NULL)
522            status=MagickFalse;
523          else
524            SafeArrayFifo(image,blob_data,blob_length);
525          if (status == MagickFalse)
526            CatchImageException(image);
527        }
528      clone_info=DestroyImageInfo(clone_info);
529    }
530  return(MagickTrue);
531}
532#endif
533