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",¶m1,¶m2); 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",¶m1,¶m2,&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",¶m1,&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",¶m1,¶m2); 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 ¶m1,¶m2,&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",¶m1,&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