% July 1992 %
% %
% %
-% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2011 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 %
#if defined(MAGICKCORE_TIFF_DELEGATE)
# if defined(MAGICKCORE_HAVE_TIFFCONF_H)
# include "tiffconf.h"
-#endif
+# endif
# include "tiff.h"
# include "tiffio.h"
# if !defined(COMPRESSION_ADOBE_DEFLATE)
# define COMPRESSION_ADOBE_DEFLATE 8
# endif
+# if !defined(PREDICTOR_HORIZONTAL)
+# define PREDICTOR_HORIZONTAL 2
+# endif
\f
/*
Typedef declarations.
{ 0, 0, (char *) NULL }
};
#endif
+#endif /* MAGICKCORE_TIFF_DELEGATE */
\f
/*
Global declarations.
static volatile MagickBooleanType
instantiate_key = MagickFalse;
-#endif
\f
/*
Forward declarations.
%
*/
-static inline size_t WriteLSBLong(FILE *file,const unsigned int value)
+static inline size_t WriteLSBLong(FILE *file,const size_t value)
{
unsigned char
buffer[4];
Read TIFF image.
*/
read_info=CloneImageInfo((ImageInfo *) NULL);
- (void) FormatMagickString(read_info->filename,MaxTextExtent,"%.1024s",
- filename);
+ (void) FormatMagickString(read_info->filename,MaxTextExtent,"%s",filename);
image=ReadTIFFImage(read_info,exception);
read_info=DestroyImageInfo(read_info);
if (image != (Image *) NULL)
(void) ConcatenateMagickString(message,".",MaxTextExtent);
exception=(ExceptionInfo *) MagickGetThreadValue(tiff_exception);
if (exception != (ExceptionInfo *) NULL)
- (void) ThrowMagickException(exception,GetMagickModule(),CoderWarning,
- message,"`%s'",module);
+ (void) ThrowMagickException(exception,GetMagickModule(),CoderError,message,
+ "`%s'",module);
}
static void TIFFGetProfiles(TIFF *tiff,Image *image)
(void) MagickSetThreadValue(tiff_exception,exception);
error_handler=TIFFSetErrorHandler(TIFFErrors);
warning_handler=TIFFSetWarningHandler(TIFFWarnings);
- tiff=TIFFClientOpen(image->filename,"r",(thandle_t) image,TIFFReadBlob,
+ tiff=TIFFClientOpen(image->filename,"rb",(thandle_t) image,TIFFReadBlob,
TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob,TIFFGetBlobSize,TIFFMapBlob,
TIFFUnmapBlob);
if (tiff == (TIFF *) NULL)
return((Image *) NULL);
}
debug=IsEventLogging();
+ (void) debug;
if (image_info->number_scenes != 0)
{
/*
{
if (0 && (image_info->verbose != MagickFalse))
TIFFPrintDirectory(tiff,stdout,MagickFalse);
+ (void) SetImageProperty(image,"tiff:endian",TIFFIsBigEndian(tiff) == 0 ?
+ "lsb" : "msb");
(void) TIFFGetFieldDefaulted(tiff,TIFFTAG_COMPRESSION,&compress_tag);
(void) TIFFGetFieldDefaulted(tiff,TIFFTAG_ORIENTATION,&orientation);
(void) TIFFGetFieldDefaulted(tiff,TIFFTAG_IMAGEWIDTH,&width);
(void) TIFFGetFieldDefaulted(tiff,TIFFTAG_PLANARCONFIG,&interlace);
(void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,&bits_per_sample);
(void) TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLEFORMAT,&sample_format);
+ if (sample_format == SAMPLEFORMAT_IEEEFP)
+ (void) SetImageProperty(image,"quantum:format","floating-point");
(void) TIFFGetFieldDefaulted(tiff,TIFFTAG_MINSAMPLEVALUE,&min_sample_value);
(void) TIFFGetFieldDefaulted(tiff,TIFFTAG_MAXSAMPLEVALUE,&max_sample_value);
(void) TIFFGetFieldDefaulted(tiff,TIFFTAG_PHOTOMETRIC,&photometric);
(void) SetImageProperty(image,"tiff:photometric","separated");
break;
}
+ case PHOTOMETRIC_YCBCR:
+ {
+ (void) SetImageProperty(image,"tiff:photometric","YCBCR");
+ break;
+ }
default:
{
(void) SetImageProperty(image,"tiff:photometric","unknown");
image->rows=(size_t) height;
image->depth=(size_t) bits_per_sample;
if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Image depth: %lu",
- (unsigned long) image->depth);
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Image depth: %.20g",
+ (double) image->depth);
lsb_first=1;
image->endian=MSBEndian;
if ((int) (*(char *) &lsb_first) != 0)
break;
}
case COMPRESSION_OJPEG: image->compression=JPEGCompression; break;
+#if defined(COMPRESSION_LZMA)
+ case COMPRESSION_LZMA: image->compression=LZMACompression; break;
+#endif
case COMPRESSION_LZW: image->compression=LZWCompression; break;
case COMPRESSION_DEFLATE: image->compression=ZipCompression; break;
case COMPRESSION_ADOBE_DEFLATE: image->compression=ZipCompression; break;
if ((photometric != PHOTOMETRIC_SEPARATED) &&
(interlace == PLANARCONFIG_SEPARATE))
method=ReadGenericMethod;
+ if (image->compression == JPEGCompression)
+ method=ReadGenericMethod;
if (TIFFIsTiled(tiff) != MagickFalse)
method=ReadTileMethod;
quantum_type=RGBQuantum;
break;
length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
quantum_type,pixels,exception);
+ (void) length;
if (SyncAuthenticPixels(image,exception) == MagickFalse)
break;
if (image->previous == (Image *) NULL)
{
if (TIFFReadRGBAStrip(tiff,(tstrip_t) y,(uint32 *) pixels) == 0)
break;
- i=(ssize_t) MagickMin((ssize_t) rows_per_strip,(ssize_t) image->rows-y);
+ i=(ssize_t) MagickMin((ssize_t) rows_per_strip,(ssize_t)
+ image->rows-y);
}
i--;
p=pixels+image->columns*i;
}
(void) SetImageStorageClass(image,DirectClass);
number_pixels=columns*rows;
- tile_pixels=(uint32 *) AcquireQuantumMemory((size_t) columns*rows,
+ tile_pixels=(uint32 *) AcquireQuantumMemory(number_pixels,
sizeof(*tile_pixels));
if (tile_pixels == (uint32 *) NULL)
{
q->green=ScaleCharToQuantum((unsigned char) TIFFGetG(*p));
q->blue=ScaleCharToQuantum((unsigned char) TIFFGetB(*p));
if (image->matte != MagickFalse)
- q->opacity=ScaleCharToQuantum((unsigned char) TIFFGetA(*p));
+ q->opacity=(Quantum) (QuantumRange-
+ ScaleCharToQuantum((unsigned char) TIFFGetA(*p)));
p--;
q--;
}
MagickInfo
*entry;
-
+
if (tiff_semaphore == (SemaphoreInfo *) NULL)
tiff_semaphore=AllocateSemaphoreInfo();
LockSemaphoreInfo(tiff_semaphore);
entry->raw=MagickTrue;
entry->endian_support=MagickTrue;
entry->adjoin=MagickFalse;
+ entry->format_type=ImplicitFormatType;
entry->seekable_stream=MagickTrue;
entry->thread_support=NoThreadSupport;
entry->description=ConstantString("Raw CCITT Group4");
MagickStatusType
flags;
+ uint32
+ tile_columns,
+ tile_rows;
+
assert(tiff_info != (TIFFInfo *) NULL);
(void) ResetMagickMemory(tiff_info,0,sizeof(*tiff_info));
option=GetImageOption(image_info,"tiff:tile-geometry");
flags=ParseAbsoluteGeometry(option,&tiff_info->tile_geometry);
if ((flags & HeightValue) == 0)
tiff_info->tile_geometry.height=tiff_info->tile_geometry.width;
- (void) TIFFSetField(tiff,TIFFTAG_TILEWIDTH,(uint32)
- tiff_info->tile_geometry.width);
- (void) TIFFSetField(tiff,TIFFTAG_TILELENGTH,(uint32)
- tiff_info->tile_geometry.height);
+ tile_columns=(uint32) tiff_info->tile_geometry.width;
+ tile_rows=(uint32) tiff_info->tile_geometry.height;
+ TIFFDefaultTileSize(tiff,&tile_columns,&tile_rows);
+ (void) TIFFSetField(tiff,TIFFTAG_TILEWIDTH,tile_columns);
+ (void) TIFFSetField(tiff,TIFFTAG_TILELENGTH,tile_rows);
+ tiff_info->tile_geometry.width=tile_columns;
+ tiff_info->tile_geometry.height=tile_rows;
tiff_info->scanlines=(unsigned char *) AcquireQuantumMemory((size_t)
- tiff_info->tile_geometry.height*TIFFScanlineSize(tiff),
- sizeof(*tiff_info->scanlines));
+ tile_rows*TIFFScanlineSize(tiff),sizeof(*tiff_info->scanlines));
tiff_info->pixels=(unsigned char *) AcquireQuantumMemory((size_t)
- TIFFTileSize(tiff),sizeof(*tiff_info->scanlines));
+ tile_rows*TIFFTileSize(tiff),sizeof(*tiff_info->scanlines));
if ((tiff_info->scanlines == (unsigned char *) NULL) ||
(tiff_info->pixels == (unsigned char *) NULL))
{
SetStringInfoLength(iptc_profile,length);
if (TIFFIsByteSwapped(tiff))
TIFFSwabArrayOfLong((uint32 *) GetStringInfoDatum(iptc_profile),
- (size_t) (length/4));
+ (unsigned long) (length/4));
(void) TIFFSetField(tiff,TIFFTAG_RICHTIFFIPTC,(uint32)
GetStringInfoLength(iptc_profile)/4,GetStringInfoDatum(iptc_profile));
iptc_profile=DestroyStringInfo(iptc_profile);
const char
*value;
+ (void) TIFFSetField(tiff,TIFFTAG_DOCUMENTNAME,image->filename);
value=GetImageProperty(image,"tiff:hostcomputer");
if (value != (const char *) NULL)
(void) TIFFSetField(tiff,TIFFTAG_HOSTCOMPUTER,value);
value=GetImageProperty(image,"tiff:model");
if (value != (const char *) NULL)
(void) TIFFSetField(tiff,TIFFTAG_MODEL,value);
- (void) TIFFSetField(tiff,TIFFTAG_SOFTWARE,
- GetMagickVersion((size_t *) NULL));
- (void) TIFFSetField(tiff,TIFFTAG_DOCUMENTNAME,image->filename);
+ value=GetImageProperty(image,"tiff:software");
+ if (value != (const char *) NULL)
+ (void) TIFFSetField(tiff,TIFFTAG_SOFTWARE,value);
value=GetImageProperty(image,"tiff:copyright");
if (value != (const char *) NULL)
(void) TIFFSetField(tiff,33432,value);
CompressionType
compression;
+ EndianType
+ endian_type;
+
ssize_t
y;
i;
size_t
- length;
+ length,
+ lsb_first;
TIFF
*tiff;
unsigned char
*pixels;
- size_t
- lsb_first;
-
/*
Open TIFF file.
*/
(void) MagickSetThreadValue(tiff_exception,&image->exception);
error_handler=TIFFSetErrorHandler((TIFFErrorHandler) TIFFErrors);
warning_handler=TIFFSetWarningHandler((TIFFErrorHandler) TIFFWarnings);
- switch (image_info->endian)
+ endian_type=UndefinedEndian;
+ option=GetImageOption(image_info,"tiff:endian");
+ if (option != (const char *) NULL)
+ {
+ if (LocaleNCompare(option,"msb",3) == 0)
+ endian_type=MSBEndian;
+ if (LocaleNCompare(option,"lsb",3) == 0)
+ endian_type=LSBEndian;;
+ }
+ switch (endian_type)
{
case LSBEndian: mode="wl"; break;
case MSBEndian: mode="wb"; break;
}
#if defined(TIFF_VERSION_BIG)
if (LocaleCompare(image_info->magick,"TIFF64") == 0)
- switch (image_info->endian)
+ switch (endian_type)
{
case LSBEndian: mode="wl8"; break;
case MSBEndian: mode="wb8"; break;
}
scene=0;
debug=IsEventLogging();
+ (void) debug;
do
{
/*
compress_tag=COMPRESSION_JPEG;
break;
}
+#if defined(COMPRESSION_LZMA)
+ case LZMACompression:
+ {
+ compress_tag=COMPRESSION_LZMA;
+ break;
+ }
+#endif
case LZWCompression:
{
compress_tag=COMPRESSION_LZW;
#if defined(YCBCR_SUPPORT) && defined(JPEG_SUPPORT)
case COMPRESSION_JPEG:
#endif
+#if defined(LZMA_SUPPORT) && defined(COMPRESSION_LZMA)
+ case COMPRESSION_LZMA:
+#endif
#if defined(LZW_SUPPORT)
case COMPRESSION_LZW:
#endif
{
photometric=PHOTOMETRIC_YCBCR;
(void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,1,1);
+ (void) SetImageStorageClass(image,DirectClass);
(void) SetImageDepth(image,8);
}
else
MagickFalse ? PHOTOMETRIC_MINISWHITE :
PHOTOMETRIC_MINISBLACK);
(void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
- if ((image_info->depth == 0) &&
+ if ((image_info->depth == 0) && (image->matte == MagickFalse) &&
(IsMonochromeImage(image,&image->exception) != MagickFalse))
{
status=SetQuantumDepth(image,quantum_info,1);
compress_tag=COMPRESSION_NONE;
endian=FILLORDER_MSB2LSB;
}
+ option=GetImageProperty(image,"tiff:fill-order");
+ if (option != (const char *) NULL)
+ {
+ if (LocaleNCompare(option,"msb",3) == 0)
+ endian=FILLORDER_MSB2LSB;
+ if (LocaleNCompare(option,"lsb",3) == 0)
+ endian=FILLORDER_LSB2MSB;
+ }
(void) TIFFSetField(tiff,TIFFTAG_COMPRESSION,compress_tag);
(void) TIFFSetField(tiff,TIFFTAG_FILLORDER,endian);
(void) TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,quantum_info->depth);
(void) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_SEPARATE);
rows_per_strip=1;
if (TIFFScanlineSize(tiff) != 0)
- rows_per_strip=(size_t) MagickMax((size_t)
- TIFFDefaultStripSize(tiff,0),1);
+ rows_per_strip=(uint32) MagickMax((size_t) TIFFDefaultStripSize(tiff,0),
+ 1);
option=GetImageOption(image_info,"tiff:rows-per-strip");
if (option != (const char *) NULL)
rows_per_strip=(size_t) strtol(option,(char **) NULL,10);
flags=ParseGeometry(sampling_factor,&geometry_info);
if ((flags & SigmaValue) == 0)
geometry_info.sigma=geometry_info.rho;
- (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,(uint16)
- geometry_info.rho,(uint16) geometry_info.sigma);
+ if (image->colorspace == YCbCrColorspace)
+ (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,(uint16)
+ geometry_info.rho,(uint16) geometry_info.sigma);
}
}
if (bits_per_sample == 12)
}
case COMPRESSION_ADOBE_DEFLATE:
{
- rows_per_strip=image->rows;
+ rows_per_strip=(uint32) image->rows;
(void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
&bits_per_sample);
if (((photometric == PHOTOMETRIC_RGB) ||
(photometric == PHOTOMETRIC_MINISBLACK)) &&
((bits_per_sample == 8) || (bits_per_sample == 16)))
- (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,2);
- (void) TIFFSetField(tiff,TIFFTAG_ZIPQUALITY,image_info->quality ==
- UndefinedCompressionQuality ? 7 : MagickMin(1L*image_info->quality/10,
- 9));
+ (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
+ (void) TIFFSetField(tiff,TIFFTAG_ZIPQUALITY,(long) (
+ image_info->quality == UndefinedCompressionQuality ? 7 :
+ MagickMin((ssize_t) image_info->quality/10,9)));
break;
}
case COMPRESSION_CCITTFAX3:
/*
Byte-aligned EOL.
*/
- rows_per_strip=image->rows;
+ rows_per_strip=(uint32) image->rows;
(void) TIFFSetField(tiff,TIFFTAG_GROUP3OPTIONS,4);
break;
}
case COMPRESSION_CCITTFAX4:
{
- rows_per_strip=image->rows;
+ rows_per_strip=(uint32) image->rows;
break;
}
+#if defined(LZMA_SUPPORT) && defined(COMPRESSION_LZMA)
+ case COMPRESSION_LZMA:
+ {
+ if (((photometric == PHOTOMETRIC_RGB) ||
+ (photometric == PHOTOMETRIC_MINISBLACK)) &&
+ ((bits_per_sample == 8) || (bits_per_sample == 16)))
+ (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
+ (void) TIFFSetField(tiff,TIFFTAG_LZMAPRESET,(long) (
+ image_info->quality == UndefinedCompressionQuality ? 7 :
+ MagickMin((ssize_t) image_info->quality/10,9)));
+ break;
+ }
+#endif
case COMPRESSION_LZW:
{
(void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
if (((photometric == PHOTOMETRIC_RGB) ||
(photometric == PHOTOMETRIC_MINISBLACK)) &&
((bits_per_sample == 8) || (bits_per_sample == 16)))
- (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,2);
+ (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
break;
}
default:
break;
}
- (void) TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,rows_per_strip);
+ option=GetImageOption(image_info,"tiff:tile-geometry");
+ if (option == (const char *) NULL)
+ (void) TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,rows_per_strip);
if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
{
unsigned short
pages;
page=(uint16) scene;
- pages=GetImageListLength(image);
+ pages=(uint16) GetImageListLength(image);
if ((image_info->adjoin != MagickFalse) && (pages > 1))
(void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
(void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,page,pages);
break;
length=ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,quantum_type,pixels,&image->exception);
+ (void) length;
if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
break;
if (image->previous == (Image *) NULL)
{
- status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
- image->rows);
+ status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
+ y,image->rows);
if (status == MagickFalse)
break;
}