diff --git a/ChangeLog b/ChangeLog index 042ded95c..e95f6bf48 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2015-10-10 Fred Kiefer + + * 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 * Source/NSGraphicsContext.m (-initWithContextInfo:): Move the diff --git a/Source/NSBitmapImageRep.m b/Source/NSBitmapImageRep.m index d9b8a3de6..fc26ec611 100644 --- a/Source/NSBitmapImageRep.m +++ b/Source/NSBitmapImageRep.m @@ -61,7 +61,13 @@ /* Backend methods (optional) */ @interface NSBitmapImageRep (GSPrivate) // 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 + (int) _localFromCompressionType: (NSTIFFCompression)type; @@ -98,39 +104,36 @@ /** Returns YES if the image stored in data can be read and decoded */ + (BOOL) canInitWithData: (NSData *)data { - TIFF *image = NULL; - if (data == nil) { return NO; } +#if HAVE_LIBPNG if ([self _bitmapIsPNG: data]) return YES; +#endif if ([self _bitmapIsPNM: data]) return YES; +#if HAVE_LIBJPEG if ([self _bitmapIsJPEG: data]) return YES; +#endif +#if HAVE_LIBUNGIF || HAVE_LIBGIF if ([self _bitmapIsGIF: data]) return YES; +#endif if ([self _bitmapIsICNS: data]) return YES; - image = NSTiffOpenDataRead ((char *)[data bytes], [data length]); + if ([self _bitmapIsTIFF: data]) + return YES; - if (image != NULL) - { - NSTiffClose (image); - return YES; - } - else - { - return NO; - } + return NO; } /** Returns a list of image filename extensions that are understood by @@ -189,10 +192,6 @@ */ + (NSArray*) imageRepsWithData: (NSData *)imageData { - int i, images; - TIFF *image; - NSMutableArray *array; - if (imageData == nil) { NSLog(@"NSBitmapImageRep: nil image data"); @@ -259,36 +258,20 @@ return [self _imageRepsWithICNSData: imageData]; } - image = NSTiffOpenDataRead((char *)[imageData bytes], [imageData length]); - if (image == NULL) + if ([self _bitmapIsTIFF: imageData]) { - NSLog(@"NSBitmapImageRep: unable to parse TIFF data"); - return [NSArray array]; + return [self _imageRepsWithTIFFData: imageData]; } - 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; + NSLog(@"NSBitmapImageRep: unable to parse bitmap image data"); + return [NSArray array]; } /** Loads only the default (first) image from the image contained in data. */ - (id) initWithData: (NSData *)imageData { - TIFF *image; + Class class; if (imageData == nil) { @@ -296,36 +279,30 @@ return nil; } - if ([object_getClass(self) _bitmapIsPNG: imageData]) + class = [self class]; + if ([class _bitmapIsPNG: imageData]) return [self _initBitmapFromPNG: imageData]; - if ([object_getClass(self) _bitmapIsPNM: imageData]) + if ([class _bitmapIsPNM: imageData]) return [self _initBitmapFromPNM: imageData errorMessage: NULL]; - if ([object_getClass(self) _bitmapIsJPEG: imageData]) + if ([class _bitmapIsJPEG: imageData]) return [self _initBitmapFromJPEG: imageData errorMessage: NULL]; - if ([object_getClass(self) _bitmapIsGIF: imageData]) + if ([class _bitmapIsGIF: imageData]) return [self _initBitmapFromGIF: imageData errorMessage: NULL]; - if ([object_getClass(self) _bitmapIsICNS: imageData]) + if ([class _bitmapIsICNS: imageData]) return [self _initBitmapFromICNS: imageData]; - image = NSTiffOpenDataRead((char *)[imageData bytes], [imageData length]); - if (image == NULL) - { - RELEASE(self); - NSLog(@"Tiff read invalid TIFF info from data"); - return nil; - } + if ([class _bitmapIsTIFF: imageData]) + return [self _initBitmapFromTIFF: imageData]; - [self _initFromTIFFImage: image number: -1]; - NSTiffClose(image); - - return self; + DESTROY(self); + return nil; } /** 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; - if(_isPlanar) + if (_isPlanar) { 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 the images stored in anArray. BUGS: Currently this only works if the - images are NSBitmapImageRep objects, and it only creates an TIFF from the - first image in the array. */ + images are NSBitmapImageRep objects. */ + (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray *)anArray { - //FIXME: This only outputs one of the ImageReps NSEnumerator *enumerator = [anArray objectEnumerator]; 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) { 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 the images stored in anArray. The image is compressed according to the compression type and factor. BUGS: Currently this only works if - the images are NSBitmapImageRep objects, and it only creates an - TIFF from the first image in the array. */ + the images are NSBitmapImageRep objects. */ + (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray *)anArray - usingCompression: (NSTIFFCompression)type + usingCompression: (NSTIFFCompression)compression factor: (float)factor { - //FIXME: This only outputs one of the ImageReps NSEnumerator *enumerator = [anArray objectEnumerator]; 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) { if ([rep isKindOfClass: self]) { - return [(NSBitmapImageRep*)rep TIFFRepresentationUsingCompression: type - factor: factor]; + [(NSBitmapImageRep*)rep _fillTIFFInfo: &info + 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 @@ -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 receiver. The TIFF data is compressed using compresssion type and factor. */ -- (NSData*) TIFFRepresentationUsingCompression: (NSTIFFCompression)type +- (NSData*) TIFFRepresentationUsingCompression: (NSTIFFCompression)compression factor: (float)factor { NSTiffInfo info; @@ -1460,56 +1478,16 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width, char *bytes = 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); if (image == 0) { [NSException raise: NSTIFFException format: @"Opening data stream for writting"]; } + + [self _fillTIFFInfo: &info + usingCompression: compression + factor: factor]; if (NSTiffWrite(image, &info, [self bitmapData]) != 0) { [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]; 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 - properties: properties]; - } + float factor = [factor_property floatValue]; + 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; @@ -1562,7 +1562,7 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width, { case NSTIFFFileType: { - NSNumber * property; + NSNumber *property; float factor = _comp_factor; NSTIFFCompression compression = _compression; if ((property = [__properties objectForKey: NSImageCompressionMethod])) @@ -1866,10 +1866,71 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width, 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 into our data structure. Reads the specified image. */ -- _initFromTIFFImage: (TIFF *)image number: (int)imageNumber +- (NSBitmapImageRep *) _initFromTIFFImage: (TIFF *)image number: (int)imageNumber { NSString* space; NSTiffInfo* info; @@ -1940,6 +2001,56 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width, 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 { NSInteger x, y; @@ -1968,25 +2079,65 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width, if (_bitsPerSample == 8) { - NSUInteger a; - - for (y = 0; y < _pixelsHigh; y++) + if (!_isPlanar) { - 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; + // Optimize for the most common case + NSUInteger a; + NSInteger offset; + NSInteger line_offset; - 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) { - NSUInteger a; - - for (y = 0; y < _pixelsHigh; y++) + if (!_isPlanar) { - 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]; - getP(self, getPSel, pixelData, x, y); - a = pixelData[ai]; - if ((a != 0) && (a != 255)) + line_offset = _bytesPerRow * y + _bitsPerPixel / 8; + for (x = 0; x < _pixelsWide; x++) { - for (i = start; i < end; i++) + offset = x + line_offset; + a = _imagePlanes[0][offset + ai]; + if (a != 255) { - NSUInteger c; - - c = (pixelData[i] * 255) / a; - if (c >= 255) + if (a == 0) { - pixelData[i] = 255; + for (i = start; i < end; i++) + { + _imagePlanes[0][offset + i] = 0; + } } 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); + } } } } diff --git a/Source/NSImage.m b/Source/NSImage.m index 30dc5d2ee..330414ba7 100644 --- a/Source/NSImage.m +++ b/Source/NSImage.m @@ -1518,7 +1518,7 @@ static NSSize GSResolutionOfImageRep(NSImageRep *rep) NSData *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) { @@ -1547,7 +1547,7 @@ static NSSize GSResolutionOfImageRep(NSImageRep *rep) NSData *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 factor: aFloat]; diff --git a/Source/nsimage-tiff.h b/Source/nsimage-tiff.h index 6f3fdd0ce..70aa6fe55 100644 --- a/Source/nsimage-tiff.h +++ b/Source/nsimage-tiff.h @@ -41,7 +41,8 @@ /* Structure to store common information about a tiff. */ typedef struct { - uint32 imageNumber; + uint16 numImages; /* number of images in tiff */ + uint16 imageNumber; /* number of current image */ uint32 subfileType; uint32 width; uint32 height; @@ -53,7 +54,6 @@ typedef struct { uint16 extraSamples; /* Alpha */ int assocAlpha; int quality; /* compression quality (for jpeg) 1 to 255 */ - int numImages; /* number of images in tiff */ int error; float xdpi; float ydpi; diff --git a/Source/tiff.m b/Source/tiff.m index 7dc7f8b97..b8fc58a5b 100644 --- a/Source/tiff.m +++ b/Source/tiff.m @@ -152,9 +152,10 @@ TiffHandleSeek(thandle_t handle, toff_t offset, int mode) case SEEK_SET: chand->position = offset; break; case SEEK_CUR: chand->position += offset; break; case SEEK_END: + // FIXME: Not sure whether this check is correct if (offset > 0 && chand->mode == 'r') return 0; - chand->position += offset; break; + chand->position = chand->size - ((chand->size > 0) ? 1 : 0) + offset; break; } return chand->position; @@ -260,6 +261,7 @@ NSTiffGetImageCount(TIFF* image) { dircount++; } + TIFFSetDirectory(image, 0); return dircount; } @@ -472,17 +474,25 @@ int NSTiffWrite(TIFF *image, NSTiffInfo *info, unsigned char *data) { void* buf = (void*)data; - uint16 sample_info[2]; + uint16 sample_info[1]; int i; unsigned int row; int error = 0; 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_IMAGELENGTH, info->height); TIFFSetField(image, TIFFTAG_COMPRESSION, info->compression); 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_BITSPERSAMPLE, info->bitsPerSample); TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, info->samplesPerPixel); @@ -549,7 +559,11 @@ NSTiffWrite(TIFF *image, NSTiffInfo *info, unsigned char *data) return -1; break; } - + + // Write out the directory as there may be more images comming + TIFFWriteDirectory(image); + TIFFFlush(image); + return error; }