Powered by Pair ImageMagick logo
Image Magick
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Globals | Related Pages

ImageMagick-6.1.1/magick/blob.c

Go to the documentation of this file.
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % BBBB L OOO BBBB % 00007 % B B L O O B B % 00008 % BBBB L O O BBBB % 00009 % B B L O O B B % 00010 % BBBB LLLLL OOO BBBB % 00011 % % 00012 % % 00013 % ImageMagick Binary Large OBjectS Methods % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % July 1999 % 00018 % % 00019 % % 00020 % Copyright 1999-2004 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.imagemagick.org/www/Copyright.html % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % 00037 % 00038 */ 00039 00040 /* 00041 Include declarations. 00042 */ 00043 #include "magick/studio.h" 00044 #include "magick/blob.h" 00045 #include "magick/blob_private.h" 00046 #include "magick/cache.h" 00047 #include "magick/client.h" 00048 #include "magick/constitute.h" 00049 #include "magick/delegate.h" 00050 #include "magick/error.h" 00051 #include "magick/error_private.h" 00052 #include "magick/image_private.h" 00053 #include "magick/list.h" 00054 #include "magick/log.h" 00055 #include "magick/magick.h" 00056 #include "magick/memory_.h" 00057 #include "magick/resource_.h" 00058 #include "magick/semaphore.h" 00059 #include "magick/string_.h" 00060 #include "magick/utility.h" 00061 #if defined(HAVE_MMAP_FILEIO) && !defined(__WINDOWS__) 00062 # include <sys/mman.h> 00063 #endif 00064 #if defined(HasZLIB) 00065 #include "zlib.h" 00066 #endif 00067 #if defined(HasBZLIB) 00068 #include "bzlib.h" 00069 #endif 00070 00071 /* 00072 Define declarations. 00073 */ 00074 #define DefaultBlobQuantum 0x3c005UL 00075 # if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) 00076 # define MAP_ANONYMOUS MAP_ANON 00077 # endif 00078 #if !defined(MAP_FAILED) 00079 #define MAP_FAILED ((void *) -1) 00080 #endif 00081 #define MinBlobExtent 65541UL 00082 #if !defined(MS_SYNC) 00083 #define MS_SYNC 0x04 00084 #endif 00085 00086 /* 00087 Typedef declarations. 00088 */ 00089 typedef enum 00090 { 00091 UndefinedStream, 00092 FileStream, 00093 StandardStream, 00094 PipeStream, 00095 ZipStream, 00096 BZipStream, 00097 FifoStream, 00098 BlobStream 00099 } StreamType; 00100 00101 struct _BlobInfo 00102 { 00103 size_t 00104 length, 00105 extent, 00106 quantum; 00107 00108 MagickBooleanType 00109 mapped, 00110 eof; 00111 00112 MagickOffsetType 00113 offset; 00114 00115 MagickSizeType 00116 size; 00117 00118 MagickBooleanType 00119 exempt, 00120 status, 00121 temporary; 00122 00123 StreamType 00124 type; 00125 00126 FILE 00127 *file; 00128 00129 StreamHandler 00130 stream; 00131 00132 unsigned char 00133 *data; 00134 00135 MagickBooleanType 00136 debug; 00137 00138 void 00139 *semaphore; 00140 00141 long 00142 reference_count; 00143 00144 unsigned long 00145 signature; 00146 }; 00147 00148 /* 00149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00150 % % 00151 % % 00152 % % 00153 + A t t a c h B l o b % 00154 % % 00155 % % 00156 % % 00157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00158 % 00159 % AttachBlob() attaches a blob to the BlobInfo structure. 00160 % 00161 % The format of the AttachBlob method is: 00162 % 00163 % void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length) 00164 % 00165 % A description of each parameter follows: 00166 % 00167 % o blob_info: Specifies a pointer to a BlobInfo structure. 00168 % 00169 % o blob: The address of a character stream in one of the image formats 00170 % understood by ImageMagick. 00171 % 00172 % o length: This size_t integer reflects the length in bytes of the blob. 00173 % 00174 % 00175 */ 00176 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob, 00177 const size_t length) 00178 { 00179 assert(blob_info != (BlobInfo *) NULL); 00180 if (blob_info->debug != MagickFalse) 00181 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 00182 blob_info->length=length; 00183 blob_info->extent=length; 00184 blob_info->quantum=DefaultBlobQuantum; 00185 blob_info->offset=0; 00186 blob_info->type=BlobStream; 00187 blob_info->file=(FILE *) NULL; 00188 blob_info->data=(unsigned char *) blob; 00189 } 00190 00191 /* 00192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00193 % % 00194 % % 00195 % % 00196 % B l o b T o F i l e % 00197 % % 00198 % % 00199 % % 00200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00201 % 00202 % BlobToFile() writes a blob to a file. It returns MagickFalse if an error 00203 % occurs otherwise MagickTrue. 00204 % 00205 % The format of the BlobToFile method is: 00206 % 00207 % MagickBooleanType BlobToFile(char *filename,const void *blob, 00208 % const size_t length,ExceptionInfo *exception) 00209 % 00210 % A description of each parameter follows: 00211 % 00212 % o filename: Write the blob to this file. 00213 % 00214 % o blob: The address of a blob. 00215 % 00216 % o length: This length in bytes of the blob. 00217 % 00218 % o exception: Return any errors or warnings in this structure. 00219 % 00220 % 00221 */ 00222 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob, 00223 const size_t length,ExceptionInfo *exception) 00224 { 00225 int 00226 file; 00227 00228 register size_t 00229 i; 00230 00231 ssize_t 00232 count; 00233 00234 assert(filename != (const char *) NULL); 00235 (void) LogMagickEvent(TraceEvent,GetMagickModule(),filename); 00236 assert(blob != (const void *) NULL); 00237 if (*filename == '\0') 00238 file=AcquireUniqueFileResource(filename); 00239 else 00240 file=open(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE); 00241 if (file == -1) 00242 { 00243 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); 00244 return(MagickFalse); 00245 } 00246 for (i=0; i < length; i+=count) 00247 { 00248 count=write(file,(char *) blob+i,Min(length-i,(size_t) 00249 MagickMaxBufferSize)); 00250 if (count <= 0) 00251 { 00252 count=0; 00253 if (errno != EINTR) 00254 break; 00255 } 00256 } 00257 (void) close(file); 00258 if (i < length) 00259 { 00260 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); 00261 return(MagickFalse); 00262 } 00263 return(MagickTrue); 00264 } 00265 00266 /* 00267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00268 % % 00269 % % 00270 % % 00271 % B l o b T o I m a g e % 00272 % % 00273 % % 00274 % % 00275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00276 % 00277 % BlobToImage() implements direct to memory image formats. It returns the 00278 % blob as an image. 00279 % 00280 % The format of the BlobToImage method is: 00281 % 00282 % Image *BlobToImage(const ImageInfo *image_info,const void *blob, 00283 % const size_t length,ExceptionInfo *exception) 00284 % 00285 % A description of each parameter follows: 00286 % 00287 % o image_info: The image info. 00288 % 00289 % o blob: The address of a character stream in one of the image formats 00290 % understood by ImageMagick. 00291 % 00292 % o length: This size_t integer reflects the length in bytes of the blob. 00293 % 00294 % o exception: Return any errors or warnings in this structure. 00295 % 00296 % 00297 */ 00298 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob, 00299 const size_t length,ExceptionInfo *exception) 00300 { 00301 const MagickInfo 00302 *magick_info; 00303 00304 Image 00305 *image; 00306 00307 ImageInfo 00308 *blob_info; 00309 00310 MagickBooleanType 00311 status; 00312 00313 assert(image_info != (ImageInfo *) NULL); 00314 assert(image_info->signature == MagickSignature); 00315 if (image_info->debug != MagickFalse) 00316 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image_info->filename); 00317 assert(exception != (ExceptionInfo *) NULL); 00318 (void) SetExceptionInfo(exception,UndefinedException); 00319 if ((blob == (const void *) NULL) || (length == 0)) 00320 { 00321 (void) ThrowMagickException(exception,GetMagickModule(),BlobError, 00322 "ZeroLengthBlobNotPermitted",image_info->filename); 00323 return((Image *) NULL); 00324 } 00325 blob_info=CloneImageInfo(image_info); 00326 blob_info->blob=(void *) blob; 00327 blob_info->length=length; 00328 if (*blob_info->magick == '\0') 00329 (void) SetImageInfo(blob_info,MagickFalse,exception); 00330 magick_info=GetMagickInfo(blob_info->magick,exception); 00331 if (magick_info == (const MagickInfo *) NULL) 00332 { 00333 blob_info=DestroyImageInfo(blob_info); 00334 return((Image *) NULL); 00335 } 00336 if (GetMagickBlobSupport(magick_info) != MagickFalse) 00337 { 00338 /* 00339 Native blob support for this image format. 00340 */ 00341 (void) CopyMagickString(blob_info->filename,image_info->filename, 00342 MaxTextExtent); 00343 (void) CopyMagickString(blob_info->magick,image_info->magick, 00344 MaxTextExtent); 00345 image=ReadImage(blob_info,exception); 00346 if (image != (Image *) NULL) 00347 (void) DetachBlob(image->blob); 00348 blob_info=DestroyImageInfo(blob_info); 00349 return(image); 00350 } 00351 /* 00352 Write blob to a temporary file on disk. 00353 */ 00354 blob_info->blob=(void *) NULL; 00355 blob_info->length=0; 00356 *blob_info->filename='\0'; 00357 status=BlobToFile(blob_info->filename,blob,length,exception); 00358 if (status == MagickFalse) 00359 { 00360 (void) RelinquishUniqueFileResource(blob_info->filename); 00361 blob_info=DestroyImageInfo(blob_info); 00362 return((Image *) NULL); 00363 } 00364 image=ReadImage(blob_info,exception); 00365 (void) RelinquishUniqueFileResource(blob_info->filename); 00366 blob_info=DestroyImageInfo(blob_info); 00367 return(image); 00368 } 00369 00370 /* 00371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00372 % % 00373 % % 00374 % % 00375 + C l o n e B l o b I n f o % 00376 % % 00377 % % 00378 % % 00379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00380 % 00381 % CloneBlobInfo() makes a duplicate of the given blob info structure, or if 00382 % blob info is NULL, a new one. 00383 % 00384 % The format of the CloneBlobInfo method is: 00385 % 00386 % BlobInfo *CloneBlobInfo(const BlobInfo *blob_info) 00387 % 00388 % A description of each parameter follows: 00389 % 00390 % o blob_info: The blob info. 00391 % 00392 % 00393 */ 00394 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info) 00395 { 00396 BlobInfo 00397 *clone_info; 00398 00399 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info)); 00400 if (clone_info == (BlobInfo *) NULL) 00401 ThrowMagickFatalException(ResourceLimitFatalError,"MemoryAllocationFailed", 00402 strerror(errno)); 00403 GetBlobInfo(clone_info); 00404 if (blob_info == (BlobInfo *) NULL) 00405 return(clone_info); 00406 clone_info->length=blob_info->length; 00407 clone_info->extent=blob_info->extent; 00408 clone_info->quantum=blob_info->quantum; 00409 clone_info->mapped=blob_info->mapped; 00410 clone_info->eof=blob_info->eof; 00411 clone_info->offset=blob_info->offset; 00412 clone_info->size=blob_info->size; 00413 clone_info->exempt=blob_info->exempt; 00414 clone_info->status=blob_info->status; 00415 clone_info->temporary=blob_info->temporary; 00416 clone_info->type=blob_info->type; 00417 clone_info->file=blob_info->file; 00418 clone_info->stream=blob_info->stream; 00419 clone_info->data=blob_info->data; 00420 clone_info->debug=IsEventLogging(); 00421 clone_info->reference_count=1; 00422 clone_info->semaphore=(SemaphoreInfo *) NULL; 00423 return(clone_info); 00424 } 00425 00426 /* 00427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00428 % % 00429 % % 00430 % % 00431 + C l o s e B l o b % 00432 % % 00433 % % 00434 % % 00435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00436 % 00437 % CloseBlob() closes a stream associated with the image. 00438 % 00439 % The format of the CloseBlob method is: 00440 % 00441 % void CloseBlob(Image *image) 00442 % 00443 % A description of each parameter follows: 00444 % 00445 % o image: The image. 00446 % 00447 % 00448 */ 00449 MagickExport void CloseBlob(Image *image) 00450 { 00451 int 00452 status; 00453 00454 /* 00455 Close image file. 00456 */ 00457 assert(image != (Image *) NULL); 00458 assert(image->signature == MagickSignature); 00459 if (image->debug != MagickFalse) 00460 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 00461 assert(image->blob != (BlobInfo *) NULL); 00462 if (image->blob->type == UndefinedStream) 00463 return; 00464 image->taint=MagickFalse; 00465 image->blob->size=GetBlobSize(image); 00466 image->blob->eof=MagickFalse; 00467 if (image->blob->exempt != MagickFalse) 00468 return; 00469 status=0; 00470 (void) SyncBlob(image); 00471 switch (image->blob->type) 00472 { 00473 case UndefinedStream: 00474 break; 00475 case FileStream: 00476 case StandardStream: 00477 case PipeStream: 00478 { 00479 status=ferror(image->blob->file); 00480 break; 00481 } 00482 case ZipStream: 00483 { 00484 #if defined(HasZLIB) 00485 (void) gzerror(image->blob->file,&status); 00486 #endif 00487 break; 00488 } 00489 case BZipStream: 00490 { 00491 #if defined(HasBZLIB) 00492 (void) BZ2_bzerror((BZFILE *) image->blob->file,&status); 00493 #endif 00494 break; 00495 } 00496 case FifoStream: 00497 case BlobStream: 00498 break; 00499 } 00500 image->blob->status=(MagickBooleanType) (status < 0); 00501 switch (image->blob->type) 00502 { 00503 case UndefinedStream: 00504 break; 00505 case FileStream: 00506 case StandardStream: 00507 { 00508 status=fclose(image->blob->file); 00509 break; 00510 } 00511 case PipeStream: 00512 { 00513 #if defined(HAVE_POPEN) 00514 status=pclose(image->blob->file); 00515 #endif 00516 break; 00517 } 00518 case ZipStream: 00519 { 00520 #if defined(HasZLIB) 00521 status=gzclose(image->blob->file); 00522 #endif 00523 break; 00524 } 00525 case BZipStream: 00526 { 00527 #if defined(HasBZLIB) 00528 BZ2_bzclose((BZFILE *) image->blob->file); 00529 #endif 00530 break; 00531 } 00532 case FifoStream: 00533 case BlobStream: 00534 break; 00535 } 00536 (void) DetachBlob(image->blob); 00537 image->blob->status=(MagickBooleanType) (status < 0); 00538 } 00539 00540 /* 00541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00542 % % 00543 % % 00544 % % 00545 % D e s t r o y B l o b % 00546 % % 00547 % % 00548 % % 00549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00550 % 00551 % DestroyBlob() deallocates memory associated with a blob. 00552 % 00553 % The format of the DestroyBlob method is: 00554 % 00555 % void DestroyBlob(Image *image) 00556 % 00557 % A description of each parameter follows: 00558 % 00559 % o image: The image. 00560 % 00561 % 00562 */ 00563 MagickExport void DestroyBlob(Image *image) 00564 { 00565 assert(image != (Image *) NULL); 00566 assert(image->signature == MagickSignature); 00567 if (image->debug != MagickFalse) 00568 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 00569 image->blob->semaphore=AcquireSemaphoreInfo(image->blob->semaphore); 00570 image->blob->reference_count--; 00571 if (image->blob->reference_count > 0) 00572 { 00573 RelinquishSemaphoreInfo(image->blob->semaphore); 00574 return; 00575 } 00576 CloseBlob(image); 00577 if (image->blob->mapped != MagickFalse) 00578 (void) UnmapBlob(image->blob->data,image->blob->length); 00579 RelinquishSemaphoreInfo(image->blob->semaphore); 00580 image->blob->semaphore=DestroySemaphoreInfo(image->blob->semaphore); 00581 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob); 00582 } 00583 00584 /* 00585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00586 % % 00587 % % 00588 % % 00589 % D e t a c h B l o b % 00590 % % 00591 % % 00592 % % 00593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00594 % 00595 % DetachBlob() detaches a blob from the BlobInfo structure. 00596 % 00597 % The format of the DetachBlob method is: 00598 % 00599 % unsigned char *DetachBlob(BlobInfo *blob_info) 00600 % 00601 % A description of each parameter follows: 00602 % 00603 % o blob_info: Specifies a pointer to a BlobInfo structure. 00604 % 00605 % 00606 */ 00607 MagickExport unsigned char *DetachBlob(BlobInfo *blob_info) 00608 { 00609 unsigned char 00610 *data; 00611 00612 assert(blob_info != (BlobInfo *) NULL); 00613 if (blob_info->debug != MagickFalse) 00614 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 00615 if (blob_info->mapped != MagickFalse) 00616 (void) UnmapBlob(blob_info->data,blob_info->length); 00617 blob_info->mapped=MagickFalse; 00618 blob_info->length=0; 00619 blob_info->offset=0; 00620 blob_info->eof=MagickFalse; 00621 blob_info->exempt=MagickFalse; 00622 blob_info->type=UndefinedStream; 00623 blob_info->file=(FILE *) NULL; 00624 data=blob_info->data; 00625 blob_info->data=(unsigned char *) NULL; 00626 blob_info->stream=(StreamHandler) NULL; 00627 return(data); 00628 } 00629 00630 /* 00631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00632 % % 00633 % % 00634 % % 00635 + E O F B l o b % 00636 % % 00637 % % 00638 % % 00639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00640 % 00641 % EOFBlob() returns a non-zero value when EOF has been detected reading from 00642 % a blob or file. 00643 % 00644 % The format of the EOFBlob method is: 00645 % 00646 % int EOFBlob(const Image *image) 00647 % 00648 % A description of each parameter follows: 00649 % 00650 % o image: The image. 00651 % 00652 % 00653 */ 00654 MagickExport int EOFBlob(const Image *image) 00655 { 00656 assert(image != (Image *) NULL); 00657 assert(image->signature == MagickSignature); 00658 if (image->debug != MagickFalse) 00659 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 00660 assert(image->blob != (BlobInfo *) NULL); 00661 assert(image->blob->type != UndefinedStream); 00662 switch (image->blob->type) 00663 { 00664 case UndefinedStream: 00665 break; 00666 case FileStream: 00667 case StandardStream: 00668 case PipeStream: 00669 { 00670 image->blob->eof=(MagickBooleanType) (feof(image->blob->file) != 0); 00671 break; 00672 } 00673 case ZipStream: 00674 { 00675 image->blob->eof=MagickFalse; 00676 break; 00677 } 00678 case BZipStream: 00679 { 00680 #if defined(HasBZLIB) 00681 int 00682 status; 00683 00684 status=0; 00685 (void) BZ2_bzerror((BZFILE *) image->blob->file,&status); 00686 image->blob->eof=(MagickBooleanType) (status == BZ_UNEXPECTED_EOF); 00687 #endif 00688 break; 00689 } 00690 case FifoStream: 00691 { 00692 image->blob->eof=MagickFalse; 00693 break; 00694 } 00695 case BlobStream: 00696 break; 00697 } 00698 return((int) image->blob->eof); 00699 } 00700 00701 /* 00702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00703 % % 00704 % % 00705 % % 00706 % F i l e T o B l o b % 00707 % % 00708 % % 00709 % % 00710 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00711 % 00712 % FileToBlob() returns the contents of a file as a blob. It returns the 00713 % file as a blob and its length. If an error occurs, NULL is returned. 00714 % 00715 % The format of the FileToBlob method is: 00716 % 00717 % unsigned char *FileToBlob(const char *filename,size_t *length, 00718 % ExceptionInfo *exception) 00719 % 00720 % A description of each parameter follows: 00721 % 00722 % o blob: FileToBlob() returns the contents of a file as a blob. If 00723 % an error occurs NULL is returned. 00724 % 00725 % o filename: The filename. 00726 % 00727 % o length: This pointer to a size_t integer sets the initial length of the 00728 % blob. On return, it reflects the actual length of the blob. 00729 % 00730 % o exception: Return any errors or warnings in this structure. 00731 % 00732 % 00733 */ 00734 MagickExport unsigned char *FileToBlob(const char *filename,size_t *length, 00735 ExceptionInfo *exception) 00736 { 00737 int 00738 file; 00739 00740 MagickOffsetType 00741 offset; 00742 00743 unsigned char 00744 *blob; 00745 00746 void 00747 *map; 00748 00749 assert(filename != (const char *) NULL); 00750 (void) LogMagickEvent(TraceEvent,GetMagickModule(),filename); 00751 assert(exception != (ExceptionInfo *) NULL); 00752 (void) SetExceptionInfo(exception,UndefinedException); 00753 file=open(filename,O_RDONLY | O_BINARY); 00754 if (file == -1) 00755 { 00756 (void) ThrowMagickException(exception,GetMagickModule(),BlobError, 00757 "UnableToOpenFile",filename,strerror(errno)); 00758 return((unsigned char *) NULL); 00759 } 00760 offset=(MagickOffsetType) MagickSeek(file,0,SEEK_END); 00761 if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset))) 00762 { 00763 (void) close(file); 00764 (void) ThrowMagickException(exception,GetMagickModule(),BlobError, 00765 "UnableToCreateBlob",filename,strerror(errno)); 00766 return((unsigned char *) NULL); 00767 } 00768 *length=(size_t) offset; 00769 blob=(unsigned char *) 00770 AcquireMagickMemory((*length+MaxTextExtent)*sizeof(*blob)); 00771 if (blob == (unsigned char *) NULL) 00772 { 00773 (void) close(file); 00774 (void) ThrowMagickException(exception,GetMagickModule(), 00775 ResourceLimitError,"MemoryAllocationFailed",filename); 00776 return((unsigned char *) NULL); 00777 } 00778 map=MapBlob(file,ReadMode,0,*length); 00779 if (map != (unsigned char *) NULL) 00780 { 00781 (void) CopyMagickMemory(blob,map,*length); 00782 (void) UnmapBlob(map,*length); 00783 } 00784 else 00785 { 00786 register size_t 00787 i; 00788 00789 ssize_t 00790 count; 00791 00792 (void) MagickSeek(file,0,SEEK_SET); 00793 for (i=0; i < *length; i+=count) 00794 { 00795 count=read(file,blob+i,Min(*length-i,(size_t) MagickMaxBufferSize)); 00796 if (count <= 0) 00797 { 00798 count=0; 00799 if (errno != EINTR) 00800 break; 00801 } 00802 } 00803 if (i < *length) 00804 { 00805 (void) close(file); 00806 blob=(unsigned char *) RelinquishMagickMemory(blob); 00807 (void) ThrowMagickException(exception,GetMagickModule(),BlobError, 00808 "UnableToReadBlob",filename,strerror(errno)); 00809 return((unsigned char *) NULL); 00810 } 00811 } 00812 blob[*length]='\0'; 00813 (void) close(file); 00814 return(blob); 00815 } 00816 00817 /* 00818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00819 % % 00820 % % 00821 % % 00822 % G e t B l o b E r r o r % 00823 % % 00824 % % 00825 % % 00826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00827 % 00828 % GetBlobError() returns MagickTrue if the blob associated with the specified image 00829 % encountered an error. 00830 % 00831 % The format of the GetBlobError method is: 00832 % 00833 % MagickBooleanType GetBlobError(const Image *image) 00834 % 00835 % A description of each parameter follows: 00836 % 00837 % o image: The image. 00838 % 00839 % 00840 */ 00841 MagickExport MagickBooleanType GetBlobError(const Image *image) 00842 { 00843 assert(image != (const Image *) NULL); 00844 assert(image->signature == MagickSignature); 00845 if (image->debug != MagickFalse) 00846 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 00847 return(image->blob->status); 00848 } 00849 00850 /* 00851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00852 % % 00853 % % 00854 % % 00855 % G e t B l o b F i l e H a n d l e % 00856 % % 00857 % % 00858 % % 00859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00860 % 00861 % GetBlobFileHandle() returns the file handleassociated with the image blob. 00862 % 00863 % The format of the GetBlobFile method is: 00864 % 00865 % FILE *GetBlobFileHandle(const Image *image) 00866 % 00867 % A description of each parameter follows: 00868 % 00869 % o image: The image. 00870 % 00871 % 00872 */ 00873 MagickExport FILE *GetBlobFileHandle(const Image *image) 00874 { 00875 assert(image != (const Image *) NULL); 00876 assert(image->signature == MagickSignature); 00877 return(image->blob->file); 00878 } 00879 00880 /* 00881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00882 % % 00883 % % 00884 % % 00885 % G e t B l o b I n f o % 00886 % % 00887 % % 00888 % % 00889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00890 % 00891 % GetBlobInfo() initializes the BlobInfo structure. 00892 % 00893 % The format of the GetBlobInfo method is: 00894 % 00895 % void GetBlobInfo(BlobInfo *blob_info) 00896 % 00897 % A description of each parameter follows: 00898 % 00899 % o blob_info: Specifies a pointer to a BlobInfo structure. 00900 % 00901 % 00902 */ 00903 MagickExport void GetBlobInfo(BlobInfo *blob_info) 00904 { 00905 assert(blob_info != (BlobInfo *) NULL); 00906 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info)); 00907 blob_info->type=UndefinedStream; 00908 blob_info->quantum=DefaultBlobQuantum; 00909 blob_info->debug=IsEventLogging(); 00910 blob_info->reference_count=1; 00911 blob_info->signature=MagickSignature; 00912 } 00913 00914 /* 00915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00916 % % 00917 % % 00918 % % 00919 + G e t B l o b S i z e % 00920 % % 00921 % % 00922 % % 00923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00924 % 00925 % GetBlobSize() returns the current length of the image file or blob; zero is 00926 % returned if the size cannot be determined. 00927 % 00928 % The format of the GetBlobSize method is: 00929 % 00930 % MagickSizeType GetBlobSize(const Image *image) 00931 % 00932 % A description of each parameter follows: 00933 % 00934 % o size: Method GetBlobSize returns the current length of the image file 00935 % or blob. 00936 % 00937 % o image: The image. 00938 % 00939 % 00940 */ 00941 MagickExport MagickSizeType GetBlobSize(const Image *image) 00942 { 00943 MagickSizeType 00944 length; 00945 00946 struct stat 00947 attributes; 00948 00949 assert(image != (Image *) NULL); 00950 assert(image->signature == MagickSignature); 00951 if (image->debug != MagickFalse) 00952 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 00953 assert(image->blob != (BlobInfo *) NULL); 00954 length=0; 00955 switch (image->blob->type) 00956 { 00957 case UndefinedStream: 00958 { 00959 length=image->blob->size; 00960 break; 00961 } 00962 case FileStream: 00963 { 00964 length=(MagickSizeType) (fstat(fileno(image->blob->file), 00965 &attributes) < 0 ? 0 : attributes.st_size); 00966 break; 00967 } 00968 case StandardStream: 00969 case PipeStream: 00970 break; 00971 case ZipStream: 00972 { 00973 #if defined(HasZLIB) 00974 length=(MagickSizeType) (stat(image->filename,&attributes) < 0 ? 0 : 00975 attributes.st_size); 00976 #endif 00977 break; 00978 } 00979 case BZipStream: 00980 { 00981 #if defined(HasBZLIB) 00982 length=(MagickSizeType) (stat(image->filename,&attributes) < 0 ? 0 : 00983 attributes.st_size); 00984 #endif 00985 break; 00986 } 00987 case FifoStream: 00988 break; 00989 case BlobStream: 00990 { 00991 length=(MagickSizeType) image->blob->length; 00992 break; 00993 } 00994 } 00995 return(length); 00996 } 00997 00998 /* 00999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01000 % % 01001 % % 01002 % % 01003 % G e t B l o b S t r e a m D a t a % 01004 % % 01005 % % 01006 % % 01007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01008 % 01009 % GetBlobStreamData() returns the stream data for the image. 01010 % 01011 % The format of the GetBlobStreamData method is: 01012 % 01013 % unsigned char *GetBlobStreamData(const Image *image) 01014 % 01015 % A description of each parameter follows: 01016 % 01017 % o image: The image. 01018 % 01019 % 01020 */ 01021 MagickExport unsigned char *GetBlobStreamData(const Image *image) 01022 { 01023 assert(image != (const Image *) NULL); 01024 assert(image->signature == MagickSignature); 01025 return(image->blob->data); 01026 } 01027 01028 /* 01029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01030 % % 01031 % % 01032 % % 01033 % G e t B l o b S t r e a m H a n d l e r % 01034 % % 01035 % % 01036 % % 01037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01038 % 01039 % GetBlobStreamHandler() returns the stream handler for the image. 01040 % 01041 % The format of the GetBlobStreamHandler method is: 01042 % 01043 % StreamHandler GetBlobStreamHandler(const Image *image) 01044 % 01045 % A description of each parameter follows: 01046 % 01047 % o image: The image. 01048 % 01049 % 01050 */ 01051 MagickExport StreamHandler GetBlobStreamHandler(const Image *image) 01052 { 01053 assert(image != (const Image *) NULL); 01054 assert(image->signature == MagickSignature); 01055 if (image->debug != MagickFalse) 01056 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 01057 return(image->blob->stream); 01058 } 01059 01060 /* 01061 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01062 % % 01063 % % 01064 % % 01065 % I m a g e T o B l o b % 01066 % % 01067 % % 01068 % % 01069 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01070 % 01071 % ImageToBlob() implements direct to memory image formats. It returns the 01072 % image as a blob and its length. The magick member of the Image structure 01073 % determines the format of the returned blob (GIF, JPEG, PNG, etc.) 01074 % 01075 % The format of the ImageToBlob method is: 01076 % 01077 % unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image, 01078 % size_t *length,ExceptionInfo *exception) 01079 % 01080 % A description of each parameter follows: 01081 % 01082 % o image_info: The image info.. 01083 % 01084 % o image: The image. 01085 % 01086 % o length: This pointer to a size_t integer sets the initial length of the 01087 % blob. On return, it reflects the actual length of the blob. 01088 % 01089 % o exception: Return any errors or warnings in this structure. 01090 % 01091 % 01092 */ 01093 MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info, 01094 Image *image,size_t *length,ExceptionInfo *exception) 01095 { 01096 const MagickInfo 01097 *magick_info; 01098 01099 ImageInfo 01100 *blob_info; 01101 01102 MagickBooleanType 01103 status; 01104 01105 unsigned char 01106 *blob; 01107 01108 assert(image_info != (const ImageInfo *) NULL); 01109 assert(image_info->signature == MagickSignature); 01110 if (image_info->debug != MagickFalse) 01111 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image_info->filename); 01112 assert(image != (Image *) NULL); 01113 assert(image->signature == MagickSignature); 01114 assert(exception != (ExceptionInfo *) NULL); 01115 (void) SetExceptionInfo(exception,UndefinedException); 01116 *length=0; 01117 blob=(unsigned char *) NULL; 01118 magick_info=GetMagickInfo(image->magick,exception); 01119 if (magick_info == (const MagickInfo *) NULL) 01120 return(blob); 01121 blob_info=CloneImageInfo(image_info); 01122 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent); 01123 if (GetMagickBlobSupport(magick_info) != MagickFalse) 01124 { 01125 /* 01126 Native blob support for this image format. 01127 */ 01128 blob_info->length=0; 01129 blob_info->blob=(void *) 01130 AcquireMagickMemory(DefaultBlobQuantum*sizeof(unsigned char)); 01131 if (blob_info->blob == (void *) NULL) 01132 (void) ThrowMagickException(exception,GetMagickModule(), 01133 ResourceLimitError,"MemoryAllocationFailed",image->filename); 01134 else 01135 { 01136 image->blob->exempt=MagickTrue; 01137 *image->filename='\0'; 01138 status=WriteImage(blob_info,image); 01139 if ((status == MagickFalse) || (image->blob->length == 0)) 01140 { 01141 blob_info->blob=(void *) RelinquishMagickMemory(blob_info->blob); 01142 InheritException(exception,&image->exception); 01143 } 01144 else 01145 { 01146 image->blob->data=(unsigned char *) 01147 ResizeMagickMemory(image->blob->data,image->blob->length); 01148 blob=image->blob->data; 01149 *length=image->blob->length; 01150 (void) DetachBlob(image->blob); 01151 } 01152 } 01153 } 01154 else 01155 { 01156 char 01157 unique[MaxTextExtent]; 01158 01159 int 01160 file; 01161 01162 /* 01163 Write file to disk in blob image format. 01164 */ 01165 file=AcquireUniqueFileResource(unique); 01166 if (file == -1) 01167 (void) ThrowMagickException(exception,GetMagickModule(),BlobError, 01168 "UnableToWriteBlob",image->filename,strerror(errno)); 01169 else 01170 { 01171 (void) FormatMagickString(image->filename,MaxTextExtent,"%s:%s", 01172 image->magick,unique); 01173 status=WriteImage(blob_info,image); 01174 if (status == MagickFalse) 01175 InheritException(exception,&image->exception); 01176 else 01177 blob=FileToBlob(image->filename,length,exception); 01178 (void) RelinquishUniqueFileResource(unique); 01179 } 01180 } 01181 blob_info=DestroyImageInfo(blob_info); 01182 return(blob); 01183 } 01184 01185 /* 01186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01187 % % 01188 % % 01189 % % 01190 % I m a g e T o F i l e % 01191 % % 01192 % % 01193 % % 01194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01195 % 01196 % ImageToFile() writes an image to a file. It returns MagickFalse if an error 01197 % occurs otherwise MagickTrue. 01198 % 01199 % The format of the ImageToFile method is: 01200 % 01201 % MagickBooleanType ImageToFile(Image *image,char *filename, 01202 % ExceptionInfo *exception) 01203 % 01204 % A description of each parameter follows: 01205 % 01206 % o image: The image. 01207 % 01208 % o filename: Write the image to this file. 01209 % 01210 % o exception: Return any errors or warnings in this structure. 01211 % 01212 % 01213 */ 01214 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename, 01215 ExceptionInfo *exception) 01216 { 01217 int 01218 file; 01219 01220 register size_t 01221 i; 01222 01223 size_t 01224 length; 01225 01226 ssize_t 01227 count; 01228 01229 unsigned char 01230 *buffer; 01231 01232 assert(image != (Image *) NULL); 01233 assert(image->signature == MagickSignature); 01234 if (image->debug != MagickFalse) 01235 (void) LogMagickEvent(TraceEvent,GetMagickModule(),filename); 01236 assert(filename != (const char *) NULL); 01237 if (*filename == '\0') 01238 file=AcquireUniqueFileResource(filename); 01239 else 01240 if (LocaleCompare(filename,"-") == 0) 01241 file=fileno(stdout); 01242 else 01243 file=open(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE); 01244 if (file == -1) 01245 { 01246 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); 01247 return(MagickFalse); 01248 } 01249 buffer=(unsigned char *) 01250 AcquireMagickMemory(MagickMaxBufferSize*sizeof(*buffer)); 01251 if (buffer == (unsigned char *) NULL) 01252 { 01253 (void) close(file); 01254 (void) ThrowMagickException(exception,GetMagickModule(), 01255 ResourceLimitError,"MemoryAllocationError",filename); 01256 return(MagickFalse); 01257 } 01258 length=0; 01259 for (i=0; (count=ReadBlob(image,MagickMaxBufferSize,buffer)) > 0; ) 01260 { 01261 length=(size_t) count; 01262 for (i=0; i < length; i+=count) 01263 { 01264 count=write(file,buffer+i,(size_t) (length-i)); 01265 if (count <= 0) 01266 { 01267 count=0; 01268 if (errno != EINTR) 01269 break; 01270 } 01271 } 01272 if (i < length) 01273 break; 01274 } 01275 (void) close(file); 01276 buffer=(unsigned char *) RelinquishMagickMemory(buffer); 01277 if (i < length) 01278 { 01279 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); 01280 return(MagickFalse); 01281 } 01282 return(MagickTrue); 01283 } 01284 01285 /* 01286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01287 % % 01288 % % 01289 % % 01290 % I s B l o b E x e m p t % 01291 % % 01292 % % 01293 % % 01294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01295 % 01296 % IsBlobExempt() returns true if the blob is exempt. 01297 % 01298 % The format of the IsBlobExempt method is: 01299 % 01300 % MagickBooleanType IsBlobExempt(const Image *image) 01301 % 01302 % A description of each parameter follows: 01303 % 01304 % o image: The image. 01305 % 01306 % 01307 */ 01308 MagickExport MagickBooleanType IsBlobExempt(const Image *image) 01309 { 01310 assert(image != (const Image *) NULL); 01311 assert(image->signature == MagickSignature); 01312 if (image->debug != MagickFalse) 01313 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 01314 return(image->blob->exempt); 01315 } 01316 01317 /* 01318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01319 % % 01320 % % 01321 % % 01322 % I s B l o b S e e k a b l e % 01323 % % 01324 % % 01325 % % 01326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01327 % 01328 % IsBlobSeekable() returns true if the blob is seekable. 01329 % 01330 % The format of the IsBlobSeekable method is: 01331 % 01332 % MagickBooleanType IsBlobSeekable(const Image *image) 01333 % 01334 % A description of each parameter follows: 01335 % 01336 % o image: The image. 01337 % 01338 % 01339 */ 01340 MagickExport MagickBooleanType IsBlobSeekable(const Image *image) 01341 { 01342 MagickBooleanType 01343 seekable; 01344 01345 assert(image != (const Image *) NULL); 01346 assert(image->signature == MagickSignature); 01347 if (image->debug != MagickFalse) 01348 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 01349 seekable=(MagickBooleanType) ((image->blob->type == FileStream) || 01350 (image->blob->type == BlobStream)); 01351 return(seekable); 01352 } 01353 01354 /* 01355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01356 % % 01357 % % 01358 % % 01359 % I s B l o b T e m p o r a r y % 01360 % % 01361 % % 01362 % % 01363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01364 % 01365 % IsBlobTemporary() returns true if the blob is temporary. 01366 % 01367 % The format of the IsBlobTemporary method is: 01368 % 01369 % MagickBooleanType IsBlobTemporary(const Image *image) 01370 % 01371 % A description of each parameter follows: 01372 % 01373 % o image: The image. 01374 % 01375