Method to get all images from an ICNS file.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@33062 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2011-05-18 20:07:02 +00:00
parent 6c54fd6be5
commit 2608a790ed
4 changed files with 149 additions and 84 deletions

View file

@ -1,3 +1,13 @@
2011-05-18 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSBitmapImageRep+ICNS.h
* Source/NSBitmapImageRep+ICNS.m: New method to load all the
images from file. Plus a few additional changes.
* Source/NSBitmapImageRep.m (+imageRepsWithData:): Use new ICNS
method to get all images from file.
* Source/NSBitmapImageRep.m (+imageRepWithData:): Use
-initWithData: instead of +imageRepsWithData:.
2011-05-15 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSView.m (-removeFromSuperview): Use

View file

@ -34,6 +34,7 @@
@interface NSBitmapImageRep (ICNS)
+ (BOOL) _bitmapIsICNS: (NSData *)imageData;
+ (NSArray*) _imageRepsWithICNSData: (NSData *)imageData;
- (id) _initBitmapFromICNS: (NSData *)imageData;
// - (NSData *) _ICNSRepresentationWithProperties: (NSDictionary *) properties;
@end

View file

@ -307,6 +307,11 @@ static int icns_init_image_for_type(icns_type_t iconType,
icns_icon_info_t info;
info = icns_get_image_info_for_type(iconType);
if (info.iconChannels == 0)
{
return 1;
}
return icns_init_image(info.iconWidth, info.iconHeight, info.iconChannels,
info.iconDepth, imageOut);
}
@ -477,6 +482,66 @@ typedef struct pixel_t
return NO;
}
- (id) _initBitmapFromICNSImage: (icns_image_t*)iconImage
{
unsigned int iconWidth = 0, iconHeight = 0;
unsigned int rgbBufferPos = 0;
unsigned int rgbBufferSize = 0;
unsigned char *rgbBuffer = NULL; /* image converted to rgb */
int i = 0, j = 0;
int imageChannels = 0;
int sPP = 4;
iconWidth = iconImage->imageWidth;
iconHeight = iconImage->imageHeight;
// allocate the buffer...
rgbBufferSize = iconHeight * (iconWidth * sizeof(unsigned char) * sPP);
rgbBuffer = NSZoneMalloc([self zone], rgbBufferSize);
if (rgbBuffer == NULL)
{
NSLog(@"Couldn't allocate memory for image data from ICNS.");
RELEASE(self);
return nil;
}
imageChannels = iconImage->imageChannels;
rgbBufferPos = 0;
for (i = 0; i < iconHeight; i++)
{
for (j = 0; j < iconWidth; j++)
{
pixel_t *src_rgb_pixel;
src_rgb_pixel = (pixel_t *)&(iconImage->imageData[i*iconWidth*imageChannels+j*imageChannels]);
rgbBuffer[rgbBufferPos++] = src_rgb_pixel->r;
rgbBuffer[rgbBufferPos++] = src_rgb_pixel->g;
rgbBuffer[rgbBufferPos++] = src_rgb_pixel->b;
rgbBuffer[rgbBufferPos++] = src_rgb_pixel->a;
}
}
/* initialize self */
[self initWithBitmapDataPlanes: &rgbBuffer
pixelsWide: iconWidth
pixelsHigh: iconHeight
bitsPerSample: 8
samplesPerPixel: sPP
hasAlpha: YES
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
// FIXME: Not sure whether this format is pre-multiplied
bitmapFormat: NSAlphaNonpremultipliedBitmapFormat
bytesPerRow: iconWidth * sPP
bitsPerPixel: 8 * sPP];
_imageData = [[NSData alloc] initWithBytesNoCopy: rgbBuffer
length: rgbBufferSize];
return self;
}
- (id) _initBitmapFromICNS: (NSData *)imageData
{
int error = 0;
@ -486,17 +551,10 @@ typedef struct pixel_t
unsigned long dataOffset = 0;
icns_byte_t *data = NULL;
icns_type_t typeStr = ICNS_NULL_TYPE;
unsigned int iconWidth = 0, iconHeight = 0;
icns_image_t iconImage;
int sPP = 4;
unsigned char *rgbBuffer = NULL; /* image converted to rgb */
unsigned int rgbBufferPos = 0;
unsigned int rgbBufferSize = 0;
int i = 0, j = 0;
int imageChannels = 0;
error = icns_import_family_data(size, bytes, &iconFamily);
if(error != ICNS_STATUS_OK)
if (error != ICNS_STATUS_OK)
{
NSLog(@"Error reading ICNS data.");
RELEASE(self);
@ -514,10 +572,8 @@ typedef struct pixel_t
memcpy(&element, (data + dataOffset), 8);
//
// Temporarily limit to 48 until we can find a way to
// utilize the other representations in the icns file.
//
if (icns_types_equal(element.elementType, ICNS_48x48_32BIT_DATA)
|| (icns_types_equal(typeStr, ICNS_NULL_TYPE)
&& (icns_types_equal(element.elementType, ICNS_32x32_32BIT_DATA)
@ -543,59 +599,72 @@ typedef struct pixel_t
return nil;
}
iconWidth = iconImage.imageWidth;
iconHeight = iconImage.imageHeight;
// allocate the buffer...
rgbBufferSize = iconHeight * (iconWidth * sizeof(unsigned char) * sPP);
rgbBuffer = NSZoneMalloc([self zone], rgbBufferSize);
if (rgbBuffer == NULL)
{
NSLog(@"Couldn't allocate memory for image data from ICNS.");
RELEASE(self);
icns_free_image(&iconImage);
free(iconFamily);
return nil;
}
imageChannels = iconImage.imageChannels;
rgbBufferPos = 0;
for (i = 0; i < iconHeight; i++)
{
for (j = 0; j < iconWidth; j++)
{
pixel_t *src_rgb_pixel;
src_rgb_pixel = (pixel_t *)&(iconImage.imageData[i*iconWidth*imageChannels+j*imageChannels]);
rgbBuffer[rgbBufferPos++] = src_rgb_pixel->r;
rgbBuffer[rgbBufferPos++] = src_rgb_pixel->g;
rgbBuffer[rgbBufferPos++] = src_rgb_pixel->b;
rgbBuffer[rgbBufferPos++] = src_rgb_pixel->a;
}
}
self = [self _initBitmapFromICNSImage: &iconImage];
icns_free_image(&iconImage);
free(iconFamily);
/* initialize self */
[self initWithBitmapDataPlanes: &rgbBuffer
pixelsWide: iconWidth
pixelsHigh: iconHeight
bitsPerSample: 8
samplesPerPixel: sPP
hasAlpha: YES
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
// FIXME: Not sure whether this format is pre-multiplied
bitmapFormat: NSAlphaNonpremultipliedBitmapFormat
bytesPerRow: iconWidth * sPP
bitsPerPixel: 8 * sPP];
_imageData = [[NSData alloc] initWithBytesNoCopy: rgbBuffer
length: rgbBufferSize];
return self;
}
+ (NSArray*) _imageRepsWithICNSData: (NSData *)imageData
{
NSMutableArray *array = [NSMutableArray array];
int error = 0;
int size = [imageData length];
icns_byte_t *bytes = (icns_byte_t *)[imageData bytes];
icns_family_t *iconFamily = NULL;
unsigned long dataOffset = 0;
icns_byte_t *data = NULL;
error = icns_import_family_data(size, bytes, &iconFamily);
if (error != ICNS_STATUS_OK)
{
NSLog(@"Error reading ICNS data.");
RELEASE(self);
return array;
}
// skip the header...
dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t);
data = (icns_byte_t *)iconFamily;
// read each icon...
while (((dataOffset + 8) < iconFamily->resourceSize))
{
icns_element_t element;
icns_type_t typeStr = ICNS_NULL_TYPE;
icns_image_t iconImage;
memcpy(&element, (data + dataOffset), 8);
memcpy(&typeStr, &(element.elementType), 4);
// extract the image...
memset(&iconImage, 0, sizeof(icns_image_t));
error = icns_get_image32_with_mask_from_family(iconFamily,
typeStr,
&iconImage);
//NSLog(@"Read image %c %c %c %c result %d size %d", typeStr.c[0], typeStr.c[1], typeStr.c[2], typeStr.c[3], error, element.elementSize);
if (!error)
{
NSBitmapImageRep* imageRep;
imageRep = [[self alloc] _initBitmapFromICNSImage: &iconImage];
if (imageRep)
{
[array addObject: imageRep];
RELEASE(imageRep);
}
icns_free_image(&iconImage);
}
// next...
dataOffset += element.elementSize;
}
free(iconFamily);
return array;
}
@end

View file

@ -180,14 +180,7 @@
*/
+ (id) imageRepWithData: (NSData *)imageData
{
NSArray* array;
array = [self imageRepsWithData: imageData];
if ([array count])
{
return [array objectAtIndex: 0];
}
return nil;
return [[self alloc] initWithData: imageData];
}
/**<p>Returns an array containing newly allocated NSBitmapImageRep
@ -211,7 +204,7 @@
NSBitmapImageRep *rep;
NSArray *a;
rep=[[self alloc] _initBitmapFromPNG: imageData];
rep = [[self alloc] _initBitmapFromPNG: imageData];
if (!rep)
return [NSArray array];
a = [NSArray arrayWithObject: rep];
@ -224,7 +217,7 @@
NSBitmapImageRep *rep;
NSArray *a;
rep=[[self alloc] _initBitmapFromPNM: imageData
rep = [[self alloc] _initBitmapFromPNM: imageData
errorMessage: NULL];
if (!rep)
return [NSArray array];
@ -238,7 +231,7 @@
NSBitmapImageRep *rep;
NSArray *a;
rep=[[self alloc] _initBitmapFromJPEG: imageData
rep = [[self alloc] _initBitmapFromJPEG: imageData
errorMessage: NULL];
if (!rep)
return [NSArray array];
@ -252,7 +245,7 @@
NSBitmapImageRep *rep;
NSArray *a;
rep=[[self alloc] _initBitmapFromGIF: imageData
rep = [[self alloc] _initBitmapFromGIF: imageData
errorMessage: NULL];
if (!rep)
return [NSArray array];
@ -263,15 +256,7 @@
if ([self _bitmapIsICNS: imageData])
{
NSBitmapImageRep *rep;
NSArray *a;
rep=[[self alloc] _initBitmapFromICNS: imageData];
if (!rep)
return [NSArray array];
a = [NSArray arrayWithObject: rep];
DESTROY(rep);
return a;
return [self _imageRepsWithICNSData: imageData];
}
image = NSTiffOpenDataRead((char *)[imageData bytes], [imageData length]);
@ -298,11 +283,11 @@
return array;
}
/** Loads only the default (first) image from the TIFF image contained in
/** Loads only the default (first) image from the image contained in
data. */
- (id) initWithData: (NSData *)imageData
{
TIFF *image;
TIFF *image;
if (imageData == nil)
{
@ -328,7 +313,6 @@
if ([isa _bitmapIsICNS: imageData])
return [self _initBitmapFromICNS: imageData];
image = NSTiffOpenDataRead((char *)[imageData bytes], [imageData length]);
if (image == NULL)
{
@ -337,8 +321,9 @@
return nil;
}
[self _initFromTIFFImage:image number: -1];
[self _initFromTIFFImage: image number: -1];
NSTiffClose(image);
return self;
}