/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- BlobStreamTypeToString
- ReadBlobStream
- ExtendBlobWriteStream
- WriteBlobStream
- AttachBlob
- BlobIsSeekable
- BlobReserveSize
- BlobToFile
- BlobToImage
- CloneBlobInfo
- CloseBlob
- DestroyBlob
- DestroyBlobInfo
- DetachBlob
- EOFBlob
- FileToBlob
- GetBlobFileHandle
- GetBlobInfo
- GetBlobSize
- GetBlobStatus
- GetBlobStreamData
- GetBlobTemporary
- ChopPathComponents
- AddConfigurePath
- GetConfigureBlob
- ImageToBlob
- ImageToFile
- MapBlob
- MSBOrderLong
- MSBOrderShort
- FormMultiPartFilename
- OpenBlob
- PingBlob
- ReadBlob
- ReadBlobZC
- ReadBlobByte
- ReadBlobLSBDouble
- ReadBlobLSBDoubles
- ReadBlobLSBLong
- ReadBlobLSBLongs
- ReadBlobLSBShort
- ReadBlobLSBFloat
- ReadBlobLSBFloats
- ReadBlobMSBFloat
- ReadBlobMSBFloats
- ReadBlobMSBDouble
- ReadBlobMSBDoubles
- ReadBlobMSBLong
- ReadBlobMSBShort
- ReadBlobMSBShorts
- ReadBlobString
- ReferenceBlob
- SeekBlob
- SetBlobClosable
- SetBlobTemporary
- SyncBlob
- TellBlob
- UnmapBlob
- WriteBlob
- WriteBlobByte
- WriteBlobFile
- WriteBlobLSBLong
- WriteBlobLSBShort
- ReadBlobLSBShorts
- WriteBlobMSBLong
- ReadBlobMSBLongs
- WriteBlobMSBShort
- WriteBlobString
/*
% Copyright (C) 2003 - 2010 GraphicsMagick Group
% Copyright (C) 2002 ImageMagick Studio
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
%
% This program is covered by multiple licenses, which are described in
% Copyright.txt. You should have received a copy of Copyright.txt with this
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% 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 %
% %
% %
% GraphicsMagick Binary Large OBject Methods %
% %
% %
% Software Design %
% John Cristy %
% July 1999 %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
%
*/
/*
Include declarations.
*/
#include "magick/studio.h"
#if defined(MSWINDOWS) || defined(__CYGWIN__)
# include "magick/nt_feature.h"
#endif
#include "magick/blob.h"
#include "magick/confirm_access.h"
#include "magick/constitute.h"
#include "magick/delegate.h"
#include "magick/enum_strings.h"
#include "magick/log.h"
#include "magick/map.h"
#include "magick/magick.h"
#include "magick/magick_endian.h"
#include "magick/module.h"
#include "magick/pixel_cache.h"
#include "magick/resource.h"
#include "magick/semaphore.h"
#include "magick/tempfile.h"
#include "magick/utility.h"
#if defined(HasZLIB)
# include "zlib.h"
#endif
#if defined(HasBZLIB)
# include "bzlib.h"
#endif
/*
Define declarations.
*/
#define DefaultBlobQuantum 65541
/*
Enum declarations.
*/
typedef enum
{
UndefinedStream, /* Closed or open error */
FileStream, /* Opened with stdio fopen() or via image_info->file */
StandardStream, /* Stdin or stdout (filename "-") */
PipeStream, /* Command pipe stream opened via popen() */
ZipStream, /* Opened with zlib's gzopen() */
BZipStream, /* Opened with bzlib's BZ2_bzopen() */
BlobStream /* Memory mapped, or in allocated RAM */
} StreamType;
/*
Typedef declarations.
*/
struct _BlobInfo
{
size_t
length, /* The current size of the BLOB data. */
extent, /* The amount of backing store currently allocated */
quantum; /* The amount by which to increase the size of the backing store */
unsigned int
mapped, /* True if backing store is a memory mapped file. */
eof; /* True if input data has been entirely read. */
magick_off_t
offset, /* Current offset (I/O point) as would be returned by TellBlob() */
size; /* Size of the underlying file, or the BLOB */
unsigned int
exempt, /* True if file descriptor should not be closed.*/
status, /* Error status. 0 == good */
temporary; /* Associated file is a temporary file */
StreamType
type; /* Classification for how BLOB I/O is implemented. */
FILE
*file; /* File handle for I/O (if any) */
BlobMode
mode; /* Blob open mode */
unsigned char
*data; /* Blob or memory mapped data. */
MagickBool
fsync; /* Fsync on close if true */
SemaphoreInfo
*semaphore; /* Lock for reference_count access */
long
reference_count; /* Number of times this blob is referenced. */
unsigned long
signature; /* Numeric value used to evaluate structure integrity. */
};
/*
Forward Declarations
*/
static int SyncBlob(Image *image);
/*
Some systems have unlocked versions of getc & putc which are faster
when multi-threading is enabled. Blobs do not require multi-thread
support since Images are only allowed to be accessed by one thread at
a time. Using the unlocked version improves performance by about 30%.
*/
#if defined(HAVE_PTHREAD)
# if defined(HAVE_GETC_UNLOCKED)
# undef getc
# define getc getc_unlocked
# endif
# if defined(HAVE_PUTC_UNLOCKED)
# undef putc
# define putc putc_unlocked
# endif
#endif
static const char *BlobStreamTypeToString(StreamType stream_type)
{
const char
*type_string="Undefined";
switch (stream_type)
{
case UndefinedStream:
type_string="Undefined";
break;
case FileStream:
type_string="File";
break;
case StandardStream:
type_string="Standard";
break;
case PipeStream:
type_string="Pipe";
break;
case ZipStream:
type_string="Zip";
break;
case BZipStream:
type_string="BZip";
break;
case BlobStream:
type_string="Blob";
break;
}
return type_string;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b S t r e a m %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobStream() allocates the requested data size, or the amount
% remaining (whichever is smaller) from a BlobStream. This function
% should only be invoked for Blobs of type 'BlobStream'. The number of
% bytes available from the requested length is returned. If fewer bytes
% are available than requested, the Blob EOF flag is set True. A user
% provided pointer is updated with the address of the data. This pointer
% is only valid while the BlobStream remains mapped or allocated.
%
% The format of the ReadBlobStream method is:
%
% size_t ReadBlobStream(Image *image,const size_t length,void **data)
%
% A description of each parameter follows:
%
% o image: The image.
%
% o length: The requested amount of data.
%
% o data: A pointer to where the address of the data should be returned.
%
*/
static inline size_t ReadBlobStream(Image *image,const size_t length,
void **data)
{
size_t
available;
if (image->blob->offset >= (magick_off_t) image->blob->length)
{
image->blob->eof=MagickTrue;
return 0;
}
*data=(void *)(image->blob->data+image->blob->offset);
available=Min(length,image->blob->length-image->blob->offset);
image->blob->offset+=available;
if (available < length)
image->blob->eof=True;
return available;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b S t r e a m %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WriteBlobStream() writes data to an in-memory Blob This function
% should only be invoked for Blobs of type 'BlobStream'. The number of
% bytes written is returned.
%
% The format of the WriteBlobStream method is:
%
% size_t WriteBlobStream(Image *image,const size_t length,
% const void *data)
%
% A description of each parameter follows:
%
% o image: The image.
%
% o length: The requested amount of data.
%
% o data: A pointer to where the data resides.
%
*/
static void *ExtendBlobWriteStream(Image *image,const size_t length)
{
if ((image->blob->offset+length) >= image->blob->extent)
{
if ((image->blob->mapped) && (image->blob->file != (FILE *) NULL))
{
/* Memory mapped file */
int
filedes;
size_t
extent,
quantum;
unsigned char
*data;
image->blob->data=0;
filedes=fileno(image->blob->file);
quantum=image->blob->quantum;
quantum<<=1;
extent=image->blob->extent;
extent+=length+quantum;
if ((ftruncate(filedes,extent) == 0) &&
((data=(unsigned char*) MapBlob(filedes,WriteMode,0,extent)) != 0))
{
image->blob->quantum=quantum;
image->blob->extent=extent;
image->blob->data=data;
(void) SyncBlob(image);
}
}
else
{
/* In-memory Blob */
image->blob->quantum<<=1;
image->blob->extent+=length+image->blob->quantum;
MagickReallocMemory(unsigned char *,image->blob->data,image->blob->extent+1);
(void) SyncBlob(image);
}
if (image->blob->data == (unsigned char *) NULL)
{
DetachBlob(image->blob);
return 0;
}
}
return image->blob->data+image->blob->offset;
}
static inline size_t WriteBlobStream(Image *image,const size_t length,
const void *data)
{
void
*dest;
dest=image->blob->data+image->blob->offset;
if ((image->blob->offset+length) >= image->blob->extent)
if ((dest=ExtendBlobWriteStream(image,length)) == (void *) NULL)
return 0;
(void) memcpy(dest,data,length);
image->blob->offset+=length;
if (image->blob->offset > (magick_off_t) image->blob->length)
image->blob->length=image->blob->offset;
return length;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% 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 GraphicsMagick.
%
% 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);
blob_info->length=length;
blob_info->extent=length;
blob_info->quantum=DefaultBlobQuantum;
blob_info->offset=0;
blob_info->type=BlobStream;
blob_info->file=(FILE *) NULL;
blob_info->data=(unsigned char *) blob;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% B l o b I s S e e k a b l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% BlobIsSeekable() returns MagickTrue if the blob supports seeks
% (SeekBlob() is functional).
%
% The format of the BlobIsSeekable method is:
%
% MagickBool BlobIsSeekable(const Image *image)
%
% A description of each parameter follows:
%
% o image: Image to query
%
%
*/
MagickExport MagickBool BlobIsSeekable(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->blob != (const BlobInfo *) NULL);
return ((image->blob->type == FileStream) ||
(image->blob->type == BlobStream));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% B l o b R e s e r v e S i z e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% BlobReserveSize() sets the output size of the blob or file. This is used
% as a means to minimize memory or filesystem fragmentation if the final
% output size is known in advance. While it is possible that file
% fragmentation is reduced, it is also possible that file write
% performance is reduced by changing a write operation to a read, modify,
% write operation.
%
% The format of the BlobReserveSize method is:
%
% MagickPassFail BlobReserveSize(Image *image, magick_off_t size)
%
% A description of each parameter follows:
%
% o image: Image to update
%
% o size: New output size.
%
*/
MagickExport MagickPassFail BlobReserveSize(Image *image, magick_off_t size)
{
MagickPassFail
status;
status=MagickPass;
if ((FileStream == image->blob->type) ||
((BlobStream == image->blob->type) &&
(image->blob->mapped) && (image->blob->file != (FILE *) NULL)))
{
#if defined(HAVE_POSIX_FALLOCATE)
int
err_status;
if ((err_status=posix_fallocate(fileno(image->blob->file),
0UL, size)) != 0)
{
ThrowException(&image->exception,BlobError,UnableToWriteBlob,strerror(err_status));
status=MagickFail;
}
#endif /* HAVE_POSIX_FALLOCATE */
}
#if 0
if (FileStream == image->blob->type)
{
/*
File I/O
Should use posix_fallocate()
#include <fcntl.h>
int posix_fallocate(int fd, off_t offset, off_t len);
or
Linux fallocate()
#include <linux/falloc.h>
long fallocate(int fd, int mode, loff_t offset, loff_t len);
*/
if (ftruncate(fileno(image->blob->file),size) != 0)
{
ThrowException(&image->exception,BlobError,UnableToWriteBlob,strerror(errno));
status=MagickFail;
}
}
#endif
if (BlobStream == image->blob->type)
{
if ((image->blob->mapped) && (image->blob->file != (FILE *) NULL))
{
/*
Memory mapped file I/O
*/
int
filedes;
size_t
extent;
unsigned char
*data;
image->blob->data=0;
filedes=fileno(image->blob->file);
extent=size;
/*
Truncate to new size.
*/
if (ftruncate(filedes,extent) != 0)
{
ThrowException(&image->exception,BlobError,UnableToWriteBlob,strerror(errno));
status=MagickFail;
}
if (status != MagickFail)
{
/*
Extend memory mapping.
*/
if ((data=(unsigned char*) MapBlob(filedes,WriteMode,0,extent)) != 0)
{
image->blob->extent=extent;
image->blob->data=data;
(void) SyncBlob(image);
}
else
{
ThrowException(&image->exception,BlobError,UnableToWriteBlob,strerror(errno));
}
}
if (status == MagickFail)
{
DetachBlob(image->blob);
}
}
else
{
/*
In-memory blob
*/
image->blob->extent=size;
MagickReallocMemory(unsigned char *,image->blob->data,image->blob->extent+1);
(void) SyncBlob(image);
if (image->blob->data == (unsigned char *) NULL)
{
ThrowException(&image->exception,ResourceLimitError,MemoryAllocationFailed,
NULL);
DetachBlob(image->blob);
status=MagickFail;
}
}
}
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Request to reserve %" MAGICK_OFF_F "u output bytes %s",
size,
(status == MagickFail ? "failed" : "succeeded"));
return status;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% B l o b T o F i l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% BlobToFile() writes a blob to a file. It returns MagickFail if an error
% occurs otherwise MagickPass.
%
% The format of the BlobToFile method is:
%
% MagickPassFail BlobToFile(const char *filename,const void *blob,
% const size_t length,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o status: BlobToFile returns MagickPass on success; otherwise, it
% returns MagickFail if an error occurs.
%
% 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 MagickPassFail BlobToFile(const char *filename,const void *blob,
const size_t length,ExceptionInfo *exception)
{
ssize_t
count;
int
file;
register size_t
i;
assert(filename != (const char *) NULL);
assert(blob != (const void *) NULL);
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Copying memory BLOB to file %s\n",filename);
if (MagickConfirmAccess(FileWriteConfirmAccessMode,filename,exception)
== MagickFail)
return MagickFail;
file=open(filename,O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,0777);
if (file == -1)
{
ThrowException(exception,BlobError,UnableToWriteBlob,filename);
return(MagickFail);
}
for (i=0; i < length; i+=count)
{
count=write(file,(char *) blob+i,length-i);
if (count <= 0)
break;
}
(void) close(file);
if (i < length)
{
ThrowException(exception,BlobError,UnableToWriteBlob,filename);
return(MagickFail);
}
return(MagickPass);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% 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 GraphicsMagick.
%
% 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
*clone_info;
unsigned int
status;
assert(image_info != (ImageInfo *) NULL);
assert(image_info->signature == MagickSignature);
assert(exception != (ExceptionInfo *) NULL);
(void) LogMagickEvent(BlobEvent,GetMagickModule(), "Entering BlobToImage");
/* SetExceptionInfo(exception,UndefinedException); */
if ((blob == (const void *) NULL) || (length == 0))
{
ThrowException(exception,OptionError,NullBlobArgument,
image_info->magick);
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Leaving BlobToImage");
return((Image *) NULL);
}
clone_info=CloneImageInfo(image_info);
clone_info->blob=(void *) blob;
clone_info->length=length;
if (clone_info->magick[0] == '\0')
(void) SetImageInfo(clone_info,SETMAGICK_READ,exception);
magick_info=GetMagickInfo(clone_info->magick,exception);
if (magick_info == (const MagickInfo *) NULL)
{
DestroyImageInfo(clone_info);
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Leaving BlobToImage");
return((Image *) NULL);
}
if (magick_info->blob_support)
{
/*
Native blob support for this image format.
*/
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Using native BLOB support");
(void) strlcpy(clone_info->filename,image_info->filename,
MaxTextExtent);
(void) strlcpy(clone_info->magick,image_info->magick,MaxTextExtent);
image=ReadImage(clone_info,exception);
if (image != (Image *) NULL)
DetachBlob(image->blob);
DestroyImageInfo(clone_info);
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Leaving BlobToImage");
return(image);
}
/*
Write blob to a temporary file on disk.
*/
clone_info->blob=(void *) NULL;
clone_info->length=0;
if(!AcquireTemporaryFileName(clone_info->filename))
{
ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,
clone_info->filename);
DestroyImageInfo(clone_info);
return((Image *) NULL);
}
status=BlobToFile(clone_info->filename,blob,length,exception);
if (status == MagickFail)
{
DestroyImageInfo(clone_info);
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Leaving BlobToImage");
return((Image *) NULL);
}
image=ReadImage(clone_info,exception);
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Removing temporary file \"%s\"\n",clone_info->filename);
(void) LiberateTemporaryFile(clone_info->filename);
DestroyImageInfo(clone_info);
(void) LogMagickEvent(BlobEvent,GetMagickModule(), "Leaving BlobToImage");
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 clone_info: Method CloneBlobInfo returns a duplicate of the given
% blob info, or if blob info is NULL a new one.
%
% o quantize_info: a structure of type info.
%
%
*/
MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
{
BlobInfo
*clone_info;
clone_info=MagickAllocateMemory(BlobInfo *,sizeof(BlobInfo));
if (clone_info == (BlobInfo *) NULL)
MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
UnableToCloneBlobInfo);
GetBlobInfo(clone_info);
if (blob_info == (BlobInfo *) NULL)
return(clone_info);
clone_info->length=blob_info->length;
clone_info->extent=blob_info->extent;
clone_info->quantum=blob_info->quantum;
clone_info->mapped=blob_info->mapped;
clone_info->eof=blob_info->eof;
clone_info->offset=blob_info->offset;
clone_info->size=blob_info->size;
clone_info->exempt=blob_info->exempt;
clone_info->status=blob_info->status;
clone_info->temporary=blob_info->temporary;
clone_info->type=blob_info->type;
clone_info->file=blob_info->file;
clone_info->data=blob_info->data;
clone_info->reference_count=1;
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:
%
% void CloseBlob(Image *image)
%
% A description of each parameter follows:
%
% o image: The image.
%
%
*/
MagickExport void CloseBlob(Image *image)
{
int
status;
/*
Close image file.
*/
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
/*
If blob was not allocated, or blob type is UndefinedStream then it
doesn't need to be closed.
*/
if ((image->blob == (BlobInfo *) NULL) ||
(image->blob->type == UndefinedStream))
return;
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Closing %sStream blob %p",
BlobStreamTypeToString(image->blob->type),
&image->blob);
status=0;
switch (image->blob->type)
{
case UndefinedStream:
break;
case FileStream:
case StandardStream:
case PipeStream:
{
status=ferror(image->blob->file);
break;
}
case ZipStream:
{
#if defined(HasZLIB)
(void) gzerror(image->blob->file,&status);
#endif
break;
}
case BZipStream:
{
#if defined(HasBZLIB)
(void) BZ2_bzerror(image->blob->file,&status);
#endif
break;
}
case BlobStream:
break;
}
errno=0;
image->taint=False;
image->blob->size=GetBlobSize(image);
image->blob->eof=False;
image->blob->status=status < 0;
image->blob->mode=UndefinedBlobMode;
if (image->blob->exempt)
return;
switch (image->blob->type)
{
case UndefinedStream:
break;
case FileStream:
case StandardStream:
{
if (image->blob->fsync)
{
(void) fflush(image->blob->file);
(void) fsync(fileno(image->blob->file));
}
status=fclose(image->blob->file);
break;
}
case PipeStream:
{
#if defined(HAVE_PCLOSE)
status=pclose(image->blob->file);
#endif /* defined(HAVE_PCLOSE) */
break;
}
case ZipStream:
{
#if defined(HasZLIB)
status=gzclose(image->blob->file);
#endif
break;
}
case BZipStream:
{
#if defined(HasBZLIB)
BZ2_bzclose(image->blob->file);
#endif
break;
}
case BlobStream:
{
if (image->blob->file != (FILE *) NULL)
{
/*
Truncate memory-mapped output file to size.
*/
(void) ftruncate(fileno(image->blob->file),image->blob->length);
if (image->blob->fsync)
(void) fsync(fileno(image->blob->file));
status=fclose(image->blob->file);
}
break;
}
}
DetachBlob(image->blob);
image->blob->status=status < 0;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% D e s t r o y B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DestroyBlob() deallocates memory associated with a blob. The blob is
% a reference counted object so the object is only destroyed once its
% reference count decreases to zero.
%
% 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)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
if (image->blob != (BlobInfo *) NULL)
{
MagickBool
destroy;
assert(image->blob->signature == MagickSignature);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Destroy blob, image=%p, filename=\"%s\"",
image,image->filename);
LockSemaphoreInfo(image->blob->semaphore);
image->blob->reference_count--;
assert(image->blob->reference_count >= 0);
destroy=(image->blob->reference_count > 0 ? MagickFalse : MagickTrue);
UnlockSemaphoreInfo(image->blob->semaphore);
if (destroy)
{
/*
Destroy blob object.
*/
if (image->blob->type != UndefinedStream)
CloseBlob(image);
if (image->blob->mapped)
(void) UnmapBlob(image->blob->data,image->blob->length);
DestroySemaphoreInfo(&image->blob->semaphore);
(void) memset((void *) image->blob,0xbf,sizeof(BlobInfo));
MagickFreeMemory(image->blob);
}
image->blob=(BlobInfo *) NULL;
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% D e s t r o y B l o b I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DestroyBlobInfo() deallocates memory associated with an BlobInfo structure.
% The blob is a reference counted object so the object is only destroyed once
% its reference count decreases to zero. Use of DestroyBlob is preferred over
% this function since it assures that the blob is closed prior to destruction.
%
% This function is no longer used within GraphicsMagick.
%
% The format of the DestroyBlobInfo method is:
%
% void DestroyBlobInfo(BlobInfo *blob)
%
% A description of each parameter follows:
%
% o blob: Specifies a pointer to a BlobInfo structure.
%
%
*/
MagickExport void DestroyBlobInfo(BlobInfo *blob)
{
if (blob != (BlobInfo *) NULL)
{
MagickBool
destroy;
assert(blob->signature == MagickSignature);
LockSemaphoreInfo(blob->semaphore);
blob->reference_count--;
assert(blob->reference_count >= 0);
destroy=(blob->reference_count > 0 ? MagickFalse : MagickTrue);
UnlockSemaphoreInfo(blob->semaphore);
if (destroy)
{
if (blob->mapped)
(void) UnmapBlob(blob->data,blob->length);
DestroySemaphoreInfo(&blob->semaphore);
(void) memset((void *)blob,0xbf,sizeof(BlobInfo));
MagickFreeMemory(blob);
}
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% 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)
{
assert(blob_info != (BlobInfo *) NULL);
if (blob_info->mapped)
{
(void) UnmapBlob(blob_info->data,blob_info->length);
LiberateMagickResource(MapResource,blob_info->length);
}
blob_info->mapped=False;
blob_info->length=0;
blob_info->offset=0;
blob_info->eof=False;
blob_info->exempt=False;
blob_info->type=UndefinedStream;
blob_info->file=(FILE *) NULL;
blob_info->data=(unsigned char *) NULL;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ 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 status: Method EOFBlob returns 0 on success; otherwise, it
% returns -1 and set errno to indicate the error.
%
% o image: The image.
%
%
*/
MagickExport int EOFBlob(const Image *image)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
switch (image->blob->type)
{
case UndefinedStream:
break;
case FileStream:
case StandardStream:
case PipeStream:
{
image->blob->eof=feof(image->blob->file);
break;
}
case ZipStream:
{
image->blob->eof=False;
break;
}
case BZipStream:
{
#if defined(HasBZLIB)
int
status;
(void) BZ2_bzerror(image->blob->file,&status);
image->blob->eof=status == BZ_UNEXPECTED_EOF;
#endif
break;
}
case BlobStream:
break;
}
return(image->blob->eof);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% F i l e T o B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FileToBlob() returns the contents of a file as a blob. It returns the
% file as a blob and its length. If an error occurs, NULL is returned.
%
% The format of the FileToBlob method is:
%
% void *FileToBlob(const char *filename,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 length: This pointer to a size_t integer sets the initial length of the
% blob. On return, it reflects the actual length of the blob.
%
% o exception: Return any errors or warnings in this structure.
%
%
*/
MagickExport void *FileToBlob(const char *filename,size_t *length,
ExceptionInfo *exception)
{
magick_off_t
offset;
int
file;
unsigned char
*blob;
ssize_t
count;
register size_t
i;
assert(filename != (const char *) NULL);
assert(exception != (ExceptionInfo *) NULL);
/* SetExceptionInfo(exception,UndefinedException); */
if (MagickConfirmAccess(FileReadConfirmAccessMode,filename,exception)
== MagickFail)
return MagickFail;
file=open(filename,O_RDONLY | O_BINARY,0777);
if (file == -1)
{
ThrowException(exception,BlobError,UnableToOpenFile,filename);
return((void *) NULL);
}
offset=MagickSeek(file,0,SEEK_END);
if ((offset < 0) || (offset != (magick_off_t) ((size_t) offset)))
{
(void) close(file);
ThrowException3(exception,BlobError,UnableToSeekToOffset,
UnableToCreateBlob);
return((void *) NULL);
}
*length=(size_t) offset;
blob=MagickAllocateMemory(unsigned char *,*length+1);
if (blob == (unsigned char *) NULL)
{
(void) close(file);
ThrowException(exception,ResourceLimitError,MemoryAllocationFailed,
MagickMsg(BlobError,UnableToCreateBlob));
return((void *) NULL);
}
(void) MagickSeek(file,0,SEEK_SET);
for (i=0; i < *length; i+=count)
{
count=read(file,blob+i,*length-i);
if (count <= 0)
break;
}
if (i < *length)
{
(void) close(file);
MagickFreeMemory(blob);
ThrowException3(exception,BlobError,UnableToReadToOffset,
UnableToCreateBlob);
return((void *) NULL);
}
blob[*length]='\0';
(void) close(file);
return(blob);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t B l o b F i l e H a n d l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetBlobFileHandle() returns the stdio file handle associated with the
% image blob. If there is no associated file handle, then a null pointer
% is returned.
%
% The format of the GetBlobFileHandle method is:
%
% FILE *GetBlobFileHandle(const Image *image)
%
% A description of each parameter follows:
%
% o image: Image to query
%
%
*/
MagickExport FILE *GetBlobFileHandle(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->blob != (const BlobInfo *) NULL);
return (image->blob->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(BlobInfo));
blob_info->quantum=DefaultBlobQuantum;
blob_info->fsync=MagickFalse;
blob_info->reference_count=1;
blob_info->semaphore=AllocateSemaphoreInfo();
blob_info->signature=MagickSignature;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ 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:
%
% magick_off_t GetBlobSize(const Image *image)
%
% A description of each parameter follows:
%
% o size: Method GetBlobSize returns the current length of the image file
% or blob.
%
% o image: The image.
%
%
*/
MagickExport magick_off_t GetBlobSize(const Image *image)
{
MagickStatStruct_t
attributes;
magick_off_t
offset;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(image->blob != (BlobInfo *) NULL);
offset=0;
switch (image->blob->type)
{
case UndefinedStream:
offset=image->blob->size;
break;
case FileStream:
{
offset=(MagickFstat(fileno(image->blob->file),&attributes) < 0 ? 0 :
attributes.st_size);
break;
}
case StandardStream:
case PipeStream:
break;
case ZipStream:
case BZipStream:
{
offset=(MagickStat(image->filename,&attributes) < 0 ? 0 :
attributes.st_size);
break;
}
case BlobStream:
{
offset=image->blob->length;
break;
}
}
return(offset);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t B l o b S t a t u s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetBlobStatus() returns the blob error status.
%
% The format of the GetBlobStatus method is:
%
% int GetBlobStatus(const Image *image)
%
% A description of each parameter follows:
%
% o image: The image.
%
%
*/
MagickExport int GetBlobStatus(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
return(image->blob->status);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% 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 data is only
% available if the data is stored on the heap, or is memory mapped.
% Otherwise a NULL value is returned.
%
% The format of the GetBlobStreamData method is:
%
% unsigned char *GetBlobStreamData(const Image *image)
%
% A description of each parameter follows:
%
% o image: The image.
%
%
*/
MagickExport unsigned char *GetBlobStreamData(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
if (image->blob->type != BlobStream)
return 0;
return(image->blob->data);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t B l o b T e m p o r a r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetBlobTemporary() returns MagickTrue if the file associated with the blob
% is a temporary file and should be removed when the associated image is
% destroyed.
%
% The format of the GetBlobTemporary method is:
%
% MagickBool GetBlobTemporary(const Image *image)
%
% A description of each parameter follows:
%
% o image: Image to query
%
%
*/
MagickExport MagickBool GetBlobTemporary(const Image *image)
{
assert(image != (const Image *) NULL);
assert(image->blob != (const BlobInfo *) NULL);
return (image->blob->temporary != False);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t C o n f i g u r e B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetConfigureBlob() returns the specified configure file as a blob.
%
% The format of the GetConfigureBlob method is:
%
% void *GetConfigureBlob(const char *filename,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o filename: The configure file name.
%
% o path: return the full path information of the configure file.
%
% o length: This pointer to a size_t integer sets the initial length of the
% blob. On return, it reflects the actual length of the blob.
%
% o exception: Return any errors or warnings in this structure.
%
%
*/
#if !defined(UseInstalledMagick) && defined(POSIX)
static void ChopPathComponents(char *path,const unsigned long components)
{
long
count;
register char
*p;
if (*path == '\0')
return;
p=path+strlen(path);
if (*p == *DirectorySeparator)
*p='\0';
for (count=0; (count < (long) components) && (p > path); p--)
if (*p == *DirectorySeparator)
{
*p='\0';
count++;
}
}
#endif
static void AddConfigurePath(MagickMap path_map, unsigned int *path_index,
const char *path,ExceptionInfo *exception)
{
char
key[MaxTextExtent];
FormatString(key,"%u",*path_index);
(void) MagickMapAddEntry(path_map,key,(void *)path,0,exception);
(*path_index)++;
}
MagickExport void *GetConfigureBlob(const char *filename,char *path,
size_t *length,ExceptionInfo *exception)
{
MagickMap
path_map;
MagickMapIterator
path_map_iterator;
const char
*key;
unsigned char
*blob=0;
unsigned int
logging,
path_index=0;
assert(filename != (const char *) NULL);
assert(path != (char *) NULL);
assert(length != (size_t *) NULL);
assert(exception != (ExceptionInfo *) NULL);
logging=IsEventLogging();
(void) strlcpy(path,filename,MaxTextExtent);
path_map=MagickMapAllocateMap(MagickMapCopyString,MagickMapDeallocateString);
{
/*
Allow the configuration file search path to be explicitly
specified.
*/
const char
*magick_configure_path = getenv("MAGICK_CONFIGURE_PATH");
if ( magick_configure_path )
{
const char
*end = NULL,
*start = magick_configure_path;
end=start+strlen(start);
while ( start < end )
{
char
buffer[MaxTextExtent];
const char
*separator;
int
string_length;
separator = strchr(start,DirectoryListSeparator);
if (separator)
string_length=separator-start;
else
string_length=end-start;
if (string_length > MaxTextExtent-1)
string_length = MaxTextExtent-1;
(void) strlcpy(buffer,start,string_length+1);
if (buffer[string_length-1] != DirectorySeparator[0])
(void) strlcat(buffer,DirectorySeparator,sizeof(buffer));
AddConfigurePath(path_map,&path_index,buffer,exception);
start += string_length+1;
}
}
}
#if defined(UseInstalledMagick)
# if defined(MagickShareConfigPath)
AddConfigurePath(path_map,&path_index,MagickShareConfigPath,exception);
# endif /* defined(MagickShareConfigPath) */
# if defined(MagickLibConfigPath)
AddConfigurePath(path_map,&path_index,MagickLibConfigPath,exception);
# endif /* defined(MagickLibConfigPath) */
# if defined(MSWINDOWS) && !(defined(MagickLibConfigPath) || defined(MagickShareConfigPath))
{
char
*registry_key,
*key_value;
/*
Locate file via registry key.
*/
registry_key="ConfigurePath";
key_value=NTRegistryKeyLookup(registry_key);
if (key_value == (char *) NULL)
{
ThrowException(exception,ConfigureError,RegistryKeyLookupFailed,registry_key);
return 0;
}
FormatString(path,"%.1024s%s",key_value,DirectorySeparator);
AddConfigurePath(path_map,&path_index,path,exception);
}
# endif /* defined(MSWINDOWS) */
#else /* !defined(UseInstalledMagick) */
{
const char
*magick_home;
/*
Search under MAGICK_HOME.
*/
magick_home=getenv("MAGICK_HOME");
if (magick_home)
{
#if defined(POSIX)
FormatString(path,"%.1024s/share/%s/",magick_home,
MagickShareConfigSubDir);
AddConfigurePath(path_map,&path_index,path,exception);
FormatString(path,"%.1024s/lib/%s/",magick_home,
MagickLibConfigSubDir);
AddConfigurePath(path_map,&path_index,path,exception);
#else
FormatString(path,"%.1024s%s",magick_home,
DirectorySeparator);
AddConfigurePath(path_map,&path_index,path,exception);
#endif /* defined(POSIX) */
}
}
if (getenv("HOME") != (char *) NULL)
{
/*
Search $HOME/.magick.
*/
FormatString(path,"%.1024s%s%s",getenv("HOME"),
*getenv("HOME") == '/' ? "/.magick" : "",DirectorySeparator);
AddConfigurePath(path_map,&path_index,path,exception);
}
if (*SetClientPath((char *) NULL) != '\0')
{
#if defined(POSIX)
char
prefix[MaxTextExtent];
/*
Search based on executable directory if directory is known.
*/
(void) strlcpy(prefix,SetClientPath((char *) NULL),MaxTextExtent);
ChopPathComponents(prefix,1);
FormatString(path,"%.1024s/lib/%s/",prefix,MagickLibConfigSubDir);
AddConfigurePath(path_map,&path_index,path,exception);
FormatString(path,"%.1024s/share/%s/",prefix,MagickShareConfigSubDir);
AddConfigurePath(path_map,&path_index,path,exception);
#else /* defined(POSIX) */
FormatString(path,"%.1024s%s",SetClientPath((char *) NULL),
DirectorySeparator);
AddConfigurePath(path_map,&path_index,path,exception);
#endif /* !defined(POSIX) */
}
/*
Search current directory.
*/
AddConfigurePath(path_map,&path_index,"",exception);
#endif /* !defined(UseInstalledMagick) */
path_map_iterator=MagickMapAllocateIterator(path_map);
if (logging)
{
char
list_separator[2],
*search_path=0;
list_separator[0]=DirectoryListSeparator;
list_separator[1]='\0';
while(MagickMapIterateNext(path_map_iterator,&key))
{
if (search_path)
(void) ConcatenateString(&search_path,list_separator);
(void) ConcatenateString(&search_path,
(const char *) MagickMapDereferenceIterator(path_map_iterator,0));
}
(void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
"Searching for file \"%s\" in path \"%s\"",filename,search_path);
MagickFreeMemory(search_path);
MagickMapIterateToFront(path_map_iterator);
}
while(MagickMapIterateNext(path_map_iterator,&key))
{
char
test_path[MaxTextExtent];
FILE
*file;
FormatString(test_path,"%.1024s%.256s",
(const char *)MagickMapDereferenceIterator(path_map_iterator,0),
filename);
file=fopen(test_path,"rb");
if (file )
{
if (logging)
(void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
"Found: %.1024s",test_path);
(void) strcpy(path,test_path);
(void) MagickFseek(file,0L,SEEK_END);
*length=MagickFtell(file); /* FIXME: ftell returns long, but size_t may be unsigned */
if (*length > 0)
{
(void) MagickFseek(file,0L,SEEK_SET);
blob=MagickAllocateMemory(unsigned char *,(*length)+1);
if (blob)
{
*length=fread((void *)blob, 1, *length, file);
blob[*length]='\0';
}
}
(void) fclose(file);
if (blob)
break;
}
if (logging)
{
(void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
"Tried: %.1024s [%.1024s]",test_path,
strerror(errno));
errno=0;
}
}
MagickMapDeallocateIterator(path_map_iterator);
MagickMapDeallocateMap(path_map);
if (blob)
return(blob);
#if defined(MSWINDOWS)
{
void
*resource;
resource=NTResourceToBlob(filename);
if (resource)
return resource;
}
#endif /* defined(MSWINDOWS) */
ThrowException(exception,ConfigureError,UnableToAccessConfigureFile,
filename);
return 0;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% I m a g e T o B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ImageToBlob() implements direct to memory image formats. It returns the
% image as a blob and its length. The magick member of the Image structure
% determines the format of the returned blob(GIG, JPEG, PNG, etc.)
%
% 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: This pointer to a size_t integer sets the initial length of the
% blob. On return, it reflects 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)
{
char
filename[MaxTextExtent],
unique[MaxTextExtent];
const MagickInfo
*magick_info;
ImageInfo
*clone_info;
unsigned char
*blob;
unsigned int
status;
assert(image_info != (const ImageInfo *) NULL);
assert(image_info->signature == MagickSignature);
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(exception != (ExceptionInfo *) NULL);
image->logging=IsEventLogging();
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),"Entering ImageToBlob");
/* SetExceptionInfo(exception,UndefinedException); */
clone_info=CloneImageInfo(image_info);
(void) strlcpy(clone_info->magick,image->magick,MaxTextExtent);
magick_info=GetMagickInfo(clone_info->magick,exception);
if (magick_info == (const MagickInfo *) NULL)
{
DestroyImageInfo(clone_info);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Exiting ImageToBlob");
return((void *) NULL);
}
if (magick_info->blob_support)
{
/*
Native blob support for this image format.
*/
clone_info->blob=MagickAllocateMemory(void *,65535L);
if (clone_info->blob == (void *) NULL)
{
ThrowException(exception,ResourceLimitError,MemoryAllocationFailed,
MagickMsg(BlobError,UnableToCreateBlob));
DestroyImageInfo(clone_info);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Exiting ImageToBlob");
return((void *) NULL);
}
clone_info->length=0;
image->blob->exempt=True;
*image->filename='\0';
status=WriteImage(clone_info,image);
if (status == False)
{
ThrowException(exception,BlobError,UnableToWriteBlob,
clone_info->magick);
MagickFreeMemory(image->blob->data);
DestroyImageInfo(clone_info);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Exiting ImageToBlob");
return((void *) NULL);
}
MagickReallocMemory(unsigned char *,image->blob->data,image->blob->length+1);
blob=image->blob->data;
*length=image->blob->length;
DetachBlob(image->blob);
DestroyImageInfo(clone_info);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Exiting ImageToBlob");
return(blob);
}
/*
Write file to disk in blob image format.
*/
(void) strlcpy(filename,image->filename,MaxTextExtent);
if(!AcquireTemporaryFileName(unique))
{
ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,
unique);
DestroyImageInfo(clone_info);
return((void *) NULL);
}
FormatString(image->filename,"%.1024s:%.1024s",image->magick,unique);
status=WriteImage(clone_info,image);
DestroyImageInfo(clone_info);
if (status == False)
{
(void) LiberateTemporaryFile(unique);
ThrowException(exception,BlobError,UnableToWriteBlob,image->filename);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Exiting ImageToBlob");
return((void *) NULL);
}
/*
Read image from disk as blob.
*/
blob=(unsigned char *) FileToBlob(image->filename,length,exception);
(void) LiberateTemporaryFile(image->filename);
(void) strlcpy(image->filename,filename,MaxTextExtent);
if (blob == (unsigned char *) NULL)
{
ThrowException(exception,BlobError,UnableToReadFile,filename);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Exiting ImageToBlob");
return((void *) NULL);
}
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Exiting ImageToBlob");
return(blob);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% I m a g e T o F i l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ImageToFile() copies the input image from an open blob stream to a file.
% It returns False if an error occurs otherwise True. This function is used
% to handle coders which are unable to stream the data in using Blob I/O.
% Instead of streaming the data in, the data is streammed to a temporary
% file, and the coder accesses the temorary file directly.
%
% The format of the ImageToFile method is:
%
% MagickPassFail ImageToFile(Image *image,const char *filename,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o status: ImageToFile returns MagickPass on success; otherwise, it
% returns MagickFail if an error occurs.
%
% o image: The image.
%
% o filename: Write the image to this file.
%
% o exception: Return any errors or warnings in this structure.
%
%
*/
MagickExport MagickPassFail ImageToFile(Image *image,const char *filename,
ExceptionInfo *exception)
{
#define MaxBufferSize 65541
char
*buffer;
ssize_t
count;
int
file;
register size_t
i;
size_t
length;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(filename != (const char *) NULL);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Copying from Blob stream to file %s",filename);
if (MagickConfirmAccess(FileWriteConfirmAccessMode,filename,exception)
== MagickFail)
return MagickFail;
file=open(filename,O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,0777);
if (file == -1)
{
ThrowException(exception,BlobError,UnableToWriteBlob,filename);
return(MagickFail);
}
buffer=MagickAllocateMemory(char *,MaxBufferSize);
if (buffer == (char *) NULL)
{
(void) close(file);
ThrowException(exception,ResourceLimitError,MemoryAllocationFailed,
filename);
return(MagickFail);
}
for (i=0; (length=ReadBlob(image,MaxBufferSize,buffer)) > 0; )
{
for (i=0; i < length; i+=count)
{
count=write(file,buffer+i,length-i);
if (count <= 0)
break;
}
if (i < length)
break;
}
(void) close(file);
MagickFreeMemory(buffer);
return(i < length);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ 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,off_t offset,size_t length)
%
% A description of each parameter follows:
%
% o status: Method MapBlob returns the address of the blob as well as
% its length in bytes.
%
% 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,magick_off_t offset,
size_t length)
{
#if defined(HAVE_MMAP_FILEIO)
void
*map;
/*
Map file.
*/
if (file == -1)
return((void *) NULL);
switch (mode)
{
case ReadMode:
default:
{
map=(void *) mmap((char *) NULL,length,PROT_READ,MAP_PRIVATE,file,
(off_t)offset);
#if 0
#if defined(HAVE_MADVISE)
if (map != (void *) MAP_FAILED)
{
#if defined(MADV_SEQUENTIAL)
/* Note: It has been noticed that madvise() wastes time if
the file has been accessed recently so pages are already
in RAM. ... */
(void) madvise(map,length,MADV_SEQUENTIAL);
#endif /* defined(MADV_SEQUENTIAL) */
#if defined(MADV_WILLNEED)
(void) madvise(map,length,MADV_WILLNEED);
#endif /* defined(MADV_WILLNEED) */
}
#endif /* defined(HAVE_MADVISE) */
#endif
break;
}
case WriteMode:
{
map=(void *) mmap((char *) NULL,length,PROT_WRITE,MAP_SHARED,file,(off_t)offset);
#if defined(MADV_SEQUENTIAL)
(void) madvise(map,length,MADV_SEQUENTIAL);
#endif /* defined(MADV_SEQUENTIAL) */
break;
}
case IOMode:
{
map=(void *) mmap((char *) NULL,length,(PROT_READ | PROT_WRITE),
MAP_SHARED,file,(off_t)offset);
break;
}
}
if (map == (void *) MAP_FAILED)
{
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Failed to mmap fd %d using %s mode at offset %"
MAGICK_OFF_F "u and length %" MAGICK_OFF_F
"u (%d=\"%s\").",file,MapModeToString(mode),offset,
(magick_off_t) length,errno,strerror(errno));
return((void *) NULL);
}
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Mmapped fd %d using %s mode at offset %" MAGICK_OFF_F
"u and length %" MAGICK_OFF_F "u to address 0x%p",
file,MapModeToString(mode),offset,(magick_off_t) length,
map);
return((void *) map);
#else
return((void *) NULL);
#endif
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ M S B O r d e r L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method 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 p: 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;
register unsigned char
*p,
*q;
assert(buffer != (unsigned char *) NULL);
q=buffer+length;
while (buffer < q)
{
p=buffer+3;
c=(*p);
*p=(*buffer);
*buffer++=(unsigned char) c;
p=buffer+1;
c=(*p);
*p=(*buffer);
*buffer++=(unsigned char) c;
buffer+=2;
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ M S B O r d e r S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method 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;
register unsigned char
*q;
assert(p != (unsigned char *) NULL);
q=p+length;
while (p < q)
{
c=(*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:
%
% MagickPassFail OpenBlob(const ImageInfo *image_info,Image *image,
% const BlobMode mode,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o status: Method OpenBlob returns MagickPass if the file is successfully
% opened otherwise MagickFail.
%
% o image_info: The image info.
%
% o image: The image.
%
% o mode: The mode for opening the file.
%
*/
static void FormMultiPartFilename(Image *image, const ImageInfo *image_info)
{
MagickBool
force;
char
filename[MaxTextExtent];
/*
Form filename for multi-part images.
*/
force = ((!image_info->adjoin) &&
((image->previous != (Image *) NULL) ||
(image->next != (Image *) NULL)));
if (MagickSceneFileName(filename,image->filename,".%lu",force,
GetImageIndexInList(image)))
(void) strlcpy(image->filename,filename,MaxTextExtent);
if (!image_info->adjoin)
if ((image->previous != (Image *) NULL) ||
(image->next != (Image *) NULL))
{
/* Propagate magick to next image in list. */
if (image->next != (Image *) NULL)
(void) strlcpy(image->next->magick,image->magick,
MaxTextExtent);
}
}
MagickExport MagickPassFail OpenBlob(const ImageInfo *image_info,Image *image,
const BlobMode mode,ExceptionInfo *exception)
{
char
filename[MaxTextExtent],
*type;
assert(image_info != (ImageInfo *) NULL);
assert(image_info->signature == MagickSignature);
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Opening Blob for image 0x%p using %s mode ...",image,
BlobModeToString(mode));
if (image_info->blob != (void *) NULL)
{
AttachBlob(image->blob,image_info->blob,image_info->length);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" attached image_info->blob to blob 0x%p",&image->blob);
return(MagickPass);
}
DetachBlob(image->blob);
image->blob->mode=mode;
switch (mode)
{
default: type=(char *) "r"; break;
case ReadBlobMode: type=(char *) "r"; break;
case ReadBinaryBlobMode: type=(char *) "rb"; break;
case WriteBlobMode: type=(char *) "w"; break;
case WriteBinaryBlobMode: type=(char *) "w+b"; break;
}
/*
Open image file.
*/
(void) strlcpy(filename,image->filename,MaxTextExtent);
if (LocaleCompare(filename,"-") == 0)
{
/*
Handle stdin/stdout stream
*/
if (*type == 'r')
{
image->blob->file=stdin;
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" using stdin as StandardStream blob 0x%p",
&image->blob);
}
else
{
image->blob->file=stdout;
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" using stdout as StandardStream blob 0x%p",
&image->blob);
}
#if defined(MSWINDOWS)
if (strchr(type,'b') != (char *) NULL)
setmode(_fileno(image->blob->file),_O_BINARY);
#endif
image->blob->type=StandardStream;
image->blob->exempt=True;
}
else
#if defined(HAVE_POPEN)
if (*filename == '|')
{
char
mode_string[MaxTextExtent];
/*
Pipe image to ("w") or from ("r") a system command.
*/
#if !defined(MSWINDOWS)
if (*type == 'w')
(void) signal(SIGPIPE,SIG_IGN);
#endif
(void) strlcpy(mode_string,type,sizeof(mode_string));
mode_string[1]='\0';
image->blob->file=(FILE *) NULL;
if (MagickConfirmAccess(FileExecuteConfirmAccessMode,filename+1,
exception) != MagickFail)
image->blob->file=(FILE *) popen(filename+1,mode_string);
if (image->blob->file != (FILE *) NULL)
{
image->blob->type=PipeStream;
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" popened \"%s\" as PipeStream blob 0x%p",
filename+1,&image->blob);
}
}
else
#endif /* defined(HAVE_POPEN) */
{
if (*type == 'w')
{
/*
Form filename for multi-part images.
*/
if (!image_info->adjoin)
FormMultiPartFilename(image,image_info);
(void) strcpy(filename,image->filename);
}
#if defined(HasZLIB)
if (((strlen(filename) > 2) &&
(LocaleCompare(filename+strlen(filename)-2,".Z") == 0)) ||
((strlen(filename) > 3) &&
(LocaleCompare(filename+strlen(filename)-3,".gz") == 0)) ||
((strlen(filename) > 5) &&
(LocaleCompare(filename+strlen(filename)-5,".svgz") == 0)))
{
image->blob->file=(FILE *) NULL;
if (MagickConfirmAccess((type[0] == 'r' ? FileReadConfirmAccessMode :
FileWriteConfirmAccessMode),filename,
exception) != MagickFail)
image->blob->file=(FILE *) gzopen(filename,type);
if (image->blob->file != (FILE *) NULL)
{
image->blob->type=ZipStream;
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" opened file %s as ZipStream blob 0x%p",
filename,&image->blob);
}
}
else
#endif
#if defined(HasBZLIB)
if ((strlen(filename) > 4) &&
(LocaleCompare(filename+strlen(filename)-4,".bz2") == 0))
{
image->blob->file=(FILE *) NULL;
if (MagickConfirmAccess((type[0] == 'r' ? FileReadConfirmAccessMode :
FileWriteConfirmAccessMode),filename,
exception) != MagickFail)
image->blob->file=(FILE *) BZ2_bzopen(filename,type);
if (image->blob->file != (FILE *) NULL)
{
image->blob->type=BZipStream;
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" opened file %s as BZipStream blob 0x%p",
filename,&image->blob);
}
}
else
#endif
if (image_info->file != (FILE *) NULL)
{
image->blob->file=image_info->file;
image->blob->type=FileStream;
image->blob->exempt=True;
(void) rewind(image->blob->file);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" opened image_info->file (%d) as FileStream blob 0x%p",
fileno(image_info->file),&image->blob);
}
else
{
image->blob->file=(FILE *) NULL;
if (MagickConfirmAccess((type[0] == 'r' ? FileReadConfirmAccessMode :
FileWriteConfirmAccessMode),filename,
exception) != MagickFail)
image->blob->file=(FILE *) fopen(filename,type);
if (image->blob->file != (FILE *) NULL)
{
char
*env = NULL;
unsigned char
magick[MaxTextExtent];
size_t
count;
size_t
vbuf_size;
vbuf_size=MagickGetFileSystemBlockSize();
if (setvbuf(image->blob->file,NULL,_IOFBF,vbuf_size) != 0)
{
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" setvbuf of %lu bytes returns failure!",
(unsigned long) vbuf_size);
}
else
{
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" I/O buffer set to %lu bytes",
(unsigned long) vbuf_size);
}
/*
Enable fsync-on-close mode if requested.
*/
if (((WriteBlobMode == mode) || (WriteBinaryBlobMode == mode)) &&
(env = getenv("MAGICK_IO_FSYNC")))
{
if (LocaleCompare(env,"TRUE") == 0)
{
image->blob->fsync=MagickTrue;
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" fsync() on close requested");
}
}
image->blob->type=FileStream;
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" opened file \"%s\" as FileStream blob 0x%p",
filename,&image->blob);
if ((ReadBlobMode == mode) || (ReadBinaryBlobMode == mode))
{
/*
Read file header and check magick bytes.
*/
(void) memset((void *) magick,0,MaxTextExtent);
count=fread(magick,MaxTextExtent,1,image->blob->file);
(void) rewind(image->blob->file);
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" read %ld magic header bytes",
(long) count*MaxTextExtent);
#if defined(HasZLIB)
if ((magick[0] == 0x1FU) && (magick[1] == 0x8BU) &&
(magick[2] == 0x08U))
{
(void) fclose(image->blob->file);
image->blob->file=(FILE *) gzopen(filename,type);
if (image->blob->file != (FILE *) NULL)
{
image->blob->type=ZipStream;
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" reopened file \"%s\" as ZipStream blob 0x%p",
filename,&image->blob);
}
}
#endif
#if defined(HasBZLIB)
if (strncmp((char *) magick,"BZh",3) == 0)
{
(void) fclose(image->blob->file);
image->blob->file=(FILE *) BZ2_bzopen(filename,type);
if (image->blob->file != (FILE *) NULL)
{
image->blob->type=BZipStream;
if (image->logging)
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
" reopened file %s as BZipStream blob %p",
filename,&image->blob);
}
}
#endif
}
}
}
if (image->blob->type == FileStream)
{
const char* env_val;
if (*type == 'r')
{
/*
Support reading from a file using memory mapping.
This code was used for years and definitely speeds
re-reading of the same file, but it has been
discovered that some operating systems (e.g. FreeBSD
and Apple's OS-X) fail to perform automatic
read-ahead for network files. It will be disabled
by default until we add a way to force read-ahead.
*/
if (((env_val = getenv("MAGICK_MMAP_READ")) != NULL) &&
(LocaleCompare(env_val,"TRUE") == 0))
{
const MagickInfo
*magick_info;
MagickStatStruct_t
attributes;
magick_info=GetMagickInfo(image_info->magick,&image->exception);
if ((magick_info != (const MagickInfo *) NULL) &&
magick_info->blob_support)
{
if ((MagickFstat(fileno(image->blob->file),&attributes) >= 0) &&
(attributes.st_size > MinBlobExtent) &&
(attributes.st_size == (off_t) ((size_t) attributes.st_size)))
{
size_t
length;
void
*blob;
length=(size_t) attributes.st_size;
if (AcquireMagickResource(MapResource,length))
{
blob=MapBlob(fileno(image->blob->file),ReadMode,0,length);
if (blob != (void *) NULL)
{
/*
Format supports blobs-- use memory-mapped I/O.
*/
if (image_info->file != (FILE *) NULL)
image->blob->exempt=False;
else
{
(void) fclose(image->blob->file);
image->blob->file=(FILE *) NULL;
}
AttachBlob(image->blob,blob,length);
image->blob->mapped=True;
}
else
{
LiberateMagickResource(MapResource,length);
}
}
}
}
}
}
else if (*type == 'w')
{
/*
Support writing to a file using memory mapping.
This is an experimental feature which only partially
works so it is disabled by default.
FIXME: Does not work at all in conjunction with MAGICK_MMAP_READ
and causes crashes in the test suite so I guess it is not ready yet.
*/
if (((env_val = getenv("MAGICK_MMAP_WRITE")) != NULL) &&
(LocaleCompare(env_val,"TRUE") == 0))
{
size_t
length;
void
*blob;
length=8192;
blob=MapBlob(fileno(image->blob->file),WriteMode,0,length);
if (blob != (void *) NULL)
{
image->blob->type=BlobStream;
image->blob->quantum=DefaultBlobQuantum;
image->blob->data=blob;
image->blob->mapped=True;
(void) SyncBlob(image);
}
}
}
}
}
image->blob->status=False;
if (image->blob->type != UndefinedStream)
image->blob->size=GetBlobSize(image);
if (*type == 'r')
{
image->next=(Image *) NULL;
image->previous=(Image *) NULL;
}
return(image->blob->type != UndefinedStream);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% 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 GraphicsMagick.
%
% 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 *PingBlob(const ImageInfo *image_info,const void *blob,
const size_t length,ExceptionInfo *exception)
{
Image
*image;
ImageInfo
*clone_info;
assert(image_info != (ImageInfo *) NULL);
assert(image_info->signature == MagickSignature);
assert(exception != (ExceptionInfo *) NULL);
/* SetExceptionInfo(exception,UndefinedException); */
if (((blob == (const void *) NULL)) || (length == 0))
{
ThrowException(exception,OptionError,NullBlobArgument,
image_info->magick);
return((Image *) NULL);
}
clone_info=CloneImageInfo(image_info);
clone_info->blob=(void *) blob;
clone_info->length=length;
clone_info->ping=MagickTrue;
if (clone_info->size == (char *) NULL)
clone_info->size=AllocateString(DefaultTileGeometry);
image=ReadImage(clone_info,exception);
DestroyImageInfo(clone_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.
%
% The format of the ReadBlob method is:
%
% size_t ReadBlob(Image *image,const size_t length,void *data)
%
% A description of each parameter follows:
%
% o count: Method ReadBlob returns the number of bytes read.
%
% 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 size_t ReadBlob(Image *image,const size_t length,void *data)
{
size_t
count;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
assert(data != (void *) NULL);
count=0;
switch (image->blob->type)
{
case UndefinedStream:
break;
case FileStream:
case StandardStream:
case PipeStream:
{
if (length == 1)
{
int
c;
if ((c=getc(image->blob->file)) != EOF)
{
*((unsigned char *)data)=(unsigned char) c;
count=1;
}
else
{
count=0;
}
}
else
{
count=fread(data,1,length,image->blob->file);
}
break;
}
case ZipStream:
{
#if defined(HasZLIB)
count=gzread(image->blob->file,data,length);
#endif
break;
}
case BZipStream:
{
#if defined(HasBZLIB)
count=BZ2_bzread(image->blob->file,data,length);
#endif
break;
}
case BlobStream:
{
void
*source_void = 0;
const unsigned char
*source;
count=ReadBlobStream(image,length,&source_void);
source=source_void;
if (count <= 10)
{
register size_t
i;
register unsigned char
*target=(unsigned char*) data;
for(i=count; i > 0; i--)
{
*target=*source;
target++;
source++;
}
}
else
(void) memcpy(data,source,count);
break;
}
}
return(count);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b Z C %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobZC() reads data from the blob or image file and returns it. It
% returns the number of bytes read. Provision is made for a "zero-copy"
% transfer if the blob data is already in memory.
%
% This method is currently EXPERIMENTAL!
%
% The format of the ReadBlob method is:
%
% size_t ReadBlob(Image *image,const size_t length,void *data)
%
% A description of each parameter follows:
%
% o count: Method ReadBlob returns the number of bytes read.
%
% 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. If the data may be accessed without a copy, then
% the provided pointer is updated to point to the location of
% the data in memory, and no copy is performed.
%
%
*/
MagickExport size_t ReadBlobZC(Image *image,const size_t length,void **data)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
assert(data != (void *) NULL);
if (image->blob->type == BlobStream)
return (ReadBlobStream(image,length,data));
assert(*data != (void *) NULL);
return ReadBlob(image,length,*data);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b B y t e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobByte reads a single byte from the image file and returns it.
% An EOF value is returned if there are no more bytes available on the input
% stream (similar to stdio's fgetc()).
%
% The format of the ReadBlobByte method is:
%
% int ReadBlobByte(Image *image)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobByte returns an integer read from the file.
%
% o image: The image.
%
%
*/
MagickExport int ReadBlobByte(Image *image)
{
unsigned char
c;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
switch (image->blob->type)
{
case FileStream:
case StandardStream:
case PipeStream:
{
return getc(image->blob->file);
}
case BlobStream:
{
if (image->blob->offset < (magick_off_t) image->blob->length)
{
c=*((unsigned char *)image->blob->data+image->blob->offset);
image->blob->offset++;
return (c);
}
image->blob->eof=True;
break;
}
default:
{
/* Do things the slow way */
if (ReadBlob(image,1,&c) == 1)
return (c);
}
}
return(EOF);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B D o u b l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobLSBDouble reads a double value as a 64 bit quantity in
% least-significant byte first order. If insufficient octets are available
% to compose the value, then zero is returned, and EOFBlob() may be used to
% detect that the input is in EOF state.
%
% The format of the ReadBlobLSBDouble method is:
%
% double ReadBlobLSBDouble(Image *image)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobLSBDouble returns a double read from
% the file. Zero is returned if insufficient data is available.
%
% o image: The image.
%
%
*/
MagickExport double ReadBlobLSBDouble(Image * image)
{
union
{
double d;
unsigned char chars[8];
} dbl_buffer;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(sizeof(dbl_buffer) == sizeof(double));
if (ReadBlob(image, 8, dbl_buffer.chars) != 8)
dbl_buffer.d = 0.0;
#if defined(WORDS_BIGENDIAN)
MagickSwabDouble(&dbl_buffer.d);
#endif
return (dbl_buffer.d);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B D o u b l e s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobLSBDoubles reads an array of little-endian 64-bit "double"
% values from the file or BLOB and returns them in native order.
%
% The format of the ReadBlobLSBDoubles method is:
%
% size_t ReadBlobLSBDoubles(Image *image, size_t octets, double *data)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobLSBDoubles returns the number of octets
% which were actually read.
%
% o image: The image.
%
% o octets: The number of bytes of data to read.
%
% o data: The address of a user-supplied buffer in which to write
% the decoded data. The buffer must be suitably aligned for the
% data type.
%
*/
MagickExport size_t ReadBlobLSBDoubles(Image *image, size_t octets, double *data)
{
size_t
octets_read;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(data != (double *) NULL);
octets_read=ReadBlob(image,octets,data);
#if defined(WORDS_BIGENDIAN)
if (octets_read >= sizeof(double))
MagickSwabArrayOfDouble(data,(octets_read+sizeof(double)-1)/sizeof(double));
#endif
return octets_read;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobLSBLong reads an unsigned 32 bit value in least-significant
% byte first order. If insufficient octets are available to compose the
% value, then zero is returned, and EOFBlob() may be used to detect that
% the input is in EOF state.
%
% The format of the ReadBlobLSBLong method is:
%
% magick_uint32_t ReadBlobLSBLong(Image *image)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobLSBLong returns an unsigned 32-bit value from
% the file. Zero is returned if insufficient data is available.
%
% o image: The image.
%
%
*/
MagickExport magick_uint32_t ReadBlobLSBLong(Image *image)
{
unsigned char
buffer[4];
magick_uint32_t
value;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
if (ReadBlob(image,4,buffer) != 4)
return(0U);
value=buffer[3] << 24;
value|=buffer[2] << 16;
value|=buffer[1] << 8;
value|=buffer[0];
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B L o n g s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobLSBLongs reads an array of little-endian 32-bit "long"
% values from the file or BLOB and returns them in native order.
%
% The format of the ReadBlobLSBLongs method is:
%
% size_t ReadBlobLSBLongs(Image *image, size_t octets,
% magick_uint32_t *data)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobLSBLongs returns the number of octets
% which were actually read.
%
% o image: The image.
%
% o octets: The number of bytes of data to read.
%
% o data: The address of a user-supplied buffer in which to write
% the decoded data. The buffer must be suitably aligned for the
% data type.
%
*/
MagickExport size_t ReadBlobLSBLongs(Image *image, size_t octets,
magick_uint32_t *data)
{
size_t
octets_read;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(data != (magick_uint32_t *) NULL);
octets_read=ReadBlob(image,octets,data);
#if defined(WORDS_BIGENDIAN)
if (octets_read >= sizeof(magick_uint32_t))
MagickSwabArrayOfUInt32(data,(octets_read+sizeof(magick_uint32_t)-1)/sizeof(magick_uint32_t));
#endif
return octets_read;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobLSBShort reads a 16-bit unsigned value in least-significant
% byte first order. If insufficient octets are available to compose the
% value, then zero is returned, and EOFBlob() may be used to detect that
% the input is in EOF state.
%
% The format of the ReadBlobLSBShort method is:
%
% unsigned short ReadBlobLSBShort(Image *image)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobLSBShort returns an unsigned 16-bit value
% read from the file. Zero is returned if insufficient data is available.
%
% o image: The image.
%
%
*/
MagickExport magick_uint16_t ReadBlobLSBShort(Image *image)
{
unsigned char
buffer[2];
magick_uint16_t
value;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
if (ReadBlob(image,2,buffer) != 2)
return(0U);
value=buffer[1] << 8;
value|=buffer[0];
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B F l o a t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobLSBFloat reads a float value as a 32 bit quantity in
% least-significant byte first order. If insufficient octets are available
% to compose the value, then zero is returned, and EOFBlob() may be used to
% detect that the input is in EOF state.
%
% The format of the ReadBlobLSBFloat method is:
%
% float ReadBlobLSBFloat(Image *image)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobLSBFloat returns a float read from
% the file. Zero is returned if insufficient data is available.
%
% o image: The image.
%
%
*/
MagickExport float ReadBlobLSBFloat(Image * image)
{
union
{
float f;
unsigned char chars[4];
} flt_buffer;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(sizeof(flt_buffer) == sizeof(float));
if (ReadBlob(image, 4, flt_buffer.chars) != 4)
flt_buffer.f = 0.0;
#if defined(WORDS_BIGENDIAN)
MagickSwabFloat(&flt_buffer.f);
#endif
return (flt_buffer.f);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B F l o a t s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobLSBFloats reads an array of little-endian 32-bit "float"
% values from the file or BLOB and returns them in native order.
%
% The format of the ReadBlobLSBFloats method is:
%
% size_t ReadBlobLSBFloats(Image *image, size_t octets, float *data)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobLSBFloats returns the number of octets
% which were actually read.
%
% o image: The image.
%
% o octets: The number of bytes of data to read.
%
% o data: The address of a user-supplied buffer in which to write
% the decoded data. The buffer must be suitably aligned for the
% data type.
%
*/
MagickExport size_t ReadBlobLSBFloats(Image *image, size_t octets, float *data)
{
size_t
octets_read;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(data != (float *) NULL);
octets_read=ReadBlob(image,octets,data);
#if defined(WORDS_BIGENDIAN)
if (octets_read >= sizeof(float))
MagickSwabArrayOfFloat(data,(octets_read+sizeof(float)-1)/sizeof(float));
#endif
return octets_read;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B F l o a t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobMSBFloat reads a float value as a 32 bit quantity in
% most-significant byte first order. If insufficient octets are available
% to compose the value, then zero is returned, and EOFBlob() may be used to
% detect that the input is in EOF state.
%
% The format of the ReadBlobMSBFloat method is:
%
% float ReadBlobMSBFloat(Image *image)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobMSBFloat returns a float read from
% the file. Zero is returned if insufficient data is available.
%
% o image: The image.
%
%
*/
MagickExport float ReadBlobMSBFloat(Image * image)
{
union
{
float f;
unsigned char chars[4];
} flt_buffer;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(sizeof(flt_buffer) == sizeof(float));
if (ReadBlob(image, 4, flt_buffer.chars) != 4)
flt_buffer.f = 0.0;
#if !defined(WORDS_BIGENDIAN)
MagickSwabFloat(&flt_buffer.f);
#endif
return (flt_buffer.f);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B F l o a t s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobMSBFloats reads an array of big-endian 32-bit "float"
% values from the file or BLOB and returns them in native order.
%
% The format of the ReadBlobMSBFloats method is:
%
% size_t ReadBlobMSBFloats(Image *image, size_t octets, float *data)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobMSBFloats returns the number of octets
% which were actually read.
%
% o image: The image.
%
% o octets: The number of bytes of data to read.
%
% o data: The address of a user-supplied buffer in which to write
% the decoded data. The buffer must be suitably aligned for the
% data type.
%
*/
MagickExport size_t ReadBlobMSBFloats(Image *image, size_t octets, float *data)
{
size_t
octets_read;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(data != (float *) NULL);
octets_read=ReadBlob(image,octets,data);
#if !defined(WORDS_BIGENDIAN)
if (octets_read >= sizeof(float))
MagickSwabArrayOfFloat(data,(octets_read+sizeof(float)-1)/sizeof(float));
#endif
return octets_read;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B D o u b l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobMSBDouble reads a double value as a 64 bit quantity in
% most-significant byte first order. If insufficient octets are available
% to compose the value, then zero is returned, and EOFBlob() may be used
% to detect that the input is in EOF state.
%
% The format of the ReadBlobMSBDouble method is:
%
% double ReadBlobMSBDouble(Image *image)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobMSBDouble returns a double read from
% the file. Zero is returned if insufficient data is available.
%
% o image: The image.
%
%
*/
MagickExport double ReadBlobMSBDouble(Image * image)
{
union
{
double d;
unsigned char chars[8];
} dbl_buffer;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(sizeof(dbl_buffer) == sizeof(double));
if (ReadBlob(image, 8, dbl_buffer.chars) != 8)
dbl_buffer.d = 0.0;
#if !defined(WORDS_BIGENDIAN)
MagickSwabDouble(&dbl_buffer.d);
#endif
return (dbl_buffer.d);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B D o u b l e s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobMSBDoubles reads an array of big-endian 64-bit "double"
% values from the file or BLOB and returns them in native order.
%
% The format of the ReadBlobMSBDoubles method is:
%
% size_t ReadBlobMSBDoubles(Image *image, size_t octets, double *data)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobMSBDoubles returns the number of octets
% which were actually read.
%
% o image: The image.
%
% o octets: The number of bytes of data to read.
%
% o data: The address of a user-supplied buffer in which to write
% the decoded data. The buffer must be suitably aligned for the
% data type.
%
*/
MagickExport size_t ReadBlobMSBDoubles(Image *image, size_t octets, double *data)
{
size_t
octets_read;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(data != (double *) NULL);
octets_read=ReadBlob(image,octets,data);
#if !defined(WORDS_BIGENDIAN)
if (octets_read > 0)
MagickSwabArrayOfDouble(data,(octets_read+sizeof(double)-1)/sizeof(double));
#endif
return octets_read;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadBlobMSBLong() reads a 32 bit unsigned value in most-significant byte
% first order. If insufficient octets are available to compose the value,
% then zero is returned, and EOFBlob() may be used to detect that the input
% is in EOF state.
%
% The format of the ReadBlobMSBLong method is:
%
% magick_uint32_t ReadBlobMSBLong(Image *image)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobMSBLong returns an unsigned 32-bit value
% read from the file. Zero is returned if insufficient data is available.
%
% o image: The image.
%
%
%
*/
MagickExport magick_uint32_t ReadBlobMSBLong(Image *image)
{
unsigned char
buffer[4];
magick_uint32_t
value;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
if (ReadBlob(image,4,buffer) != 4)
return(0U);
value=buffer[0] << 24;
value|=buffer[1] << 16;
value|=buffer[2] << 8;
value|=buffer[3];
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobMSBShort reads a 16 bit unsigned value in most-significant
% byte first order. If insufficient octets are available to compose the
% value, then zero is returned, and EOFBlob() may be used to detect that
% the input is in EOF state.
%
% The format of the ReadBlobMSBShort method is:
%
% magick_uint16_t ReadBlobMSBShort(Image *image)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobMSBShort returns an unsigned 16-bit value read
% from the file. Zero is returned if insufficient data is available.
%
% o image: The image.
%
%
*/
MagickExport magick_uint16_t ReadBlobMSBShort(Image *image)
{
unsigned char
buffer[2];
magick_uint16_t
value;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
if (ReadBlob(image,2,buffer) != 2)
return(0U);
value=buffer[0] << 8;
value|=buffer[1];
return(value);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B S h o r t s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobMSBShorts reads an array of big-endian 16-bit "short"
% values from the file or BLOB and returns them in native order.
%
% The format of the ReadBlobMSBShorts method is:
%
% size_t ReadBlobMSBShorts(Image *image, size_t octets,
% magick_uint16_t *data)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobMSBShorts returns the number of octets
% which were actually read.
%
% o image: The image.
%
% o octets: The number of bytes of data to read.
%
% o data: The address of a user-supplied buffer in which to write
% the decoded data. The buffer must be suitably aligned for the
% data type.
%
*/
MagickExport size_t ReadBlobMSBShorts(Image *image, size_t octets,
magick_uint16_t *data)
{
size_t
octets_read;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(data != (magick_uint16_t *) NULL);
octets_read=ReadBlob(image,octets,data);
#if !defined(WORDS_BIGENDIAN)
if (octets_read >= sizeof(magick_uint32_t))
MagickSwabArrayOfUInt16(data,(octets_read+sizeof(magick_uint16_t)-1)/sizeof(magick_uint16_t));
#endif
return octets_read;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ 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 status: Method ReadBlobString returns the string on success, otherwise,
% a null is returned.
%
% o image: The image.
%
% o string: The address of a character buffer.
%
%
*/
MagickExport char *ReadBlobString(Image *image,char *string)
{
int
c;
register unsigned int
i;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
for (i=0; i < (MaxTextExtent-1); i++)
{
c=ReadBlobByte(image);
if (c == EOF)
{
if (i == 0)
return((char *) NULL);
break;
}
string[i]=c;
if ((string[i] == '\n') || (string[i] == '\r'))
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 == MagickSignature);
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:
%
% magick_off_t SeekBlob(Image *image,const magick_off_t offset,
% const int whence)
%
% A description of each parameter follows:
%
% o offset: Method SeekBlob returns the offset from the beginning
% of the file or blob.
%
% 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 magick_off_t SeekBlob(Image *image,const magick_off_t offset,
const int whence)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
switch (image->blob->type)
{
case UndefinedStream:
break;
case FileStream:
{
if (MagickFseek(image->blob->file,offset,whence) < 0)
return(-1);
image->blob->offset=TellBlob(image);
break;
}
case StandardStream:
case PipeStream:
return(-1);
case ZipStream:
{
#if defined(HasZLIB)
if (gzseek(image->blob->file,(off_t) offset,whence) < 0)
return(-1);
#endif
image->blob->offset=TellBlob(image);
break;
}
case BZipStream:
return(-1);
case BlobStream:
{
switch (whence)
{
case SEEK_SET:
default:
{
if (offset < 0)
return(-1);
image->blob->offset=offset;
break;
}
case SEEK_CUR:
{
if ((image->blob->offset+offset) < 0)
return(-1);
image->blob->offset+=offset;
break;
}
case SEEK_END:
{
if ((magick_off_t)
(image->blob->offset+image->blob->length+offset) < 0)
return(-1);
image->blob->offset=image->blob->length+offset;
break;
}
}
if (image->blob->offset <= (magick_off_t) image->blob->length)
image->blob->eof=False;
else
if (image->blob->mapped)
return(-1);
else
{
image->blob->extent=image->blob->offset+image->blob->quantum;
MagickReallocMemory(unsigned char *,image->blob->data,image->blob->extent+1);
(void) SyncBlob(image);
if (image->blob->data == (unsigned char *) NULL)
{
DetachBlob(image->blob);
return(-1);
}
}
break;
}
}
return(image->blob->offset);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% S e t B l o b C l o s a b l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetBlobClosable() enables closing the blob if MagickTrue is passed, and
% exempts the blob from being closed if False is passed. Blobs are closable
% by default (default MagickTrue).
%
% The format of the SetBlobClosable method is:
%
% void SetBlobClosable(Image *image, MagickBool closeable)
%
% A description of each parameter follows:
%
% o image: Image to update
%
% o closeable: Set to FALSE in order to disable closing the blob.
%
*/
MagickExport void SetBlobClosable(Image *image, MagickBool closeable)
{
assert(image != (const Image *) NULL);
assert(image->blob != (const BlobInfo *) NULL);
image->blob->exempt = (closeable != False);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% S e t B l o b T e m p o r a r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetBlobTemporary() sets a boolean flag (default False) to specify if
% the file associated with the blob is a temporary file and should be
% removed when the associated image is destroyed.
%
% The format of the SetBlobTemporary method is:
%
% void SetBlobTemporary(Image *image, MagickBool isTemporary)
%
% A description of each parameter follows:
%
% o image: Image to update
%
% o isTemporary: Set to True to indicate that the file associated with
% the blob is temporary.
%
*/
MagickExport void SetBlobTemporary(Image *image, MagickBool isTemporary)
{
assert(image != (const Image *) NULL);
assert(image->blob != (const BlobInfo *) NULL);
image->blob->temporary = isTemporary;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S y n c B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SyncBlob() flushes the datastream if it is a file or synchonizes 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 status: Method SyncBlob returns 0 on success; otherwise, it
% returns -1 and set errno to indicate the error.
%
% o image: The image.
%
%
*/
static int SyncBlob(Image *image)
{
int
status;
register Image
*p;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
for (p=image; p->previous != (Image *) NULL; p=p->previous);
for ( ; p->next != (Image *) NULL; p=p->next)
if (p->blob != image->blob)
*p->blob=(*image->blob);
status=0;
switch (image->blob->type)
{
case UndefinedStream:
break;
case FileStream:
case StandardStream:
case PipeStream:
{
status=fflush(image->blob->file);
break;
}
case ZipStream:
{
#if defined(HasZLIB)
status=gzflush(image->blob->file,Z_SYNC_FLUSH);
#endif
break;
}
case BZipStream:
{
#if defined(HasBZLIB)
status=BZ2_bzflush(image->blob->file);
#endif
break;
}
case BlobStream:
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:
%
% magick_off_t TellBlob(const Image *image)
%
% A description of each parameter follows:
%
% o offset: Method TellBlob returns the current value of the blob or
% file position success; otherwise, it returns -1 and sets errno to
% indicate the error.
%
% o image: The image.
%
%
*/
MagickExport magick_off_t TellBlob(const Image *image)
{
magick_off_t
offset;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
offset=(-1);
switch (image->blob->type)
{
case UndefinedStream:
break;
case FileStream:
{
offset=MagickFtell(image->blob->file);
break;
}
case StandardStream:
case PipeStream:
case ZipStream:
{
#if defined(HasZLIB)
offset=gztell(image->blob->file);
#endif
break;
}
case BZipStream:
break;
case BlobStream:
{
offset=image->blob->offset;
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:
%
% MagickPassFail UnmapBlob(void *map,const size_t length)
%
% A description of each parameter follows:
%
% o status: Method UnmapBlob returns MagickPass on success; otherwise,
% it returns MagickFail and sets errno to indicate the error.
%
% o map: The address of the binary large object.
%
% o length: The length of the binary large object.
%
%
*/
MagickExport MagickPassFail UnmapBlob(void *map,const size_t length)
{
#if defined(HAVE_MMAP_FILEIO)
int
status;
(void) LogMagickEvent(BlobEvent,GetMagickModule(),
"Munmap file mapping at address 0x%p and length %lu",
map,(unsigned long) length);
status=munmap(map,length);
return(status == 0);
#else
return(MagickFail);
#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:
%
% size_t WriteBlob(Image *image,const size_t length,const void *data)
%
% A description of each parameter follows:
%
% o count: Method WriteBlob returns the number of bytes written to the
% blob.
%
% 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 size_t WriteBlob(Image *image,const size_t length,const void *data)
{
size_t
count;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(data != (const char *) NULL);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
count=length;
switch (image->blob->type)
{
case UndefinedStream:
break;
case FileStream:
case StandardStream:
case PipeStream:
{
if (length == 1)
{
if((putc((int)*((unsigned char *)data),image->blob->file)) != EOF)
count=1;
else
count=0;
}
else
{
count=fwrite((char *) data,1,length,image->blob->file);
}
break;
}
case ZipStream:
{
#if defined(HasZLIB)
count=gzwrite(image->blob->file,(void *) data,length);
#endif
break;
}
case BZipStream:
{
#if defined(HasBZLIB)
count=BZ2_bzwrite(image->blob->file,(void *) data,length);
#endif
break;
}
case BlobStream:
{
count=WriteBlobStream(image,length,data);
break;
}
}
return(count);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b B y t e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method WriteBlobByte writes an integer to a blob. It returns the number of
% bytes written (either 0 or 1);
%
% The format of the WriteBlobByte method is:
%
% size_t WriteBlobByte(Image *image,const unsigned int value)
%
% A description of each parameter follows.
%
% o count: Method WriteBlobByte returns the number of bytes written.
%
% o image: The image.
%
% o value: Specifies the value to write.
%
%
*/
MagickExport size_t WriteBlobByte(Image *image,const magick_uint8_t value)
{
unsigned char
c;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
switch (image->blob->type)
{
case FileStream:
case StandardStream:
case PipeStream:
{
if(putc((int) value,image->blob->file) != EOF)
return 1;
return 0;
}
/* case BlobStream: TBD */
default:
{
c=(unsigned char) value;
return(WriteBlob(image,1,&c));
}
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b F i l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method WriteBlobFile writes the content of a disk file to a blob stream.
% MagickPass is returned if the file is copied successfully.
%
% The format of the WriteBlobFile method is:
%
% MagickPassFail WriteBlobFile(Image *image,const char *filename)
%
% A description of each parameter follows.
%
% o count: Method WriteBlobByte returns the number of bytes written.
%
% o image: The image.
%
% o filename: The filename to copy to blob.
%
%
*/
MagickExport MagickPassFail WriteBlobFile(Image *image,const char *filename)
{
int
file;
MagickStatStruct_t
attributes;
unsigned char
*buffer;
size_t
length;
size_t
count;
ssize_t
result;
register size_t
i;
MagickPassFail
status;
status=MagickFail;
if (MagickConfirmAccess(FileReadConfirmAccessMode,filename,
&image->exception) == MagickFail)
return MagickFail;
file=open(filename,O_RDONLY | O_BINARY,0777);
if (file != -1)
{
/* st_size has type off_t */
if ((MagickFstat(file,&attributes) == 0) &&
(attributes.st_size == (off_t) ((size_t) attributes.st_size)) &&
(attributes.st_size > (off_t) ((size_t) 0)))
{
length=(size_t) attributes.st_size;
count = 32768;
if (count > length)
count = length;
buffer=MagickAllocateMemory(unsigned char *,count);
if (buffer != (unsigned char *) NULL)
{
for (i=0; i < length; i+=count)
{
result=read(file,buffer,count);
if (result <= 0)
break;
if (WriteBlob(image,result,buffer) != (size_t) result)
break;
}
MagickFreeMemory(buffer);
}
(void) close(file);
status = MagickPass;
}
}
return status;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b L S B L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method WriteBlobLSBLong writes a 32 bit quantity in least-significant byte
% first order.
%
% The format of the WriteBlobLSBLong method is:
%
% size_t WriteBlobLSBLong(Image *image,const magick_uint32_t value)
%
% A description of each parameter follows.
%
% o count: Method WriteBlobLSBLong returns the number of bytes written.
%
% o image: The image.
%
% o value: Specifies the value to write.
%
%
*/
MagickExport size_t WriteBlobLSBLong(Image *image,const magick_uint32_t value)
{
unsigned char
buffer[4];
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
buffer[0]=(unsigned char) value;
buffer[1]=(unsigned char) (value >> 8);
buffer[2]=(unsigned char) (value >> 16);
buffer[3]=(unsigned char) (value >> 24);
return(WriteBlob(image,4,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b L S B S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method WriteBlobLSBShort writes a 16 bit value in least-significant byte
% first order.
%
% The format of the WriteBlobLSBShort method is:
%
% size_t WriteBlobLSBShort(Image *image,const magick_uint16_t value)
%
% A description of each parameter follows.
%
% o count: Method WriteBlobLSBShort returns the number of bytes written.
%
% o image: The image.
%
% o value: Specifies the value to write.
%
%
*/
MagickExport size_t WriteBlobLSBShort(Image *image,const magick_uint16_t value)
{
unsigned char
buffer[2];
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
buffer[0]=(unsigned char) value;
buffer[1]=(unsigned char) (value >> 8);
return(WriteBlob(image,2,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b L S B S h o r t s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobLSBShorts reads an array of little-endian 16-bit "short"
% values from the file or BLOB and returns them in native order.
%
% The format of the ReadBlobLSBShorts method is:
%
% size_t ReadBlobLSBShorts(Image *image, size_t octets,
% magick_uint16_t *data)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobLSBShorts returns the number of octets
% which were actually read.
%
% o image: The image.
%
% o octets: The number of bytes of data to read.
%
% o data: The address of a user-supplied buffer in which to write
% the decoded data. The buffer must be suitably aligned for the
% data type.
%
*/
MagickExport size_t ReadBlobLSBShorts(Image *image, size_t octets,
magick_uint16_t *data)
{
size_t
octets_read;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(data != (magick_uint16_t *) NULL);
octets_read=ReadBlob(image,octets,data);
#if defined(WORDS_BIGENDIAN)
if (octets_read >= sizeof(magick_uint16_t))
MagickSwabArrayOfUInt16(data,(octets_read+sizeof(magick_uint16_t)-1)/sizeof(magick_uint16_t));
#endif
return octets_read;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b M S B L o n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method WriteBlobMSBLong writes a 32 bit value in most-significant byte
% first order.
%
% The format of the WriteBlobMSBLong method is:
%
% size_t WriteBlobMSBLong(Image *image,const magick_uint32_t value)
%
% A description of each parameter follows.
%
% o count: Method WriteBlobMSBLong returns the number of bytes written.
%
% o value: Specifies the value to write.
%
% o image: The image.
%
%
*/
MagickExport size_t WriteBlobMSBLong(Image *image,const magick_uint32_t value)
{
size_t
count;
unsigned char
buffer[4];
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
buffer[0]=(unsigned char) (value >> 24);
buffer[1]=(unsigned char) (value >> 16);
buffer[2]=(unsigned char) (value >> 8);
buffer[3]=(unsigned char) value;
if (image->blob->type == BlobStream)
count=WriteBlobStream(image,4,buffer);
else
count=WriteBlob(image,4,buffer);
return count;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ R e a d B l o b M S B L o n g s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method ReadBlobMSBLongs reads an array of big-endian 32-bit "long"
% values from the file or BLOB and returns them in native order.
%
% The format of the ReadBlobMSBLongs method is:
%
% size_t ReadBlobMSBLongs(Image *image, size_t octets,
% magick_uint32_t *data)
%
% A description of each parameter follows.
%
% o value: Method ReadBlobMSBLongs returns the number of octets
% which were actually read.
%
% o image: The image.
%
% o octets: The number of bytes of data to read.
%
% o data: The address of a user-supplied buffer in which to write
% the decoded data. The buffer must be suitably aligned for the
% data type.
%
*/
MagickExport size_t ReadBlobMSBLongs(Image *image, size_t octets,
magick_uint32_t *data)
{
size_t
octets_read;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(data != (magick_uint32_t *) NULL);
octets_read=ReadBlob(image,octets,data);
#if !defined(WORDS_BIGENDIAN)
if (octets_read >= sizeof(magick_uint32_t))
MagickSwabArrayOfUInt32(data,(octets_read+sizeof(magick_uint32_t)-1)/sizeof(magick_uint32_t));
#endif
return octets_read;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b M S B S h o r t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method WriteBlobMSBShort writes a 16 bit value in most-significant byte
% first order.
%
% The format of the WriteBlobMSBShort method is:
%
% size_t WriteBlobMSBShort(Image *image,const magick_uint16_t value)
%
% A description of each parameter follows.
%
% o count: Method WriteBlobMSBShort returns the number of bytes written.
%
% o value: Specifies the value to write.
%
% o file: Specifies the file to write the data to.
%
%
*/
MagickExport size_t WriteBlobMSBShort(Image *image,const magick_uint16_t value)
{
unsigned char
buffer[2];
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
buffer[0]=(unsigned char) (value >> 8);
buffer[1]=(unsigned char) value;
return(WriteBlob(image,2,buffer));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ W r i t e B l o b S t r i n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method WriteBlobString write a string to a blob. It returns the number of
% characters written.
%
% The format of the WriteBlobString method is:
%
% size_t WriteBlobString(Image *image,const char *string)
%
% A description of each parameter follows.
%
% o count: Method WriteBlobString returns the number of characters written.
%
% o image: The image.
%
% o string: Specifies the string to write.
%
%
*/
MagickExport size_t WriteBlobString(Image *image,const char *string)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(string != (const char *) NULL);
return(WriteBlob(image,strlen(string),string));
}