Add new image loaders.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@18331 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Alexander Malmberg 2004-01-07 23:53:15 +00:00
parent 4e578145fe
commit 3f7866a8ed
9 changed files with 977 additions and 9 deletions

View file

@ -1,3 +1,24 @@
2004-01-08 00:47 Alexander Malmberg <alexander@malmberg.org>
* configure.ac: Fail with a verbose error message if libjpeg or
libpng can't be found. Add --disable-jpeg/--disable-png options that
override this.
* configure: Regenerate.
* Source/GNUmakefile: Add NSBitmapImageRep+JPEG.m,
NSBitmapImageRep+PNG.m, and NSBitmapImageRep+PNM.m .
* Source/NSBitmapImageRep.m (+canInitWithData:) Check if one of the
new loaders can handle the data.
(+imageUnfilteredFileTypes): Include the types from the new loaders.
(+imageRepsWithData:, -initWithData:): Use the new loaders to load
images.
* Source/NSBitmapImageRep+JPEG.m, Source/NSBitmapImageRep+JPEG.h,
Source/NSBitmapImageRep+PNG.m, Source/NSBitmapImageRep+PNG.h,
Source/NSBitmapImageRep+PNM.m, Source/NSBitmapImageRep+PNM.h:
New files with image loaders for JPEG, PNG, and PNM.
2003-01-07 Fred Kiefer <FredKiefer@gmx.de>
* Headers/Additions/GNUstepGUI/GSHbox.h:

View file

@ -50,6 +50,9 @@ NSApplication.m \
NSAttributedString.m \
NSBezierPath.m \
NSBitmapImageRep.m \
NSBitmapImageRep+JPEG.m \
NSBitmapImageRep+PNG.m \
NSBitmapImageRep+PNM.m \
NSBox.m \
NSBrowser.m \
NSBrowserCell.m \

View file

@ -0,0 +1,44 @@
/* NSBitmapImageRep+JPEG.h
Functionality for reading jpeg images
Copyright (C) 2003 Free Software Foundation, Inc.
Written by: Stefan Kleine Stegemann <stefan@wms-network.de>
Date: Nov 2003
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.
*/
#ifndef _NSBitmapImageRep_JPEG_H_include
#define _NSBitmapImageRep_JPEG_H_include
#include "AppKit/NSBitmapImageRep.h"
@interface NSBitmapImageRep (JPEGReading)
+ (BOOL) _bitmapIsJPEG: (NSData *)imageData;
- (id) _initBitmapFromJPEG: (NSData *)imageData
errorMessage: (NSString **)errorMsg;
@end
#endif // _NSBitmapImageRep_JPEG_H_include

View file

@ -0,0 +1,376 @@
/* NSBitmapImageRep+JPEG.m
Methods for reading jpeg images
Copyright (C) 2003 Free Software Foundation, Inc.
Written by: Stefan Kleine Stegemann <stefan@wms-network.de>
Date: Nov 2003
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 "config.h"
#include "NSBitmapImageRep+JPEG.h"
#if HAVE_LIBJPEG
#include <Foundation/NSString.h>
#include <Foundation/NSData.h>
#include <Foundation/NSException.h>
#include "AppKit/NSGraphics.h"
#include <jerror.h>
#include <jpeglib.h>
#include <setjmp.h>
/* -----------------------------------------------------------
The following functions are for interacting with the
jpeg library
----------------------------------------------------------- */
/* A custom error manager for the jpeg library
* that 'inherits' from libjpeg's standard
* error manager. */
struct gs_jpeg_error_mgr
{
struct jpeg_error_mgr parent;
/* marks where to return after an error (instead of
simply exiting) */
jmp_buf setjmpBuffer;
/* a pointer to the last error message, nil if no
error occured. if present, string is autoreleased. */
NSString *error;
};
typedef struct gs_jpeg_error_mgr *gs_jpeg_error_mgr_ptr;
/* Print the last jpeg library error and returns
* the control to the caller of the libary.
* libjpegs default error handling would exit
* after printing the error. */
static void gs_jpeg_error_exit(j_common_ptr cinfo)
{
gs_jpeg_error_mgr_ptr myerr = (gs_jpeg_error_mgr_ptr)cinfo->err;
(*cinfo->err->output_message)(cinfo);
/* jump back to the caller of the library */
longjmp(myerr->setjmpBuffer, 1);
}
/* Save the error message in error. */
static void gs_jpeg_output_message(j_common_ptr cinfo)
{
char msgBuffer[JMSG_LENGTH_MAX];
gs_jpeg_error_mgr_ptr myerr = (gs_jpeg_error_mgr_ptr)cinfo->err;
(*cinfo->err->format_message)(cinfo, msgBuffer);
myerr->error = [NSString stringWithCString: msgBuffer];
}
/* Initialize our error manager */
static void gs_jpeg_error_mgr_init(gs_jpeg_error_mgr_ptr errMgr)
{
errMgr->error = nil;
}
/* ------------------------------------------------------------------*/
/* A custom data source manager that allows the jpeg library
* to read it's data from memory. It 'inherits' from the
* default jpeg source manager. */
typedef struct
{
struct jpeg_source_mgr parent;
/* the data to be passed to the library functions */
const unsigned char *data;
unsigned int length;
} gs_jpeg_source_mgr;
typedef gs_jpeg_source_mgr *gs_jpeg_source_ptr;
static void gs_init_source(j_decompress_ptr cinfo)
{
/* nothing to do here (so far) */
}
static boolean gs_fill_input_buffer(j_decompress_ptr cinfo)
{
gs_jpeg_source_ptr src = (gs_jpeg_source_ptr)cinfo->src;
/* we make all data available at once */
if (src->length == 0)
{
ERREXIT(cinfo, JERR_INPUT_EMPTY);
}
src->parent.next_input_byte = src->data;
src->parent.bytes_in_buffer = src->length;
return TRUE;
}
static void gs_skip_input_data(j_decompress_ptr cinfo, long numBytes)
{
gs_jpeg_source_ptr src = (gs_jpeg_source_ptr)cinfo->src;
if (numBytes > 0)
{
src->parent.next_input_byte += numBytes;
src->parent.bytes_in_buffer -= numBytes;
}
}
static void gs_term_source(j_decompress_ptr cinfo)
{
/* nothing to do here */
}
/* Prepare a decompression object for input from memory. The
* caller is responsible for providing and releasing the
* data. After decompression is done, gs_jpeg_memory_src_destroy
* has to be called. */
static void gs_jpeg_memory_src_create(j_decompress_ptr cinfo, NSData *data)
{
gs_jpeg_source_ptr src;
cinfo->src = (struct jpeg_source_mgr *)malloc(sizeof(gs_jpeg_source_mgr));
src = (gs_jpeg_source_ptr)cinfo->src;
src = (gs_jpeg_source_ptr) cinfo->src;
src->parent.init_source = gs_init_source;
src->parent.fill_input_buffer = gs_fill_input_buffer;
src->parent.skip_input_data = gs_skip_input_data;
src->parent.resync_to_restart = jpeg_resync_to_restart; /* use default */
src->parent.term_source = gs_term_source;
src->parent.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
src->parent.next_input_byte = NULL; /* until buffer loaded */
src->data = (const unsigned char *)[data bytes];
src->length = [data length];
}
/* Destroy the source manager of the jpeg decompression object. */
static void gs_jpeg_memory_src_destroy(j_decompress_ptr cinfo)
{
gs_jpeg_source_ptr src = (gs_jpeg_source_ptr)cinfo->src;
free(src); // does not free the data
cinfo->src = NULL;
}
/* -----------------------------------------------------------
The jpeg loading part of NSBitmapImageRep
----------------------------------------------------------- */
@implementation NSBitmapImageRep (JPEGReading)
/* Return YES if this looks like a JPEG. */
+ (BOOL) _bitmapIsJPEG: (NSData *)imageData
{
struct jpeg_decompress_struct cinfo;
struct gs_jpeg_error_mgr jerrMgr;
/* Be sure imageData contains data */
if (![imageData length])
{
return NO;
}
/* Establish the our custom error handler */
gs_jpeg_error_mgr_init(&jerrMgr);
cinfo.err = jpeg_std_error(&jerrMgr.parent);
jerrMgr.parent.error_exit = gs_jpeg_error_exit;
jerrMgr.parent.output_message = gs_jpeg_output_message;
// establish return context for error handling
if (setjmp(jerrMgr.setjmpBuffer))
{
gs_jpeg_memory_src_destroy(&cinfo);
jpeg_destroy_decompress(&cinfo);
return NO;
}
/* read the header to see if we have a jpeg */
jpeg_create_decompress(&cinfo);
/* Establish our own data source manager */
gs_jpeg_memory_src_create(&cinfo, imageData);
jpeg_read_header(&cinfo, TRUE);
gs_jpeg_memory_src_destroy(&cinfo);
jpeg_destroy_decompress(&cinfo);
return YES;
}
/* Read the jpeg image. Assume it is from a jpeg file and imageData is not
nil. */
- (id) _initBitmapFromJPEG: (NSData *)imageData
errorMessage: (NSString **)errorMsg
{
struct jpeg_decompress_struct cinfo;
struct gs_jpeg_error_mgr jerrMgr;
JDIMENSION sclcount, samplesPerRow, i, j, rowSize;
JSAMPARRAY sclbuffer = NULL;
unsigned char *imgbuffer = NULL;
if (!(self = [super init]))
return nil;
/* Establish the our custom error handler */
gs_jpeg_error_mgr_init(&jerrMgr);
cinfo.err = jpeg_std_error(&jerrMgr.parent);
jerrMgr.parent.error_exit = gs_jpeg_error_exit;
jerrMgr.parent.output_message = gs_jpeg_output_message;
// establish return context for error handling
if (setjmp(jerrMgr.setjmpBuffer))
{
/* assign the description of possible occured error to errorMsg */
if (errorMsg)
*errorMsg = (jerrMgr.error ? jerrMgr.error : nil);
gs_jpeg_memory_src_destroy(&cinfo);
jpeg_destroy_decompress(&cinfo);
if (imgbuffer)
{
free(imgbuffer);
}
RELEASE(self);
return nil;
}
/* jpeg-decompression */
jpeg_create_decompress(&cinfo);
/* Establish our own data source manager */
gs_jpeg_memory_src_create(&cinfo, imageData);
jpeg_read_header(&cinfo, TRUE);
/* we use RGB as target color space */
cinfo.out_color_space = JCS_RGB;
/* decompress */
jpeg_start_decompress(&cinfo);
/* process the decompressed data */
samplesPerRow = cinfo.output_width * cinfo.output_components;
rowSize = samplesPerRow * sizeof(unsigned char);
NSAssert(sizeof(JSAMPLE) == sizeof(unsigned char),
@"unexpected sample size");
sclbuffer = cinfo.mem->alloc_sarray((j_common_ptr)&cinfo,
JPOOL_IMAGE,
samplesPerRow,
cinfo.rec_outbuf_height);
/* sclbuffer is freed when cinfo is destroyed */
imgbuffer = NSZoneMalloc([self zone], cinfo.output_height * rowSize);
if (!imgbuffer)
{
NSLog(@"NSBitmapImageRep+JPEG: failed to allocated image buffer");
RELEASE(self);
return nil;
}
i = 0;
while (cinfo.output_scanline < cinfo.output_height)
{
sclcount = jpeg_read_scanlines(&cinfo, sclbuffer, cinfo.rec_outbuf_height);
for (j = 0; j < sclcount; j++)
{
// copy a row to the image buffer
memcpy((imgbuffer + (i * rowSize)),
*(sclbuffer + (j * rowSize)),
rowSize);
i++;
}
}
/* done */
jpeg_finish_decompress(&cinfo);
gs_jpeg_memory_src_destroy(&cinfo);
jpeg_destroy_decompress(&cinfo);
if (jerrMgr.parent.num_warnings)
{
NSLog(@"NSBitmapImageRep+JPEG: %d warnings during jpeg decompression, image may be corrupted",
jerrMgr.parent.num_warnings);
}
// create the imagerep
//BITS_IN_JSAMPLE is defined by libjpeg
[self initWithBitmapDataPlanes: &imgbuffer
pixelsWide: cinfo.output_width
pixelsHigh: cinfo.output_height
bitsPerSample: BITS_IN_JSAMPLE
samplesPerPixel: cinfo.output_components
hasAlpha: (cinfo.output_components == 3 ? NO : YES)
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bytesPerRow: rowSize
bitsPerPixel: BITS_IN_JSAMPLE * cinfo.output_components];
_imageData = [[NSData alloc]
initWithBytesNoCopy: imgbuffer
length: (rowSize * cinfo.output_height)];
return self;
}
@end
#else /* !HAVE_LIBJPEG */
@implementation NSBitmapImageRep (JPEGReading)
+ (BOOL) _bitmapIsJPEG: (NSData *)imageData
{
return NO;
}
- (id) _initBitmapFromJPEG: (NSData *)imageData
errorMessage: (NSString **)errorMsg
{
RELEASE(self);
return nil;
}
@end
#endif /* !HAVE_LIBJPEG */

View file

@ -0,0 +1,39 @@
/*
NSBitmapImageRep+PNG.h
Methods for loading .png images.
Copyright (C) 2003 Free Software Foundation, Inc.
Written by: Alexander Malmberg <alexander@malmberg.org>
Date: 2003-12-07
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.
*/
#ifndef _NSBitmapImageRep_PNG_H_include
#define _NSBitmapImageRep_PNG_H_include
#include "AppKit/NSBitmapImageRep.h"
@interface NSBitmapImageRep (PNG)
+ (BOOL) _bitmapIsPNG: (NSData *)imageData;
- (id) _initBitmapFromPNG: (NSData *)imageData;
@end
#endif

View file

@ -0,0 +1,237 @@
/*
NSBitmapImageRep+PNG.m
Methods for loading .png images.
Copyright (C) 2003 Free Software Foundation, Inc.
Written by: Alexander Malmberg <alexander@malmberg.org>
Date: 2003-12-07
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 "config.h"
#include "NSBitmapImageRep+PNG.h"
#if HAVE_LIBPNG
#include <png.h>
#include <Foundation/NSData.h>
#include <Foundation/NSException.h>
#include "AppKit/NSGraphics.h"
@implementation NSBitmapImageRep (PNG)
+ (BOOL) _bitmapIsPNG: (NSData *)imageData
{
if (![imageData length])
return NO;
if (!png_sig_cmp((png_bytep)[imageData bytes], 0, [imageData length]))
return YES;
return NO;
}
typedef struct
{
NSData *data;
unsigned int offset;
} reader_struct_t;
static void reader_func(png_structp png_struct, png_bytep data,
png_size_t length)
{
reader_struct_t *r = png_get_io_ptr(png_struct);
if (r->offset + length > [r->data length])
{
png_error(png_struct, "end of buffer");
return;
}
memcpy(data, [r->data bytes] + r->offset, length);
r->offset += length;
}
- (id) _initBitmapFromPNG: (NSData *)imageData
{
png_structp png_struct;
png_infop png_info, png_end_info;
int width,height;
unsigned char *buf;
int bytes_per_row;
int type,channels,depth;
BOOL alpha;
int bpp;
NSString *colorspace;
reader_struct_t reader;
if (!(self = [super init]))
return nil;
png_struct = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_struct)
{
RELEASE(self);
return nil;
}
png_info = png_create_info_struct(png_struct);
if (!png_info)
{
png_destroy_read_struct(&png_struct, NULL, NULL);
RELEASE(self);
return nil;
}
png_end_info = png_create_info_struct(png_struct);
if (!png_end_info)
{
png_destroy_read_struct(&png_struct, &png_info, NULL);
RELEASE(self);
return nil;
}
if (setjmp(png_jmpbuf(png_struct)))
{
png_destroy_read_struct(&png_struct, &png_info, &png_end_info);
RELEASE(self);
return nil;
}
reader.data = imageData;
reader.offset = 0;
png_set_read_fn(png_struct, &reader, reader_func);
png_read_info(png_struct, png_info);
width = png_get_image_width(png_struct, png_info);
height = png_get_image_height(png_struct, png_info);
bytes_per_row = png_get_rowbytes(png_struct, png_info);
type = png_get_color_type(png_struct, png_info);
channels = png_get_channels(png_struct, png_info);
depth = png_get_bit_depth(png_struct, png_info);
switch (type)
{
case PNG_COLOR_TYPE_GRAY:
colorspace = NSCalibratedWhiteColorSpace;
alpha = NO;
NSAssert(channels == 1, @"unexpected channel/color_type combination");
bpp = depth;
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
colorspace = NSCalibratedWhiteColorSpace;
alpha = YES;
NSAssert(channels == 2, @"unexpected channel/color_type combination");
bpp = depth * 2;
break;
case PNG_COLOR_TYPE_PALETTE:
png_set_palette_to_rgb(png_struct);
channels = 3;
depth = 8;
alpha = NO;
if (png_get_valid(png_struct, png_info, PNG_INFO_tRNS))
{
alpha = YES;
channels++;
png_set_tRNS_to_alpha(png_struct);
}
bpp = channels * 8;
bytes_per_row = channels * width;
colorspace = NSCalibratedRGBColorSpace;
break;
case PNG_COLOR_TYPE_RGB:
colorspace = NSCalibratedRGBColorSpace;
alpha = NO;
bpp = channels * depth; /* channels might be 4 if there's a filler */
channels = 3;
break;
case PNG_COLOR_TYPE_RGB_ALPHA:
colorspace = NSCalibratedRGBColorSpace;
alpha = YES;
NSAssert(channels == 4, @"unexpected channel/color_type combination");
bpp = 4 * depth;
break;
default:
NSLog(@"NSBitmapImageRep+PNG: unknown color type %i", type);
RELEASE(self);
return nil;
}
buf = NSZoneMalloc([self zone], bytes_per_row * height);
{
unsigned char *row_pointers[height];
int i;
for (i=0;i<height;i++)
row_pointers[i]=buf+i*bytes_per_row;
png_read_image(png_struct, row_pointers);
}
[self initWithBitmapDataPlanes: &buf
pixelsWide: width
pixelsHigh: height
bitsPerSample: depth
samplesPerPixel: channels
hasAlpha: alpha
isPlanar: NO
colorSpaceName: colorspace
bytesPerRow: bytes_per_row
bitsPerPixel: bpp];
_imageData = [[NSData alloc]
initWithBytesNoCopy: buf
length: bytes_per_row * height];
png_destroy_read_struct(&png_struct, &png_info, &png_end_info);
return self;
}
@end
#else /* !HAVE_LIBPNG */
@implementation NSBitmapImageRep (PNG)
+ (BOOL) _bitmapIsPNG: (NSData *)imageData
{
return NO;
}
- (id) _initBitmapFromPNG: (NSData *)imageData
{
RELEASE(self);
return nil;
}
@end
#endif /* !HAVE_LIBPNG */

View file

@ -0,0 +1,42 @@
/* bitmap
Functions for reading bitmap images
Copyright (C) 2003 Free Software Foundation, Inc.
Written by: Adam Fedor <fedor@gnu.org>
Date: Oct 2003
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.
*/
#ifndef _NSBitmapImageRep_PNM_H_include
#define _NSBitmapImageRep_PNM_H_include
#include "AppKit/NSBitmapImageRep.h"
@interface NSBitmapImageRep (PNM)
+ (BOOL) _bitmapIsPNM: (NSData *)imageData;
-(id) _initBitmapFromPNM: (NSData *)imageData
errorMessage: (NSString **)error;
@end
#endif

View file

@ -0,0 +1,134 @@
/* NSBitmapImageRep+PNM
Methods for reading PNM images
Copyright (C) 2003 Free Software Foundation, Inc.
Written by: Adam Fedor <fedor@gnu.org>
Date: Oct 2003
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 "NSBitmapImageRep+PNM.h"
#include <Foundation/NSData.h>
#include "AppKit/NSGraphics.h"
@implementation NSBitmapImageRep (PNM)
/* Return YES if this is a pgm or ppm file (raw only for now) */
+ (BOOL) _bitmapIsPNM: (NSData *)imageData
{
const char *bytes = [imageData bytes];
/*
3/4 bytes header line, 4/5 bytes size, 2/3 bytes depth. Thus, the image
must have a least 9 bytes.
*/
if ([imageData length]<9)
return NO;
if (bytes[0] == 'P' && (bytes[2]=='\n' || bytes[2]=='\r'))
{
if (bytes[1] == '5' || bytes[1] == '6')
return YES;
}
return NO;
}
#define GET_LINE() \
do \
{ \
char *p = buffer; \
while ( *ptr != '\n' && *ptr != '\r' && (ptr-bytes) < length) \
{ \
*p++ = *ptr++; \
if (p == &buffer[sizeof(buffer)]) \
{ \
ERRMSG(@"PNM header line too long"); \
} \
} \
ptr++; \
*p = '\0'; \
} while (0)
#define ERRMSG(msg) \
do { NSLog(@"Error loading PNM: %@", msg); if (error) *error = msg; RELEASE(self); return nil; } while (0)
/* Read the ppm image. Assume it is a ppm file and imageData is not nil */
-(id) _initBitmapFromPNM: (NSData *)imageData errorMessage: (NSString **)error
{
int num, xsize, ysize, levels;
char ptype;
char buffer[256], *pchar;
unsigned length;
id colorspace;
const char *ptr;
const char *bytes = [imageData bytes];
/* magic number */
ptr = bytes;
length = [imageData length];
GET_LINE();
if (bytes[0] != 'P')
ERRMSG(@"Invalid PNM header (magic number)");
ptype = bytes[1];
if (ptype != '5' && ptype != '6')
ERRMSG(@"Unsupported PNM type");
do
{
GET_LINE();
} while (buffer[0] == '#');
num = sscanf(buffer, "%d %d", &xsize, &ysize);
if (num != 2)
ERRMSG(@"Invalid PNM header (xsize/ysize)");
GET_LINE();
num = sscanf(buffer, "%d", &levels);
if (num != 1)
ERRMSG(@"Invalid PNM header (levels)");
colorspace = (ptype == '5') ? NSDeviceBlackColorSpace : NSDeviceRGBColorSpace;
self = [self initWithBitmapDataPlanes: NULL
pixelsWide: xsize
pixelsHigh: ysize
bitsPerSample: 8
samplesPerPixel: (ptype == '5') ? 1 : 3
hasAlpha: NO
isPlanar: NO
colorSpaceName: colorspace
bytesPerRow: 0
bitsPerPixel: 0];
if ([self bytesPerRow] * ysize > (length - (ptr - bytes)) )
ERRMSG(@"Invalid PNM file (short data)");
pchar = [self bitmapData];
if (levels < 256)
{
memcpy(pchar, ptr, [self bytesPerRow] * ysize);
}
else
{
ERRMSG(@"Cannot handle > 256 level PNM files");
}
return self;
}
@end

View file

@ -2,7 +2,7 @@
<abstract>Bitmap image representation.</abstract>
Copyright (C) 1996 Free Software Foundation, Inc.
Copyright (C) 1996, 2003, 2004 Free Software Foundation, Inc.
Author: Adam Fedor <fedor@gnu.org>
Date: Feb 1996
@ -30,6 +30,12 @@
#include <math.h>
#include <tiff.h>
#include "AppKit/NSBitmapImageRep.h"
#include "NSBitmapImageRep+JPEG.h"
#include "NSBitmapImageRep+PNG.h"
#include "NSBitmapImageRep+PNM.h"
#include <Foundation/NSArray.h>
#include <Foundation/NSData.h>
#include <Foundation/NSDebug.h>
@ -37,7 +43,6 @@
#include <Foundation/NSFileManager.h>
#include <Foundation/NSValue.h>
#include "AppKit/AppKitExceptions.h"
#include "AppKit/NSBitmapImageRep.h"
#include "AppKit/NSGraphics.h"
#include "AppKit/NSGraphicsContext.h"
#include "AppKit/NSPasteboard.h"
@ -94,6 +99,15 @@ static BOOL supports_lzw_compression = NO;
return NO;
}
if ([self _bitmapIsPNG: data])
return YES;
if ([self _bitmapIsPNM: data])
return YES;
if ([self _bitmapIsJPEG: data])
return YES;
image = NSTiffOpenDataRead ((char *)[data bytes], [data length]);
if (image != NULL)
@ -117,15 +131,20 @@ static BOOL supports_lzw_compression = NO;
{
NSArray *wtypes = [self _wrasterFileTypes];
types = [[NSMutableArray alloc] initWithObjects:
@"tiff", @"tif",
@"pnm", @"ppm",
#if HAVE_LIBJPEG
@"jpeg", @"jpg",
#endif
#if HAVE_LIBPNG
@"png",
#endif
nil];
if (wtypes != nil)
{
types = [wtypes mutableCopy];
[(NSMutableArray *)types insertObject: @"tiff" atIndex: 0];
[(NSMutableArray *)types insertObject: @"tif" atIndex: 1];
}
else
{
types = [[NSArray alloc] initWithObjects: @"tiff", @"tif", nil];
[(NSMutableArray *)types addObjectsFromArray: wtypes];
}
}
@ -175,6 +194,47 @@ static BOOL supports_lzw_compression = NO;
return [NSArray array];
}
if ([self _bitmapIsPNG: imageData])
{
NSBitmapImageRep *rep;
NSArray *a;
rep=[[self alloc] _initBitmapFromPNG: imageData];
if (!rep)
return [NSArray array];
a = [NSArray arrayWithObject: rep];
DESTROY(rep);
return a;
}
if ([self _bitmapIsPNM: imageData])
{
NSBitmapImageRep *rep;
NSArray *a;
rep=[[self alloc] _initBitmapFromPNM: imageData
errorMessage: NULL];
if (!rep)
return [NSArray array];
a = [NSArray arrayWithObject: rep];
DESTROY(rep);
return a;
}
if ([self _bitmapIsJPEG: imageData])
{
NSBitmapImageRep *rep;
NSArray *a;
rep=[[self alloc] _initBitmapFromJPEG: imageData
errorMessage: NULL];
if (!rep)
return [NSArray array];
a = [NSArray arrayWithObject: rep];
DESTROY(rep);
return a;
}
image = NSTiffOpenDataRead((char *)[imageData bytes], [imageData length]);
if (image == NULL)
{
@ -211,6 +271,18 @@ static BOOL supports_lzw_compression = NO;
return nil;
}
if ([isa _bitmapIsPNG: imageData])
return [self _initBitmapFromPNG: imageData];
if ([isa _bitmapIsPNM: imageData])
return [self _initBitmapFromPNM: imageData
errorMessage: NULL];
if ([isa _bitmapIsJPEG: imageData])
return [self _initBitmapFromJPEG: imageData
errorMessage: NULL];
image = NSTiffOpenDataRead((char *)[imageData bytes], [imageData length]);
if (image == NULL)
{