mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-25 17:21:02 +00:00
* Source/nsimage-tiff.h: Correct field types.
* Source/NSImage.m (-TIFFRepresentation) (TIFFRepresentationUsingCompression:factor:): Pass on bitmaps only. * Source/NSBitmapImageRep.m: Implement methods to generate tiff for multiple bitmaps. * Source/tiff.m: Fix long standing bug in TiffHandleSeek. In NSTiffWrite write image tiff directory to allow for multiple images. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@39050 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
95dbc26988
commit
b8fb4e24b1
5 changed files with 377 additions and 160 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2015-10-10 Fred Kiefer <FredKiefer@gmx.de>
|
||||||
|
|
||||||
|
* Source/nsimage-tiff.h: Correct field types.
|
||||||
|
* Source/NSImage.m (-TIFFRepresentation)
|
||||||
|
(TIFFRepresentationUsingCompression:factor:): Pass on bitmaps only.
|
||||||
|
* Source/NSBitmapImageRep.m: Implement methods to generate tiff
|
||||||
|
for multiple bitmaps.
|
||||||
|
* Source/tiff.m: Fix long standing bug in TiffHandleSeek.
|
||||||
|
In NSTiffWrite write image tiff directory to allow for multiple
|
||||||
|
images.
|
||||||
|
|
||||||
2015-10-09 Fred Kiefer <FredKiefer@gmx.de>
|
2015-10-09 Fred Kiefer <FredKiefer@gmx.de>
|
||||||
|
|
||||||
* Source/NSGraphicsContext.m (-initWithContextInfo:): Move the
|
* Source/NSGraphicsContext.m (-initWithContextInfo:): Move the
|
||||||
|
|
|
@ -61,7 +61,13 @@
|
||||||
/* Backend methods (optional) */
|
/* Backend methods (optional) */
|
||||||
@interface NSBitmapImageRep (GSPrivate)
|
@interface NSBitmapImageRep (GSPrivate)
|
||||||
// GNUstep extension
|
// GNUstep extension
|
||||||
- _initFromTIFFImage: (TIFF *)image number: (int)imageNumber;
|
+ (BOOL) _bitmapIsTIFF: (NSData *)data;
|
||||||
|
+ (NSArray*) _imageRepsWithTIFFData: (NSData *)imageData;
|
||||||
|
- (NSBitmapImageRep *) _initBitmapFromTIFF: (NSData *)imageData;
|
||||||
|
- (NSBitmapImageRep *) _initFromTIFFImage: (TIFF *)image number: (int)imageNumber;
|
||||||
|
- (void) _fillTIFFInfo: (NSTiffInfo*)info
|
||||||
|
usingCompression: (NSTIFFCompression)type
|
||||||
|
factor: (float)factor;
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
+ (int) _localFromCompressionType: (NSTIFFCompression)type;
|
+ (int) _localFromCompressionType: (NSTIFFCompression)type;
|
||||||
|
@ -98,39 +104,36 @@
|
||||||
/** Returns YES if the image stored in data can be read and decoded */
|
/** Returns YES if the image stored in data can be read and decoded */
|
||||||
+ (BOOL) canInitWithData: (NSData *)data
|
+ (BOOL) canInitWithData: (NSData *)data
|
||||||
{
|
{
|
||||||
TIFF *image = NULL;
|
|
||||||
|
|
||||||
if (data == nil)
|
if (data == nil)
|
||||||
{
|
{
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_LIBPNG
|
||||||
if ([self _bitmapIsPNG: data])
|
if ([self _bitmapIsPNG: data])
|
||||||
return YES;
|
return YES;
|
||||||
|
#endif
|
||||||
|
|
||||||
if ([self _bitmapIsPNM: data])
|
if ([self _bitmapIsPNM: data])
|
||||||
return YES;
|
return YES;
|
||||||
|
|
||||||
|
#if HAVE_LIBJPEG
|
||||||
if ([self _bitmapIsJPEG: data])
|
if ([self _bitmapIsJPEG: data])
|
||||||
return YES;
|
return YES;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_LIBUNGIF || HAVE_LIBGIF
|
||||||
if ([self _bitmapIsGIF: data])
|
if ([self _bitmapIsGIF: data])
|
||||||
return YES;
|
return YES;
|
||||||
|
#endif
|
||||||
|
|
||||||
if ([self _bitmapIsICNS: data])
|
if ([self _bitmapIsICNS: data])
|
||||||
return YES;
|
return YES;
|
||||||
|
|
||||||
image = NSTiffOpenDataRead ((char *)[data bytes], [data length]);
|
if ([self _bitmapIsTIFF: data])
|
||||||
|
return YES;
|
||||||
|
|
||||||
if (image != NULL)
|
return NO;
|
||||||
{
|
|
||||||
NSTiffClose (image);
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a list of image filename extensions that are understood by
|
/** Returns a list of image filename extensions that are understood by
|
||||||
|
@ -189,10 +192,6 @@
|
||||||
*/
|
*/
|
||||||
+ (NSArray*) imageRepsWithData: (NSData *)imageData
|
+ (NSArray*) imageRepsWithData: (NSData *)imageData
|
||||||
{
|
{
|
||||||
int i, images;
|
|
||||||
TIFF *image;
|
|
||||||
NSMutableArray *array;
|
|
||||||
|
|
||||||
if (imageData == nil)
|
if (imageData == nil)
|
||||||
{
|
{
|
||||||
NSLog(@"NSBitmapImageRep: nil image data");
|
NSLog(@"NSBitmapImageRep: nil image data");
|
||||||
|
@ -259,36 +258,20 @@
|
||||||
return [self _imageRepsWithICNSData: imageData];
|
return [self _imageRepsWithICNSData: imageData];
|
||||||
}
|
}
|
||||||
|
|
||||||
image = NSTiffOpenDataRead((char *)[imageData bytes], [imageData length]);
|
if ([self _bitmapIsTIFF: imageData])
|
||||||
if (image == NULL)
|
|
||||||
{
|
{
|
||||||
NSLog(@"NSBitmapImageRep: unable to parse TIFF data");
|
return [self _imageRepsWithTIFFData: imageData];
|
||||||
return [NSArray array];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
images = NSTiffGetImageCount(image);
|
NSLog(@"NSBitmapImageRep: unable to parse bitmap image data");
|
||||||
NSDebugLLog(@"NSImage", @"Image contains %d directories", images);
|
return [NSArray array];
|
||||||
array = [NSMutableArray arrayWithCapacity: images];
|
|
||||||
for (i = 0; i < images; i++)
|
|
||||||
{
|
|
||||||
NSBitmapImageRep* imageRep;
|
|
||||||
imageRep = [[self alloc] _initFromTIFFImage: image number: i];
|
|
||||||
if (imageRep)
|
|
||||||
{
|
|
||||||
[array addObject: imageRep];
|
|
||||||
RELEASE(imageRep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NSTiffClose(image);
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Loads only the default (first) image from the image contained in
|
/** Loads only the default (first) image from the image contained in
|
||||||
data. */
|
data. */
|
||||||
- (id) initWithData: (NSData *)imageData
|
- (id) initWithData: (NSData *)imageData
|
||||||
{
|
{
|
||||||
TIFF *image;
|
Class class;
|
||||||
|
|
||||||
if (imageData == nil)
|
if (imageData == nil)
|
||||||
{
|
{
|
||||||
|
@ -296,36 +279,30 @@
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([object_getClass(self) _bitmapIsPNG: imageData])
|
class = [self class];
|
||||||
|
if ([class _bitmapIsPNG: imageData])
|
||||||
return [self _initBitmapFromPNG: imageData];
|
return [self _initBitmapFromPNG: imageData];
|
||||||
|
|
||||||
if ([object_getClass(self) _bitmapIsPNM: imageData])
|
if ([class _bitmapIsPNM: imageData])
|
||||||
return [self _initBitmapFromPNM: imageData
|
return [self _initBitmapFromPNM: imageData
|
||||||
errorMessage: NULL];
|
errorMessage: NULL];
|
||||||
|
|
||||||
if ([object_getClass(self) _bitmapIsJPEG: imageData])
|
if ([class _bitmapIsJPEG: imageData])
|
||||||
return [self _initBitmapFromJPEG: imageData
|
return [self _initBitmapFromJPEG: imageData
|
||||||
errorMessage: NULL];
|
errorMessage: NULL];
|
||||||
|
|
||||||
if ([object_getClass(self) _bitmapIsGIF: imageData])
|
if ([class _bitmapIsGIF: imageData])
|
||||||
return [self _initBitmapFromGIF: imageData
|
return [self _initBitmapFromGIF: imageData
|
||||||
errorMessage: NULL];
|
errorMessage: NULL];
|
||||||
|
|
||||||
if ([object_getClass(self) _bitmapIsICNS: imageData])
|
if ([class _bitmapIsICNS: imageData])
|
||||||
return [self _initBitmapFromICNS: imageData];
|
return [self _initBitmapFromICNS: imageData];
|
||||||
|
|
||||||
image = NSTiffOpenDataRead((char *)[imageData bytes], [imageData length]);
|
if ([class _bitmapIsTIFF: imageData])
|
||||||
if (image == NULL)
|
return [self _initBitmapFromTIFF: imageData];
|
||||||
{
|
|
||||||
RELEASE(self);
|
|
||||||
NSLog(@"Tiff read invalid TIFF info from data");
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
[self _initFromTIFFImage: image number: -1];
|
DESTROY(self);
|
||||||
NSTiffClose(image);
|
return nil;
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initialize with bitmap data from a rect within the focused view */
|
/** Initialize with bitmap data from a rect within the focused view */
|
||||||
|
@ -861,7 +838,7 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
||||||
}
|
}
|
||||||
|
|
||||||
line_offset = _bytesPerRow * y;
|
line_offset = _bytesPerRow * y;
|
||||||
if(_isPlanar)
|
if (_isPlanar)
|
||||||
{
|
{
|
||||||
if (_bitsPerSample == 8)
|
if (_bitsPerSample == 8)
|
||||||
{
|
{
|
||||||
|
@ -1393,48 +1370,89 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
||||||
//
|
//
|
||||||
/** Produces an NSData object containing a TIFF representation of all
|
/** Produces an NSData object containing a TIFF representation of all
|
||||||
the images stored in anArray. BUGS: Currently this only works if the
|
the images stored in anArray. BUGS: Currently this only works if the
|
||||||
images are NSBitmapImageRep objects, and it only creates an TIFF from the
|
images are NSBitmapImageRep objects. */
|
||||||
first image in the array. */
|
|
||||||
+ (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray *)anArray
|
+ (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray *)anArray
|
||||||
{
|
{
|
||||||
//FIXME: This only outputs one of the ImageReps
|
|
||||||
NSEnumerator *enumerator = [anArray objectEnumerator];
|
NSEnumerator *enumerator = [anArray objectEnumerator];
|
||||||
NSImageRep *rep;
|
NSImageRep *rep;
|
||||||
|
TIFF *image;
|
||||||
|
NSTiffInfo info;
|
||||||
|
char *bytes = 0;
|
||||||
|
long length = 0;
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
image = NSTiffOpenDataWrite(&bytes, &length);
|
||||||
|
if (image == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSTIFFException
|
||||||
|
format: @"Opening data stream for writting"];
|
||||||
|
}
|
||||||
|
|
||||||
while ((rep = [enumerator nextObject]) != nil)
|
while ((rep = [enumerator nextObject]) != nil)
|
||||||
{
|
{
|
||||||
if ([rep isKindOfClass: self])
|
if ([rep isKindOfClass: self])
|
||||||
{
|
{
|
||||||
return [(NSBitmapImageRep*)rep TIFFRepresentation];
|
NSTIFFCompression compression;
|
||||||
|
float factor;
|
||||||
|
NSBitmapImageRep *bitmap = (NSBitmapImageRep*)rep;
|
||||||
|
|
||||||
|
[bitmap getCompression: &compression
|
||||||
|
factor: &factor];
|
||||||
|
[bitmap _fillTIFFInfo: &info
|
||||||
|
usingCompression: compression
|
||||||
|
factor: factor];
|
||||||
|
info.imageNumber = num++;
|
||||||
|
info.numImages = [anArray count];
|
||||||
|
info.subfileType = FILETYPE_PAGE;
|
||||||
|
if (NSTiffWrite(image, &info, [bitmap bitmapData]) != 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSTIFFException format: @"Writing data"];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
NSTiffClose(image);
|
||||||
|
return [NSData dataWithBytesNoCopy: bytes length: length];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Produces an NSData object containing a TIFF representation of all
|
/** Produces an NSData object containing a TIFF representation of all
|
||||||
the images stored in anArray. The image is compressed according to
|
the images stored in anArray. The image is compressed according to
|
||||||
the compression type and factor. BUGS: Currently this only works if
|
the compression type and factor. BUGS: Currently this only works if
|
||||||
the images are NSBitmapImageRep objects, and it only creates an
|
the images are NSBitmapImageRep objects. */
|
||||||
TIFF from the first image in the array. */
|
|
||||||
+ (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray *)anArray
|
+ (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray *)anArray
|
||||||
usingCompression: (NSTIFFCompression)type
|
usingCompression: (NSTIFFCompression)compression
|
||||||
factor: (float)factor
|
factor: (float)factor
|
||||||
{
|
{
|
||||||
//FIXME: This only outputs one of the ImageReps
|
|
||||||
NSEnumerator *enumerator = [anArray objectEnumerator];
|
NSEnumerator *enumerator = [anArray objectEnumerator];
|
||||||
NSImageRep *rep;
|
NSImageRep *rep;
|
||||||
|
NSTiffInfo info;
|
||||||
|
TIFF *image;
|
||||||
|
char *bytes = 0;
|
||||||
|
long length = 0;
|
||||||
|
|
||||||
|
image = NSTiffOpenDataWrite(&bytes, &length);
|
||||||
|
if (image == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSTIFFException
|
||||||
|
format: @"Opening data stream for writting"];
|
||||||
|
}
|
||||||
|
|
||||||
while ((rep = [enumerator nextObject]) != nil)
|
while ((rep = [enumerator nextObject]) != nil)
|
||||||
{
|
{
|
||||||
if ([rep isKindOfClass: self])
|
if ([rep isKindOfClass: self])
|
||||||
{
|
{
|
||||||
return [(NSBitmapImageRep*)rep TIFFRepresentationUsingCompression: type
|
[(NSBitmapImageRep*)rep _fillTIFFInfo: &info
|
||||||
factor: factor];
|
usingCompression: compression
|
||||||
|
factor: factor];
|
||||||
|
if (NSTiffWrite(image, &info, [(NSBitmapImageRep*)rep bitmapData]) != 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSTIFFException format: @"Writing data"];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
NSTiffClose(image);
|
||||||
|
return [NSData dataWithBytesNoCopy: bytes length: length];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns an NSData object containing a TIFF representation of the
|
/** Returns an NSData object containing a TIFF representation of the
|
||||||
|
@ -1452,7 +1470,7 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
||||||
/** Returns an NSData object containing a TIFF representation of the
|
/** Returns an NSData object containing a TIFF representation of the
|
||||||
receiver. The TIFF data is compressed using compresssion type
|
receiver. The TIFF data is compressed using compresssion type
|
||||||
and factor. */
|
and factor. */
|
||||||
- (NSData*) TIFFRepresentationUsingCompression: (NSTIFFCompression)type
|
- (NSData*) TIFFRepresentationUsingCompression: (NSTIFFCompression)compression
|
||||||
factor: (float)factor
|
factor: (float)factor
|
||||||
{
|
{
|
||||||
NSTiffInfo info;
|
NSTiffInfo info;
|
||||||
|
@ -1460,56 +1478,16 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
||||||
char *bytes = 0;
|
char *bytes = 0;
|
||||||
long length = 0;
|
long length = 0;
|
||||||
|
|
||||||
info.imageNumber = 0;
|
|
||||||
info.subfileType = 255;
|
|
||||||
info.width = _pixelsWide;
|
|
||||||
info.height = _pixelsHigh;
|
|
||||||
info.bitsPerSample = _bitsPerSample;
|
|
||||||
info.samplesPerPixel = _numColors;
|
|
||||||
|
|
||||||
if ([self canBeCompressedUsing: type] == NO)
|
|
||||||
{
|
|
||||||
type = NSTIFFCompressionNone;
|
|
||||||
factor = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_isPlanar)
|
|
||||||
info.planarConfig = PLANARCONFIG_SEPARATE;
|
|
||||||
else
|
|
||||||
info.planarConfig = PLANARCONFIG_CONTIG;
|
|
||||||
|
|
||||||
if ([_colorSpace isEqual: NSDeviceRGBColorSpace]
|
|
||||||
|| [_colorSpace isEqual: NSCalibratedRGBColorSpace])
|
|
||||||
info.photoInterp = PHOTOMETRIC_RGB;
|
|
||||||
else if ([_colorSpace isEqual: NSDeviceWhiteColorSpace]
|
|
||||||
|| [_colorSpace isEqual: NSCalibratedWhiteColorSpace])
|
|
||||||
info.photoInterp = PHOTOMETRIC_MINISBLACK;
|
|
||||||
else if ([_colorSpace isEqual: NSDeviceBlackColorSpace]
|
|
||||||
|| [_colorSpace isEqual: NSCalibratedBlackColorSpace])
|
|
||||||
info.photoInterp = PHOTOMETRIC_MINISWHITE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NSWarnMLog(@"Unknown colorspace %@.", _colorSpace);
|
|
||||||
info.photoInterp = PHOTOMETRIC_RGB;
|
|
||||||
}
|
|
||||||
|
|
||||||
info.extraSamples = (_hasAlpha) ? 1 : 0;
|
|
||||||
info.assocAlpha = (_format & NSAlphaNonpremultipliedBitmapFormat) ? 0 : 1;
|
|
||||||
info.compression = [NSBitmapImageRep _localFromCompressionType: type];
|
|
||||||
if (factor < 0)
|
|
||||||
factor = 0;
|
|
||||||
if (factor > 1)
|
|
||||||
factor = 1;
|
|
||||||
info.quality = factor * 100;
|
|
||||||
info.numImages = 1;
|
|
||||||
info.error = 0;
|
|
||||||
|
|
||||||
image = NSTiffOpenDataWrite(&bytes, &length);
|
image = NSTiffOpenDataWrite(&bytes, &length);
|
||||||
if (image == 0)
|
if (image == 0)
|
||||||
{
|
{
|
||||||
[NSException raise: NSTIFFException
|
[NSException raise: NSTIFFException
|
||||||
format: @"Opening data stream for writting"];
|
format: @"Opening data stream for writting"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self _fillTIFFInfo: &info
|
||||||
|
usingCompression: compression
|
||||||
|
factor: factor];
|
||||||
if (NSTiffWrite(image, &info, [self bitmapData]) != 0)
|
if (NSTiffWrite(image, &info, [self bitmapData]) != 0)
|
||||||
{
|
{
|
||||||
[NSException raise: NSTIFFException format: @"Writing data"];
|
[NSException raise: NSTIFFException format: @"Writing data"];
|
||||||
|
@ -1533,13 +1511,35 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
||||||
NSEnumerator *enumerator = [imageReps objectEnumerator];
|
NSEnumerator *enumerator = [imageReps objectEnumerator];
|
||||||
NSImageRep *rep;
|
NSImageRep *rep;
|
||||||
|
|
||||||
while ((rep = [enumerator nextObject]) != nil)
|
if (storageType == NSTIFFFileType)
|
||||||
{
|
{
|
||||||
if ([rep isKindOfClass: self])
|
NSNumber *comp_property = [properties objectForKey: NSImageCompressionMethod];
|
||||||
|
NSNumber *factor_property = [properties objectForKey: NSImageCompressionFactor];
|
||||||
|
|
||||||
|
if ((comp_property != nil) && (factor_property != nil))
|
||||||
{
|
{
|
||||||
return [(NSBitmapImageRep*)rep representationUsingType: storageType
|
float factor = [factor_property floatValue];
|
||||||
properties: properties];
|
NSTIFFCompression compression = [comp_property unsignedShortValue];
|
||||||
}
|
|
||||||
|
return [self TIFFRepresentationOfImageRepsInArray: imageReps
|
||||||
|
usingCompression: compression
|
||||||
|
factor: factor];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return [self TIFFRepresentationOfImageRepsInArray: imageReps];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while ((rep = [enumerator nextObject]) != nil)
|
||||||
|
{
|
||||||
|
if ([rep isKindOfClass: self])
|
||||||
|
{
|
||||||
|
return [(NSBitmapImageRep*)rep representationUsingType: storageType
|
||||||
|
properties: properties];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -1562,7 +1562,7 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
||||||
{
|
{
|
||||||
case NSTIFFFileType:
|
case NSTIFFFileType:
|
||||||
{
|
{
|
||||||
NSNumber * property;
|
NSNumber *property;
|
||||||
float factor = _comp_factor;
|
float factor = _comp_factor;
|
||||||
NSTIFFCompression compression = _compression;
|
NSTIFFCompression compression = _compression;
|
||||||
if ((property = [__properties objectForKey: NSImageCompressionMethod]))
|
if ((property = [__properties objectForKey: NSImageCompressionMethod]))
|
||||||
|
@ -1866,10 +1866,71 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
||||||
return NSTIFFCompressionNone;
|
return NSTIFFCompressionNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (BOOL) _bitmapIsTIFF: (NSData *)data
|
||||||
|
{
|
||||||
|
TIFF *image = NSTiffOpenDataRead((char *)[data bytes], [data length]);
|
||||||
|
|
||||||
|
if (image != NULL)
|
||||||
|
{
|
||||||
|
NSTiffClose(image);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray*) _imageRepsWithTIFFData: (NSData *)imageData
|
||||||
|
{
|
||||||
|
int i, images;
|
||||||
|
TIFF *image;
|
||||||
|
NSMutableArray *array;
|
||||||
|
|
||||||
|
image = NSTiffOpenDataRead((char *)[imageData bytes], [imageData length]);
|
||||||
|
if (image == NULL)
|
||||||
|
{
|
||||||
|
NSLog(@"NSBitmapImageRep: unable to parse TIFF data");
|
||||||
|
return [NSArray array];
|
||||||
|
}
|
||||||
|
|
||||||
|
images = NSTiffGetImageCount(image);
|
||||||
|
NSDebugLLog(@"NSImage", @"Image contains %d directories", images);
|
||||||
|
array = [NSMutableArray arrayWithCapacity: images];
|
||||||
|
for (i = 0; i < images; i++)
|
||||||
|
{
|
||||||
|
NSBitmapImageRep* imageRep;
|
||||||
|
imageRep = [[self alloc] _initFromTIFFImage: image number: i];
|
||||||
|
if (imageRep)
|
||||||
|
{
|
||||||
|
[array addObject: imageRep];
|
||||||
|
RELEASE(imageRep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NSTiffClose(image);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSBitmapImageRep *) _initBitmapFromTIFF: (NSData *)imageData
|
||||||
|
{
|
||||||
|
TIFF *image = NSTiffOpenDataRead((char *)[imageData bytes], [imageData length]);
|
||||||
|
|
||||||
|
if (image == NULL)
|
||||||
|
{
|
||||||
|
RELEASE(self);
|
||||||
|
NSLog(@"Tiff read invalid TIFF info from data");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self _initFromTIFFImage: image number: -1];
|
||||||
|
NSTiffClose(image);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
/* Given a TIFF image (from the libtiff library), load the image information
|
/* Given a TIFF image (from the libtiff library), load the image information
|
||||||
into our data structure. Reads the specified image. */
|
into our data structure. Reads the specified image. */
|
||||||
- _initFromTIFFImage: (TIFF *)image number: (int)imageNumber
|
- (NSBitmapImageRep *) _initFromTIFFImage: (TIFF *)image number: (int)imageNumber
|
||||||
{
|
{
|
||||||
NSString* space;
|
NSString* space;
|
||||||
NSTiffInfo* info;
|
NSTiffInfo* info;
|
||||||
|
@ -1940,6 +2001,56 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) _fillTIFFInfo: (NSTiffInfo*)info
|
||||||
|
usingCompression: (NSTIFFCompression)type
|
||||||
|
factor: (float)factor
|
||||||
|
{
|
||||||
|
info->numImages = 1;
|
||||||
|
info->imageNumber = 0;
|
||||||
|
info->subfileType = 255;
|
||||||
|
info->width = _pixelsWide;
|
||||||
|
info->height = _pixelsHigh;
|
||||||
|
info->bitsPerSample = _bitsPerSample;
|
||||||
|
info->samplesPerPixel = _numColors;
|
||||||
|
|
||||||
|
if (_isPlanar)
|
||||||
|
info->planarConfig = PLANARCONFIG_SEPARATE;
|
||||||
|
else
|
||||||
|
info->planarConfig = PLANARCONFIG_CONTIG;
|
||||||
|
|
||||||
|
if ([_colorSpace isEqual: NSDeviceRGBColorSpace]
|
||||||
|
|| [_colorSpace isEqual: NSCalibratedRGBColorSpace])
|
||||||
|
info->photoInterp = PHOTOMETRIC_RGB;
|
||||||
|
else if ([_colorSpace isEqual: NSDeviceWhiteColorSpace]
|
||||||
|
|| [_colorSpace isEqual: NSCalibratedWhiteColorSpace])
|
||||||
|
info->photoInterp = PHOTOMETRIC_MINISBLACK;
|
||||||
|
else if ([_colorSpace isEqual: NSDeviceBlackColorSpace]
|
||||||
|
|| [_colorSpace isEqual: NSCalibratedBlackColorSpace])
|
||||||
|
info->photoInterp = PHOTOMETRIC_MINISWHITE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSWarnMLog(@"Unknown colorspace %@.", _colorSpace);
|
||||||
|
info->photoInterp = PHOTOMETRIC_RGB;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->extraSamples = (_hasAlpha) ? 1 : 0;
|
||||||
|
info->assocAlpha = (_format & NSAlphaNonpremultipliedBitmapFormat) ? 0 : 1;
|
||||||
|
|
||||||
|
if ([self canBeCompressedUsing: type] == NO)
|
||||||
|
{
|
||||||
|
type = NSTIFFCompressionNone;
|
||||||
|
factor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->compression = [NSBitmapImageRep _localFromCompressionType: type];
|
||||||
|
if (factor < 0)
|
||||||
|
factor = 0;
|
||||||
|
if (factor > 1)
|
||||||
|
factor = 1;
|
||||||
|
info->quality = factor * 100;
|
||||||
|
info->error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
- (void) _premultiply
|
- (void) _premultiply
|
||||||
{
|
{
|
||||||
NSInteger x, y;
|
NSInteger x, y;
|
||||||
|
@ -1968,25 +2079,65 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
||||||
|
|
||||||
if (_bitsPerSample == 8)
|
if (_bitsPerSample == 8)
|
||||||
{
|
{
|
||||||
NSUInteger a;
|
if (!_isPlanar)
|
||||||
|
|
||||||
for (y = 0; y < _pixelsHigh; y++)
|
|
||||||
{
|
{
|
||||||
for (x = 0; x < _pixelsWide; x++)
|
// Optimize for the most common case
|
||||||
{
|
NSUInteger a;
|
||||||
//[self getPixel: pixelData atX: x y: y];
|
NSInteger offset;
|
||||||
getP(self, getPSel, pixelData, x, y);
|
NSInteger line_offset;
|
||||||
a = pixelData[ai];
|
|
||||||
if (a != 255)
|
|
||||||
{
|
|
||||||
for (i = start; i < end; i++)
|
|
||||||
{
|
|
||||||
NSUInteger t = a * pixelData[i] + 0x80;
|
|
||||||
|
|
||||||
pixelData[i] = ((t >> 8) + t) >> 8;
|
for (y = 0; y < _pixelsHigh; y++)
|
||||||
|
{
|
||||||
|
line_offset = _bytesPerRow * y + _bitsPerPixel / 8;
|
||||||
|
for (x = 0; x < _pixelsWide; x++)
|
||||||
|
{
|
||||||
|
offset = x + line_offset;
|
||||||
|
a = _imagePlanes[0][offset + ai];
|
||||||
|
if ((a != 0) && (a != 255))
|
||||||
|
{
|
||||||
|
for (i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
NSUInteger v = _imagePlanes[0][offset + i];
|
||||||
|
NSUInteger c;
|
||||||
|
|
||||||
|
c = (v * 255) / a;
|
||||||
|
if (c >= 255)
|
||||||
|
{
|
||||||
|
v = 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
_imagePlanes[0][offset + i] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSUInteger a;
|
||||||
|
|
||||||
|
for (y = 0; y < _pixelsHigh; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < _pixelsWide; x++)
|
||||||
|
{
|
||||||
|
//[self getPixel: pixelData atX: x y: y];
|
||||||
|
getP(self, getPSel, pixelData, x, y);
|
||||||
|
a = pixelData[ai];
|
||||||
|
if (a != 255)
|
||||||
|
{
|
||||||
|
for (i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
NSUInteger t = a * pixelData[i] + 0x80;
|
||||||
|
|
||||||
|
pixelData[i] = ((t >> 8) + t) >> 8;
|
||||||
|
}
|
||||||
|
//[self setPixel: pixelData atX: x y: y];
|
||||||
|
setP(self, setPSel, pixelData, x, y);
|
||||||
}
|
}
|
||||||
//[self setPixel: pixelData atX: x y: y];
|
|
||||||
setP(self, setPSel, pixelData, x, y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2045,33 +2196,74 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
||||||
|
|
||||||
if (_bitsPerSample == 8)
|
if (_bitsPerSample == 8)
|
||||||
{
|
{
|
||||||
NSUInteger a;
|
if (!_isPlanar)
|
||||||
|
|
||||||
for (y = 0; y < _pixelsHigh; y++)
|
|
||||||
{
|
{
|
||||||
for (x = 0; x < _pixelsWide; x++)
|
// Optimize for the most common case
|
||||||
|
NSUInteger a;
|
||||||
|
NSInteger offset;
|
||||||
|
NSInteger line_offset;
|
||||||
|
|
||||||
|
for (y = 0; y < _pixelsHigh; y++)
|
||||||
{
|
{
|
||||||
//[self getPixel: pixelData atX: x y: y];
|
line_offset = _bytesPerRow * y + _bitsPerPixel / 8;
|
||||||
getP(self, getPSel, pixelData, x, y);
|
for (x = 0; x < _pixelsWide; x++)
|
||||||
a = pixelData[ai];
|
|
||||||
if ((a != 0) && (a != 255))
|
|
||||||
{
|
{
|
||||||
for (i = start; i < end; i++)
|
offset = x + line_offset;
|
||||||
|
a = _imagePlanes[0][offset + ai];
|
||||||
|
if (a != 255)
|
||||||
{
|
{
|
||||||
NSUInteger c;
|
if (a == 0)
|
||||||
|
|
||||||
c = (pixelData[i] * 255) / a;
|
|
||||||
if (c >= 255)
|
|
||||||
{
|
{
|
||||||
pixelData[i] = 255;
|
for (i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
_imagePlanes[0][offset + i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pixelData[i] = c;
|
for (i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
NSUInteger v = _imagePlanes[0][offset + i];
|
||||||
|
NSUInteger t = a * v + 0x80;
|
||||||
|
|
||||||
|
v = ((t >> 8) + t) >> 8;
|
||||||
|
_imagePlanes[0][offset + i] = v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//[self setPixel: pixelData atX: x y: y];
|
}
|
||||||
setP(self, setPSel, pixelData, x, y);
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSUInteger a;
|
||||||
|
|
||||||
|
for (y = 0; y < _pixelsHigh; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < _pixelsWide; x++)
|
||||||
|
{
|
||||||
|
//[self getPixel: pixelData atX: x y: y];
|
||||||
|
getP(self, getPSel, pixelData, x, y);
|
||||||
|
a = pixelData[ai];
|
||||||
|
if ((a != 0) && (a != 255))
|
||||||
|
{
|
||||||
|
for (i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
NSUInteger c;
|
||||||
|
|
||||||
|
c = (pixelData[i] * 255) / a;
|
||||||
|
if (c >= 255)
|
||||||
|
{
|
||||||
|
pixelData[i] = 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pixelData[i] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//[self setPixel: pixelData atX: x y: y];
|
||||||
|
setP(self, setPSel, pixelData, x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1518,7 +1518,7 @@ static NSSize GSResolutionOfImageRep(NSImageRep *rep)
|
||||||
NSData *data;
|
NSData *data;
|
||||||
|
|
||||||
// As a result of using bitmap representations, new drawing wont show on the tiff data.
|
// As a result of using bitmap representations, new drawing wont show on the tiff data.
|
||||||
data = [bitmapClass TIFFRepresentationOfImageRepsInArray: [self representations]];
|
data = [bitmapClass TIFFRepresentationOfImageRepsInArray: [self _representationsWithCachedImages: NO]];
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
|
@ -1547,7 +1547,7 @@ static NSSize GSResolutionOfImageRep(NSImageRep *rep)
|
||||||
NSData *data;
|
NSData *data;
|
||||||
|
|
||||||
// As a result of using bitmap representations, new drawing wont show on the tiff data.
|
// As a result of using bitmap representations, new drawing wont show on the tiff data.
|
||||||
data = [bitmapClass TIFFRepresentationOfImageRepsInArray: [self representations]
|
data = [bitmapClass TIFFRepresentationOfImageRepsInArray: [self _representationsWithCachedImages: NO]
|
||||||
usingCompression: comp
|
usingCompression: comp
|
||||||
factor: aFloat];
|
factor: aFloat];
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,8 @@
|
||||||
|
|
||||||
/* Structure to store common information about a tiff. */
|
/* Structure to store common information about a tiff. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32 imageNumber;
|
uint16 numImages; /* number of images in tiff */
|
||||||
|
uint16 imageNumber; /* number of current image */
|
||||||
uint32 subfileType;
|
uint32 subfileType;
|
||||||
uint32 width;
|
uint32 width;
|
||||||
uint32 height;
|
uint32 height;
|
||||||
|
@ -53,7 +54,6 @@ typedef struct {
|
||||||
uint16 extraSamples; /* Alpha */
|
uint16 extraSamples; /* Alpha */
|
||||||
int assocAlpha;
|
int assocAlpha;
|
||||||
int quality; /* compression quality (for jpeg) 1 to 255 */
|
int quality; /* compression quality (for jpeg) 1 to 255 */
|
||||||
int numImages; /* number of images in tiff */
|
|
||||||
int error;
|
int error;
|
||||||
float xdpi;
|
float xdpi;
|
||||||
float ydpi;
|
float ydpi;
|
||||||
|
|
|
@ -152,9 +152,10 @@ TiffHandleSeek(thandle_t handle, toff_t offset, int mode)
|
||||||
case SEEK_SET: chand->position = offset; break;
|
case SEEK_SET: chand->position = offset; break;
|
||||||
case SEEK_CUR: chand->position += offset; break;
|
case SEEK_CUR: chand->position += offset; break;
|
||||||
case SEEK_END:
|
case SEEK_END:
|
||||||
|
// FIXME: Not sure whether this check is correct
|
||||||
if (offset > 0 && chand->mode == 'r')
|
if (offset > 0 && chand->mode == 'r')
|
||||||
return 0;
|
return 0;
|
||||||
chand->position += offset; break;
|
chand->position = chand->size - ((chand->size > 0) ? 1 : 0) + offset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return chand->position;
|
return chand->position;
|
||||||
|
@ -260,6 +261,7 @@ NSTiffGetImageCount(TIFF* image)
|
||||||
{
|
{
|
||||||
dircount++;
|
dircount++;
|
||||||
}
|
}
|
||||||
|
TIFFSetDirectory(image, 0);
|
||||||
return dircount;
|
return dircount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,17 +474,25 @@ int
|
||||||
NSTiffWrite(TIFF *image, NSTiffInfo *info, unsigned char *data)
|
NSTiffWrite(TIFF *image, NSTiffInfo *info, unsigned char *data)
|
||||||
{
|
{
|
||||||
void* buf = (void*)data;
|
void* buf = (void*)data;
|
||||||
uint16 sample_info[2];
|
uint16 sample_info[1];
|
||||||
int i;
|
int i;
|
||||||
unsigned int row;
|
unsigned int row;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
tmsize_t scan_line_size;
|
tmsize_t scan_line_size;
|
||||||
|
|
||||||
|
if (info->numImages > 1)
|
||||||
|
{
|
||||||
|
/* Set the page number */
|
||||||
|
TIFFSetField(image, TIFFTAG_PAGENUMBER, info->imageNumber, info->numImages);
|
||||||
|
}
|
||||||
|
|
||||||
TIFFSetField(image, TIFFTAG_IMAGEWIDTH, info->width);
|
TIFFSetField(image, TIFFTAG_IMAGEWIDTH, info->width);
|
||||||
TIFFSetField(image, TIFFTAG_IMAGELENGTH, info->height);
|
TIFFSetField(image, TIFFTAG_IMAGELENGTH, info->height);
|
||||||
TIFFSetField(image, TIFFTAG_COMPRESSION, info->compression);
|
TIFFSetField(image, TIFFTAG_COMPRESSION, info->compression);
|
||||||
if (info->compression == COMPRESSION_JPEG)
|
if (info->compression == COMPRESSION_JPEG)
|
||||||
TIFFSetField(image, TIFFTAG_JPEGQUALITY, info->quality);
|
{
|
||||||
|
TIFFSetField(image, TIFFTAG_JPEGQUALITY, info->quality);
|
||||||
|
}
|
||||||
TIFFSetField(image, TIFFTAG_SUBFILETYPE, info->subfileType);
|
TIFFSetField(image, TIFFTAG_SUBFILETYPE, info->subfileType);
|
||||||
TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, info->bitsPerSample);
|
TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, info->bitsPerSample);
|
||||||
TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, info->samplesPerPixel);
|
TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, info->samplesPerPixel);
|
||||||
|
@ -549,7 +559,11 @@ NSTiffWrite(TIFF *image, NSTiffInfo *info, unsigned char *data)
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write out the directory as there may be more images comming
|
||||||
|
TIFFWriteDirectory(image);
|
||||||
|
TIFFFlush(image);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue