/* NSBitmapImageRep.m Bitmap image representation. Copyright (C) 1996 Free Software Foundation, Inc. Author: Adam Fedor Date: Feb 1996 This file is part of the GNUstep GUI Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include /* Maximum number of planes */ #define MAX_PLANES 5 /* Backend protocol - methods that must be implemented by the backend to complete the class */ @protocol NXBitmapImageRepBackend - (BOOL) draw; @end @implementation NSBitmapImageRep /* Given a TIFF image (from the libtiff library), load the image information into our data structure. Reads the specified image. */ - _initFromImage: (TIFF *)image number: (int)imageNumber { NSString* space; NSTiffInfo* info; info = NSTiffGetInfo(imageNumber, image); if (!info) { [NSException raise:NSTIFFException format: @"Read invalid TIFF info"]; } /* 8-bit RGB will be converted to 24-bit by the tiff routines, so account for this. */ space = nil; switch(info->photoInterp) { case PHOTOMETRIC_MINISBLACK: space = NSDeviceWhiteColorSpace; break; case PHOTOMETRIC_MINISWHITE: space = NSDeviceBlackColorSpace; break; case PHOTOMETRIC_RGB: space = NSDeviceRGBColorSpace; break; case PHOTOMETRIC_PALETTE: space = NSDeviceRGBColorSpace; info->samplesPerPixel = 3; break; default: break; } [self initWithBitmapDataPlanes: NULL pixelsWide: info->width pixelsHigh: info->height bitsPerSample: info->bitsPerSample samplesPerPixel: info->samplesPerPixel hasAlpha: (info->samplesPerPixel > 3) isPlanar: (info->planarConfig == PLANARCONFIG_SEPARATE) colorSpaceName: space bytesPerRow: 0 bitsPerPixel: 0]; compression = info->compression; if (NSTiffRead(imageNumber, image, NULL, [self bitmapData])) { [NSException raise:NSTIFFException format: @"Read invalid TIFF image"]; } return self; } + (id) imageRepWithData: (NSData *)tiffData { NSArray* array; array = [self imageRepsWithData: tiffData]; if ([array count]) return [array objectAtIndex: 0]; return nil; } + (NSArray *) imageRepsWithData: (NSData *)tiffData { int images; TIFF* image; NSTiffInfo* info; NSMutableArray* array; image = NSTiffOpenData((char *)[tiffData bytes], [tiffData length], "r", NULL); if (!image) { [NSException raise:NSTIFFException format: @"Read invalid TIFF data"]; } array = [NSMutableArray arrayWithCapacity:1]; images = 0; while ((info = NSTiffGetInfo(images, image))) { NSBitmapImageRep* imageRep; OBJC_FREE(info); imageRep = [[[[self class] alloc] _initFromImage: image number: images] autorelease]; [array addObject: imageRep]; images++; } NSTiffClose(image); return array; } /* Loads only the default (first) image from the TIFF image contained in data. */ - (id) initWithData: (NSData *)tiffData { TIFF *image; image = NSTiffOpenData((char *)[tiffData bytes], [tiffData length], "r", NULL); if (!image) { [NSException raise:NSTIFFException format: @"Read invalid TIFF data"]; } [self _initFromImage:image number: -1]; NSTiffClose(image); return self; } - (id) initWithFocusedViewRect: (NSRect)rect { return [self notImplemented: _cmd]; } /* This is the designated initializer */ /* Note: If data is actaully passed to us in planes, we DO NOT own this data and we DO NOT copy it. Just assume that it will always be available. */ - (id) initWithBitmapDataPlanes: (unsigned char **)planes pixelsWide: (int)width pixelsHigh: (int)height bitsPerSample: (int)bps samplesPerPixel: (int)spp hasAlpha: (BOOL)alpha isPlanar: (BOOL)isPlanar colorSpaceName: (NSString *)colorSpaceName bytesPerRow: (int)rowBytes bitsPerPixel: (int)pixelBits; { if (!bps || !spp || !width || !height) { [NSException raise: NSInvalidArgumentException format: @"Required arguments not specified creating NSBitmapImageRep"]; } _pixelsWide = width; _pixelsHigh = height; size.width = width; size.height = height; bitsPerSample = bps; numColors = spp; hasAlpha = alpha; _isPlanar = isPlanar; _colorSpace = [colorSpaceName retain]; if (!pixelBits) pixelBits = bps * ((_isPlanar) ? 1 : spp); bitsPerPixel = pixelBits; if (!rowBytes) rowBytes = ceil((float)width * bitsPerPixel / 8); bytesPerRow = rowBytes; if (planes) { int i; OBJC_MALLOC(imagePlanes, unsigned char*, MAX_PLANES); for (i = 0; i < MAX_PLANES; i++) imagePlanes[i] = NULL; for (i = 0; i < ((_isPlanar) ? numColors : 1); i++) imagePlanes[i] = planes[i]; } return self; } - (void) dealloc { OBJC_FREE(imagePlanes); [imageData release]; [super dealloc]; } + (BOOL) canInitWithData: (NSData *)data { TIFF *image = NULL; image = NSTiffOpenData((char *)[data bytes], [data length], "r", NULL); NSTiffClose(image); return (image) ? YES : NO; } + (BOOL) canInitWithPasteboard: (NSPasteboard *)pasteboard { [self notImplemented: _cmd]; return NO; } + (NSArray *) imageFileTypes { return [self imageUnfilteredFileTypes]; } + (NSArray *) imagePasteboardTypes { return [self imageUnfilteredPasteboardTypes]; } + (NSArray *) imageUnfilteredFileTypes { return [NSArray arrayWithObjects: @"tiff", @"tif", nil]; } + (NSArray *) imageUnfilteredPasteboardTypes { return [NSArray arrayWithObjects: NSTIFFPboardType, nil]; } // // Getting Information about the Image // - (int) bitsPerPixel { return bitsPerPixel; } - (int) samplesPerPixel { return numColors; } - (BOOL) isPlanar { return _isPlanar; } - (int) numberOfPlanes { return (_isPlanar) ? numColors : 1; } - (int) bytesPerPlane { return bytesPerRow*_pixelsHigh; } - (int) bytesPerRow { return bytesPerRow; } // // Getting Image Data // - (unsigned char *) bitmapData { unsigned char *planes[MAX_PLANES]; [self getBitmapDataPlanes: planes]; return planes[0]; } - (void) getBitmapDataPlanes: (unsigned char **)data { int i; if (!imagePlanes || !imagePlanes[0]) { long length; unsigned char* bits; length = (long)numColors * bytesPerRow * _pixelsHigh * sizeof(unsigned char); imageData = [[NSMutableData dataWithLength: length] retain]; if (!imagePlanes) OBJC_MALLOC(imagePlanes, unsigned char*, MAX_PLANES); bits = [imageData mutableBytes]; if (_isPlanar) { for (i=1; i < numColors; i++) imagePlanes[i] = bits + i*bytesPerRow * _pixelsHigh; for (i= numColors; i < MAX_PLANES; i++) imagePlanes[i] = NULL; } else { imagePlanes[0] = bits; for (i= 1; i < MAX_PLANES; i++) imagePlanes[i] = NULL; } } if (data) for (i=0; i < numColors; i++) data[i] = imagePlanes[i]; } - (BOOL) draw { return NO; } // // Producing a TIFF Representation of the Image // + (NSData *) TIFFRepresentationOfImageRepsInArray: (NSArray *)anArray { [self notImplemented: _cmd]; return nil; } + (NSData *) TIFFRepresentationOfImageRepsInArray: (NSArray *)anArray usingCompression: (NSTIFFCompression)compressionType factor: (float)factor { [self notImplemented: _cmd]; return nil; } - (NSData *) TIFFRepresentation { [self notImplemented: _cmd]; return nil; } - (NSData *) TIFFRepresentationUsingCompression: (NSTIFFCompression)compressionType factor: (float)factor { [self notImplemented: _cmd]; return nil; } // // Setting and Checking Compression Types // + (void) getTIFFCompressionTypes: (const NSTIFFCompression **)list count: (int *)numTypes { [self notImplemented: _cmd]; } + (NSString *) localizedNameForTIFFCompressionType: (NSTIFFCompression)compression { [self notImplemented: _cmd]; return nil; } - (BOOL) canBeCompressedUsing: (NSTIFFCompression)compression { [self notImplemented: _cmd]; return NO; } - (void) getCompression: (NSTIFFCompression *)compression factor: (float *)factor { [self notImplemented: _cmd]; } - (void) setCompression: (NSTIFFCompression)compression factor: (float)factor { [self notImplemented: _cmd]; } // // NSCoding protocol // - (void) encodeWithCoder: aCoder { [self notImplemented: _cmd]; } - initWithCoder: aDecoder { [self notImplemented: _cmd]; return nil; } @end