This is SurfGIFDecoder.m in view mode; [Download] [Up]
/*
** Copyright (c) 1995 Netsurfer Inc. All Rights Reserved.
**
** Author: <bbum@friday.com>
*/
/* This object is included in the MiscKit by permission from the author
** and its use is governed by the MiscKit license, found in the file
** "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
** for a list of all applicable permissions and restrictions.
*/
#import <appkit/appkit.h>
#import "SurfGIFSupport.h"
#import "SurfGIFDecoder.Internal.h"
#ifdef VERBOSE
#undef VERBOSE
#undef METHOD
#undef METHODnl
#endif
#define VERBOSE if(_SDFlags.verboseMode)
#define METHOD fprintf(stderr, "[%s %s%s] ", \
object_getClassName(self), \
(self == [self class]) ? "+" : "-", \
SELNAME(_cmd))
#define METHODnl fprintf(stderr, "[%s %s%s]\n", \
object_getClassName(self), \
(self == [self class]) ? "+" : "-", \
SELNAME(_cmd))
@implementation SurfGIFDecoder
/*"
* This class encapsulates all state necessary to decode a particular
* GIF stream into an instance of NXImage. The instance of NXImage may
* contain multiple NXBitmapImageReps-- each one containing one of the
* images decoded from the GIF stream. This level of abstraction [a class
* encapsulating the decoder] is necessary to fully support the features of
* GIF in a manner compatible with NXImage and also support the move to a
* threaded environment.
*
* The GIF specification defines more than an image encapsulation schema;
* the decoder must be able to "remember" some state between decoding
* images. For example, a valid GIF stream is one that contains nothing
* but a Global Color Table -- as well, a valid GIF stream is one that
* doesn't contain any Color Tables at all; when encountered, it
* effectively inherits the color table used to decode the last image
* [hence the usefulness of a stream that is nothing but a color table].
"*/
+ initialize
{
#ifdef DEBUG
if(sizeof(SurfColorEntry32) != 4) {
NXLogError(
"SurfColorEntry32 NOT 4 bytes/32 bits is (%d bytes)\n",
sizeof(SurfColorEntry32));
exit(1);
}
if(sizeof(SurfColorEntry16) != 2) {
NXLogError(
"SurfColorEntry16 NOT 2 bytes/16 bits is (%d bytes)\n",
sizeof(SurfColorEntry16));
exit(1);
}
#endif
return self;
}
+ sharedInstance
/*"
* This method is provided for convenience and should only be used in a
* single-threaded conversion environment. In a multiple threaded
* environment, it is much safer to not use this method and to manage the
* multiple iinstances using the normal alloc/init/free paradigm.
"*/
{
static id sharedInstance = nil;
if (!sharedInstance) {
sharedInstance = [self alloc];
[sharedInstance init];
}
return sharedInstance;
}
+ (const char *const *)imageUnfilteredFileTypes
/*"
* Returns a NULL terminated array of file extensions that this decoder
* class can decode.
"*/
{
static const char *const gifTypes[] = {"gif", "GIF", NULL};
return gifTypes;
}
+ (BOOL)canLoadFromStream:(NXStream *)stream
/*"
* Returns YES if the first few bytes of stream indicate an image that an
* instance of this decoder can likely decode successfully.
"*/
{
long startingPosition = NXTell(stream);
BOOL canRead = NO;
char magic[3];
/* read the first three characters -- these should be 'GIF' for
a valid GIF stream. As per the specification, we ignore the
version number; regardless of the version, we are supposed
to read the encapsulated data and do our best.
*/
if(!NXRead(stream, magic, 3))
goto resetAndReturn;
/* First three characters should be 'GIF'
*/
if( (magic[0] == 'G') &&
(magic[1] == 'I') &&
(magic[2] == 'F') )
canRead = YES;
resetAndReturn:
/* Reset stream back to the starting postiion.
*/
NX_DURING
NXSeek(stream, startingPosition, NX_FROMSTART);
NX_HANDLER
NXLogError("Attempted to NXSeek() a stream that cannot be NXSeek()ed.");
canRead = NO;
NX_ENDHANDLER
return canRead;
}
- (void)printForDebugger:(NXStream *)stream
{
[super printForDebugger:stream];
}
- init
{
_SGIFDFlags.gctZeroUnused = YES;
_SGIFDFlags.produceSilhouette = NO;
[self _resetDecoder];
decompressionState = NXZoneMalloc([self zone], sizeof(LWZState));
return self;
}
- free
{
NX_FREE(decompressionState);
return [super free];
}
/* set/query
*/
- (BOOL) produceSilhouette
/*"
* Returns YES if decoder will produce a silhouette of the image. A
* silhuette is transparent wherever the gif is transparent and is solid
* white wherever the image is non-transparent.
"*/
{
return _SGIFDFlags.produceSilhouette;
}
- (void) setProduceSilhouette:(BOOL) aFlag
/*"
* Enables/disables silhouette mode.
*
* see #{-produceSilhouette}.
"*/
{
_SGIFDFlags.produceSilhouette = aFlag;
}
- (BOOL) gctZeroUnused
/*"
* Returns YES if the decoder will zero all unused global color table
* entries beyond the last entry for the current image. Basically, this
* ensures that if the image references an entry in the color table beyond
* the color table size (since the global color table is large enough to
* hold the maximum sized color table, overrunning the current global color
* table size CANOT cause a memory exception), the resulting pixel will be
* black.
"*/
{
return _SGIFDFlags.gctZeroUnused;
}
- (void) setGctZeroUnused:(BOOL) aFlag
/*"
* Enables/disables zeroing of unused global color table entries.
*
* see #{-gctZeroUnused}.
"*/
{
_SGIFDFlags.gctZeroUnused = aFlag;
}
- (void) setShowColorTable:(BOOL) aFlag
/*"
* If enabled, each color table will be printed in ASCII form to stderr.
"*/
{
_SGIFDFlags.showColorTable = aFlag;
}
- (BOOL) showColorTable
/*"
* Returns YES if each decoded color table is printed to stderr.
"*/
{
return _SGIFDFlags.showColorTable;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.