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-2019 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 % https://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. % 41 % 42 % 43 */ 44 45 /* 47 Include declarations. 48 */ 49 #include "MagickCore/studio.h" 50 #include "MagickCore/blob.h" 51 #include "MagickCore/blob-private.h" 52 #include "MagickCore/constitute.h" 53 #include "MagickCore/delegate.h" 54 #include "MagickCore/exception.h" 55 #include "MagickCore/exception-private.h" 56 #include "MagickCore/image.h" 57 #include "MagickCore/image-private.h" 58 #include "MagickCore/list.h" 59 #include "MagickCore/magick.h" 60 #include "MagickCore/magick-private.h" 61 #include "MagickCore/memory_.h" 62 #include "MagickCore/module.h" 63 #include "MagickCore/static.h" 64 #include "MagickCore/string_.h" 65 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__) 66 #define WIN32_LEAN_AND_MEAN 67 #define VC_EXTRALEAN 68 #include <windows.h> 69 #include <ole2.h> 70 71 /* 73 Forward declarations. 74 */ 75 static MagickBooleanType 76 WriteXTRNImage(const ImageInfo *,Image *,ExceptionInfo *exception); 77 #endif 78 79 /* 81 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 82 % % 83 % % 84 % % 85 % R e a d X T R N I m a g e % 86 % % 87 % % 88 % % 89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 90 % 91 % ReadXTRNImage() reads a XTRN image file and returns it. It 92 % allocates the memory necessary for the new Image structure and returns a 93 % pointer to the new image. 94 % 95 % The format of the ReadXTRNImage method is: 96 % 97 % Image *ReadXTRNImage(const ImageInfo *image_info, 98 % ExceptionInfo *exception) 99 % 100 % A description of each parameter follows: 101 % 102 % o image_info: Specifies a pointer to an ImageInfo structure. 103 % 104 % o exception: return any errors or warnings in this structure. 105 % 106 */ 107 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__) 108 static Image *ReadXTRNImage(const ImageInfo *image_info, 109 ExceptionInfo *exception) 110 { 111 char 112 *blob_data, 113 filename[MagickPathExtent]; 114 115 HRESULT 116 hr; 117 118 Image 119 *image; 120 121 ImageInfo 122 *clone_info; 123 124 long 125 lBoundl, 126 lBoundu; 127 128 SAFEARRAY 129 *pSafeArray; 130 131 size_t 132 blob_length; 133 134 void 135 *param1; 136 137 param1=(void *) NULL; 138 image=(Image *) NULL; 139 clone_info=CloneImageInfo(image_info); 140 if (clone_info->filename == NULL) 141 { 142 clone_info=DestroyImageInfo(clone_info); 143 ThrowReaderException(FileOpenWarning,"No filename specified"); 144 } 145 *filename='\0'; 146 (void) sscanf(clone_info->filename,"%p,%2048s",¶m1,filename); 147 hr=S_OK; 148 pSafeArray=(SAFEARRAY *) param1; 149 if (pSafeArray) 150 { 151 hr=SafeArrayGetLBound(pSafeArray,1,&lBoundl); 152 if (SUCCEEDED(hr)) 153 { 154 hr=SafeArrayGetUBound(pSafeArray,1,&lBoundu); 155 if (SUCCEEDED(hr)) 156 { 157 blob_length=lBoundu-lBoundl+1; 158 hr=SafeArrayAccessData(pSafeArray,(void**) &blob_data); 159 if (SUCCEEDED(hr)) 160 { 161 *clone_info->filename='\0'; 162 *clone_info->magick='\0'; 163 if (*filename != '\0') 164 (void) CopyMagickString(clone_info->filename,filename, 165 MagickPathExtent); 166 image=BlobToImage(clone_info,blob_data,blob_length, 167 exception); 168 hr=SafeArrayUnaccessData(pSafeArray); 169 CatchException(exception); 170 } 171 } 172 } 173 } 174 clone_info=DestroyImageInfo(clone_info); 175 return(image); 176 } 177 #endif 178 179 /* 181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 182 % % 183 % % 184 % % 185 % R e g i s t e r X T R N I m a g e % 186 % % 187 % % 188 % % 189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 190 % 191 % RegisterXTRNImage() adds attributes for the XTRN image format to 192 % the list of supported formats. The attributes include the image format 193 % tag, a method to read and/or write the format, whether the format 194 % supports the saving of more than one frame to the same file or blob, 195 % whether the format supports native in-memory I/O, and a brief 196 % description of the format. 197 % 198 % The format of the RegisterXTRNImage method is: 199 % 200 % size_t RegisterXTRNImage(void) 201 % 202 */ 203 ModuleExport size_t RegisterXTRNImage(void) 204 { 205 MagickInfo 206 *entry; 207 208 entry=AcquireMagickInfo("XTRN","XTRNARRAY", 209 "External transfer via a smart array interface"); 210 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__) 211 entry->decoder=ReadXTRNImage; 212 entry->encoder=WriteXTRNImage; 213 #endif 214 entry->flags^=CoderAdjoinFlag; 215 entry->flags|=CoderStealthFlag; 216 RegisterMagickInfo(entry); 217 return(MagickImageCoderSignature); 218 } 219 220 /* 222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 223 % % 224 % % 225 % % 226 % U n r e g i s t e r X T R N I m a g e % 227 % % 228 % % 229 % % 230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 231 % 232 % UnregisterXTRNImage() removes format registrations made by the 233 % XTRN module from the list of supported formats. 234 % 235 % The format of the UnregisterXTRNImage method is: 236 % 237 % UnregisterXTRNImage(void) 238 % 239 */ 240 ModuleExport void UnregisterXTRNImage(void) 241 { 242 UnregisterMagickInfo("XTRNARRAY"); 243 } 244 245 /* 247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 248 % % 249 % % 250 % % 251 % W r i t e X T R N I m a g e % 252 % % 253 % % 254 % % 255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 256 % 257 % WriteXTRNImage() writes an image in the XTRN encoded image format. 258 % We use GIF because it is the only format that is compressed without 259 % requiring additional optional delegates (TIFF, ZIP, etc). 260 % 261 % The format of the WriteXTRNImage method is: 262 % 263 % MagickBooleanType WriteXTRNImage(const ImageInfo *image_info, 264 % Image *image,ExceptionInfo *exception) 265 % 266 % A description of each parameter follows. 267 % 268 % o image_info: Specifies a pointer to an ImageInfo structure. 269 % 270 % o image: A pointer to a Image structure. 271 % 272 % o exception: return any errors or warnings in this structure. 273 % 274 */ 275 276 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__) 277 static size_t SafeArrayFifo(const Image *image,const void *data, 278 const size_t length) 279 { 280 SAFEARRAYBOUND NewArrayBounds[1]; /* 1 Dimension */ 281 size_t tlen=length; 282 SAFEARRAY *pSafeArray = (SAFEARRAY *)image->client_data; 283 if (pSafeArray != NULL) 284 { 285 long lBoundl, lBoundu, lCount; 286 HRESULT hr = S_OK; 287 /* First see how big the buffer currently is */ 288 hr = SafeArrayGetLBound(pSafeArray, 1, &lBoundl); 289 if (FAILED(hr)) 290 return MagickFalse; 291 hr = SafeArrayGetUBound(pSafeArray, 1, &lBoundu); 292 if (FAILED(hr)) 293 return MagickFalse; 294 lCount = lBoundu - lBoundl + 1; 295 296 if (length>0) 297 { 298 unsigned char *pReturnBuffer = NULL; 299 NewArrayBounds[0].lLbound = 0; /* Start-Index 0 */ 300 NewArrayBounds[0].cElements = (unsigned long) (length+lCount); /* # Elemente */ 301 hr = SafeArrayRedim(pSafeArray, NewArrayBounds); 302 if (FAILED(hr)) 303 return 0; 304 hr = SafeArrayAccessData(pSafeArray, (void**)&pReturnBuffer); 305 if( FAILED(hr) ) 306 return 0; 307 (void) memcpy(pReturnBuffer+lCount,(unsigned char *) data,length); 308 hr=SafeArrayUnaccessData(pSafeArray); 309 if(FAILED(hr)) 310 return 0; 311 } 312 else 313 { 314 /* Adjust the length of the buffer to fit */ 315 } 316 } 317 return(tlen); 318 } 319 320 static MagickBooleanType WriteXTRNImage(const ImageInfo *image_info, 321 Image *image,ExceptionInfo *exception) 322 { 323 char 324 filename[MagickPathExtent]; 325 326 Image 327 *p; 328 329 ImageInfo 330 *clone_info; 331 332 int 333 scene; 334 335 MagickBooleanType 336 status; 337 338 size_t 339 blob_length; 340 341 unsigned char 342 *blob_data; 343 344 void 345 *param1; 346 347 param1 = (void *) NULL; 348 status=MagickTrue; 349 clone_info=CloneImageInfo(image_info); 350 if (*clone_info->filename != '\0') 351 { 352 (void) sscanf(clone_info->filename,"%p,%2048s",¶m1,filename); 353 image->client_data=param1; 354 scene=0; 355 (void) CopyMagickString(clone_info->filename,filename, 356 MagickPathExtent); 357 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p)) 358 { 359 (void) CopyMagickString(p->filename,filename,MagickPathExtent); 360 p->scene=scene++; 361 } 362 SetImageInfo(clone_info,1,exception); 363 (void) CopyMagickString(image->magick,clone_info->magick, 364 MagickPathExtent); 365 blob_data=ImageToBlob(clone_info,image,&blob_length, 366 exception); 367 if (blob_data == (unsigned char *) NULL) 368 status=MagickFalse; 369 else 370 SafeArrayFifo(image,blob_data,blob_length); 371 if (status == MagickFalse) 372 CatchImageException(image); 373 } 374 clone_info=DestroyImageInfo(clone_info); 375 return(MagickTrue); 376 } 377 #endif 378