You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6451 lines
207 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% BBBB L OOO BBBB %
% B B L O O B B %
% BBBB L O O BBBB %
% B B L O O B B %
% BBBB LLLLL OOO BBBB %
% %
% %
% MagickCore Binary Large OBjectS Methods %
% %
% Software Design %
% Cristy %
% July 1999 %
% %
% %
% Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
% https://imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
% See the License for the specific language governing permissions and %
% limitations under the License. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
%
*/
/*
Include declarations.
*/
#ifdef __VMS
#include <types.h>
#include <mman.h>
#endif
#include "MagickCore/studio.h"
#include "MagickCore/blob.h"
#include "MagickCore/blob-private.h"
#include "MagickCore/cache.h"
#include "MagickCore/client.h"
#include "MagickCore/constitute.h"
#include "MagickCore/delegate.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/geometry.h"
#include "MagickCore/image-private.h"
#include "MagickCore/list.h"
#include "MagickCore/locale_.h"
#include "MagickCore/log.h"
#include "MagickCore/magick.h"
#include "MagickCore/memory_.h"
#include "MagickCore/memory-private.h"
#include "MagickCore/nt-base-private.h"
#include "MagickCore/option.h"
#include "MagickCore/policy.h"
#include "MagickCore/resource_.h"
#include "MagickCore/semaphore.h"
#include "MagickCore/string_.h"
#include "MagickCore/string-private.h"
#include "MagickCore/timer-private.h"
#include "MagickCore/token.h"
#include "MagickCore/utility.h"
#include "MagickCore/utility-private.h"
#if defined(MAGICKCORE_ZLIB_DELEGATE)
#include "zlib.h"
#endif
#if defined(MAGICKCORE_BZLIB_DELEGATE)
#include "bzlib.h"
#endif
/*
Define declarations.
*/
#define MagickMaxBlobExtent (8*8192)
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
# define MAP_ANONYMOUS MAP_ANON
#endif
#if !defined(MAP_FAILED)
#define MAP_FAILED ((void *) -1)
#endif
#if defined(__OS2__)
#include <io.h>
#define _O_BINARY O_BINARY
#endif
/*
Typedef declarations.
*/
typedef union FileInfo
{
FILE
*file;
#if defined(MAGICKCORE_ZLIB_DELEGATE)
gzFile
gzfile;
#endif
#if defined(MAGICKCORE_BZLIB_DELEGATE)
BZFILE
*bzfile;
#endif
} FileInfo;
struct _BlobInfo
{
size_t
length,
extent,
quantum;
BlobMode
mode;
MagickBooleanType
mapped,
eof;
int
error,
error_number;
MagickOffsetType
offset;
MagickSizeType
size;
MagickBooleanType
exempt,
synchronize,
status,
temporary;
StreamType
type;
FileInfo
file_info;
struct stat
properties;
StreamHandler
stream;
CustomStreamInfo
*custom_stream;
unsigned char
*data;
MagickBooleanType
debug;
SemaphoreInfo
*semaphore;
ssize_t
reference_count;
size_t
signature;
};
struct _CustomStreamInfo
{
CustomStreamHandler
reader,
writer;
CustomStreamSeeker
seeker;
CustomStreamTeller
teller;
void
*data;
size_t
signature;
};
/*
Forward declarations.
*/
static int
SyncBlob(Image *);
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ A c q u i r e C u s t o m S t r e a m I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% AcquireCustomStreamInfo() allocates the CustomStreamInfo structure.
%
% The format of the AcquireCustomStreamInfo method is:
%
% CustomStreamInfo *AcquireCustomStreamInfo(ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport CustomStreamInfo *AcquireCustomStreamInfo(
ExceptionInfo *magick_unused(exception))
{
CustomStreamInfo
*custom_stream;
magick_unreferenced(exception);
custom_stream=(CustomStreamInfo *) AcquireCriticalMemory(
sizeof(*custom_stream));
(void) memset(custom_stream,0,sizeof(*custom_stream));
custom_stream->signature=MagickCoreSignature;
return(custom_stream);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ A t t a c h B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% AttachBlob() attaches a blob to the BlobInfo structure.
%
% The format of the AttachBlob method is:
%
% void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
%
% A description of each parameter follows:
%
% o blob_info: Specifies a pointer to a BlobInfo structure.
%
% o blob: the address of a character stream in one of the image formats
% understood by ImageMagick.
%
% o length: This size_t integer reflects the length in bytes of the blob.
%
*/
MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
const size_t length)
{
assert(blob_info != (BlobInfo *) NULL);
if (blob_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
blob_info->length=length;
blob_info->extent=length;
blob_info->quantum=(size_t) MagickMaxBlobExtent;
blob_info->offset=0;
blob_info->type=BlobStream;
blob_info->file_info.file=(FILE *) NULL;
blob_info->data=(unsigned char *) blob;
blob_info->mapped=MagickFalse;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ A t t a c h C u s t o m S t r e a m %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% AttachCustomStream() attaches a CustomStreamInfo to the BlobInfo structure.
%
% The format of the AttachCustomStream method is:
%
% void AttachCustomStream(BlobInfo *blob_info,
% CustomStreamInfo *custom_stream)
%
% A description of each parameter follows:
%
% o blob_info: specifies a pointer to a BlobInfo structure.
%
% o custom_stream: the custom stream info.
%
*/
MagickExport void AttachCustomStream(BlobInfo *blob_info,
CustomStreamInfo *custom_stream)
{
assert(blob_info != (BlobInfo *) NULL);
assert(custom_stream != (CustomStreamInfo *) NULL);
assert(custom_stream->signature == MagickCoreSignature);
if (blob_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
blob_info->type=CustomStream;
blob_info->custom_stream=custom_stream;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ B l o b T o F i l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% BlobToFile() writes a blob to a file. It returns MagickFalse if an error
% occurs otherwise MagickTrue.
%
% The format of the BlobToFile method is:
%
% MagickBooleanType BlobToFile(char *filename,const void *blob,
% const size_t length,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o filename: Write the blob to this file.
%
% o blob: the address of a blob.
%
% o length: This length in bytes of the blob.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
const size_t length,ExceptionInfo *exception)
{
int
file;
size_t
i;
ssize_t
count;
assert(filename != (const char *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
assert(blob != (const void *) NULL);
if (*filename == '\0')
file=AcquireUniqueFileResource(filename);
else
file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
if (file == -1)
{
ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
return(MagickFalse);
}
for (i=0; i < length; i+=count)
{
count=write(file,(const char *) blob+i,MagickMin(length-i,(size_t)
MAGICK_SSIZE_MAX));
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
}
file=close(file);
if ((file == -1) || (i < length))
{
ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
return(MagickFalse);
}
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% B l o b T o I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% BlobToImage() implements direct to memory image formats. It returns the
% blob as an image.
%
% The format of the BlobToImage method is:
%
% Image *BlobToImage(const ImageInfo *image_info,const void *blob,
% const size_t length,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o blob: the address of a character stream in one of the image formats
% understood by ImageMagick.
%
% o length: This size_t integer reflects the length in bytes of the blob.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
const size_t length,ExceptionInfo *exception)
{
const MagickInfo
*magick_info;
Image
*image;
ImageInfo
*blob_info,
*clone_info;
MagickBooleanType
status;
assert(image_info != (ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(exception != (ExceptionInfo *) NULL);
if ((blob == (const void *) NULL) || (length == 0))
{
(void) ThrowMagickException(exception,GetMagickModule(),BlobError,
"ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
return((Image *) NULL);
}
blob_info=CloneImageInfo(image_info);
blob_info->blob=(void *) blob;
blob_info->length=length;
if (*blob_info->magick == '\0')
(void) SetImageInfo(blob_info,0,exception);
magick_info=GetMagickInfo(blob_info->magick,exception);
if (magick_info == (const MagickInfo *) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
blob_info->magick);
blob_info=DestroyImageInfo(blob_info);
return((Image *) NULL);
}
if (GetMagickBlobSupport(magick_info) != MagickFalse)
{
char
filename[MagickPathExtent];
/*
Native blob support for this image format.
*/
(void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
(void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
blob_info->magick,filename);
image=ReadImage(blob_info,exception);
if (image != (Image *) NULL)
(void) DetachBlob(image->blob);
blob_info=DestroyImageInfo(blob_info);
return(image);
}
/*
Write blob to a temporary file on disk.
*/
blob_info->blob=(void *) NULL;
blob_info->length=0;
*blob_info->filename='\0';
status=BlobToFile(blob_info->filename,blob,length,exception);
if (status == MagickFalse)
{
(void) RelinquishUniqueFileResource(blob_info->filename);
blob_info=DestroyImageInfo(blob_info);
return((Image *) NULL);
}
clone_info=CloneImageInfo(blob_info);
(void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
blob_info->magick,blob_info->filename);
image=ReadImage(clone_info,exception);
if (image != (Image *) NULL)
{
Image
*images;
/*
Restore original filenames and image format.
*/
for (images=GetFirstImageInList(image); images != (Image *) NULL; )
{
(void) CopyMagickString(images->filename,image_info->filename,
MagickPathExtent);
(void) CopyMagickString(images->magick_filename,image_info->filename,
MagickPathExtent);
(void) CopyMagickString(images->magick,magick_info->name,
MagickPathExtent);
images=GetNextImageInList(images);
}
}
clone_info=DestroyImageInfo(clone_info);
(void) RelinquishUniqueFileResource(blob_info->filename);
blob_info=DestroyImageInfo(blob_info);
return(image);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ C l o n e B l o b I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
% blob info is NULL, a new one.
%
% The format of the CloneBlobInfo method is:
%
% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
%
% A description of each parameter follows:
%
% o blob_info: the blob info.
%
*/
MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
{
BlobInfo
*clone_info;
SemaphoreInfo
*semaphore;
clone_info=(BlobInfo *) AcquireCriticalMemory(sizeof(*clone_info));
GetBlobInfo(clone_info);
if (blob_info == (BlobInfo *) NULL)
return(clone_info);
semaphore=clone_info->semaphore;
(void) memcpy(clone_info,blob_info,sizeof(*clone_info));
if (blob_info->mapped != MagickFalse)
(void) AcquireMagickResource(MapResource,blob_info->length);
clone_info->semaphore=semaphore;
LockSemaphoreInfo(clone_info->semaphore);
clone_info->reference_count=1;
UnlockSemaphoreInfo(clone_info->semaphore);
return(clone_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ C l o s e B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% CloseBlob() closes a stream associated with the image.
%
% The format of the CloseBlob method is:
%
% MagickBooleanType CloseBlob(Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
static inline void ThrowBlobException(BlobInfo *blob_info)
{
if ((blob_info->status == MagickFalse) && (errno != 0))
blob_info->error_number=errno;
blob_info->status=MagickTrue;
}
MagickExport MagickBooleanType CloseBlob(Image *image)
{
BlobInfo
*magick_restrict blob_info;
int
status;
/*
Close image file.
*/
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
blob_info=image->blob;
if ((blob_info == (BlobInfo *) NULL) || (blob_info->type == UndefinedStream))
return(MagickTrue);
status=SyncBlob(image);
switch (blob_info->type)
{
case UndefinedStream:
case StandardStream:
break;
case FileStream:
case PipeStream:
{
if (blob_info->synchronize != MagickFalse)
{
status=fflush(blob_info->file_info.file);
if (status != 0)
ThrowBlobException(blob_info);
status=fsync(fileno(blob_info->file_info.file));
if (status != 0)
ThrowBlobException(blob_info);
}
if ((status != 0) && (ferror(blob_info->file_info.file) != 0))
ThrowBlobException(blob_info);
break;
}
case ZipStream:
{
#if defined(MAGICKCORE_ZLIB_DELEGATE)
status=Z_OK;
(void) gzerror(blob_info->file_info.gzfile,&status);
if (status != Z_OK)
ThrowBlobException(blob_info);
#endif
break;
}
case BZipStream:
{
#if defined(MAGICKCORE_BZLIB_DELEGATE)
status=BZ_OK;
(void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
if (status != BZ_OK)
ThrowBlobException(blob_info);
#endif
break;
}
case FifoStream:
break;
case BlobStream:
{
if (blob_info->file_info.file != (FILE *) NULL)
{
if (blob_info->synchronize != MagickFalse)
{
status=fflush(blob_info->file_info.file);
if (status != 0)
ThrowBlobException(blob_info);
status=fsync(fileno(blob_info->file_info.file));
if (status != 0)
ThrowBlobException(blob_info);
}
if ((status != 0) && (ferror(blob_info->file_info.file) != 0))
ThrowBlobException(blob_info);
}
break;
}
case CustomStream:
break;
}
blob_info->size=GetBlobSize(image);
image->extent=blob_info->size;
blob_info->eof=MagickFalse;
blob_info->error=0;
blob_info->mode=UndefinedBlobMode;
if (blob_info->exempt != MagickFalse)
{
blob_info->type=UndefinedStream;
return(blob_info->status);
}
switch (blob_info->type)
{
case UndefinedStream:
case StandardStream:
break;
case FileStream:
{
if (fileno(blob_info->file_info.file) != -1)
{
status=fclose(blob_info->file_info.file);
if (status != 0)
ThrowBlobException(blob_info);
}
break;
}
case PipeStream:
{
#if defined(MAGICKCORE_HAVE_PCLOSE)
status=pclose(blob_info->file_info.file);
if (status != 0)
ThrowBlobException(blob_info);
#endif
break;
}
case ZipStream:
{
#if defined(MAGICKCORE_ZLIB_DELEGATE)
status=gzclose(blob_info->file_info.gzfile);
if (status != Z_OK)
ThrowBlobException(blob_info);
#endif
break;
}
case BZipStream:
{
#if defined(MAGICKCORE_BZLIB_DELEGATE)
BZ2_bzclose(blob_info->file_info.bzfile);
#endif
break;
}
case FifoStream:
break;
case BlobStream:
{
if (blob_info->file_info.file != (FILE *) NULL)
{
status=fclose(blob_info->file_info.file);
if (status != 0)
ThrowBlobException(blob_info);
}
break;
}
case CustomStream:
break;
}
(void) DetachBlob(blob_info);
return(blob_info->status);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% C u s t o m S t r e a m T o I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% CustomStreamToImage() is the equivalent of ReadImage(), but reads the
% formatted "file" from the suplied method rather than to an actual file.
%
% The format of the CustomStreamToImage method is:
%
% Image *CustomStreamToImage(const ImageInfo *image_info,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport Image *CustomStreamToImage(const ImageInfo *image_info,
ExceptionInfo *exception)
{
const MagickInfo
*magick_info;
Image
*image;
ImageInfo
*blob_info;
assert(image_info != (ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
assert(image_info->custom_stream->signature == MagickCoreSignature);
assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
assert(exception != (ExceptionInfo *) NULL);
blob_info=CloneImageInfo(image_info);
if (*blob_info->magick == '\0')
(void) SetImageInfo(blob_info,0,exception);
magick_info=GetMagickInfo(blob_info->magick,exception);
if (magick_info == (const MagickInfo *) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
blob_info->magick);
blob_info=DestroyImageInfo(blob_info);
return((Image *) NULL);
}
image=(Image *) NULL;
if ((GetMagickBlobSupport(magick_info) != MagickFalse) ||
(*blob_info->filename != '\0'))
{
char
filename[MagickPathExtent];
/*
Native blob support for this image format or SetImageInfo changed the
blob to a file.
*/
(void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
(void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
blob_info->magick,filename);
image=ReadImage(blob_info,exception);
if (image != (Image *) NULL)
(void) CloseBlob(image);
}
else
{
char
unique[MagickPathExtent];
int
file;
ImageInfo
*clone_info;
unsigned char
*blob;
/*
Write data to file on disk.
*/
blob_info->custom_stream=(CustomStreamInfo *) NULL;
blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
sizeof(*blob));
if (blob == (unsigned char *) NULL)
{
ThrowFileException(exception,BlobError,"UnableToReadBlob",
image_info->filename);
blob_info=DestroyImageInfo(blob_info);
return((Image *) NULL);
}
file=AcquireUniqueFileResource(unique);
if (file == -1)
{
ThrowFileException(exception,BlobError,"UnableToReadBlob",
image_info->filename);
blob=(unsigned char *) RelinquishMagickMemory(blob);
blob_info=DestroyImageInfo(blob_info);
return((Image *) NULL);
}
clone_info=CloneImageInfo(blob_info);
blob_info->file=fdopen(file,"wb+");
if (blob_info->file != (FILE *) NULL)
{
ssize_t
count;
count=(ssize_t) MagickMaxBufferExtent;
while (count == (ssize_t) MagickMaxBufferExtent)
{
count=image_info->custom_stream->reader(blob,MagickMaxBufferExtent,
image_info->custom_stream->data);
count=(ssize_t) write(file,(const char *) blob,(size_t) count);
}
(void) fclose(blob_info->file);
(void) FormatLocaleString(clone_info->filename,MagickPathExtent,
"%s:%s",blob_info->magick,unique);
image=ReadImage(clone_info,exception);
if (image != (Image *) NULL)
{
Image
*images;
/*
Restore original filenames and image format.
*/
for (images=GetFirstImageInList(image); images != (Image *) NULL; )
{
(void) CopyMagickString(images->filename,image_info->filename,
MagickPathExtent);
(void) CopyMagickString(images->magick_filename,
image_info->filename,MagickPathExtent);
(void) CopyMagickString(images->magick,magick_info->name,
MagickPathExtent);
(void) CloseBlob(images);
images=GetNextImageInList(images);
}
}
}
clone_info=DestroyImageInfo(clone_info);
blob=(unsigned char *) RelinquishMagickMemory(blob);
(void) RelinquishUniqueFileResource(unique);
}
blob_info=DestroyImageInfo(blob_info);
return(image);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ D e s t r o y B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DestroyBlob() deallocates memory associated with a blob.
%
% The format of the DestroyBlob method is:
%
% void DestroyBlob(Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport void DestroyBlob(Image *image)
{
BlobInfo
*magick_restrict blob_info;
MagickBooleanType
destroy;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->signature == MagickCoreSignature);
blob_info=image->blob;
destroy=MagickFalse;
LockSemaphoreInfo(blob_info->semaphore);
blob_info->reference_count--;
assert(blob_info->reference_count >= 0);
if (blob_info->reference_count == 0)
destroy=MagickTrue;
UnlockSemaphoreInfo(blob_info->semaphore);
if (destroy == MagickFalse)
{
image->blob=(BlobInfo *) NULL;
return;
}
(void) CloseBlob(image);
if (blob_info->mapped != MagickFalse)
{
(void) UnmapBlob(blob_info->data,blob_info->length);
RelinquishMagickResource(MapResource,blob_info->length);
}
if (blob_info->semaphore != (SemaphoreInfo *) NULL)
RelinquishSemaphoreInfo(&blob_info->semaphore);
blob_info->signature=(~MagickCoreSignature);
image->blob=(BlobInfo *) RelinquishMagickMemory(blob_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ D e s t r o y C u s t o m S t r e a m I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DestroyCustomStreamInfo() destroys memory associated with the
% CustomStreamInfo structure.
%
% The format of the DestroyCustomStreamInfo method is:
%
% CustomStreamInfo *DestroyCustomStreamInfo(CustomStreamInfo *stream_info)
%
% A description of each parameter follows:
%
% o custom_stream: the custom stream info.
%
*/
MagickExport CustomStreamInfo *DestroyCustomStreamInfo(
CustomStreamInfo *custom_stream)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(custom_stream != (CustomStreamInfo *) NULL);
assert(custom_stream->signature == MagickCoreSignature);
custom_stream->signature=(~MagickCoreSignature);
custom_stream=(CustomStreamInfo *) RelinquishMagickMemory(custom_stream);
return(custom_stream);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ D e t a c h B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DetachBlob() detaches a blob from the BlobInfo structure.
%
% The format of the DetachBlob method is:
%
% void *DetachBlob(BlobInfo *blob_info)
%
% A description of each parameter follows:
%
% o blob_info: Specifies a pointer to a BlobInfo structure.
%
*/
MagickExport void *DetachBlob(BlobInfo *blob_info)
{
void
*data;
assert(blob_info != (BlobInfo *) NULL);
if (blob_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
if (blob_info->mapped != MagickFalse)
{
(void) UnmapBlob(blob_info->data,blob_info->length);
blob_info->data=NULL;
RelinquishMagickResource(MapResource,blob_info->length);
}
blob_info->mapped=MagickFalse;
blob_info->length=0;
blob_info->offset=0;
blob_info->eof=MagickFalse;
blob_info->error=0;
blob_info->exempt=MagickFalse;
blob_info->type=UndefinedStream;
blob_info->file_info.file=(FILE *) NULL;
data=blob_info->data;
blob_info->data=(unsigned char *) NULL;
blob_info->stream=(StreamHandler) NULL;
blob_info->custom_stream=(CustomStreamInfo *) NULL;
return(data);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ D i s a s s o c i a t e B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DisassociateBlob() disassociates the image stream. It checks if the
% blob of the specified image is referenced by other images. If the reference
% count is higher then 1 a new blob is assigned to the specified image.
%
% The format of the DisassociateBlob method is:
%
% void DisassociateBlob(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport void DisassociateBlob(Image *image)
{
BlobInfo
*magick_restrict blob_info,
*clone_info;
MagickBooleanType
clone;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->signature == MagickCoreSignature);
blob_info=image->blob;
clone=MagickFalse;
LockSemaphoreInfo(blob_info->semaphore);
assert(blob_info->reference_count >= 0);
if (blob_info->reference_count > 1)
clone=MagickTrue;
UnlockSemaphoreInfo(blob_info->semaphore);
if (clone == MagickFalse)
return;
clone_info=CloneBlobInfo(blob_info);
DestroyBlob(image);
image->blob=clone_info;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ D i s c a r d B l o b B y t e s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DiscardBlobBytes() discards bytes in a blob.
%
% The format of the DiscardBlobBytes method is:
%
% MagickBooleanType DiscardBlobBytes(Image *image,
% const MagickSizeType length)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o length: the number of bytes to skip.
%
*/
MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
const MagickSizeType length)
{
MagickOffsetType
i;
size_t
quantum;
ssize_t
count;
unsigned char
buffer[MagickMinBufferExtent >> 1];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (length != (MagickSizeType) ((MagickOffsetType) length))
return(MagickFalse);
count=0;
for (i=0; i < (MagickOffsetType) length; i+=count)
{
quantum=(size_t) MagickMin(length-i,sizeof(buffer));
(void) ReadBlobStream(image,quantum,buffer,&count);
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
}
return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ D u p l i c a t e s B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DuplicateBlob() duplicates a blob descriptor.
%
% The format of the DuplicateBlob method is:
%
% void DuplicateBlob(Image *image,const Image *duplicate)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o duplicate: the duplicate image.
%
*/
MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(duplicate != (Image *) NULL);
assert(duplicate->signature == MagickCoreSignature);
DestroyBlob(image);
image->blob=ReferenceBlob(duplicate->blob);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ E O F B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% EOFBlob() returns a non-zero value when EOF has been detected reading from
% a blob or file.
%
% The format of the EOFBlob method is:
%
% int EOFBlob(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport int EOFBlob(const Image *image)
{
BlobInfo
*magick_restrict blob_info;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
blob_info=image->blob;
switch (blob_info->type)
{
case UndefinedStream:
case StandardStream:
break;
case FileStream:
case PipeStream:
{
blob_info->eof=feof(blob_info->file_info.file) != 0 ? MagickTrue :
MagickFalse;
break;
}
case ZipStream:
{
#if defined(MAGICKCORE_ZLIB_DELEGATE)
blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
MagickFalse;
#endif
break;
}
case BZipStream:
{
#if defined(MAGICKCORE_BZLIB_DELEGATE)
int
status;
status=0;
(void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
blob_info->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
#endif
break;
}
case FifoStream:
{
blob_info->eof=MagickFalse;
break;
}
case BlobStream:
break;
case CustomStream:
break;
}
return((int) blob_info->eof);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ E r r o r B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ErrorBlob() returns a non-zero value when an error has been detected reading
% from a blob or file.
%
% The format of the ErrorBlob method is:
%
% int ErrorBlob(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport int ErrorBlob(const Image *image)
{
BlobInfo
*magick_restrict blob_info;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
blob_info=image->blob;
switch (blob_info->type)
{
case UndefinedStream:
case StandardStream:
break;
case FileStream:
case PipeStream:
{
blob_info->error=ferror(blob_info->file_info.file);
break;
}
case ZipStream:
{
#if defined(MAGICKCORE_ZLIB_DELEGATE)
(void) gzerror(blob_info->file_info.gzfile,&blob_info->error);
#endif
break;
}
case BZipStream:
{
#if defined(MAGICKCORE_BZLIB_DELEGATE)
(void) BZ2_bzerror(blob_info->file_info.bzfile,&blob_info->error);
#endif
break;
}
case FifoStream:
{
blob_info->error=0;
break;
}
case BlobStream:
break;
case CustomStream:
break;
}
return(blob_info->error);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% F i l e T o B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FileToBlob() returns the contents of a file as a buffer terminated with
% the '\0' character. The length of the buffer (not including the extra
% terminating '\0' character) is returned via the 'length' parameter. Free
% the buffer with RelinquishMagickMemory().
%
% The format of the FileToBlob method is:
%
% void *FileToBlob(const char *filename,const size_t extent,
% size_t *length,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o blob: FileToBlob() returns the contents of a file as a blob. If
% an error occurs NULL is returned.
%
% o filename: the filename.
%
% o extent: The maximum length of the blob.
%
% o length: On return, this reflects the actual length of the blob.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport void *FileToBlob(const char *filename,const size_t extent,
size_t *length,ExceptionInfo *exception)
{
int
file;
MagickBooleanType
status;
MagickOffsetType
offset;
size_t
i;
ssize_t
count;
struct stat
attributes;
unsigned char
*blob;
void
*map;
assert(filename != (const char *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
assert(exception != (ExceptionInfo *) NULL);
*length=0;
status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
if (status == MagickFalse)
{
errno=EPERM;
(void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
"NotAuthorized","`%s'",filename);
return(NULL);
}
file=fileno(stdin);
if (LocaleCompare(filename,"-") != 0)
{
status=GetPathAttributes(filename,&attributes);
if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
{
ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
return(NULL);
}
file=open_utf8(filename,O_RDONLY | O_BINARY,0);
}
if (file == -1)
{
ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
return(NULL);
}
offset=(MagickOffsetType) lseek(file,0,SEEK_END);
count=0;
if ((file == fileno(stdin)) || (offset < 0) ||
(offset != (MagickOffsetType) ((ssize_t) offset)))
{
size_t
quantum;
struct stat
file_stats;
/*
Stream is not seekable.
*/
offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
quantum=(size_t) MagickMaxBufferExtent;
if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
for (i=0; blob != (unsigned char *) NULL; i+=count)
{
count=read(file,blob+i,quantum);
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
if (~((size_t) i) < (quantum+1))
{
blob=(unsigned char *) RelinquishMagickMemory(blob);
break;
}
blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
sizeof(*blob));
if ((size_t) (i+count) >= extent)
break;
}
if (LocaleCompare(filename,"-") != 0)
file=close(file);
if (blob == (unsigned char *) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
return(NULL);
}
if (file == -1)
{
blob=(unsigned char *) RelinquishMagickMemory(blob);
ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
return(NULL);
}
*length=(size_t) MagickMin(i+count,extent);
blob[*length]='\0';
return(blob);
}
*length=(size_t) MagickMin(offset,(MagickOffsetType)
MagickMin(extent,(size_t) MAGICK_SSIZE_MAX));
blob=(unsigned char *) NULL;
if (~(*length) >= (MagickPathExtent-1))
blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
sizeof(*blob));
if (blob == (unsigned char *) NULL)
{
file=close(file);
(void) ThrowMagickException(exception,GetMagickModule(),
ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
return(NULL);
}
map=MapBlob(file,ReadMode,0,*length);
if (map != (unsigned char *) NULL)
{
(void) memcpy(blob,map,*length);
(void) UnmapBlob(map,*length);
}
else
{
(void) lseek(file,0,SEEK_SET);
for (i=0; i < *length; i+=count)
{
count=read(file,blob+i,(size_t) MagickMin(*length-i,(size_t)
MAGICK_SSIZE_MAX));
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
}
if (i < *length)
{
file=close(file)-1;
blob=(unsigned char *) RelinquishMagickMemory(blob);
ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
return(NULL);
}
}
blob[*length]='\0';
if (LocaleCompare(filename,"-") != 0)
file=close(file);
if (file == -1)
{
blob=(unsigned char *) RelinquishMagickMemory(blob);
ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
}
return(blob);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% F i l e T o I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FileToImage() write the contents of a file to an image.
%
% The format of the FileToImage method is:
%
% MagickBooleanType FileToImage(Image *,const char *filename)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o filename: the filename.
%
*/
static inline ssize_t WriteBlobStream(Image *image,const size_t length,
const void *magick_restrict data)
{
BlobInfo
*magick_restrict blob_info;
MagickSizeType
extent;
unsigned char
*magick_restrict q;
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
assert(data != NULL);
blob_info=image->blob;
if (blob_info->type != BlobStream)
return(WriteBlob(image,length,(const unsigned char *) data));
extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
if (extent >= blob_info->extent)
{
extent=blob_info->extent+blob_info->quantum+length;
blob_info->quantum<<=1;
if (SetBlobExtent(image,extent) == MagickFalse)
return(0);
}
q=blob_info->data+blob_info->offset;
(void) memcpy(q,data,length);
blob_info->offset+=length;
if (blob_info->offset >= (MagickOffsetType) blob_info->length)
blob_info->length=(size_t) blob_info->offset;
return((ssize_t) length);
}
MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
ExceptionInfo *exception)
{
int
file;
MagickBooleanType
status;
size_t
length,
quantum;
ssize_t
count;
struct stat
file_stats;
unsigned char
*blob;
assert(image != (const Image *) NULL);
assert(image->signature == MagickCoreSignature);
assert(filename != (const char *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
status=IsRightsAuthorized(PathPolicyDomain,WritePolicyRights,filename);
if (status == MagickFalse)
{
errno=EPERM;
(void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
"NotAuthorized","`%s'",filename);
return(MagickFalse);
}
file=fileno(stdin);
if (LocaleCompare(filename,"-") != 0)
file=open_utf8(filename,O_RDONLY | O_BINARY,0);
if (file == -1)
{
ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
return(MagickFalse);
}
quantum=(size_t) MagickMaxBufferExtent;
if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
if (blob == (unsigned char *) NULL)
{
file=close(file);
ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
filename);
return(MagickFalse);
}
for ( ; ; )
{
count=read(file,blob,quantum);
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
length=(size_t) count;
count=WriteBlobStream(image,length,blob);
if (count != (ssize_t) length)
{
ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
break;
}
}
file=close(file);
if (file == -1)
ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
blob=(unsigned char *) RelinquishMagickMemory(blob);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t B l o b E r r o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetBlobError() returns MagickTrue if the blob associated with the specified
% image encountered an error.
%
% The format of the GetBlobError method is:
%
% MagickBooleanType GetBlobError(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport MagickBooleanType GetBlobError(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if ((image->blob->status != MagickFalse) && (image->blob->error_number != 0))
errno=image->blob->error_number;
return(image->blob->status);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t B l o b F i l e H a n d l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetBlobFileHandle() returns the file handle associated with the image blob.
%
% The format of the GetBlobFile method is:
%
% FILE *GetBlobFileHandle(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport FILE *GetBlobFileHandle(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickCoreSignature);
return(image->blob->file_info.file);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t B l o b I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetBlobInfo() initializes the BlobInfo structure.
%
% The format of the GetBlobInfo method is:
%
% void GetBlobInfo(BlobInfo *blob_info)
%
% A description of each parameter follows:
%
% o blob_info: Specifies a pointer to a BlobInfo structure.
%
*/
MagickExport void GetBlobInfo(BlobInfo *blob_info)
{
assert(blob_info != (BlobInfo *) NULL);
(void) memset(blob_info,0,sizeof(*blob_info));
blob_info->type=UndefinedStream;
blob_info->quantum=(size_t) MagickMaxBlobExtent;
blob_info->properties.st_mtime=GetMagickTime();
blob_info->properties.st_ctime=blob_info->properties.st_mtime;
blob_info->debug=IsEventLogging();
blob_info->reference_count=1;
blob_info->semaphore=AcquireSemaphoreInfo();
blob_info->signature=MagickCoreSignature;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t B l o b P r o p e r t i e s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetBlobProperties() returns information about an image blob.
%
% The format of the GetBlobProperties method is:
%
% const struct stat *GetBlobProperties(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport const struct stat *GetBlobProperties(const Image *image)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
return(&image->blob->properties);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t B l o b S i z e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetBlobSize() returns the current length of the image file or blob; zero is
% returned if the size cannot be determined.
%
% The format of the GetBlobSize method is:
%
% MagickSizeType GetBlobSize(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport MagickSizeType GetBlobSize(const Image *image)
{
BlobInfo
*magick_restrict blob_info;
MagickSizeType
extent;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(image->blob != (BlobInfo *) NULL);
blob_info=image->blob;
extent=0;
switch (blob_info->type)
{
case UndefinedStream:
case StandardStream:
{
extent=blob_info->size;
break;
}
case FileStream:
{
int
file_descriptor;
extent=(MagickSizeType) blob_info->properties.st_size;
if (extent == 0)
extent=blob_info->size;
file_descriptor=fileno(blob_info->file_info.file);
if (file_descriptor == -1)
break;
if (fstat(file_descriptor,&blob_info->properties) == 0)
extent=(MagickSizeType) blob_info->properties.st_size;
break;
}
case PipeStream:
{
extent=blob_info->size;
break;
}
case ZipStream:
case BZipStream:
{
MagickBooleanType
status;
status=GetPathAttributes(image->filename,&blob_info->properties);
if (status != MagickFalse)
extent=(MagickSizeType) blob_info->properties.st_size;
break;
}
case FifoStream:
break;
case BlobStream:
{
extent=(MagickSizeType) blob_info->length;
break;
}
case CustomStream:
{
if ((blob_info->custom_stream->teller != (CustomStreamTeller) NULL) &&
(blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL))
{
MagickOffsetType
offset;
offset=blob_info->custom_stream->teller(
blob_info->custom_stream->data);
extent=(MagickSizeType) blob_info->custom_stream->seeker(0,SEEK_END,
blob_info->custom_stream->data);
(void) blob_info->custom_stream->seeker(offset,SEEK_SET,
blob_info->custom_stream->data);
}
break;
}
}
return(extent);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t B l o b S t r e a m D a t a %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetBlobStreamData() returns the stream data for the image.
%
% The format of the GetBlobStreamData method is:
%
% void *GetBlobStreamData(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport void *GetBlobStreamData(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickCoreSignature);
return(image->blob->data);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t B l o b S t r e a m H a n d l e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetBlobStreamHandler() returns the stream handler for the image.
%
% The format of the GetBlobStreamHandler method is:
%
% StreamHandler GetBlobStreamHandler(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
return(image->blob->stream);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% I m a g e T o B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ImageToBlob() implements direct to memory image formats. It returns the
% image as a formatted blob and its length. The magick member of the Image
% structure determines the format of the returned blob (GIF, JPEG, PNG,
% etc.). This method is the equivalent of WriteImage(), but writes the
% formatted "file" to a memory buffer rather than to an actual file.
%
% The format of the ImageToBlob method is:
%
% void *ImageToBlob(const ImageInfo *image_info,Image *image,
% size_t *length,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o image: the image.
%
% o length: return the actual length of the blob.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport void *ImageToBlob(const ImageInfo *image_info,
Image *image,size_t *length,ExceptionInfo *exception)
{
const MagickInfo
*magick_info;
ImageInfo
*blob_info;
MagickBooleanType
status;
void
*blob;
assert(image_info != (const ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
assert(exception != (ExceptionInfo *) NULL);
*length=0;
blob=(unsigned char *) NULL;
blob_info=CloneImageInfo(image_info);
blob_info->adjoin=MagickFalse;
(void) SetImageInfo(blob_info,1,exception);
if (*blob_info->magick != '\0')
(void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
magick_info=GetMagickInfo(image->magick,exception);
if (magick_info == (const MagickInfo *) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
image->magick);
blob_info=DestroyImageInfo(blob_info);
return(blob);
}
(void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
if (GetMagickBlobSupport(magick_info) != MagickFalse)
{
/*
Native blob support for this image format.
*/
blob_info->length=0;
blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
sizeof(unsigned char));
if (blob_info->blob == NULL)
(void) ThrowMagickException(exception,GetMagickModule(),
ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
else
{
(void) CloseBlob(image);
image->blob->exempt=MagickTrue;
*image->filename='\0';
status=WriteImage(blob_info,image,exception);
*length=image->blob->length;
blob=DetachBlob(image->blob);
if (blob == (void *) NULL)
blob_info->blob=RelinquishMagickMemory(blob_info->blob);
else if (status == MagickFalse)
blob=RelinquishMagickMemory(blob);
else
blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
}
}
else
{
char
unique[MagickPathExtent];
int
file;
/*
Write file to disk in blob image format.
*/
file=AcquireUniqueFileResource(unique);
if (file == -1)
{
ThrowFileException(exception,BlobError,"UnableToWriteBlob",
image_info->filename);
}
else
{
blob_info->file=fdopen(file,"wb");
if (blob_info->file != (FILE *) NULL)
{
(void) FormatLocaleString(image->filename,MagickPathExtent,
"%s:%s",image->magick,unique);
status=WriteImage(blob_info,image,exception);
(void) CloseBlob(image);
(void) fclose(blob_info->file);
if (status != MagickFalse)
blob=FileToBlob(unique,~0UL,length,exception);
}
(void) RelinquishUniqueFileResource(unique);
}
}
blob_info=DestroyImageInfo(blob_info);
return(blob);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ I m a g e T o C u s t o m S t r e a m %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ImageToCustomStream() is the equivalent of WriteImage(), but writes the
% formatted "file" to the custom stream rather than to an actual file.
%
% The format of the ImageToCustomStream method is:
%
% void ImageToCustomStream(const ImageInfo *image_info,Image *image,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o image: the image.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport void ImageToCustomStream(const ImageInfo *image_info,Image *image,
ExceptionInfo *exception)
{
const MagickInfo
*magick_info;
ImageInfo
*clone_info;
MagickBooleanType
blob_support,
status;
assert(image_info != (const ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
assert(image_info->custom_stream->signature == MagickCoreSignature);
assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
assert(exception != (ExceptionInfo *) NULL);
clone_info=CloneImageInfo(image_info);
clone_info->adjoin=MagickFalse;
(void) SetImageInfo(clone_info,1,exception);
if (*clone_info->magick != '\0')
(void) CopyMagickString(image->magick,clone_info->magick,MagickPathExtent);
magick_info=GetMagickInfo(image->magick,exception);
if (magick_info == (const MagickInfo *) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
image->magick);
clone_info=DestroyImageInfo(clone_info);
return;
}
(void) CopyMagickString(clone_info->magick,image->magick,MagickPathExtent);
blob_support=GetMagickBlobSupport(magick_info);
if ((blob_support != MagickFalse) &&
(GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
{
if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
(clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
blob_support=MagickFalse;
}
if (blob_support != MagickFalse)
{
/*
Native blob support for this image format.
*/
(void) CloseBlob(image);
*image->filename='\0';
(void) WriteImage(clone_info,image,exception);
(void) CloseBlob(image);
}
else
{
char
unique[MagickPathExtent];
int
file;
unsigned char
*blob;
/*
Write file to disk in blob image format.
*/
clone_info->custom_stream=(CustomStreamInfo *) NULL;
blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
sizeof(*blob));
if (blob == (unsigned char *) NULL)
{
ThrowFileException(exception,BlobError,"UnableToWriteBlob",
image_info->filename);
clone_info=DestroyImageInfo(clone_info);
return;
}
file=AcquireUniqueFileResource(unique);
if (file == -1)
{
ThrowFileException(exception,BlobError,"UnableToWriteBlob",
image_info->filename);
blob=(unsigned char *) RelinquishMagickMemory(blob);
clone_info=DestroyImageInfo(clone_info);
return;
}
clone_info->file=fdopen(file,"wb+");
if (clone_info->file != (FILE *) NULL)
{
ssize_t
count;
(void) FormatLocaleString(image->filename,MagickPathExtent,
"%s:%s",image->magick,unique);
status=WriteImage(clone_info,image,exception);
(void) CloseBlob(image);
if (status != MagickFalse)
{
(void) fseek(clone_info->file,0,SEEK_SET);
count=(ssize_t) MagickMaxBufferExtent;
while (count == (ssize_t) MagickMaxBufferExtent)
{
count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
clone_info->file);
(void) image_info->custom_stream->writer(blob,(size_t) count,
image_info->custom_stream->data);
}
}
(void) fclose(clone_info->file);
}
blob=(unsigned char *) RelinquishMagickMemory(blob);
(void) RelinquishUniqueFileResource(unique);
}
clone_info=DestroyImageInfo(clone_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% I m a g e T o F i l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ImageToFile() writes an image to a file. It returns MagickFalse if an error
% occurs otherwise MagickTrue.
%
% The format of the ImageToFile method is:
%
% MagickBooleanType ImageToFile(Image *image,char *filename,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o filename: Write the image to this file.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
ExceptionInfo *exception)
{
int
file;
const unsigned char
*p;
size_t
i;
size_t
length,
quantum;
ssize_t
count;
struct stat
file_stats;
unsigned char
*buffer;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
assert(filename != (const char *) NULL);
if (*filename == '\0')
file=AcquireUniqueFileResource(filename);
else
if (LocaleCompare(filename,"-") == 0)
file=fileno(stdout);
else
file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
if (file == -1)
{
ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
return(MagickFalse);
}
quantum=(size_t) MagickMaxBufferExtent;
if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
if (buffer == (unsigned char *) NULL)
{
file=close(file)-1;
(void) ThrowMagickException(exception,GetMagickModule(),
ResourceLimitError,"MemoryAllocationError","`%s'",filename);
return(MagickFalse);
}
length=0;
p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
for (i=0; count > 0; )
{
length=(size_t) count;
for (i=0; i < length; i+=count)
{
count=write(file,p+i,(size_t) (length-i));
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
}
if (i < length)
break;
p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
}
if (LocaleCompare(filename,"-") != 0)
file=close(file);
buffer=(unsigned char *) RelinquishMagickMemory(buffer);
if ((file == -1) || (i < length))
{
ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
return(MagickFalse);
}
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% I m a g e s T o B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ImagesToBlob() implements direct to memory image formats. It returns the
% image sequence as a blob and its length. The magick member of the ImageInfo
% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
%
% Note, some image formats do not permit multiple images to the same image
% stream (e.g. JPEG). in this instance, just the first image of the
% sequence is returned as a blob.
%
% The format of the ImagesToBlob method is:
%
% void *ImagesToBlob(const ImageInfo *image_info,Image *images,
% size_t *length,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o images: the image list.
%
% o length: return the actual length of the blob.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
size_t *length,ExceptionInfo *exception)
{
const MagickInfo
*magick_info;
ImageInfo
*clone_info;
MagickBooleanType
status;
void
*blob;
assert(image_info != (const ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(images != (Image *) NULL);
assert(images->signature == MagickCoreSignature);
assert(exception != (ExceptionInfo *) NULL);
*length=0;
blob=(unsigned char *) NULL;
clone_info=CloneImageInfo(image_info);
(void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
exception);
if (*clone_info->magick != '\0')
(void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
magick_info=GetMagickInfo(images->magick,exception);
if (magick_info == (const MagickInfo *) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
images->magick);
clone_info=DestroyImageInfo(clone_info);
return(blob);
}
if (GetMagickAdjoin(magick_info) == MagickFalse)
{
clone_info=DestroyImageInfo(clone_info);
return(ImageToBlob(image_info,images,length,exception));
}
(void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
if (GetMagickBlobSupport(magick_info) != MagickFalse)
{
/*
Native blob support for this images format.
*/
clone_info->length=0;
clone_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
sizeof(unsigned char));
if (clone_info->blob == (void *) NULL)
(void) ThrowMagickException(exception,GetMagickModule(),
ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
else
{
(void) CloseBlob(images);
images->blob->exempt=MagickTrue;
*images->filename='\0';
status=WriteImages(clone_info,images,images->filename,exception);
*length=images->blob->length;
blob=DetachBlob(images->blob);
if (blob == (void *) NULL)
clone_info->blob=RelinquishMagickMemory(clone_info->blob);
else if (status == MagickFalse)
blob=RelinquishMagickMemory(blob);
else
blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
}
}
else
{
char
filename[MagickPathExtent],
unique[MagickPathExtent];
int
file;
/*
Write file to disk in blob images format.
*/
file=AcquireUniqueFileResource(unique);
if (file == -1)
{
ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
image_info->filename);
}
else
{
clone_info->file=fdopen(file,"wb");
if (clone_info->file != (FILE *) NULL)
{
(void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
images->magick,unique);
status=WriteImages(clone_info,images,filename,exception);
(void) CloseBlob(images);
(void) fclose(clone_info->file);
if (status != MagickFalse)
blob=FileToBlob(unique,~0UL,length,exception);
}
(void) RelinquishUniqueFileResource(unique);
}
}
clone_info=DestroyImageInfo(clone_info);
return(blob);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ I m a g e s T o C u s t o m B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ImagesToCustomStream() is the equivalent of WriteImages(), but writes the
% formatted "file" to the custom stream rather than to an actual file.
%
% The format of the ImageToCustomStream method is:
%
% void ImagesToCustomStream(const ImageInfo *image_info,Image *images,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o images: the image list.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport void ImagesToCustomStream(const ImageInfo *image_info,
Image *images,ExceptionInfo *exception)
{
const MagickInfo
*magick_info;
ImageInfo
*clone_info;
MagickBooleanType
blob_support,
status;
assert(image_info != (const ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(images != (Image *) NULL);
assert(images->signature == MagickCoreSignature);
assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
assert(image_info->custom_stream->signature == MagickCoreSignature);
assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
assert(exception != (ExceptionInfo *) NULL);
clone_info=CloneImageInfo(image_info);
(void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
exception);
if (*clone_info->magick != '\0')
(void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
magick_info=GetMagickInfo(images->magick,exception);
if (magick_info == (const MagickInfo *) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
images->magick);
clone_info=DestroyImageInfo(clone_info);
return;
}
(void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
blob_support=GetMagickBlobSupport(magick_info);
if ((blob_support != MagickFalse) &&
(GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
{
if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
(clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
blob_support=MagickFalse;
}
if (blob_support != MagickFalse)
{
/*
Native blob support for this image format.
*/
(void) CloseBlob(images);
*images->filename='\0';
(void) WriteImages(clone_info,images,images->filename,exception);
(void) CloseBlob(images);
}
else
{
char
filename[MagickPathExtent],
unique[MagickPathExtent];
int
file;
unsigned char
*blob;
/*
Write file to disk in blob image format.
*/
clone_info->custom_stream=(CustomStreamInfo *) NULL;
blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
sizeof(*blob));
if (blob == (unsigned char *) NULL)
{
ThrowFileException(exception,BlobError,"UnableToWriteBlob",
image_info->filename);
clone_info=DestroyImageInfo(clone_info);
return;
}
file=AcquireUniqueFileResource(unique);
if (file == -1)
{
ThrowFileException(exception,BlobError,"UnableToWriteBlob",
image_info->filename);
blob=(unsigned char *) RelinquishMagickMemory(blob);
clone_info=DestroyImageInfo(clone_info);
return;
}
clone_info->file=fdopen(file,"wb+");
if (clone_info->file != (FILE *) NULL)
{
ssize_t
count;
(void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
images->magick,unique);
status=WriteImages(clone_info,images,filename,exception);
(void) CloseBlob(images);
if (status != MagickFalse)
{
(void) fseek(clone_info->file,0,SEEK_SET);
count=(ssize_t) MagickMaxBufferExtent;
while (count == (ssize_t) MagickMaxBufferExtent)
{
count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
clone_info->file);
(void) image_info->custom_stream->writer(blob,(size_t) count,
image_info->custom_stream->data);
}
}
(void) fclose(clone_info->file);
}
blob=(unsigned char *) RelinquishMagickMemory(blob);
(void) RelinquishUniqueFileResource(unique);
}
clone_info=DestroyImageInfo(clone_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% I n j e c t I m a g e B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% InjectImageBlob() injects the image with a copy of itself in the specified
% format (e.g. inject JPEG into a PDF image).
%
% The format of the InjectImageBlob method is:
%
% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
% Image *image,Image *inject_image,const char *format,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info..
%
% o image: the image.
%
% o inject_image: inject into the image stream.
%
% o format: the image format.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
{
char
filename[MagickPathExtent];
FILE
*unique_file;
Image
*byte_image;
ImageInfo
*write_info;
int
file;
MagickBooleanType
status;
ssize_t
i;
size_t
quantum;
ssize_t
count;
struct stat
file_stats;
unsigned char
*buffer;
/*
Write inject image to a temporary file.
*/
assert(image_info != (ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(inject_image != (Image *) NULL);
assert(inject_image->signature == MagickCoreSignature);
assert(exception != (ExceptionInfo *) NULL);
unique_file=(FILE *) NULL;
file=AcquireUniqueFileResource(filename);
if (file != -1)
unique_file=fdopen(file,"wb");
if ((file == -1) || (unique_file == (FILE *) NULL))
{
(void) CopyMagickString(image->filename,filename,MagickPathExtent);
ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
image->filename);
return(MagickFalse);
}
byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
if (byte_image == (Image *) NULL)
{
(void) fclose(unique_file);
(void) RelinquishUniqueFileResource(filename);
return(MagickFalse);
}
(void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
format,filename);
DestroyBlob(byte_image);
byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
write_info=CloneImageInfo(image_info);
SetImageInfoFile(write_info,unique_file);
status=WriteImage(write_info,byte_image,exception);
write_info=DestroyImageInfo(write_info);
byte_image=DestroyImage(byte_image);
(void) fclose(unique_file);
if (status == MagickFalse)
{
(void) RelinquishUniqueFileResource(filename);
return(MagickFalse);
}
/*
Inject into image stream.
*/
file=open_utf8(filename,O_RDONLY | O_BINARY,0);
if (file == -1)
{
(void) RelinquishUniqueFileResource(filename);
ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
image_info->filename);
return(MagickFalse);
}
quantum=(size_t) MagickMaxBufferExtent;
if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
if (buffer == (unsigned char *) NULL)
{
(void) RelinquishUniqueFileResource(filename);
file=close(file);
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
}
for (i=0; ; i+=count)
{
count=read(file,buffer,quantum);
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
MagickFalse;
}
file=close(file);
if (file == -1)
ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
(void) RelinquishUniqueFileResource(filename);
buffer=(unsigned char *) RelinquishMagickMemory(buffer);
return(status);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% I s B l o b E x e m p t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% IsBlobExempt() returns true if the blob is exempt.
%
% The format of the IsBlobExempt method is:
%
% MagickBooleanType IsBlobExempt(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport MagickBooleanType IsBlobExempt(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
return(image->blob->exempt);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% I s B l o b S e e k a b l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% IsBlobSeekable() returns true if the blob is seekable.
%
% The format of the IsBlobSeekable method is:
%
% MagickBooleanType IsBlobSeekable(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
{
BlobInfo
*magick_restrict blob_info;
assert(image != (const Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
blob_info=image->blob;
switch (blob_info->type)
{
case BlobStream:
return(MagickTrue);
case FileStream:
{
int
status;
if (blob_info->file_info.file == (FILE *) NULL)
return(MagickFalse);
status=fseek(blob_info->file_info.file,0,SEEK_CUR);
return(status == -1 ? MagickFalse : MagickTrue);
}
case ZipStream:
{
#if defined(MAGICKCORE_ZLIB_DELEGATE)
MagickOffsetType
offset;
if (blob_info->file_info.gzfile == (gzFile) NULL)
return(MagickFalse);
offset=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
return(offset < 0 ? MagickFalse : MagickTrue);
#else
break;
#endif
}
case UndefinedStream:
case BZipStream:
case FifoStream:
case PipeStream:
case StandardStream:
break;
case CustomStream:
{
if ((blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL) &&
(blob_info->custom_stream->teller != (CustomStreamTeller) NULL))
return(MagickTrue);
break;
}
default:
break;
}
return(MagickFalse);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% I s B l o b T e m p o r a r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% IsBlobTemporary() returns true if the blob is temporary.
%
% The format of the IsBlobTemporary method is:
%
% MagickBooleanType IsBlobTemporary(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
return(image->blob->temporary);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ M a p B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MapBlob() creates a mapping from a file to a binary large object.
%
% The format of the MapBlob method is:
%
% void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
% const size_t length)
%
% A description of each parameter follows:
%
% o file: map this file descriptor.
%
% o mode: ReadMode, WriteMode, or IOMode.
%
% o offset: starting at this offset within the file.
%
% o length: the length of the mapping is returned in this pointer.
%
*/
MagickExport void *MapBlob(int file,const MapMode mode,
const MagickOffsetType offset,const size_t length)
{
#if defined(MAGICKCORE_HAVE_MMAP)
int
flags,
protection;
void
*map;
/*
Map file.
*/
flags=0;
if (file == -1)
#if defined(MAP_ANONYMOUS)
flags|=MAP_ANONYMOUS;
#else
return(NULL);
#endif
switch (mode)
{
case ReadMode:
default:
{
protection=PROT_READ;
flags|=MAP_PRIVATE;
break;
}
case WriteMode:
{
protection=PROT_WRITE;
flags|=MAP_SHARED;
break;
}
case IOMode:
{
protection=PROT_READ | PROT_WRITE;
flags|=MAP_SHARED;
break;
}
}
#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
map=mmap((char *) NULL,length,protection,flags,file,offset);
#else
map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,offset);
if (map == MAP_FAILED)
map=mmap((char *) NULL,length,protection,flags,file,offset);
#endif
if (map == MAP_FAILED)
return(NULL);
return(map);
#else
(void) file;
(void) mode;
(void) offset;
(void) length;
return(NULL);
#endif
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ M S B O r d e r L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MSBOrderLong() converts a least-significant byte first buffer of integers to
% most-significant byte first.
%
% The format of the MSBOrderLong method is:
%
% void MSBOrderLong(unsigned char *buffer,const size_t length)
%
% A description of each parameter follows.
%
% o buffer: Specifies a pointer to a buffer of integers.
%
% o length: Specifies the length of the buffer.
%
*/
MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
{
int
c;
unsigned char
*p,
*q;
assert(buffer != (unsigned char *) NULL);
q=buffer+length;
while (buffer < q)
{
p=buffer+3;
c=(int) (*p);
*p=(*buffer);
*buffer++=(unsigned char) c;
p=buffer+1;
c=(int) (*p);
*p=(*buffer);
*buffer++=(unsigned char) c;
buffer+=2;
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ M S B O r d e r S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MSBOrderShort() converts a least-significant byte first buffer of integers
% to most-significant byte first.
%
% The format of the MSBOrderShort method is:
%
% void MSBOrderShort(unsigned char *p,const size_t length)
%
% A description of each parameter follows.
%
% o p: Specifies a pointer to a buffer of integers.
%
% o length: Specifies the length of the buffer.
%
*/
MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
{
int
c;
unsigned char
*q;
assert(p != (unsigned char *) NULL);
q=p+length;
while (p < q)
{
c=(int) (*p);
*p=(*(p+1));
p++;
*p++=(unsigned char) c;
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ O p e n B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% OpenBlob() opens a file associated with the image. A file name of '-' sets
% the file to stdin for type 'r' and stdout for type 'w'. If the filename
% suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
% compressed for type 'w'. If the filename prefix is '|', it is piped to or
% from a system command.
%
% The format of the OpenBlob method is:
%
% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
% const BlobMode mode,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o image: the image.
%
% o mode: the mode for opening the file.
%
*/
static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
Image *image)
{
const char
*option;
int
status;
size_t
size;
size=MagickMinBufferExtent;
option=GetImageOption(image_info,"stream:buffer-size");
if (option != (const char *) NULL)
size=StringToUnsignedLong(option);
status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
_IONBF : _IOFBF,size);
return(status == 0 ? MagickTrue : MagickFalse);
}
MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
Image *image,const BlobMode mode,ExceptionInfo *exception)
{
BlobInfo
*magick_restrict blob_info;
char
extension[MagickPathExtent],
filename[MagickPathExtent];
const char
*type;
MagickBooleanType
status;
PolicyRights
rights;
assert(image_info != (ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
blob_info=image->blob;
if (image_info->blob != (void *) NULL)
{
if (image_info->stream != (StreamHandler) NULL)
blob_info->stream=(StreamHandler) image_info->stream;
AttachBlob(blob_info,image_info->blob,image_info->length);
return(MagickTrue);
}
if ((image_info->custom_stream != (CustomStreamInfo *) NULL) &&
(*image->filename == '\0'))
{
blob_info->type=CustomStream;
blob_info->custom_stream=image_info->custom_stream;
return(MagickTrue);
}
(void) DetachBlob(blob_info);
blob_info->mode=mode;
switch (mode)
{
default: type="r"; break;
case ReadBlobMode: type="r"; break;
case ReadBinaryBlobMode: type="rb"; break;
case WriteBlobMode: type="w"; break;
case WriteBinaryBlobMode: type="w+b"; break;
case AppendBlobMode: type="a"; break;
case AppendBinaryBlobMode: type="a+b"; break;
}
if (*type != 'r')
blob_info->synchronize=image_info->synchronize;
if (image_info->stream != (StreamHandler) NULL)
{
blob_info->stream=image_info->stream;
if (*type == 'w')
{
blob_info->type=FifoStream;
return(MagickTrue);
}
}
/*
Open image file.
*/
*filename='\0';
(void) CopyMagickString(filename,image->filename,MagickPathExtent);
rights=ReadPolicyRights;
if (*type == 'w')
rights=WritePolicyRights;
if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
{
errno=EPERM;
(void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
"NotAuthorized","`%s'",filename);
return(MagickFalse);
}
if ((LocaleCompare(filename,"-") == 0) ||
((*filename == '\0') && (image_info->file == (FILE *) NULL)))
{
blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
if (strchr(type,'b') != (char *) NULL)
setmode(fileno(blob_info->file_info.file),_O_BINARY);
#endif
blob_info->type=StandardStream;
blob_info->exempt=MagickTrue;
return(SetStreamBuffering(image_info,image));
}
if ((LocaleNCompare(filename,"fd:",3) == 0) &&
(IsGeometry(filename+3) != MagickFalse))
{
char
fileMode[MagickPathExtent];
*fileMode =(*type);
fileMode[1]='\0';
blob_info->file_info.file=fdopen(StringToLong(filename+3),fileMode);
if (blob_info->file_info.file == (FILE *) NULL)
{
ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
return(MagickFalse);
}
#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
if (strchr(type,'b') != (char *) NULL)
setmode(fileno(blob_info->file_info.file),_O_BINARY);
#endif
blob_info->type=FileStream;
blob_info->exempt=MagickTrue;
return(SetStreamBuffering(image_info,image));
}
#if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
if (*filename == '|')
{
char
fileMode[MagickPathExtent],
*sanitize_command;
/*
Pipe image to or from a system command.
*/
#if defined(SIGPIPE)
if (*type == 'w')
(void) signal(SIGPIPE,SIG_IGN);
#endif
*fileMode =(*type);
fileMode[1]='\0';
sanitize_command=SanitizeString(filename+1);
blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,fileMode);
sanitize_command=DestroyString(sanitize_command);
if (blob_info->file_info.file == (FILE *) NULL)
{
ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
return(MagickFalse);
}
blob_info->type=PipeStream;
blob_info->exempt=MagickTrue;
return(SetStreamBuffering(image_info,image));
}
#endif
status=GetPathAttributes(filename,&blob_info->properties);
#if defined(S_ISFIFO)
if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
{
blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
if (blob_info->file_info.file == (FILE *) NULL)
{
ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
return(MagickFalse);
}
blob_info->type=FileStream;
blob_info->exempt=MagickTrue;
return(SetStreamBuffering(image_info,image));
}
#endif
GetPathComponent(image->filename,ExtensionPath,extension);
if (*type == 'w')
{
(void) CopyMagickString(filename,image->filename,MagickPathExtent);
if ((image_info->adjoin == MagickFalse) ||
(strchr(filename,'%') != (char *) NULL))
{
/*
Form filename for multi-part images.
*/
(void) InterpretImageFilename(image_info,image,image->filename,(int)
image->scene,filename,exception);
if ((LocaleCompare(filename,image->filename) == 0) &&
((GetPreviousImageInList(image) != (Image *) NULL) ||
(GetNextImageInList(image) != (Image *) NULL)))
{
char
path[MagickPathExtent];
GetPathComponent(image->filename,RootPath,path);
if (*extension == '\0')
(void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
path,(double) image->scene);
else
(void) FormatLocaleString(filename,MagickPathExtent,
"%s-%.20g.%s",path,(double) image->scene,extension);
}
(void) CopyMagickString(image->filename,filename,MagickPathExtent);
#if defined(macintosh)
SetApplicationType(filename,image_info->magick,'8BIM');
#endif
}
}
if (image_info->file != (FILE *) NULL)
{
blob_info->file_info.file=image_info->file;
blob_info->type=FileStream;
blob_info->exempt=MagickTrue;
}
else
if (*type == 'r')
{
blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
if (blob_info->file_info.file != (FILE *) NULL)
{
size_t
count;
unsigned char
magick[3];
blob_info->type=FileStream;
(void) SetStreamBuffering(image_info,image);
(void) memset(magick,0,sizeof(magick));
count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
(void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
#if defined(MAGICKCORE_POSIX_SUPPORT)
(void) fflush(blob_info->file_info.file);
#endif
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" read %.20g magic header bytes",(double) count);
#if defined(MAGICKCORE_ZLIB_DELEGATE)
if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
((int) magick[2] == 0x08))
{
if (blob_info->file_info.file != (FILE *) NULL)
(void) fclose(blob_info->file_info.file);
blob_info->file_info.file=(FILE *) NULL;
blob_info->file_info.gzfile=gzopen(filename,"rb");
if (blob_info->file_info.gzfile != (gzFile) NULL)
blob_info->type=ZipStream;
}
#endif
#if defined(MAGICKCORE_BZLIB_DELEGATE)
if (strncmp((char *) magick,"BZh",3) == 0)
{
if (blob_info->file_info.file != (FILE *) NULL)
(void) fclose(blob_info->file_info.file);
blob_info->file_info.file=(FILE *) NULL;
blob_info->file_info.bzfile=BZ2_bzopen(filename,"r");
if (blob_info->file_info.bzfile != (BZFILE *) NULL)
blob_info->type=BZipStream;
}
#endif
if (blob_info->type == FileStream)
{
const MagickInfo
*magick_info;
ExceptionInfo
*sans_exception;
size_t
length;
sans_exception=AcquireExceptionInfo();
magick_info=GetMagickInfo(image_info->magick,sans_exception);
sans_exception=DestroyExceptionInfo(sans_exception);
length=(size_t) blob_info->properties.st_size;
if ((magick_info != (const MagickInfo *) NULL) &&
(GetMagickBlobSupport(magick_info) != MagickFalse) &&
(length > MagickMaxBufferExtent) &&
(AcquireMagickResource(MapResource,length) != MagickFalse))
{
void
*blob;
blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
length);
if (blob == (void *) NULL)
RelinquishMagickResource(MapResource,length);
else
{
/*
Format supports blobs-- use memory-mapped I/O.
*/
if (image_info->file != (FILE *) NULL)
blob_info->exempt=MagickFalse;
else
{
(void) fclose(blob_info->file_info.file);
blob_info->file_info.file=(FILE *) NULL;
}
AttachBlob(blob_info,blob,length);
blob_info->mapped=MagickTrue;
}
}
}
}
}
else
#if defined(MAGICKCORE_ZLIB_DELEGATE)
if ((LocaleCompare(extension,"Z") == 0) ||
(LocaleCompare(extension,"gz") == 0) ||
(LocaleCompare(extension,"wmz") == 0) ||
(LocaleCompare(extension,"svgz") == 0))
{
blob_info->file_info.gzfile=gzopen(filename,"wb");
if (blob_info->file_info.gzfile != (gzFile) NULL)
blob_info->type=ZipStream;
}
else
#endif
#if defined(MAGICKCORE_BZLIB_DELEGATE)
if (LocaleCompare(extension,"bz2") == 0)
{
blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
if (blob_info->file_info.bzfile != (BZFILE *) NULL)
blob_info->type=BZipStream;
}
else
#endif
{
blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
if (blob_info->file_info.file != (FILE *) NULL)
{
blob_info->type=FileStream;
(void) SetStreamBuffering(image_info,image);
}
}
blob_info->status=MagickFalse;
blob_info->error_number=MagickFalse;
if (blob_info->type != UndefinedStream)
blob_info->size=GetBlobSize(image);
else
{
ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
return(MagickFalse);
}
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ P i n g B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% PingBlob() returns all the attributes of an image or image sequence except
% for the pixels. It is much faster and consumes far less memory than
% BlobToImage(). On failure, a NULL image is returned and exception
% describes the reason for the failure.
%
% The format of the PingBlob method is:
%
% Image *PingBlob(const ImageInfo *image_info,const void *blob,
% const size_t length,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o blob: the address of a character stream in one of the image formats
% understood by ImageMagick.
%
% o length: This size_t integer reflects the length in bytes of the blob.
%
% o exception: return any errors or warnings in this structure.
%
*/
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
static size_t PingStream(const Image *magick_unused(image),
const void *magick_unused(pixels),const size_t columns)
{
magick_unreferenced(image);
magick_unreferenced(pixels);
return(columns);
}
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
const size_t length,ExceptionInfo *exception)
{
const MagickInfo
*magick_info;
Image
*image;
ImageInfo
*clone_info,
*ping_info;
MagickBooleanType
status;
assert(image_info != (ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(exception != (ExceptionInfo *) NULL);
if ((blob == (const void *) NULL) || (length == 0))
{
(void) ThrowMagickException(exception,GetMagickModule(),BlobError,
"ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
return((Image *) NULL);
}
ping_info=CloneImageInfo(image_info);
ping_info->blob=(void *) blob;
ping_info->length=length;
ping_info->ping=MagickTrue;
if (*ping_info->magick == '\0')
(void) SetImageInfo(ping_info,0,exception);
magick_info=GetMagickInfo(ping_info->magick,exception);
if (magick_info == (const MagickInfo *) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
ping_info->magick);
ping_info=DestroyImageInfo(ping_info);
return((Image *) NULL);
}
if (GetMagickBlobSupport(magick_info) != MagickFalse)
{
char
filename[MagickPathExtent];
/*
Native blob support for this image format.
*/
(void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
(void) FormatLocaleString(ping_info->filename,MagickPathExtent,"%s:%s",
ping_info->magick,filename);
image=ReadStream(ping_info,&PingStream,exception);
if (image != (Image *) NULL)
(void) DetachBlob(image->blob);
ping_info=DestroyImageInfo(ping_info);
return(image);
}
/*
Write blob to a temporary file on disk.
*/
ping_info->blob=(void *) NULL;
ping_info->length=0;
*ping_info->filename='\0';
status=BlobToFile(ping_info->filename,blob,length,exception);
if (status == MagickFalse)
{
(void) RelinquishUniqueFileResource(ping_info->filename);
ping_info=DestroyImageInfo(ping_info);
return((Image *) NULL);
}
clone_info=CloneImageInfo(ping_info);
(void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
ping_info->magick,ping_info->filename);
image=ReadStream(clone_info,&PingStream,exception);
if (image != (Image *) NULL)
{
Image
*images;
/*
Restore original filenames and image format.
*/
for (images=GetFirstImageInList(image); images != (Image *) NULL; )
{
(void) CopyMagickString(images->filename,image_info->filename,
MagickPathExtent);
(void) CopyMagickString(images->magick_filename,image_info->filename,
MagickPathExtent);
(void) CopyMagickString(images->magick,magick_info->name,
MagickPathExtent);
images=GetNextImageInList(images);
}
}
clone_info=DestroyImageInfo(clone_info);
(void) RelinquishUniqueFileResource(ping_info->filename);
ping_info=DestroyImageInfo(ping_info);
return(image);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlob() reads data from the blob or image file and returns it. It
% returns the number of bytes read. If length is zero, ReadBlob() returns
% zero and has no other results. If length is greater than MAGICK_SSIZE_MAX, the
% result is unspecified.
%
% The format of the ReadBlob method is:
%
% ssize_t ReadBlob(Image *image,const size_t length,void *data)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o length: Specifies an integer representing the number of bytes to read
% from the file.
%
% o data: Specifies an area to place the information requested from the
% file.
%
*/
MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
{
BlobInfo
*magick_restrict blob_info;
int
c;
unsigned char
*q;
ssize_t
count;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
if (length == 0)
return(0);
assert(data != (void *) NULL);
blob_info=image->blob;
count=0;
q=(unsigned char *) data;
switch (blob_info->type)
{
case UndefinedStream:
break;
case StandardStream:
case FileStream:
case PipeStream:
{
switch (length)
{
default:
{
count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
break;
}
case 4:
{
c=getc(blob_info->file_info.file);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
case 3:
{
c=getc(blob_info->file_info.file);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
case 2:
{
c=getc(blob_info->file_info.file);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
case 1:
{
c=getc(blob_info->file_info.file);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
case 0:
break;
}
if ((count != (ssize_t) length) &&
(ferror(blob_info->file_info.file) != 0))
ThrowBlobException(blob_info);
break;
}
case ZipStream:
{
#if defined(MAGICKCORE_ZLIB_DELEGATE)
int
status;
switch (length)
{
default:
{
ssize_t
i;
for (i=0; i < (ssize_t) length; i+=count)
{
count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
(unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
}
count=i;
break;
}
case 4:
{
c=gzgetc(blob_info->file_info.gzfile);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
case 3:
{
c=gzgetc(blob_info->file_info.gzfile);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
case 2:
{
c=gzgetc(blob_info->file_info.gzfile);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
case 1:
{
c=gzgetc(blob_info->file_info.gzfile);
if (c == EOF)
break;
*q++=(unsigned char) c;
count++;
}
case 0:
break;
}
status=Z_OK;
(void) gzerror(blob_info->file_info.gzfile,&status);
if ((count != (ssize_t) length) && (status != Z_OK))
ThrowBlobException(blob_info);
if (blob_info->eof == MagickFalse)
blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
MagickFalse;
#endif
break;
}
case BZipStream:
{
#if defined(MAGICKCORE_BZLIB_DELEGATE)
int
status;
ssize_t
i;
for (i=0; i < (ssize_t) length; i+=count)
{
count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,
(unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
}
count=i;
status=BZ_OK;
(void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
if ((count != (ssize_t) length) && (status != BZ_OK))
ThrowBlobException(blob_info);
#endif
break;
}
case FifoStream:
break;
case BlobStream:
{
const unsigned char
*p;
if (blob_info->offset >= (MagickOffsetType) blob_info->length)
{
blob_info->eof=MagickTrue;
break;
}
p=blob_info->data+blob_info->offset;
count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
blob_info->length-blob_info->offset);
blob_info->offset+=count;
if (count != (ssize_t) length)
blob_info->eof=MagickTrue;
(void) memcpy(q,p,(size_t) count);
break;
}
case CustomStream:
{
if (blob_info->custom_stream->reader != (CustomStreamHandler) NULL)
count=blob_info->custom_stream->reader(q,length,
blob_info->custom_stream->data);
break;
}
}
return(count);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b B y t e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobByte() reads a single byte from the image file and returns it.
%
% The format of the ReadBlobByte method is:
%
% int ReadBlobByte(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport int ReadBlobByte(Image *image)
{
BlobInfo
*magick_restrict blob_info;
const unsigned char
*p;
unsigned char
buffer[1];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
blob_info=image->blob;
switch (blob_info->type)
{
case StandardStream:
case FileStream:
case PipeStream:
{
int
c;
p=(const unsigned char *) buffer;
c=getc(blob_info->file_info.file);
if (c == EOF)
return(EOF);
*buffer=(unsigned char) c;
break;
}
default:
{
ssize_t
count;
p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
if (count != 1)
return(EOF);
break;
}
}
return((int) (*p));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b D o u b l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
% specified by the endian member of the image structure.
%
% The format of the ReadBlobDouble method is:
%
% double ReadBlobDouble(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport double ReadBlobDouble(Image *image)
{
union
{
MagickSizeType
unsigned_value;
double
double_value;
} quantum;
quantum.double_value=0.0;
quantum.unsigned_value=ReadBlobLongLong(image);
return(quantum.double_value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b F l o a t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
% specified by the endian member of the image structure.
%
% The format of the ReadBlobFloat method is:
%
% float ReadBlobFloat(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport float ReadBlobFloat(Image *image)
{
union
{
unsigned int
unsigned_value;
float
float_value;
} quantum;
quantum.float_value=0.0;
quantum.unsigned_value=ReadBlobLong(image);
return(quantum.float_value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
% byte-order specified by the endian member of the image structure.
%
% The format of the ReadBlobLong method is:
%
% unsigned int ReadBlobLong(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport unsigned int ReadBlobLong(Image *image)
{
const unsigned char
*p;
ssize_t
count;
unsigned char
buffer[4];
unsigned int
value;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
*buffer='\0';
p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
if (count != 4)
return(0UL);
if (image->endian == LSBEndian)
{
value=(unsigned int) (*p++);
value|=(unsigned int) (*p++) << 8;
value|=(unsigned int) (*p++) << 16;
value|=(unsigned int) (*p++) << 24;
return(value);
}
value=(unsigned int) (*p++) << 24;
value|=(unsigned int) (*p++) << 16;
value|=(unsigned int) (*p++) << 8;
value|=(unsigned int) (*p++);
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L o n g L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
% byte-order specified by the endian member of the image structure.
%
% The format of the ReadBlobLongLong method is:
%
% MagickSizeType ReadBlobLongLong(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport MagickSizeType ReadBlobLongLong(Image *image)
{
MagickSizeType
value;
const unsigned char
*p;
ssize_t
count;
unsigned char
buffer[8];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
*buffer='\0';
p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
if (count != 8)
return(MagickULLConstant(0));
if (image->endian == LSBEndian)
{
value=(MagickSizeType) (*p++);
value|=(MagickSizeType) (*p++) << 8;
value|=(MagickSizeType) (*p++) << 16;
value|=(MagickSizeType) (*p++) << 24;
value|=(MagickSizeType) (*p++) << 32;
value|=(MagickSizeType) (*p++) << 40;
value|=(MagickSizeType) (*p++) << 48;
value|=(MagickSizeType) (*p++) << 56;
return(value);
}
value=(MagickSizeType) (*p++) << 56;
value|=(MagickSizeType) (*p++) << 48;
value|=(MagickSizeType) (*p++) << 40;
value|=(MagickSizeType) (*p++) << 32;
value|=(MagickSizeType) (*p++) << 24;
value|=(MagickSizeType) (*p++) << 16;
value|=(MagickSizeType) (*p++) << 8;
value|=(MagickSizeType) (*p++);
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
% specified by the endian member of the image structure.
%
% The format of the ReadBlobShort method is:
%
% unsigned short ReadBlobShort(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport unsigned short ReadBlobShort(Image *image)
{
const unsigned char
*p;
unsigned short
value;
ssize_t
count;
unsigned char
buffer[2];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
*buffer='\0';
p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
if (count != 2)
return((unsigned short) 0U);
if (image->endian == LSBEndian)
{
value=(unsigned short) (*p++);
value|=(unsigned short) (*p++) << 8;
return(value);
}
value=(unsigned short) ((unsigned short) (*p++) << 8);
value|=(unsigned short) (*p++);
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
% least-significant byte first order.
%
% The format of the ReadBlobLSBLong method is:
%
% unsigned int ReadBlobLSBLong(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport unsigned int ReadBlobLSBLong(Image *image)
{
const unsigned char
*p;
unsigned int
value;
ssize_t
count;
unsigned char
buffer[4];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
*buffer='\0';
p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
if (count != 4)
return(0U);
value=(unsigned int) (*p++);
value|=(unsigned int) (*p++) << 8;
value|=(unsigned int) (*p++) << 16;
value|=(unsigned int) (*p++) << 24;
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B S i g n e d L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
% least-significant byte first order.
%
% The format of the ReadBlobLSBSignedLong method is:
%
% signed int ReadBlobLSBSignedLong(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport signed int ReadBlobLSBSignedLong(Image *image)
{
union
{
unsigned int
unsigned_value;
signed int
signed_value;
} quantum;
quantum.unsigned_value=ReadBlobLSBLong(image);
return(quantum.signed_value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
% least-significant byte first order.
%
% The format of the ReadBlobLSBShort method is:
%
% unsigned short ReadBlobLSBShort(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport unsigned short ReadBlobLSBShort(Image *image)
{
const unsigned char
*p;
unsigned short
value;
ssize_t
count;
unsigned char
buffer[2];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
*buffer='\0';
p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
if (count != 2)
return((unsigned short) 0U);
value=(unsigned short) (*p++);
value|=(unsigned short) (*p++) << 8;
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B S i g n e d S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
% least-significant byte-order.
%
% The format of the ReadBlobLSBSignedShort method is:
%
% signed short ReadBlobLSBSignedShort(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport signed short ReadBlobLSBSignedShort(Image *image)
{
union
{
unsigned short
unsigned_value;
signed short
signed_value;
} quantum;
quantum.unsigned_value=ReadBlobLSBShort(image);
return(quantum.signed_value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
% most-significant byte first order.
%
% The format of the ReadBlobMSBLong method is:
%
% unsigned int ReadBlobMSBLong(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport unsigned int ReadBlobMSBLong(Image *image)
{
const unsigned char
*p;
unsigned int
value;
ssize_t
count;
unsigned char
buffer[4];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
*buffer='\0';
p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
if (count != 4)
return(0UL);
value=(unsigned int) (*p++) << 24;
value|=(unsigned int) (*p++) << 16;
value|=(unsigned int) (*p++) << 8;
value|=(unsigned int) (*p++);
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B L o n g L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
% in most-significant byte first order.
%
% The format of the ReadBlobMSBLongLong method is:
%
% unsigned int ReadBlobMSBLongLong(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
{
const unsigned char
*p;
MagickSizeType
value;
ssize_t
count;
unsigned char
buffer[8];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
*buffer='\0';
p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
if (count != 8)
return(MagickULLConstant(0));
value=(MagickSizeType) (*p++) << 56;
value|=(MagickSizeType) (*p++) << 48;
value|=(MagickSizeType) (*p++) << 40;
value|=(MagickSizeType) (*p++) << 32;
value|=(MagickSizeType) (*p++) << 24;
value|=(MagickSizeType) (*p++) << 16;
value|=(MagickSizeType) (*p++) << 8;
value|=(MagickSizeType) (*p++);
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
% most-significant byte first order.
%
% The format of the ReadBlobMSBShort method is:
%
% unsigned short ReadBlobMSBShort(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport unsigned short ReadBlobMSBShort(Image *image)
{
const unsigned char
*p;
unsigned short
value;
ssize_t
count;
unsigned char
buffer[2];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
*buffer='\0';
p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
if (count != 2)
return((unsigned short) 0U);
value=(unsigned short) ((*p++) << 8);
value|=(unsigned short) (*p++);
return((unsigned short) (value & 0xffff));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B S i g n e d L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
% most-significant byte-order.
%
% The format of the ReadBlobMSBSignedLong method is:
%
% signed int ReadBlobMSBSignedLong(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport signed int ReadBlobMSBSignedLong(Image *image)
{
union
{
unsigned int
unsigned_value;
signed int
signed_value;
} quantum;
quantum.unsigned_value=ReadBlobMSBLong(image);
return(quantum.signed_value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B S i g n e d S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
% most-significant byte-order.
%
% The format of the ReadBlobMSBSignedShort method is:
%
% signed short ReadBlobMSBSignedShort(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport signed short ReadBlobMSBSignedShort(Image *image)
{
union
{
unsigned short
unsigned_value;
signed short
signed_value;
} quantum;
quantum.unsigned_value=ReadBlobMSBShort(image);
return(quantum.signed_value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b S i g n e d L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
% byte-order specified by the endian member of the image structure.
%
% The format of the ReadBlobSignedLong method is:
%
% signed int ReadBlobSignedLong(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport signed int ReadBlobSignedLong(Image *image)
{
union
{
unsigned int
unsigned_value;
signed int
signed_value;
} quantum;
quantum.unsigned_value=ReadBlobLong(image);
return(quantum.signed_value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b S i g n e d S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
% byte-order specified by the endian member of the image structure.
%
% The format of the ReadBlobSignedShort method is:
%
% signed short ReadBlobSignedShort(Image *image)
%
% A description of each parameter follows.
%
% o image: the image.
%
*/
MagickExport signed short ReadBlobSignedShort(Image *image)
{
union
{
unsigned short
unsigned_value;
signed short
signed_value;
} quantum;
quantum.unsigned_value=ReadBlobShort(image);
return(quantum.signed_value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b S t r e a m %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobStream() reads data from the blob or image file and returns it. It
% returns a pointer to the data buffer you supply or to the image memory
% buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
% returns a count of zero and has no other results. If length is greater than
% MAGICK_SSIZE_MAX, the result is unspecified.
%
% The format of the ReadBlobStream method is:
%
% const void *ReadBlobStream(Image *image,const size_t length,
% void *magick_restrict data,ssize_t *count)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o length: Specifies an integer representing the number of bytes to read
% from the file.
%
% o count: returns the number of bytes read.
%
% o data: Specifies an area to place the information requested from the
% file.
%
*/
MagickExport magick_hot_spot const void *ReadBlobStream(Image *image,
const size_t length,void *magick_restrict data,ssize_t *count)
{
BlobInfo
*magick_restrict blob_info;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
assert(count != (ssize_t *) NULL);
blob_info=image->blob;
if (blob_info->type != BlobStream)
{
assert(data != NULL);
*count=ReadBlob(image,length,(unsigned char *) data);
return(data);
}
if (blob_info->offset >= (MagickOffsetType) blob_info->length)
{
*count=0;
blob_info->eof=MagickTrue;
return(data);
}
data=blob_info->data+blob_info->offset;
*count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
blob_info->length-blob_info->offset);
blob_info->offset+=(*count);
if (*count != (ssize_t) length)
blob_info->eof=MagickTrue;
return(data);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b S t r i n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobString() reads characters from a blob or file until a newline
% character is read or an end-of-file condition is encountered.
%
% The format of the ReadBlobString method is:
%
% char *ReadBlobString(Image *image,char *string)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o string: the address of a character buffer.
%
*/
MagickExport char *ReadBlobString(Image *image,char *string)
{
int
c;
ssize_t
i;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
for (i=0; i < (MagickPathExtent-1L); i++)
{
c=ReadBlobByte(image);
if (c == EOF)
{
if (i == 0)
return((char *) NULL);
break;
}
string[i]=c;
if (c == '\n')
{
if ((i > 0) && (string[i-1] == '\r'))
i--;
break;
}
}
string[i]='\0';
return(string);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e f e r e n c e B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReferenceBlob() increments the reference count associated with the pixel
% blob returning a pointer to the blob.
%
% The format of the ReferenceBlob method is:
%
% BlobInfo ReferenceBlob(BlobInfo *blob_info)
%
% A description of each parameter follows:
%
% o blob_info: the blob_info.
%
*/
MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
{
assert(blob != (BlobInfo *) NULL);
assert(blob->signature == MagickCoreSignature);
if (blob->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
LockSemaphoreInfo(blob->semaphore);
blob->reference_count++;
UnlockSemaphoreInfo(blob->semaphore);
return(blob);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S e e k B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SeekBlob() sets the offset in bytes from the beginning of a blob or file
% and returns the resulting offset.
%
% The format of the SeekBlob method is:
%
% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
% const int whence)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o offset: Specifies an integer representing the offset in bytes.
%
% o whence: Specifies an integer representing how the offset is
% treated relative to the beginning of the blob as follows:
%
% SEEK_SET Set position equal to offset bytes.
% SEEK_CUR Set position to current location plus offset.
% SEEK_END Set position to EOF plus offset.
%
*/
MagickExport MagickOffsetType SeekBlob(Image *image,
const MagickOffsetType offset,const int whence)
{
BlobInfo
*magick_restrict blob_info;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
blob_info=image->blob;
switch (blob_info->type)
{
case UndefinedStream:
break;
case StandardStream:
case PipeStream:
return(-1);
case FileStream:
{
if ((offset < 0) && (whence == SEEK_SET))
return(-1);
if (fseek(blob_info->file_info.file,offset,whence) < 0)
return(-1);
blob_info->offset=TellBlob(image);
break;
}
case ZipStream:
{
#if defined(MAGICKCORE_ZLIB_DELEGATE)
if (gzseek(blob_info->file_info.gzfile,offset,whence) < 0)
return(-1);
#endif
blob_info->offset=TellBlob(image);
break;
}
case BZipStream:
return(-1);
case FifoStream:
return(-1);
case BlobStream:
{
switch (whence)
{
case SEEK_SET:
default:
{
if (offset < 0)
return(-1);
blob_info->offset=offset;
break;
}
case SEEK_CUR:
{
if (((offset > 0) && (blob_info->offset > (MAGICK_SSIZE_MAX-offset))) ||
((offset < 0) && (blob_info->offset < (MAGICK_SSIZE_MIN-offset))))
{
errno=EOVERFLOW;
return(-1);
}
if ((blob_info->offset+offset) < 0)
return(-1);
blob_info->offset+=offset;
break;
}
case SEEK_END:
{
if (((MagickOffsetType) blob_info->length+offset) < 0)
return(-1);
blob_info->offset=blob_info->length+offset;
break;
}
}
if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
{
blob_info->eof=MagickFalse;
break;
}
if (blob_info->offset >= (MagickOffsetType) ((off_t) blob_info->extent))
return(-1);
break;
}
case CustomStream:
{
if (blob_info->custom_stream->seeker == (CustomStreamSeeker) NULL)
return(-1);
blob_info->offset=blob_info->custom_stream->seeker(offset,whence,
blob_info->custom_stream->data);
break;
}
}
return(blob_info->offset);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S e t B l o b E x e m p t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetBlobExempt() sets the blob exempt status.
%
% The format of the SetBlobExempt method is:
%
% MagickBooleanType SetBlobExempt(const Image *image,
% const MagickBooleanType exempt)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o exempt: Set to true if this blob is exempt from being closed.
%
*/
MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
image->blob->exempt=exempt;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S e t B l o b E x t e n t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetBlobExtent() ensures enough space is allocated for the blob. If the
% method is successful, subsequent writes to bytes in the specified range are
% guaranteed not to fail.
%
% The format of the SetBlobExtent method is:
%
% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o extent: the blob maximum extent.
%
*/
MagickExport MagickBooleanType SetBlobExtent(Image *image,
const MagickSizeType extent)
{
BlobInfo
*magick_restrict blob_info;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
blob_info=image->blob;
switch (blob_info->type)
{
case UndefinedStream:
break;
case StandardStream:
return(MagickFalse);
case FileStream:
{
MagickOffsetType
offset;
ssize_t
count;
if (extent != (MagickSizeType) ((off_t) extent))
return(MagickFalse);
offset=SeekBlob(image,0,SEEK_END);
if (offset < 0)
return(MagickFalse);
if ((MagickSizeType) offset >= extent)
break;
offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
if (offset < 0)
break;
count=(ssize_t) fwrite((const unsigned char *) "",1,1,
blob_info->file_info.file);
#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
if (blob_info->synchronize != MagickFalse)
{
int
file;
file=fileno(blob_info->file_info.file);
if ((file == -1) || (offset < 0))
return(MagickFalse);
(void) posix_fallocate(file,offset,extent-offset);
}
#endif
offset=SeekBlob(image,offset,SEEK_SET);
if (count != 1)
return(MagickFalse);
break;
}
case PipeStream:
case ZipStream:
return(MagickFalse);
case BZipStream:
return(MagickFalse);
case FifoStream:
return(MagickFalse);
case BlobStream:
{
if (extent != (MagickSizeType) ((size_t) extent))
return(MagickFalse);
if (blob_info->mapped != MagickFalse)
{
MagickOffsetType
offset;
ssize_t
count;
(void) UnmapBlob(blob_info->data,blob_info->length);
RelinquishMagickResource(MapResource,blob_info->length);
if (extent != (MagickSizeType) ((off_t) extent))
return(MagickFalse);
offset=SeekBlob(image,0,SEEK_END);
if (offset < 0)
return(MagickFalse);
if ((MagickSizeType) offset >= extent)
break;
offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
count=(ssize_t) fwrite((const unsigned char *) "",1,1,
blob_info->file_info.file);
#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
if (blob_info->synchronize != MagickFalse)
{
int
file;
file=fileno(blob_info->file_info.file);
if ((file == -1) || (offset < 0))
return(MagickFalse);
(void) posix_fallocate(file,offset,extent-offset);
}
#endif
offset=SeekBlob(image,offset,SEEK_SET);
if (count != 1)
return(MagickFalse);
(void) AcquireMagickResource(MapResource,extent);
blob_info->data=(unsigned char*) MapBlob(fileno(
blob_info->file_info.file),WriteMode,0,(size_t) extent);
blob_info->extent=(size_t) extent;
blob_info->length=(size_t) extent;
(void) SyncBlob(image);
break;
}
blob_info->extent=(size_t) extent;
blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
blob_info->extent+1,sizeof(*blob_info->data));
(void) SyncBlob(image);
if (blob_info->data == (unsigned char *) NULL)
{
(void) DetachBlob(blob_info);
return(MagickFalse);
}
break;
}
case CustomStream:
break;
}
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S e t C u s t o m S t r e a m D a t a %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetCustomStreamData() sets the stream info data member.
%
% The format of the SetCustomStreamData method is:
%
% void SetCustomStreamData(CustomStreamInfo *custom_stream,void *)
%
% A description of each parameter follows:
%
% o custom_stream: the custom stream info.
%
% o data: an object containing information about the custom stream.
%
*/
MagickExport void SetCustomStreamData(CustomStreamInfo *custom_stream,
void *data)
{
assert(custom_stream != (CustomStreamInfo *) NULL);
assert(custom_stream->signature == MagickCoreSignature);
custom_stream->data=data;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S e t C u s t o m S t r e a m R e a d e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetCustomStreamReader() sets the stream info reader member.
%
% The format of the SetCustomStreamReader method is:
%
% void SetCustomStreamReader(CustomStreamInfo *custom_stream,
% CustomStreamHandler reader)
%
% A description of each parameter follows:
%
% o custom_stream: the custom stream info.
%
% o reader: a function to read from the stream.
%
*/
MagickExport void SetCustomStreamReader(CustomStreamInfo *custom_stream,
CustomStreamHandler reader)
{
assert(custom_stream != (CustomStreamInfo *) NULL);
assert(custom_stream->signature == MagickCoreSignature);
custom_stream->reader=reader;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S e t C u s t o m S t r e a m S e e k e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetCustomStreamSeeker() sets the stream info seeker member.
%
% The format of the SetCustomStreamReader method is:
%
% void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
% CustomStreamSeeker seeker)
%
% A description of each parameter follows:
%
% o custom_stream: the custom stream info.
%
% o seeker: a function to seek in the custom stream.
%
*/
MagickExport void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
CustomStreamSeeker seeker)
{
assert(custom_stream != (CustomStreamInfo *) NULL);
assert(custom_stream->signature == MagickCoreSignature);
custom_stream->seeker=seeker;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S e t C u s t o m S t r e a m T e l l e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetCustomStreamTeller() sets the stream info teller member.
%
% The format of the SetCustomStreamTeller method is:
%
% void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
% CustomStreamTeller *teller)
%
% A description of each parameter follows:
%
% o custom_stream: the custom stream info.
%
% o teller: a function to set the position in the stream.
%
*/
MagickExport void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
CustomStreamTeller teller)
{
assert(custom_stream != (CustomStreamInfo *) NULL);
assert(custom_stream->signature == MagickCoreSignature);
custom_stream->teller=teller;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S e t C u s t o m S t r e a m W r i t e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetCustomStreamWriter() sets the stream info writer member.
%
% The format of the SetCustomStreamWriter method is:
%
% void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
% CustomStreamHandler *writer)
%
% A description of each parameter follows:
%
% o custom_stream: the custom stream info.
%
% o writer: a function to write to the custom stream.
%
*/
MagickExport void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
CustomStreamHandler writer)
{
assert(custom_stream != (CustomStreamInfo *) NULL);
assert(custom_stream->signature == MagickCoreSignature);
custom_stream->writer=writer;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S y n c B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SyncBlob() flushes the datastream if it is a file or synchronizes the data
% attributes if it is an blob.
%
% The format of the SyncBlob method is:
%
% int SyncBlob(Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
static int SyncBlob(Image *image)
{
BlobInfo
*magick_restrict blob_info;
int
status;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
blob_info=image->blob;
status=0;
switch (blob_info->type)
{
case UndefinedStream:
case StandardStream:
break;
case FileStream:
case PipeStream:
{
status=fflush(blob_info->file_info.file);
break;
}
case ZipStream:
{
#if defined(MAGICKCORE_ZLIB_DELEGATE)
status=gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
#endif
break;
}
case BZipStream:
{
#if defined(MAGICKCORE_BZLIB_DELEGATE)
status=BZ2_bzflush(blob_info->file_info.bzfile);
#endif
break;
}
case FifoStream:
break;
case BlobStream:
break;
case CustomStream:
break;
}
return(status);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ T e l l B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% TellBlob() obtains the current value of the blob or file position.
%
% The format of the TellBlob method is:
%
% MagickOffsetType TellBlob(const Image *image)
%
% A description of each parameter follows:
%
% o image: the image.
%
*/
MagickExport MagickOffsetType TellBlob(const Image *image)
{
BlobInfo
*magick_restrict blob_info;
MagickOffsetType
offset;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
blob_info=image->blob;
offset=(-1);
switch (blob_info->type)
{
case UndefinedStream:
case StandardStream:
break;
case FileStream:
{
offset=ftell(blob_info->file_info.file);
break;
}
case PipeStream:
break;
case ZipStream:
{
#if defined(MAGICKCORE_ZLIB_DELEGATE)
offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
#endif
break;
}
case BZipStream:
break;
case FifoStream:
break;
case BlobStream:
{
offset=blob_info->offset;
break;
}
case CustomStream:
{
if (blob_info->custom_stream->teller != (CustomStreamTeller) NULL)
offset=blob_info->custom_stream->teller(blob_info->custom_stream->data);
break;
}
}
return(offset);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ U n m a p B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% UnmapBlob() deallocates the binary large object previously allocated with
% the MapBlob method.
%
% The format of the UnmapBlob method is:
%
% MagickBooleanType UnmapBlob(void *map,const size_t length)
%
% A description of each parameter follows:
%
% o map: the address of the binary large object.
%
% o length: the length of the binary large object.
%
*/
MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
{
#if defined(MAGICKCORE_HAVE_MMAP)
int
status;
status=munmap(map,length);
return(status == -1 ? MagickFalse : MagickTrue);
#else
(void) map;
(void) length;
return(MagickFalse);
#endif
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlob() writes data to a blob or image file. It returns the number of
% bytes written.
%
% The format of the WriteBlob method is:
%
% ssize_t WriteBlob(Image *image,const size_t length,const void *data)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o length: Specifies an integer representing the number of bytes to
% write to the file.
%
% o data: The address of the data to write to the blob or file.
%
*/
MagickExport ssize_t WriteBlob(Image *image,const size_t length,
const void *data)
{
BlobInfo
*magick_restrict blob_info;
int
c;
const unsigned char
*p;
unsigned char
*q;
ssize_t
count;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
if (length == 0)
return(0);
assert(data != (const void *) NULL);
blob_info=image->blob;
count=0;
p=(const unsigned char *) data;
q=(unsigned char *) data;
switch (blob_info->type)
{
case UndefinedStream:
break;
case StandardStream:
case FileStream:
case PipeStream:
{
switch (length)
{
default:
{
count=(ssize_t) fwrite((const char *) data,1,length,
blob_info->file_info.file);
break;
}
case 4:
{
c=putc((int) *p++,blob_info->file_info.file);
if (c == EOF)
break;
count++;
}
case 3:
{
c=putc((int) *p++,blob_info->file_info.file);
if (c == EOF)
break;
count++;
}
case 2:
{
c=putc((int) *p++,blob_info->file_info.file);
if (c == EOF)
break;
count++;
}
case 1:
{
c=putc((int) *p++,blob_info->file_info.file);
if (c == EOF)
break;
count++;
}
case 0:
break;
}
if ((count != (ssize_t) length) &&
(ferror(blob_info->file_info.file) != 0))
ThrowBlobException(blob_info);
break;
}
case ZipStream:
{
#if defined(MAGICKCORE_ZLIB_DELEGATE)
int
status;
switch (length)
{
default:
{
ssize_t
i;
for (i=0; i < (ssize_t) length; i+=count)
{
count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
(unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
}
count=i;
break;
}
case 4:
{
c=gzputc(blob_info->file_info.gzfile,(int) *p++);
if (c == EOF)
break;
count++;
}
case 3:
{
c=gzputc(blob_info->file_info.gzfile,(int) *p++);
if (c == EOF)
break;
count++;
}
case 2:
{
c=gzputc(blob_info->file_info.gzfile,(int) *p++);
if (c == EOF)
break;
count++;
}
case 1:
{
c=gzputc(blob_info->file_info.gzfile,(int) *p++);
if (c == EOF)
break;
count++;
}
case 0:
break;
}
status=Z_OK;
(void) gzerror(blob_info->file_info.gzfile,&status);
if ((count != (ssize_t) length) && (status != Z_OK))
ThrowBlobException(blob_info);
#endif
break;
}
case BZipStream:
{
#if defined(MAGICKCORE_BZLIB_DELEGATE)
int
status;
ssize_t
i;
for (i=0; i < (ssize_t) length; i+=count)
{
count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
(int) MagickMin(length-i,MagickMaxBufferExtent));
if (count <= 0)
{
count=0;
if (errno != EINTR)
break;
}
}
count=i;
status=BZ_OK;
(void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
if ((count != (ssize_t) length) && (status != BZ_OK))
ThrowBlobException(blob_info);
#endif
break;
}
case FifoStream:
{
count=(ssize_t) blob_info->stream(image,data,length);
break;
}
case BlobStream:
{
if ((blob_info->offset+(MagickOffsetType) length) >=
(MagickOffsetType) blob_info->extent)
{
if (blob_info->mapped != MagickFalse)
return(0);
blob_info->extent+=length+blob_info->quantum;
blob_info->quantum<<=1;
blob_info->data=(unsigned char *) ResizeQuantumMemory(
blob_info->data,blob_info->extent+1,sizeof(*blob_info->data));
(void) SyncBlob(image);
if (blob_info->data == (unsigned char *) NULL)
{
(void) DetachBlob(blob_info);
return(0);
}
}
q=blob_info->data+blob_info->offset;
(void) memcpy(q,p,length);
blob_info->offset+=length;
if (blob_info->offset >= (MagickOffsetType) blob_info->length)
blob_info->length=(size_t) blob_info->offset;
count=(ssize_t) length;
break;
}
case CustomStream:
{
if (blob_info->custom_stream->writer != (CustomStreamHandler) NULL)
count=blob_info->custom_stream->writer((unsigned char *) data,
length,blob_info->custom_stream->data);
break;
}
}
return(count);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b B y t e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobByte() write an integer to a blob. It returns the number of bytes
% written (either 0 or 1);
%
% The format of the WriteBlobByte method is:
%
% ssize_t WriteBlobByte(Image *image,const unsigned char value)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o value: Specifies the value to write.
%
*/
MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
{
BlobInfo
*magick_restrict blob_info;
ssize_t
count;
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
blob_info=image->blob;
count=0;
switch (blob_info->type)
{
case StandardStream:
case FileStream:
case PipeStream:
{
int
c;
c=putc((int) value,blob_info->file_info.file);
if (c == EOF)
{
if (ferror(blob_info->file_info.file) != 0)
ThrowBlobException(blob_info);
break;
}
count++;
break;
}
default:
{
count=WriteBlobStream(image,1,&value);
break;
}
}
return(count);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b F l o a t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
% specified by the endian member of the image structure.
%
% The format of the WriteBlobFloat method is:
%
% ssize_t WriteBlobFloat(Image *image,const float value)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o value: Specifies the value to write.
%
*/
MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
{
union
{
unsigned int
unsigned_value;
float
float_value;
} quantum;
quantum.unsigned_value=0U;
quantum.float_value=value;
return(WriteBlobLong(image,quantum.unsigned_value));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
% byte-order specified by the endian member of the image structure.
%
% The format of the WriteBlobLong method is:
%
% ssize_t WriteBlobLong(Image *image,const unsigned int value)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o value: Specifies the value to write.
%
*/
MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
{
unsigned char
buffer[4];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->endian == LSBEndian)
{
buffer[0]=(unsigned char) value;
buffer[1]=(unsigned char) (value >> 8);
buffer[2]=(unsigned char) (value >> 16);
buffer[3]=(unsigned char) (value >> 24);
return(WriteBlobStream(image,4,buffer));
}
buffer[0]=(unsigned char) (value >> 24);
buffer[1]=(unsigned char) (value >> 16);
buffer[2]=(unsigned char) (value >> 8);
buffer[3]=(unsigned char) value;
return(WriteBlobStream(image,4,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b L o n g L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in the
% byte-order specified by the endian member of the image structure.
%
% The format of the WriteBlobLongLong method is:
%
% ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
%
% A description of each parameter follows.
%
% o value: Specifies the value to write.
%
% o image: the image.
%
*/
MagickExport ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
{
unsigned char
buffer[8];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->endian == LSBEndian)
{
buffer[0]=(unsigned char) value;
buffer[1]=(unsigned char) (value >> 8);
buffer[2]=(unsigned char) (value >> 16);
buffer[3]=(unsigned char) (value >> 24);
buffer[4]=(unsigned char) (value >> 32);
buffer[5]=(unsigned char) (value >> 40);
buffer[6]=(unsigned char) (value >> 48);
buffer[7]=(unsigned char) (value >> 56);
return(WriteBlobStream(image,8,buffer));
}
buffer[0]=(unsigned char) (value >> 56);
buffer[1]=(unsigned char) (value >> 48);
buffer[2]=(unsigned char) (value >> 40);
buffer[3]=(unsigned char) (value >> 32);
buffer[4]=(unsigned char) (value >> 24);
buffer[5]=(unsigned char) (value >> 16);
buffer[6]=(unsigned char) (value >> 8);
buffer[7]=(unsigned char) value;
return(WriteBlobStream(image,8,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobShort() writes a short value as a 16-bit quantity in the
% byte-order specified by the endian member of the image structure.
%
% The format of the WriteBlobShort method is:
%
% ssize_t WriteBlobShort(Image *image,const unsigned short value)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o value: Specifies the value to write.
%
*/
MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
{
unsigned char
buffer[2];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
if (image->endian == LSBEndian)
{
buffer[0]=(unsigned char) value;
buffer[1]=(unsigned char) (value >> 8);
return(WriteBlobStream(image,2,buffer));
}
buffer[0]=(unsigned char) (value >> 8);
buffer[1]=(unsigned char) value;
return(WriteBlobStream(image,2,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b S i g n e d L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobSignedLong() writes a signed value as a 32-bit quantity in the
% byte-order specified by the endian member of the image structure.
%
% The format of the WriteBlobSignedLong method is:
%
% ssize_t WriteBlobSignedLong(Image *image,const signed int value)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o value: Specifies the value to write.
%
*/
MagickExport ssize_t WriteBlobSignedLong(Image *image,const signed int value)
{
union
{
unsigned int
unsigned_value;
signed int
signed_value;
} quantum;
unsigned char
buffer[4];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
quantum.signed_value=value;
if (image->endian == LSBEndian)
{
buffer[0]=(unsigned char) quantum.unsigned_value;
buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
return(WriteBlobStream(image,4,buffer));
}
buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
buffer[3]=(unsigned char) quantum.unsigned_value;
return(WriteBlobStream(image,4,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b L S B L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
% least-significant byte first order.
%
% The format of the WriteBlobLSBLong method is:
%
% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o value: Specifies the value to write.
%
*/
MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
{
unsigned char
buffer[4];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
buffer[0]=(unsigned char) value;
buffer[1]=(unsigned char) (value >> 8);
buffer[2]=(unsigned char) (value >> 16);
buffer[3]=(unsigned char) (value >> 24);
return(WriteBlobStream(image,4,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b L S B S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
% least-significant byte first order.
%
% The format of the WriteBlobLSBShort method is:
%
% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o value: Specifies the value to write.
%
*/
MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
{
unsigned char
buffer[2];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
buffer[0]=(unsigned char) value;
buffer[1]=(unsigned char) (value >> 8);
return(WriteBlobStream(image,2,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b L S B S i g n e d L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
% least-significant byte first order.
%
% The format of the WriteBlobLSBSignedLong method is:
%
% ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o value: Specifies the value to write.
%
*/
MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
{
union
{
unsigned int
unsigned_value;
signed int
signed_value;
} quantum;
unsigned char
buffer[4];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
quantum.signed_value=value;
buffer[0]=(unsigned char) quantum.unsigned_value;
buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
return(WriteBlobStream(image,4,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b L S B S i g n e d S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
% in least-significant byte first order.
%
% The format of the WriteBlobLSBSignedShort method is:
%
% ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o value: Specifies the value to write.
%
*/
MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
const signed short value)
{
union
{
unsigned short
unsigned_value;
signed short
signed_value;
} quantum;
unsigned char
buffer[2];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
quantum.signed_value=value;
buffer[0]=(unsigned char) quantum.unsigned_value;
buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
return(WriteBlobStream(image,2,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b M S B L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
% most-significant byte first order.
%
% The format of the WriteBlobMSBLong method is:
%
% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
%
% A description of each parameter follows.
%
% o value: Specifies the value to write.
%
% o image: the image.
%
*/
MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
{
unsigned char
buffer[4];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
buffer[0]=(unsigned char) (value >> 24);
buffer[1]=(unsigned char) (value >> 16);
buffer[2]=(unsigned char) (value >> 8);
buffer[3]=(unsigned char) value;
return(WriteBlobStream(image,4,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b M S B S i g n e d S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
% in most-significant byte first order.
%
% The format of the WriteBlobMSBSignedShort method is:
%
% ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o value: Specifies the value to write.
%
*/
MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
const signed short value)
{
union
{
unsigned short
unsigned_value;
signed short
signed_value;
} quantum;
unsigned char
buffer[2];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
quantum.signed_value=value;
buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
buffer[1]=(unsigned char) quantum.unsigned_value;
return(WriteBlobStream(image,2,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b M S B S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
% most-significant byte first order.
%
% The format of the WriteBlobMSBShort method is:
%
% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
%
% A description of each parameter follows.
%
% o value: Specifies the value to write.
%
% o file: Specifies the file to write the data to.
%
*/
MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
{
unsigned char
buffer[2];
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
buffer[0]=(unsigned char) (value >> 8);
buffer[1]=(unsigned char) value;
return(WriteBlobStream(image,2,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b S t r i n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobString() write a string to a blob. It returns the number of
% characters written.
%
% The format of the WriteBlobString method is:
%
% ssize_t WriteBlobString(Image *image,const char *string)
%
% A description of each parameter follows.
%
% o image: the image.
%
% o string: Specifies the string to write.
%
*/
MagickExport ssize_t WriteBlobString(Image *image,const char *string)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickCoreSignature);
assert(string != (const char *) NULL);
return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
}