mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-23 03:11:18 +00:00
Merge NSBitmapImageRep/+JPEG/+PNG .m files with GUI trunk revision 40273
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/branches/gnustep_testplant_branch@40279 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
25897d63e8
commit
43bbbfd027
3 changed files with 395 additions and 206 deletions
|
@ -33,6 +33,7 @@
|
|||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
#import "AppKit/NSGraphics.h"
|
||||
#import "NSBitmapImageRepPrivate.h"
|
||||
#import "NSBitmapImageRep+JPEG.h"
|
||||
#import "GSGuiPrivate.h"
|
||||
|
||||
|
@ -533,34 +534,31 @@ static void gs_jpeg_memory_dest_destroy (j_compress_ptr cinfo)
|
|||
int height;
|
||||
int row_stride;
|
||||
int quality = 90;
|
||||
NSNumber *qualityNumber = nil;
|
||||
NSNumber *progressiveNumber = nil;
|
||||
NSString *colorSpace = nil;
|
||||
BOOL isRGB;
|
||||
NSNumber *qualityNumber;
|
||||
NSNumber *progressiveNumber;
|
||||
NSString *colorSpace;
|
||||
struct jpeg_compress_struct cinfo;
|
||||
struct gs_jpeg_error_mgr jerrMgr;
|
||||
JSAMPROW row_pointer[1]; // pointer to a single row
|
||||
|
||||
// TODO: handles planar images
|
||||
|
||||
if ([self isPlanar])
|
||||
if ([self isPlanar] || [self hasAlpha])
|
||||
{
|
||||
NSString * em = @"JPEG image rep: Planar Image, not handled yet !";
|
||||
if (errorMsg != NULL)
|
||||
*errorMsg = em;
|
||||
else
|
||||
NSLog (@"JPEG image rep: Planar Image, not handled yet !");
|
||||
return nil;
|
||||
// note we will strip alpha from RGBA
|
||||
NSBitmapImageRep *converted = [self _convertToFormatBitsPerSample: _bitsPerSample
|
||||
samplesPerPixel: [self hasAlpha] ? _numColors - 1 : _numColors
|
||||
hasAlpha: NO
|
||||
isPlanar: NO
|
||||
colorSpaceName: _colorSpace
|
||||
bitmapFormat: _format & ~NSAlphaNonpremultipliedBitmapFormat & ~NSAlphaFirstBitmapFormat
|
||||
bytesPerRow: 0
|
||||
bitsPerPixel: 0];
|
||||
|
||||
return [converted _JPEGRepresentationWithProperties: properties
|
||||
errorMessage: errorMsg];
|
||||
}
|
||||
|
||||
memset((void*)&cinfo, 0, sizeof(struct jpeg_compress_struct));
|
||||
|
||||
imageSource = [self bitmapData];
|
||||
sPP = [self samplesPerPixel];
|
||||
width = [self size].width;
|
||||
height = [self size].height;
|
||||
row_stride = width * sPP;
|
||||
|
||||
/* Establish the our custom error handler */
|
||||
gs_jpeg_error_mgr_init(&jerrMgr);
|
||||
cinfo.err = jpeg_std_error(&jerrMgr.parent);
|
||||
|
@ -586,33 +584,49 @@ static void gs_jpeg_memory_dest_destroy (j_compress_ptr cinfo)
|
|||
|
||||
gs_jpeg_memory_dest_create (&cinfo, &ret);
|
||||
|
||||
// set parameters
|
||||
|
||||
colorSpace = [self colorSpaceName];
|
||||
isRGB = ([colorSpace isEqualToString: NSDeviceRGBColorSpace]
|
||||
|| [colorSpace isEqualToString: NSCalibratedRGBColorSpace]);
|
||||
imageSource = [self bitmapData];
|
||||
sPP = [self samplesPerPixel];
|
||||
width = [self size].width;
|
||||
height = [self size].height;
|
||||
row_stride = width * sPP;
|
||||
|
||||
// set parameters
|
||||
cinfo.image_width = width;
|
||||
cinfo.image_height = height;
|
||||
// note we will strip alpha from RGBA
|
||||
cinfo.input_components = (isRGB && [self hasAlpha])? 3 : sPP;
|
||||
cinfo.in_color_space = JCS_UNKNOWN;
|
||||
if (isRGB) cinfo.in_color_space = JCS_RGB;
|
||||
if (sPP == 1) cinfo.in_color_space = JCS_GRAYSCALE;
|
||||
if ([colorSpace isEqualToString: NSDeviceCMYKColorSpace])
|
||||
cinfo.input_components = sPP;
|
||||
if (sPP == 1)
|
||||
{
|
||||
cinfo.in_color_space = JCS_GRAYSCALE;
|
||||
}
|
||||
else if ([colorSpace isEqualToString: NSDeviceRGBColorSpace]
|
||||
|| [colorSpace isEqualToString: NSCalibratedRGBColorSpace])
|
||||
{
|
||||
cinfo.in_color_space = JCS_RGB;
|
||||
}
|
||||
else if ([colorSpace isEqualToString: NSDeviceCMYKColorSpace])
|
||||
{
|
||||
cinfo.in_color_space = JCS_CMYK;
|
||||
if (cinfo.in_color_space == JCS_UNKNOWN)
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"JPEG image rep: Using unknown color space with unpredictable results");
|
||||
|
||||
gs_jpeg_memory_dest_destroy (&cinfo);
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
return nil;
|
||||
}
|
||||
|
||||
jpeg_set_defaults (&cinfo);
|
||||
|
||||
// set quality
|
||||
// we expect a value between 0..1, 0 being lowest, 1 highest quality
|
||||
|
||||
qualityNumber = [properties objectForKey: NSImageCompressionFactor];
|
||||
if (qualityNumber != nil)
|
||||
{
|
||||
quality = (int) ([qualityNumber floatValue] * 100.0);
|
||||
}
|
||||
jpeg_set_quality (&cinfo, quality, TRUE);
|
||||
|
||||
// set progressive mode
|
||||
progressiveNumber = [properties objectForKey: NSImageProgressive];
|
||||
|
@ -626,35 +640,9 @@ static void gs_jpeg_memory_dest_destroy (j_compress_ptr cinfo)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
// compress the image
|
||||
|
||||
jpeg_set_quality (&cinfo, quality, TRUE);
|
||||
jpeg_start_compress (&cinfo, TRUE);
|
||||
|
||||
if (isRGB && [self hasAlpha]) // strip alpha channel before encoding
|
||||
{
|
||||
unsigned char * RGB, * pRGB, * pRGBA;
|
||||
unsigned int iRGB, iRGBA;
|
||||
RGB = malloc(sizeof(unsigned char)*3*width);
|
||||
while (cinfo.next_scanline < cinfo.image_height)
|
||||
{
|
||||
iRGBA = cinfo.next_scanline * row_stride;
|
||||
pRGBA = &imageSource[iRGBA];
|
||||
pRGB = RGB;
|
||||
for (iRGB = 0; iRGB < 3*width; iRGB += 3)
|
||||
{
|
||||
memcpy(pRGB, pRGBA, 3);
|
||||
pRGB +=3;
|
||||
pRGBA +=4;
|
||||
}
|
||||
row_pointer[0] = RGB;
|
||||
jpeg_write_scanlines (&cinfo, row_pointer, 1);
|
||||
}
|
||||
free(RGB);
|
||||
}
|
||||
else // no alpha channel
|
||||
{
|
||||
while (cinfo.next_scanline < cinfo.image_height)
|
||||
{
|
||||
int index = cinfo.next_scanline * row_stride;
|
||||
|
@ -662,12 +650,9 @@ static void gs_jpeg_memory_dest_destroy (j_compress_ptr cinfo)
|
|||
row_pointer[0] = &imageSource[index];
|
||||
jpeg_write_scanlines (&cinfo, row_pointer, 1);
|
||||
}
|
||||
}
|
||||
|
||||
jpeg_finish_compress(&cinfo);
|
||||
|
||||
gs_jpeg_memory_dest_destroy (&cinfo);
|
||||
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
|
||||
return AUTORELEASE(ret);
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
#import "AppKit/NSGraphics.h"
|
||||
#import "NSBitmapImageRepPrivate.h"
|
||||
#import "NSBitmapImageRep+PNG.h"
|
||||
|
||||
|
||||
|
@ -219,26 +220,26 @@ static void reader_func(png_structp png_struct, png_bytep data,
|
|||
png_bytep row_pointers[height];
|
||||
int i;
|
||||
|
||||
for (i=0;i<height;i++)
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
row_pointers[i]=buf+i*bytes_per_row;
|
||||
row_pointers[i] = buf + i * bytes_per_row;
|
||||
}
|
||||
|
||||
png_read_image(png_struct, row_pointers);
|
||||
}
|
||||
|
||||
self = [self initWithBitmapDataPlanes: &buf
|
||||
pixelsWide: width
|
||||
pixelsHigh: height
|
||||
bitsPerSample: depth
|
||||
samplesPerPixel: channels
|
||||
hasAlpha: alpha
|
||||
isPlanar: NO
|
||||
colorSpaceName: colorspace
|
||||
bitmapFormat: NSAlphaNonpremultipliedBitmapFormat
|
||||
bytesPerRow: bytes_per_row
|
||||
bitsPerPixel: bpp];
|
||||
|
||||
pixelsWide: width
|
||||
pixelsHigh: height
|
||||
bitsPerSample: depth
|
||||
samplesPerPixel: channels
|
||||
hasAlpha: alpha
|
||||
isPlanar: NO
|
||||
colorSpaceName: colorspace
|
||||
bitmapFormat: NSAlphaNonpremultipliedBitmapFormat
|
||||
bytesPerRow: bytes_per_row
|
||||
bitsPerPixel: bpp];
|
||||
|
||||
_imageData = [[NSData alloc]
|
||||
initWithBytesNoCopy: buf
|
||||
length: bytes_per_row * height];
|
||||
|
@ -320,10 +321,19 @@ static void writer_func(png_structp png_struct, png_bytep data,
|
|||
NSNumber * gammaNumber = nil;
|
||||
double gamma = 0.0;
|
||||
|
||||
// FIXME: Need to convert to non-pre-multiplied format
|
||||
if ([self isPlanar]) // don't handle planar yet
|
||||
// Need to convert to non-pre-multiplied format
|
||||
if ([self isPlanar] || !(_format & NSAlphaNonpremultipliedBitmapFormat))
|
||||
{
|
||||
return nil;
|
||||
NSBitmapImageRep *converted = [self _convertToFormatBitsPerSample: _bitsPerSample
|
||||
samplesPerPixel: _numColors
|
||||
hasAlpha: _hasAlpha
|
||||
isPlanar: NO
|
||||
colorSpaceName: _colorSpace
|
||||
bitmapFormat: _format | NSAlphaNonpremultipliedBitmapFormat
|
||||
bytesPerRow: _bytesPerRow
|
||||
bitsPerPixel: _bitsPerPixel];
|
||||
|
||||
return [converted _PNGRepresentationWithProperties: properties];
|
||||
}
|
||||
// get the image parameters
|
||||
width = [self pixelsWide];
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#import "NSBitmapImageRep+PNG.h"
|
||||
#import "NSBitmapImageRep+PNM.h"
|
||||
#import "NSBitmapImageRep+ICNS.h"
|
||||
#import "NSBitmapImageRepPrivate.h"
|
||||
#import "GSGuiPrivate.h"
|
||||
|
||||
#include "nsimage-tiff.h"
|
||||
|
@ -58,25 +59,6 @@
|
|||
/* Maximum number of planes */
|
||||
#define MAX_PLANES 5
|
||||
|
||||
/* Backend methods (optional) */
|
||||
@interface NSBitmapImageRep (GSPrivate)
|
||||
// GNUstep extension
|
||||
- _initFromTIFFImage: (TIFF *)image number: (int)imageNumber;
|
||||
|
||||
// Internal
|
||||
+ (int) _localFromCompressionType: (NSTIFFCompression)type;
|
||||
+ (NSTIFFCompression) _compressionTypeFromLocal: (int)type;
|
||||
- (void) _premultiply;
|
||||
- (void) _unpremultiply;
|
||||
- (NSBitmapImageRep *) _convertToFormatBitsPerSample: (NSInteger)bps
|
||||
samplesPerPixel: (NSInteger)spp
|
||||
hasAlpha: (BOOL)alpha
|
||||
isPlanar: (BOOL)isPlanar
|
||||
colorSpaceName: (NSString*)colorSpaceName
|
||||
bitmapFormat: (NSBitmapFormat)bitmapFormat
|
||||
bytesPerRow: (NSInteger)rowBytes
|
||||
bitsPerPixel: (NSInteger)pixelBits;
|
||||
@end
|
||||
|
||||
/**
|
||||
<unit>
|
||||
|
@ -98,40 +80,37 @@
|
|||
/** 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;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a list of image filename extensions that are understood by
|
||||
NSBitmapImageRep. */
|
||||
|
@ -189,10 +168,6 @@
|
|||
*/
|
||||
+ (NSArray*) imageRepsWithData: (NSData *)imageData
|
||||
{
|
||||
int i, images;
|
||||
TIFF *image;
|
||||
NSMutableArray *array;
|
||||
|
||||
if (imageData == nil)
|
||||
{
|
||||
NSLog(@"NSBitmapImageRep: nil image data");
|
||||
|
@ -259,36 +234,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);
|
||||
NSLog(@"NSBitmapImageRep: unable to parse bitmap image data");
|
||||
return [NSArray array];
|
||||
}
|
||||
}
|
||||
NSTiffClose(image);
|
||||
|
||||
return 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,38 +255,32 @@
|
|||
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");
|
||||
if ([class _bitmapIsTIFF: imageData])
|
||||
return [self _initBitmapFromTIFF: imageData];
|
||||
|
||||
DESTROY(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
[self _initFromTIFFImage: image number: -1];
|
||||
NSTiffClose(image);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/** Initialize with bitmap data from a rect within the focused view */
|
||||
- (id) initWithFocusedViewRect: (NSRect)rect
|
||||
{
|
||||
|
@ -1393,49 +1346,116 @@ _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;
|
||||
NSData *data;
|
||||
|
||||
image = NSTiffOpenDataWrite(&bytes, &length);
|
||||
if (image == 0)
|
||||
{
|
||||
[NSException raise: NSTIFFException
|
||||
format: @"Opening data stream for writing"];
|
||||
}
|
||||
|
||||
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"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSTiffClose(image);
|
||||
data = [NSData dataWithBytesNoCopy: bytes length: length];
|
||||
if (num > 0)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: Not sure wether this is the correct behaviour, at least it was
|
||||
// the old one of this method.
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
/** 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;
|
||||
int num = 0;
|
||||
NSData *data;
|
||||
|
||||
image = NSTiffOpenDataWrite(&bytes, &length);
|
||||
if (image == 0)
|
||||
{
|
||||
[NSException raise: NSTIFFException
|
||||
format: @"Opening data stream for writing"];
|
||||
}
|
||||
|
||||
while ((rep = [enumerator nextObject]) != nil)
|
||||
{
|
||||
if ([rep isKindOfClass: self])
|
||||
{
|
||||
return [(NSBitmapImageRep*)rep TIFFRepresentationUsingCompression: type
|
||||
[(NSBitmapImageRep*)rep _fillTIFFInfo: &info
|
||||
usingCompression: compression
|
||||
factor: factor];
|
||||
info.imageNumber = num++;
|
||||
info.numImages = [anArray count];
|
||||
info.subfileType = FILETYPE_PAGE;
|
||||
if (NSTiffWrite(image, &info, [(NSBitmapImageRep*)rep bitmapData]) != 0)
|
||||
{
|
||||
[NSException raise: NSTIFFException format: @"Writing data"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSTiffClose(image);
|
||||
data = [NSData dataWithBytesNoCopy: bytes length: length];
|
||||
if (num > 0)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: Not sure wether this is the correct behaviour, at least it was
|
||||
// the old one of this method.
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns an NSData object containing a TIFF representation of the
|
||||
receiver. */
|
||||
|
@ -1452,7 +1472,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 +1480,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"];
|
||||
format: @"Opening data stream for writing"];
|
||||
}
|
||||
|
||||
[self _fillTIFFInfo: &info
|
||||
usingCompression: compression
|
||||
factor: factor];
|
||||
if (NSTiffWrite(image, &info, [self bitmapData]) != 0)
|
||||
{
|
||||
[NSException raise: NSTIFFException format: @"Writing data"];
|
||||
|
@ -1533,6 +1513,27 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
|||
NSEnumerator *enumerator = [imageReps objectEnumerator];
|
||||
NSImageRep *rep;
|
||||
|
||||
if (storageType == NSTIFFFileType)
|
||||
{
|
||||
NSNumber *comp_property = [properties objectForKey: NSImageCompressionMethod];
|
||||
NSNumber *factor_property = [properties objectForKey: NSImageCompressionFactor];
|
||||
|
||||
if ((comp_property != nil) && (factor_property != nil))
|
||||
{
|
||||
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])
|
||||
|
@ -1541,6 +1542,7 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
|||
properties: properties];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
@ -1761,7 +1763,7 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
|||
|
||||
copy = (NSBitmapImageRep*)[super copyWithZone: zone];
|
||||
|
||||
copy->_properties = [_properties copyWithZone: zone];
|
||||
copy->_properties = [_properties mutableCopyWithZone: zone];
|
||||
copy->_imageData = [_imageData mutableCopyWithZone: zone];
|
||||
copy->_imagePlanes = NSZoneMalloc(zone, sizeof(unsigned char*) * MAX_PLANES);
|
||||
if (_imageData == nil)
|
||||
|
@ -1817,8 +1819,8 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
|||
self = [super initWithCoder: aDecoder];
|
||||
if ([aDecoder allowsKeyedCoding])
|
||||
{
|
||||
data = [aDecoder decodeObjectForKey: @"NSTIFFRepresentation"];
|
||||
}
|
||||
data = [aDecoder decodeObjectForKey: @"NSTIFFRepresentation"];
|
||||
}
|
||||
else
|
||||
{
|
||||
data = [aDecoder decodeObject];
|
||||
|
@ -1866,10 +1868,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 +2003,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 = 0;
|
||||
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,12 +2081,52 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
|||
|
||||
if (_bitsPerSample == 8)
|
||||
{
|
||||
if (!_isPlanar)
|
||||
{
|
||||
// Optimize for the most common case
|
||||
NSUInteger a;
|
||||
NSInteger offset;
|
||||
NSInteger line_offset;
|
||||
|
||||
for (y = 0; y < _pixelsHigh; y++)
|
||||
{
|
||||
line_offset = _bytesPerRow * y;
|
||||
for (x = 0; x < _pixelsWide; x++)
|
||||
{
|
||||
offset = (_bitsPerPixel * x) / 8 + line_offset;
|
||||
a = _imagePlanes[0][offset + ai];
|
||||
if (a != 255)
|
||||
{
|
||||
if (a == 0)
|
||||
{
|
||||
for (i = start; i < end; i++)
|
||||
{
|
||||
_imagePlanes[0][offset + i] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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];
|
||||
|
@ -1991,6 +2144,7 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CGFloat scale;
|
||||
|
@ -2045,12 +2199,51 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
|||
|
||||
if (_bitsPerSample == 8)
|
||||
{
|
||||
if (!_isPlanar)
|
||||
{
|
||||
// Optimize for the most common case
|
||||
NSUInteger a;
|
||||
NSInteger offset;
|
||||
NSInteger line_offset;
|
||||
|
||||
for (y = 0; y < _pixelsHigh; y++)
|
||||
{
|
||||
line_offset = _bytesPerRow * y;
|
||||
for (x = 0; x < _pixelsWide; x++)
|
||||
{
|
||||
offset = (_bitsPerPixel * x) / 8 + 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];
|
||||
|
@ -2076,6 +2269,7 @@ _set_bit_value(unsigned char *base, long msb_off, int bit_width,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CGFloat scale;
|
||||
|
|
Loading…
Reference in a new issue