xtrn.c revision fa589d6096099562cbc2bc14e508931968a8c055
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_) 113# pragma warning(disable : 4477) 114static Image *ReadXTRNImage(const ImageInfo *image_info, 115 ExceptionInfo *exception) 116{ 117 Image 118 *image; 119 120 ImageInfo 121 *clone_info; 122 123 void 124 *param1, 125 *param2, 126 *param3; 127 128 param1 = param2 = param3 = (void *) NULL; 129 image = (Image *) NULL; 130 clone_info=CloneImageInfo(image_info); 131 if (clone_info->filename == NULL) 132 { 133 clone_info=DestroyImageInfo(clone_info); 134 ThrowReaderException(FileOpenWarning,"No filename specified"); 135 } 136 if (LocaleCompare(image_info->magick,"XTRNFILE") == 0) 137 { 138 image=ReadImage(clone_info,exception); 139 CatchException(exception); 140 } 141 else if (LocaleCompare(image_info->magick,"XTRNIMAGE") == 0) 142 { 143 Image 144 **image_ptr; 145 146#ifdef ALL_IMAGEINFO 147 ImageInfo 148 **image_info_ptr; 149#endif 150 151 (void) sscanf(clone_info->filename,"%lx,%lx",¶m1,¶m2); 152 image_ptr=(Image **) param2; 153 if (*image_ptr != (Image *) NULL) 154 image=CloneImage(*image_ptr,0,0,MagickFalse,exception); 155#ifdef ALL_IMAGEINFO 156 image_info_ptr=(ImageInfo **) param1; 157 if (*image_info_ptr != (ImageInfo *) NULL) 158 image_info=*image_info_ptr; 159#endif 160 } 161 else if (LocaleCompare(image_info->magick,"XTRNBLOB") == 0) 162 { 163 char 164 **blob_data; 165 166 size_t 167 *blob_length; 168 169 char 170 filename[MagickPathExtent]; 171 172 (void) sscanf(clone_info->filename,"%lx,%lx,%2048s",¶m1,¶m2, 173 filename); 174 blob_data=(char **) param1; 175 blob_length=(size_t *) param2; 176 image=BlobToImage(clone_info,*blob_data,*blob_length,exception); 177 CatchException(exception); 178 } 179 else if (LocaleCompare(image_info->magick,"XTRNARRAY") == 0) 180 { 181 char 182 *blob_data, 183 filename[MagickPathExtent]; 184 185 HRESULT 186 hr; 187 188 long 189 lBoundl, 190 lBoundu; 191 192 SAFEARRAY 193 *pSafeArray; 194 195 size_t 196 blob_length; 197 198 *filename='\0'; 199 (void) sscanf(clone_info->filename,"%lx,%2048s",¶m1,filename); 200 hr=S_OK; 201 pSafeArray=(SAFEARRAY *) param1; 202 if (pSafeArray) 203 { 204 hr = SafeArrayGetLBound(pSafeArray, 1, &lBoundl); 205 if (SUCCEEDED(hr)) 206 { 207 hr = SafeArrayGetUBound(pSafeArray, 1, &lBoundu); 208 if (SUCCEEDED(hr)) 209 { 210 blob_length = lBoundu - lBoundl + 1; 211 hr = SafeArrayAccessData(pSafeArray,(void**) &blob_data); 212 if(SUCCEEDED(hr)) 213 { 214 *clone_info->filename='\0'; 215 *clone_info->magick='\0'; 216 if (*filename != '\0') 217 (void) CopyMagickString(clone_info->filename,filename, 218 MagickPathExtent); 219 image=BlobToImage(clone_info,blob_data,blob_length, 220 exception); 221 hr=SafeArrayUnaccessData(pSafeArray); 222 CatchException(exception); 223 } 224 } 225 } 226 } 227 } 228 clone_info=DestroyImageInfo(clone_info); 229 return(image); 230} 231# pragma warning(default : 4477) 232#endif 233 234/* 235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 236% % 237% % 238% % 239% R e g i s t e r X T R N I m a g e % 240% % 241% % 242% % 243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 244% 245% RegisterXTRNImage() adds attributes for the XTRN image format to 246% the list of supported formats. The attributes include the image format 247% tag, a method to read and/or write the format, whether the format 248% supports the saving of more than one frame to the same file or blob, 249% whether the format supports native in-memory I/O, and a brief 250% description of the format. 251% 252% The format of the RegisterXTRNImage method is: 253% 254% size_t RegisterXTRNImage(void) 255% 256*/ 257ModuleExport size_t RegisterXTRNImage(void) 258{ 259 MagickInfo 260 *entry; 261 262 entry=AcquireMagickInfo("XTRN","XTRNFILE","External transfer of a file"); 263#if defined(_VISUALC_) 264 entry->decoder=ReadXTRNImage; 265 entry->encoder=WriteXTRNImage; 266#endif 267 entry->flags^=CoderAdjoinFlag; 268 entry->flags|=CoderStealthFlag; 269 RegisterMagickInfo(entry); 270 entry=AcquireMagickInfo("XTRN","XTRNIMAGE", 271 "External transfer of a image in memory"); 272#if defined(_VISUALC_) 273 entry->decoder=ReadXTRNImage; 274 entry->encoder=WriteXTRNImage; 275#endif 276 entry->flags^=CoderAdjoinFlag; 277 entry->flags|=CoderStealthFlag; 278 RegisterMagickInfo(entry); 279 entry=AcquireMagickInfo("XTRN","XTRNBLOB", 280 "IExternal transfer of a blob in memory"); 281#if defined(_VISUALC_) 282 entry->decoder=ReadXTRNImage; 283 entry->encoder=WriteXTRNImage; 284#endif 285 entry->flags^=CoderAdjoinFlag; 286 entry->flags|=CoderStealthFlag; 287 RegisterMagickInfo(entry); 288 entry=AcquireMagickInfo("XTRN","XTRNARRAY", 289 "External transfer via a smart array interface"); 290#if defined(_VISUALC_) 291 entry->decoder=ReadXTRNImage; 292 entry->encoder=WriteXTRNImage; 293#endif 294 entry->flags^=CoderAdjoinFlag; 295 entry->flags|=CoderStealthFlag; 296 RegisterMagickInfo(entry); 297 return(MagickImageCoderSignature); 298} 299 300/* 301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 302% % 303% % 304% % 305% U n r e g i s t e r X T R N I m a g e % 306% % 307% % 308% % 309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 310% 311% UnregisterXTRNImage() removes format registrations made by the 312% XTRN module from the list of supported formats. 313% 314% The format of the UnregisterXTRNImage method is: 315% 316% UnregisterXTRNImage(void) 317% 318*/ 319ModuleExport void UnregisterXTRNImage(void) 320{ 321 UnregisterMagickInfo("XTRNFILE"); 322 UnregisterMagickInfo("XTRNIMAGE"); 323 UnregisterMagickInfo("XTRNBLOB"); 324 UnregisterMagickInfo("XTRNARRAY"); 325} 326 327/* 328%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 329% % 330% % 331% % 332% W r i t e X T R N I m a g e % 333% % 334% % 335% % 336%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 337% 338% WriteXTRNImage() writes an image in the XTRN encoded image format. 339% We use GIF because it is the only format that is compressed without 340% requiring additional optional delegates (TIFF, ZIP, etc). 341% 342% The format of the WriteXTRNImage method is: 343% 344% MagickBooleanType WriteXTRNImage(const ImageInfo *image_info, 345% Image *image,ExceptionInfo *exception) 346% 347% A description of each parameter follows. 348% 349% o image_info: Specifies a pointer to an ImageInfo structure. 350% 351% o image: A pointer to a Image structure. 352% 353% o exception: return any errors or warnings in this structure. 354% 355*/ 356 357#if defined(_VISUALC_) 358static size_t SafeArrayFifo(const Image *image,const void *data, 359 const size_t length) 360{ 361 SAFEARRAYBOUND NewArrayBounds[1]; /* 1 Dimension */ 362 size_t tlen=length; 363 SAFEARRAY *pSafeArray = (SAFEARRAY *)image->client_data; 364 if (pSafeArray != NULL) 365 { 366 long lBoundl, lBoundu, lCount; 367 HRESULT hr = S_OK; 368 /* First see how big the buffer currently is */ 369 hr = SafeArrayGetLBound(pSafeArray, 1, &lBoundl); 370 if (FAILED(hr)) 371 return MagickFalse; 372 hr = SafeArrayGetUBound(pSafeArray, 1, &lBoundu); 373 if (FAILED(hr)) 374 return MagickFalse; 375 lCount = lBoundu - lBoundl + 1; 376 377 if (length>0) 378 { 379 unsigned char *pReturnBuffer = NULL; 380 NewArrayBounds[0].lLbound = 0; /* Start-Index 0 */ 381 NewArrayBounds[0].cElements = (unsigned long) (length+lCount); /* # Elemente */ 382 hr = SafeArrayRedim(pSafeArray, NewArrayBounds); 383 if (FAILED(hr)) 384 return 0; 385 hr = SafeArrayAccessData(pSafeArray, (void**)&pReturnBuffer); 386 if( FAILED(hr) ) 387 return 0; 388 (void) memcpy(pReturnBuffer+lCount,(unsigned char *) data,length); 389 hr=SafeArrayUnaccessData(pSafeArray); 390 if(FAILED(hr)) 391 return 0; 392 } 393 else 394 { 395 /* Adjust the length of the buffer to fit */ 396 } 397 } 398 return(tlen); 399} 400#endif 401 402#if defined(_VISUALC_) 403# pragma warning(disable : 4477) 404static MagickBooleanType WriteXTRNImage(const ImageInfo *image_info, 405 Image *image,ExceptionInfo *exception) 406{ 407 Image * 408 p; 409 410 ImageInfo 411 *clone_info; 412 413 int 414 scene; 415 416 MagickBooleanType 417 status; 418 419 void 420 *param1, 421 *param2, 422 *param3; 423 424 param1 = param2 = param3 = (void *) NULL; 425 status=MagickTrue; 426 if (LocaleCompare(image_info->magick,"XTRNFILE") == 0) 427 { 428 clone_info=CloneImageInfo(image_info); 429 *clone_info->magick='\0'; 430 status=WriteImage(clone_info,image,exception); 431 if (status == MagickFalse) 432 CatchImageException(image); 433 clone_info=DestroyImageInfo(clone_info); 434 } 435 else if (LocaleCompare(image_info->magick,"XTRNIMAGE") == 0) 436 { 437 Image 438 **image_ptr; 439 440 ImageInfo 441 **image_info_ptr; 442 443 clone_info=CloneImageInfo(image_info); 444 if (clone_info->filename[0]) 445 { 446 (void) sscanf(clone_info->filename,"%lx,%lx",¶m1,¶m2); 447 image_info_ptr=(ImageInfo **) param1; 448 image_ptr=(Image **) param2; 449 if ((image_info_ptr != (ImageInfo **) NULL) && 450 (image_ptr != (Image **) NULL)) 451 { 452 *image_ptr=CloneImage(image,0,0,MagickFalse,exception); 453 *image_info_ptr=clone_info; 454 } 455 } 456 } 457 else if (LocaleCompare(image_info->magick,"XTRNBLOB") == 0) 458 { 459 char 460 **blob_data; 461 462 size_t 463 *blob_length; 464 465 char 466 filename[MagickPathExtent]; 467 468 clone_info=CloneImageInfo(image_info); 469 if (clone_info->filename[0]) 470 { 471 (void) sscanf(clone_info->filename,"%lx,%lx,%2048s", 472 ¶m1,¶m2,filename); 473 474 blob_data=(char **) param1; 475 blob_length=(size_t *) param2; 476 scene = 0; 477 (void) CopyMagickString(clone_info->filename,filename, 478 MagickPathExtent); 479 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p)) 480 { 481 (void) CopyMagickString(p->filename,filename,MagickPathExtent); 482 p->scene=scene++; 483 } 484 SetImageInfo(clone_info,1,exception); 485 (void) CopyMagickString(image->magick,clone_info->magick, 486 MagickPathExtent); 487 if (*blob_length == 0) 488 *blob_length=8192; 489 *blob_data=(char *) ImageToBlob(clone_info,image,blob_length, 490 exception); 491 if (*blob_data == NULL) 492 status=MagickFalse; 493 if (status == MagickFalse) 494 CatchImageException(image); 495 } 496 clone_info=DestroyImageInfo(clone_info); 497 } 498 else if (LocaleCompare(image_info->magick,"XTRNARRAY") == 0) 499 { 500 char 501 filename[MagickPathExtent]; 502 503 size_t 504 blob_length; 505 506 unsigned char 507 *blob_data; 508 509 clone_info=CloneImageInfo(image_info); 510 if (*clone_info->filename != '\0') 511 { 512 (void) sscanf(clone_info->filename,"%lx,%2048s",¶m1,filename); 513 image->client_data=param1; 514 scene=0; 515 (void) CopyMagickString(clone_info->filename,filename, 516 MagickPathExtent); 517 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p)) 518 { 519 (void) CopyMagickString(p->filename,filename,MagickPathExtent); 520 p->scene=scene++; 521 } 522 SetImageInfo(clone_info,1,exception); 523 (void) CopyMagickString(image->magick,clone_info->magick, 524 MagickPathExtent); 525 blob_data=ImageToBlob(clone_info,image,&blob_length, 526 exception); 527 if (blob_data == (unsigned char *) NULL) 528 status=MagickFalse; 529 else 530 SafeArrayFifo(image,blob_data,blob_length); 531 if (status == MagickFalse) 532 CatchImageException(image); 533 } 534 clone_info=DestroyImageInfo(clone_info); 535 } 536 return(MagickTrue); 537} 538# pragma warning(default : 4477) 539#endif 540