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