Image encoding support - first cut

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@5633 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 1999-12-28 16:02:01 +00:00
parent fc1dab4d2c
commit 7518839b85
9 changed files with 556 additions and 234 deletions

View file

@ -1,3 +1,15 @@
Tue Dec 28 15:58:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
Initial hack of support for encoding/decoding images - untested.
* Source/NSBitmapImageRep.m: Code for writing tiffs etc.
* Source/NSImage.m: Archiving support and tifying.
* Source/NSImageRep.m: Archiving support and tifying.
* Source/tiff.m: modifications for compression and for writing.
* Headers/gnustep/gui/NSBitmapImageRep.h: tidy and support writing.
* Headers/gnustep/gui/NSImage.h: ditto
* Headers/gnustep/gui/NSImageRep.h: ditto
* Headers/gnustep/gui/nsimage-tiff.h: ditto
1999-12-24 David Lazaro <khelekir@encomix.es> 1999-12-24 David Lazaro <khelekir@encomix.es>
* Source/NSMenuView.m ([NSMenuView -trackWithEvent:]): Added hysteresis * Source/NSMenuView.m ([NSMenuView -trackWithEvent:]): Added hysteresis

View file

@ -54,6 +54,7 @@ typedef enum _NSTIFFCompression {
unsigned int numColors; unsigned int numColors;
unsigned int bitsPerPixel; unsigned int bitsPerPixel;
unsigned short compression; unsigned short compression;
float comp_factor;
BOOL _isPlanar; BOOL _isPlanar;
unsigned char **imagePlanes; unsigned char **imagePlanes;
NSMutableData *imageData; NSMutableData *imageData;
@ -101,10 +102,10 @@ typedef enum _NSTIFFCompression {
// //
+ (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray*)anArray; + (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray*)anArray;
+ (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray*)anArray + (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray*)anArray
usingCompression:(NSTIFFCompression)compressionType usingCompression: (NSTIFFCompression)type
factor: (float)factor; factor: (float)factor;
- (NSData*) TIFFRepresentation; - (NSData*) TIFFRepresentation;
- (NSData *)TIFFRepresentationUsingCompression:(NSTIFFCompression)compressionType - (NSData*) TIFFRepresentationUsingCompression: (NSTIFFCompression)type
factor: (float)factor; factor: (float)factor;
// //
@ -112,7 +113,7 @@ typedef enum _NSTIFFCompression {
// //
+ (void) getTIFFCompressionTypes: (const NSTIFFCompression**)list + (void) getTIFFCompressionTypes: (const NSTIFFCompression**)list
count: (int*)numTypes; count: (int*)numTypes;
+ (NSString *)localizedNameForTIFFCompressionType:(NSTIFFCompression)compression; + (NSString*) localizedNameForTIFFCompressionType: (NSTIFFCompression)type;
- (BOOL) canBeCompressedUsing: (NSTIFFCompression)compression; - (BOOL) canBeCompressedUsing: (NSTIFFCompression)compression;
- (void) getCompression: (NSTIFFCompression*)compression - (void) getCompression: (NSTIFFCompression*)compression
factor: (float*)factor; factor: (float*)factor;
@ -122,8 +123,8 @@ typedef enum _NSTIFFCompression {
// //
// NSCoding protocol // NSCoding protocol
// //
- (void)encodeWithCoder:aCoder; - (void) encodeWithCoder: (NSCoder*)aCoder;
- initWithCoder:aDecoder; - (id) initWithCoder: (NSCoder*)aDecoder;
@end @end

View file

@ -49,20 +49,14 @@
NSString *name; NSString *name;
NSSize _size; NSSize _size;
struct __imageFlags { struct __imageFlags {
unsigned archiveByName: 1;
unsigned scalable: 1; unsigned scalable: 1;
unsigned dataRetained: 1; unsigned dataRetained: 1;
unsigned flipDraw: 1; unsigned flipDraw: 1;
unsigned uniqueWindow:1;
unsigned uniqueWasExplicitlySet:1;
unsigned sizeWasExplicitlySet: 1; unsigned sizeWasExplicitlySet: 1;
unsigned builtIn:1;
unsigned needsToExpand:1;
unsigned useEPSOnResolutionMismatch: 1; unsigned useEPSOnResolutionMismatch: 1;
unsigned colorMatchPreferred: 1; unsigned colorMatchPreferred: 1;
unsigned multipleResolutionMatching: 1; unsigned multipleResolutionMatching: 1;
unsigned subImage:1;
unsigned aSynch:1;
unsigned archiveByName:1;
unsigned cacheSeparately: 1; unsigned cacheSeparately: 1;
unsigned unboundedCacheDepth: 1; unsigned unboundedCacheDepth: 1;
unsigned syncLoad: 1; unsigned syncLoad: 1;
@ -192,8 +186,8 @@
// //
// NSCoding protocol // NSCoding protocol
// //
- (void)encodeWithCoder:aCoder; - (void) encodeWithCoder: (NSCoder*)aCoder;
- initWithCoder:aDecoder; - (id) initWithCoder: (NSCoder*)aDecoder;
@end @end

View file

@ -42,7 +42,7 @@ enum {
NSImageRepMatchesDevice NSImageRepMatchesDevice
}; };
@interface NSImageRep : NSObject <NSCoding> @interface NSImageRep : NSObject <NSCoding, NSCopying>
{ {
// Attributes // Attributes
NSString* _colorSpace; NSString* _colorSpace;

View file

@ -48,6 +48,7 @@ typedef struct {
u_short planarConfig; /* meshed or separate */ u_short planarConfig; /* meshed or separate */
u_short photoInterp; /* photometric interpretation of bitmap data, */ u_short photoInterp; /* photometric interpretation of bitmap data, */
u_short compression; u_short compression;
int quality; /* compression quality (for jpeg) 1 to 255 */
int numImages; /* number of images in tiff */ int numImages; /* number of images in tiff */
int error; int error;
} NSTiffInfo; } NSTiffInfo;
@ -61,8 +62,8 @@ typedef struct {
typedef char* realloc_data_callback(char* data, long size); typedef char* realloc_data_callback(char* data, long size);
extern TIFF* NSTiffOpenData(char* data, long size, const char* mode, extern TIFF* NSTiffOpenDataRead(const char* data, long size);
realloc_data_callback* realloc_data); extern TIFF* NSTiffOpenDataWrite(char **data, long *size);
extern int NSTiffClose(TIFF* image); extern int NSTiffClose(TIFF* image);
extern int NSTiffWrite(TIFF* image, NSTiffInfo* info, char* data); extern int NSTiffWrite(TIFF* image, NSTiffInfo* info, char* data);

View file

@ -93,6 +93,7 @@
bytesPerRow: 0 bytesPerRow: 0
bitsPerPixel: 0]; bitsPerPixel: 0];
compression = info->compression; compression = info->compression;
comp_factor = 255 * (1 - ((float)info->quality)/100.0);
if (NSTiffRead(imageNumber, image, NULL, [self bitmapData])) if (NSTiffRead(imageNumber, image, NULL, [self bitmapData]))
{ {
@ -119,8 +120,7 @@
NSTiffInfo *info; NSTiffInfo *info;
NSMutableArray*array; NSMutableArray*array;
image = NSTiffOpenData((char *)[tiffData bytes], [tiffData length], image = NSTiffOpenDataRead((char *)[tiffData bytes], [tiffData length]);
"r", NULL);
if (!image) if (!image)
{ {
[NSException raise:NSTIFFException format: @"Read invalid TIFF data"]; [NSException raise:NSTIFFException format: @"Read invalid TIFF data"];
@ -133,8 +133,8 @@
NSBitmapImageRep* imageRep; NSBitmapImageRep* imageRep;
OBJC_FREE(info); OBJC_FREE(info);
imageRep = [[[[self class] alloc] imageRep = AUTORELEASE([[[self class] alloc]
_initFromImage: image number: images] autorelease]; _initFromImage: image number: images]);
[array addObject: imageRep]; [array addObject: imageRep];
images++; images++;
} }
@ -149,9 +149,8 @@
{ {
TIFF *image; TIFF *image;
image = NSTiffOpenData((char *)[tiffData bytes], [tiffData length], image = NSTiffOpenDataRead((char *)[tiffData bytes], [tiffData length]);
"r", NULL); if (image == 0)
if (!image)
{ {
[NSException raise:NSTIFFException format: @"Read invalid TIFF data"]; [NSException raise:NSTIFFException format: @"Read invalid TIFF data"];
} }
@ -195,7 +194,7 @@
numColors = spp; numColors = spp;
hasAlpha = alpha; hasAlpha = alpha;
_isPlanar = isPlanar; _isPlanar = isPlanar;
_colorSpace = [colorSpaceName retain]; _colorSpace = RETAIN(colorSpaceName);
if (!pixelBits) if (!pixelBits)
pixelBits = bps * ((_isPlanar) ? 1 : spp); pixelBits = bps * ((_isPlanar) ? 1 : spp);
bitsPerPixel = pixelBits; bitsPerPixel = pixelBits;
@ -218,7 +217,7 @@
- (void) dealloc - (void) dealloc
{ {
OBJC_FREE(imagePlanes); OBJC_FREE(imagePlanes);
[imageData release]; RELEASE(imageData);
[super dealloc]; [super dealloc];
} }
@ -232,16 +231,18 @@
copy->numColors = numColors; copy->numColors = numColors;
copy->bitsPerPixel = bitsPerPixel; copy->bitsPerPixel = bitsPerPixel;
copy->compression = compression; copy->compression = compression;
copy->comp_factor = comp_factor;
copy->_isPlanar = _isPlanar; copy->_isPlanar = _isPlanar;
copy->imagePlanes = 0; copy->imagePlanes = 0;
copy->imageData = [imageData copy]; copy->imageData = [imageData copy];
return copy; return copy;
} }
+ (BOOL) canInitWithData: (NSData *)data + (BOOL) canInitWithData: (NSData *)data
{ {
TIFF *image = NULL; TIFF *image = NULL;
image = NSTiffOpenData((char *)[data bytes], [data length], "r", NULL); image = NSTiffOpenDataRead((char *)[data bytes], [data length]);
NSTiffClose(image); NSTiffClose(image);
return (image) ? YES : NO; return (image) ? YES : NO;
@ -249,8 +250,7 @@
+ (BOOL) canInitWithPasteboard: (NSPasteboard *)pasteboard + (BOOL) canInitWithPasteboard: (NSPasteboard *)pasteboard
{ {
[self notImplemented: _cmd]; return [[pasteboard types] containsObject: NSTIFFPboardType];
return NO;
} }
+ (NSArray *) imageFileTypes + (NSArray *) imageFileTypes
@ -327,7 +327,7 @@
length = (long)numColors * bytesPerRow * _pixelsHigh length = (long)numColors * bytesPerRow * _pixelsHigh
* sizeof(unsigned char); * sizeof(unsigned char);
imageData = [[NSMutableData dataWithLength: length] retain]; imageData = RETAIN([NSMutableData dataWithLength: length]);
if (!imagePlanes) if (!imagePlanes)
OBJC_MALLOC(imagePlanes, unsigned char*, MAX_PLANES); OBJC_MALLOC(imagePlanes, unsigned char*, MAX_PLANES);
bits = [imageData mutableBytes]; bits = [imageData mutableBytes];
@ -366,7 +366,7 @@
} }
+ (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray *)anArray + (NSData*) TIFFRepresentationOfImageRepsInArray: (NSArray *)anArray
usingCompression: (NSTIFFCompression)compressionType usingCompression: (NSTIFFCompression)type
factor: (float)factor factor: (float)factor
{ {
[self notImplemented: _cmd]; [self notImplemented: _cmd];
@ -375,15 +375,61 @@
- (NSData*) TIFFRepresentation - (NSData*) TIFFRepresentation
{ {
[self notImplemented: _cmd]; NSTiffInfo info;
return nil; TIFF *image;
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 (_isPlanar)
info.planarConfig = PLANARCONFIG_SEPARATE;
else
info.planarConfig = PLANARCONFIG_CONTIG;
if (_colorSpace == NSDeviceRGBColorSpace)
info.photoInterp = PHOTOMETRIC_RGB;
else if (_colorSpace == NSDeviceWhiteColorSpace)
info.photoInterp = PHOTOMETRIC_MINISBLACK;
else if (_colorSpace == NSDeviceBlackColorSpace)
info.photoInterp = PHOTOMETRIC_MINISWHITE;
else
info.photoInterp = PHOTOMETRIC_RGB;
info.compression = compression;
info.quality = (1 - ((float)comp_factor)/255.0) * 100;
info.numImages = 1;
info.error = 0;
image = NSTiffOpenDataWrite(&bytes, &length);
if (image == 0)
{
[NSException raise: NSTIFFException format: @"Write TIFF open failed"];
}
if (NSTiffWrite(image, &info, [self bitmapData]) != 0)
{
[NSException raise: NSTIFFException format: @"Write TIFF data failed"];
}
NSTiffClose(image);
return [NSData dataWithBytesNoCopy: bytes length: length];
} }
- (NSData *) TIFFRepresentationUsingCompression: (NSTIFFCompression)compressionType - (NSData*) TIFFRepresentationUsingCompression: (NSTIFFCompression)type
factor: (float)factor factor: (float)factor
{ {
[self notImplemented: _cmd]; NSData *data;
return nil; NSTIFFCompression oldType = compression;
float oldFact = comp_factor;
[self setCompression: type factor: factor];
data = [self TIFFRepresentation];
[self setCompression: oldType factor: oldFact];
return data;
} }
// //
@ -392,31 +438,71 @@
+ (void) getTIFFCompressionTypes: (const NSTIFFCompression **)list + (void) getTIFFCompressionTypes: (const NSTIFFCompression **)list
count: (int *)numTypes count: (int *)numTypes
{ {
[self notImplemented: _cmd]; static NSTIFFCompression types[] = {
NSTIFFCompressionNone,
NSTIFFCompressionCCITTFAX3,
NSTIFFCompressionCCITTFAX4,
NSTIFFCompressionLZW,
NSTIFFCompressionJPEG,
NSTIFFCompressionPackBits
};
*list = types;
*numTypes = sizeof(types)/sizeof(*types);
} }
+ (NSString *) localizedNameForTIFFCompressionType: (NSTIFFCompression)compression + (NSString*) localizedNameForTIFFCompressionType: (NSTIFFCompression)type
{ {
[self notImplemented: _cmd]; switch (type)
return nil; {
case NSTIFFCompressionNone: return @"NSTIFFCompressionNone";
case NSTIFFCompressionCCITTFAX3: return @"NSTIFFCompressionCCITTFAX3";
case NSTIFFCompressionCCITTFAX4: return @"NSTIFFCompressionCCITTFAX4";
case NSTIFFCompressionLZW: return @"NSTIFFCompressionLZW";
case NSTIFFCompressionJPEG: return @"NSTIFFCompressionJPEG";
case NSTIFFCompressionNEXT: return @"NSTIFFCompressionNEXT";
case NSTIFFCompressionPackBits: return @"NSTIFFCompressionPackBits";
case NSTIFFCompressionOldJPEG: return @"NSTIFFCompressionOldJPEG";
default: return nil;
}
} }
- (BOOL) canBeCompressedUsing: (NSTIFFCompression)compression - (BOOL) canBeCompressedUsing: (NSTIFFCompression)type
{ {
[self notImplemented: _cmd]; switch (type)
{
case NSTIFFCompressionCCITTFAX3:
case NSTIFFCompressionCCITTFAX4:
if (numColors == 1 && bitsPerSample == 1)
return YES;
else
return NO;
case NSTIFFCompressionNone:
case NSTIFFCompressionLZW:
case NSTIFFCompressionJPEG:
case NSTIFFCompressionPackBits:
return YES;
case NSTIFFCompressionNEXT:
case NSTIFFCompressionOldJPEG:
default:
return NO; return NO;
} }
- (void) getCompression: (NSTIFFCompression *)compression
factor: (float *)factor
{
[self notImplemented: _cmd];
} }
- (void) setCompression: (NSTIFFCompression)compression - (void) getCompression: (NSTIFFCompression*)type
factor: (float*)factor
{
*type = compression;
*factor = comp_factor;
}
- (void) setCompression: (NSTIFFCompression)type
factor: (float)factor factor: (float)factor
{ {
[self notImplemented: _cmd]; compression = type;
comp_factor = factor;
} }
// //
@ -424,13 +510,19 @@
// //
- (void) encodeWithCoder: (NSCoder*)aCoder - (void) encodeWithCoder: (NSCoder*)aCoder
{ {
[self notImplemented: _cmd]; NSData *data = [self TIFFRepresentation];
[super encodeWithCoder: aCoder];
[data encodeWithCoder: aCoder];
} }
- (id) initWithCoder: (NSCoder*)aDecoder - (id) initWithCoder: (NSCoder*)aDecoder
{ {
[self notImplemented: _cmd]; NSData *data;
return nil;
self = [super initWithCoder: aDecoder];
data = [aDecoder decodeObject];
return [self initWithData: data];
} }
@end @end

View file

@ -253,10 +253,11 @@ static Class cacheClass = 0;
image = [[self allocWithZone: NSDefaultMallocZone()] image = [[self allocWithZone: NSDefaultMallocZone()]
initByReferencingFile: path]; initByReferencingFile: path];
if (image) if (image != nil)
{ {
[image setName: aName]; [image setName: aName];
RELEASE(image); // Retained in dictionary. RELEASE(image); // Retained in dictionary.
image->_flags.archiveByName = YES;
} }
return image; return image;
} }
@ -763,11 +764,10 @@ static Class cacheClass = 0;
unsigned i, count; unsigned i, count;
GSRepData *repd; GSRepData *repd;
if (!imageRepArray) if (_flags.syncLoad == YES)
return; {
if (_flags.syncLoad)
[self _loadImageFilenames]; [self _loadImageFilenames];
}
count = [imageRepArray count]; count = [imageRepArray count];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
@ -1067,10 +1067,114 @@ NSDebugLLog(@"NSImage", @"Partial %@ ... %@ %d", repd->bg, _color, repd->rep);
// NSCoding // NSCoding
- (void) encodeWithCoder: (NSCoder*)coder - (void) encodeWithCoder: (NSCoder*)coder
{ {
BOOL flag;
flag = _flags.archiveByName;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
if (flag == YES)
{
/*
* System image - just encode the name.
*/
[coder encodeValueOfObjCType: @encode(id) at: &name];
}
else
{
NSMutableArray *a;
NSEnumerator *e;
NSImageRep *r;
/*
* If the image is not yet loaded - load it now.
*/
if (_flags.syncLoad)
{
[self _loadImageFilenames];
}
/*
* Normal image - encode the ivars
*/
[coder encodeValueOfObjCType: @encode(NSSize) at: &_size];
[coder encodeValueOfObjCType: @encode(id) at: &_color];
flag = _flags.scalable;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.dataRetained;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.flipDraw;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.sizeWasExplicitlySet;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.useEPSOnResolutionMismatch;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.colorMatchPreferred;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.multipleResolutionMatching;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.cacheSeparately;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
flag = _flags.unboundedCacheDepth;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
/*
* Now encode an array of all the image reps (excluding cache)
*/
a = [NSMutableArray arrayWithCapacity: 2];
e = [[self representations] objectEnumerator];
while ((r = [e nextObject]) != nil)
{
if ([r isKindOfClass: [NSCachedImageRep class]] == NO)
{
[a addObject: r];
}
}
[coder encodeValueOfObjCType: @encode(id) at: &a];
}
} }
- (id) initWithCoder: (NSCoder*)coder - (id) initWithCoder: (NSCoder*)coder
{ {
BOOL flag;
[coder decodeValueOfObjCType: @encode(BOOL) at: &flag];
if (flag == YES)
{
NSString *theName = [coder decodeObject];
RELEASE(self);
self = RETAIN([NSImage imageNamed: theName]);
}
else
{
NSArray *a;
[coder decodeValueOfObjCType: @encode(NSSize) at: &_size];
[coder decodeValueOfObjCType: @encode(id) at: &_color];
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.scalable = flag;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.dataRetained = flag;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.flipDraw = flag;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.sizeWasExplicitlySet = flag;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.useEPSOnResolutionMismatch = flag;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.colorMatchPreferred = flag;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.multipleResolutionMatching = flag;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.cacheSeparately = flag;
[coder encodeValueOfObjCType: @encode(BOOL) at: &flag];
_flags.unboundedCacheDepth = flag;
/*
* get the image reps and add them.
*/
a = [coder decodeObject];
[self addRepresentations: a];
}
return self; return self;
} }

View file

@ -30,6 +30,7 @@
#include <string.h> #include <string.h>
#include <Foundation/NSArray.h> #include <Foundation/NSArray.h>
#include <Foundation/NSData.h> #include <Foundation/NSData.h>
#include <Foundation/NSException.h>
#include <Foundation/NSNotification.h> #include <Foundation/NSNotification.h>
#include <AppKit/NSImageRep.h> #include <AppKit/NSImageRep.h>
#include <AppKit/NSBitmapImageRep.h> #include <AppKit/NSBitmapImageRep.h>
@ -85,15 +86,10 @@ static NSMutableArray* imageReps = NULL;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
Class rep = [imageReps objectAtIndex: i]; Class rep = [imageReps objectAtIndex: i];
#if 0
if ([[rep imageFileTypes] indexOfObject: ext] != NSNotFound) if ([[rep imageFileTypes] indexOfObject: ext] != NSNotFound)
#else
/* xxxFIXME: not implemented in gcc-2.7.2 runtime. */
if ([rep respondsToSelector: @selector(imageFileTypes)]
&& [[rep imageFileTypes] indexOfObject: ext] != NSNotFound)
#endif
{ {
NSData* data = [NSData dataWithContentsOfFile: filename]; NSData* data = [NSData dataWithContentsOfFile: filename];
if ([rep respondsToSelector: @selector(imageRepsWithData:)]) if ([rep respondsToSelector: @selector(imageRepsWithData:)])
[array addObjectsFromArray: [rep imageRepsWithData: data]]; [array addObjectsFromArray: [rep imageRepsWithData: data]];
else if ([rep respondsToSelector: @selector(imageRepWithData:)]) else if ([rep respondsToSelector: @selector(imageRepWithData:)])
@ -125,11 +121,12 @@ static NSMutableArray* imageReps = NULL;
{ {
NSString* ptype; NSString* ptype;
Class rep = [imageReps objectAtIndex: i]; Class rep = [imageReps objectAtIndex: i];
if ([rep respondsToSelector: @selector(imagePasteboardTypes)]
&& (ptype = ptype = [pasteboard availableTypeFromArray: [rep imagePasteboardTypes]];
[pasteboard availableTypeFromArray: [rep imagePasteboardTypes]])) if (ptype != nil)
{ {
NSData* data = [pasteboard dataForType: ptype]; NSData* data = [pasteboard dataForType: ptype];
if ([rep respondsToSelector: @selector(imageRepsWithData:)]) if ([rep respondsToSelector: @selector(imageRepsWithData:)])
[array addObjectsFromArray: [rep imageRepsWithData: data]]; [array addObjectsFromArray: [rep imageRepsWithData: data]];
else if ([rep respondsToSelector: @selector(imageRepWithData:)]) else if ([rep respondsToSelector: @selector(imageRepWithData:)])
@ -350,8 +347,7 @@ static NSMutableArray* imageReps = NULL;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
Class rep = [imageReps objectAtIndex: i]; Class rep = [imageReps objectAtIndex: i];
if ([rep respondsToSelector: @selector(imageFileTypes)] if ([[rep imageFileTypes] indexOfObject: type] != NSNotFound)
&& [[rep imageFileTypes] indexOfObject: type] != NSNotFound)
{ {
return rep; return rep;
} }
@ -367,8 +363,8 @@ static NSMutableArray* imageReps = NULL;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
Class rep = [imageReps objectAtIndex: i]; Class rep = [imageReps objectAtIndex: i];
if ([rep respondsToSelector: @selector(imagePasteboardTypes)]
&& ([[rep imagePasteboardTypes] indexOfObject: type] != NSNotFound)) if ([[rep imagePasteboardTypes] indexOfObject: type] != NSNotFound)
{ {
return rep; return rep;
} }
@ -378,7 +374,21 @@ static NSMutableArray* imageReps = NULL;
+ (void) registerImageRepClass: (Class)imageRepClass + (void) registerImageRepClass: (Class)imageRepClass
{ {
if ([imageReps containsObject: imageRepClass] == NO)
{
Class c = imageRepClass;
while (c != nil && c != [NSObject class] && c != [NSImageRep class])
{
c = [c superclass];
}
if (c != [NSImageRep class])
{
[NSException raise: NSInvalidArgumentException
format: @"Attempt to register non-imagerep class"];
}
[imageReps addObject: imageRepClass]; [imageReps addObject: imageRepClass];
}
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
postNotificationName: NSImageRepRegistryChangedNotification postNotificationName: NSImageRepRegistryChangedNotification
object: self]; object: self];

View file

@ -3,11 +3,13 @@
Functions for dealing with tiff images. Functions for dealing with tiff images.
Copyright (C) 1996 Free Software Foundation, Inc. Copyright (C) 1996,1999 Free Software Foundation, Inc.
Author: Adam Fedor <fedor@colorado.edu> Author: Adam Fedor <fedor@colorado.edu>
Date: Feb 1996 Date: Feb 1996
Support for writing tiffs: Richard Frith-Macdonald
This file is part of the GNUstep GUI Library. This file is part of the GNUstep GUI Library.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
@ -73,7 +75,8 @@ typedef struct {
long size; long size;
long position; long position;
const char* mode; const char* mode;
realloc_data_callback* realloc_data; char **outdata;
long *outposition;
} chandle_t; } chandle_t;
/* Client functions that provide reading/writing of data for libtiff */ /* Client functions that provide reading/writing of data for libtiff */
@ -99,14 +102,17 @@ TiffHandleWrite(thandle_t handle, tdata_t buf, toff_t count)
return 0; return 0;
if (chand->position + count > chand->size) if (chand->position + count > chand->size)
{ {
if (chand->realloc_data == NULL)
return 0;
chand->size = chand->position + count + 1; chand->size = chand->position + count + 1;
chand->data = chand->realloc_data(chand->data, chand->size); chand->data = objc_realloc(chand->data, chand->size);
*(chand->outdata) = chand->data;
if (chand->data == NULL) if (chand->data == NULL)
return 0; return 0;
} }
memcpy(chand->data + chand->position, buf, count); memcpy(chand->data + chand->position, buf, count);
chand->position += count;
if (chand->position > *(chand->outposition))
*(chand->outposition) = chand->position;
return count; return count;
} }
@ -168,18 +174,38 @@ TiffHandleUnmap(thandle_t handle, tdata_t data, toff_t size)
/* Open a tiff from a stream. Returns NULL if can't read tiff information. */ /* Open a tiff from a stream. Returns NULL if can't read tiff information. */
TIFF* TIFF*
NSTiffOpenData(char* data, long size, const char* mode, NSTiffOpenDataRead(const char* data, long size)
realloc_data_callback* realloc_data)
{ {
chandle_t* handle; chandle_t* handle;
NSDebugLog (@"NSTiffOpenData\n"); NSDebugLog (@"NSTiffOpenData\n");
OBJC_MALLOC(handle, chandle_t, 1); OBJC_MALLOC(handle, chandle_t, 1);
handle->data = data; handle->data = (char*)data;
handle->outdata = 0;
handle->position = 0; handle->position = 0;
handle->outposition = 0;
handle->size = size; handle->size = size;
handle->mode = mode; handle->mode = "r";
handle->realloc_data = realloc_data; return TIFFClientOpen("NSData", "r",
return TIFFClientOpen("NSData", mode, (thandle_t)handle,
TiffHandleRead, TiffHandleWrite,
TiffHandleSeek, TiffHandleClose,
TiffHandleSize,
TiffHandleMap, TiffHandleUnmap);
}
TIFF*
NSTiffOpenDataWrite(char **data, long *size)
{
chandle_t* handle;
NSDebugLog (@"NSTiffOpenData\n");
OBJC_MALLOC(handle, chandle_t, 1);
handle->data = *data;
handle->outdata = data;
handle->position = 0;
handle->outposition = size;
handle->size = *size;
handle->mode = "w";
return TIFFClientOpen("NSData", "w",
(thandle_t)handle, (thandle_t)handle,
TiffHandleRead, TiffHandleWrite, TiffHandleRead, TiffHandleWrite,
TiffHandleSeek, TiffHandleClose, TiffHandleSeek, TiffHandleClose,
@ -214,6 +240,7 @@ NSTiffGetInfo(int imageNumber, TIFF* image)
TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &info->width); TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &info->width);
TIFFGetField(image, TIFFTAG_IMAGELENGTH, &info->height); TIFFGetField(image, TIFFTAG_IMAGELENGTH, &info->height);
TIFFGetField(image, TIFFTAG_COMPRESSION, &info->compression); TIFFGetField(image, TIFFTAG_COMPRESSION, &info->compression);
TIFFGetField(image, TIFFTAG_JPEGQUALITY, &info->quality);
TIFFGetField(image, TIFFTAG_SUBFILETYPE, &info->subfileType); TIFFGetField(image, TIFFTAG_SUBFILETYPE, &info->subfileType);
/* If the following tags aren't present then use the TIFF defaults. */ /* If the following tags aren't present then use the TIFF defaults. */
@ -386,10 +413,91 @@ NSTiffRead(int imageNumber, TIFF* image, NSTiffInfo* info, char* data)
return error; return error;
} }
#define WRITE_SCANLINE(sample) \
if (TIFFWriteScanline(image, buf, row, sample) != 1) { \
NSLog(@"tiff: bad data write on line %d\n", row); \
error = 1; \
break; \
}
int int
NSWriteTiff(TIFF* image, NSTiffInfo* info, char* data) NSWriteTiff(TIFF* image, NSTiffInfo* info, char* data)
{ {
return 0; tdata_t buf = (tdata_t)data;
int i;
int row;
int error = 0;
TIFFSetField(image, TIFFTAG_IMAGEWIDTH, info->width);
TIFFSetField(image, TIFFTAG_IMAGELENGTH, info->height);
TIFFSetField(image, TIFFTAG_COMPRESSION, info->compression);
TIFFSetField(image, TIFFTAG_JPEGQUALITY, info->quality);
TIFFSetField(image, TIFFTAG_SUBFILETYPE, info->subfileType);
TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, info->bitsPerSample);
TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, info->samplesPerPixel);
TIFFSetField(image, TIFFTAG_PLANARCONFIG, info->planarConfig);
TIFFSetField(image, TIFFTAG_PHOTOMETRIC, info->photoInterp);
switch (info->photoInterp)
{
case PHOTOMETRIC_MINISBLACK:
case PHOTOMETRIC_MINISWHITE:
if (info->planarConfig == PLANARCONFIG_CONTIG)
{
int line = ceil((float)info->width * info->bitsPerSample / 8.0);
for (row = 0; row < info->height; ++row)
{
WRITE_SCANLINE(0)
buf += line;
}
}
else
{
int line = ceil((float)info->width / 8.0);
for (i = 0; i < info->samplesPerPixel; i++)
{
for (row = 0; row < info->height; ++row)
{
WRITE_SCANLINE(i)
buf += line;
}
}
}
break;
case PHOTOMETRIC_RGB:
if (info->planarConfig == PLANARCONFIG_CONTIG)
{
NSDebugLog(@"PHOTOMETRIC_RGB: CONTIG\n");
for (row = 0; row < info->height; ++row)
{
WRITE_SCANLINE(0)
buf += info->width * info->samplesPerPixel;
}
}
else
{
NSDebugLog(@"PHOTOMETRIC_RGB: NOT CONTIG\n");
for (i = 0; i < info->samplesPerPixel; i++)
{
for (row = 0; row < info->height; ++row)
{
WRITE_SCANLINE(i)
buf += info->width;
}
}
}
break;
default:
TIFFError(TIFFFileName(image),
"Can't write photometric %d", info->photoInterp);
break;
}
return error;
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/