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.