mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-22 16:10:48 +00:00
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:
parent
4e578145fe
commit
3f7866a8ed
9 changed files with 977 additions and 9 deletions
21
ChangeLog
21
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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 \
|
||||
|
|
44
Source/NSBitmapImageRep+JPEG.h
Normal file
44
Source/NSBitmapImageRep+JPEG.h
Normal 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
|
||||
|
||||
|
376
Source/NSBitmapImageRep+JPEG.m
Normal file
376
Source/NSBitmapImageRep+JPEG.m
Normal 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 */
|
||||
|
39
Source/NSBitmapImageRep+PNG.h
Normal file
39
Source/NSBitmapImageRep+PNG.h
Normal 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
|
237
Source/NSBitmapImageRep+PNG.m
Normal file
237
Source/NSBitmapImageRep+PNG.m
Normal 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 */
|
||||
|
42
Source/NSBitmapImageRep+PNM.h
Normal file
42
Source/NSBitmapImageRep+PNM.h
Normal 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
|
||||
|
134
Source/NSBitmapImageRep+PNM.m
Normal file
134
Source/NSBitmapImageRep+PNM.m
Normal 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
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue