This is ImageSvGIF.m in view mode; [Download] [Up]
#import "../ImageSave.h"
#import <appkit/NXImage.h>
#import <appkit/SavePanel.h>
#import <stdio.h>
#import <libc.h>
#import <string.h>
#import "../ToyView.h"
#import "../ToyWin.h"
#import "../ColorMap.h"
#import "../strfunc.h"
#import "../common.h"
#import "save.h"
#import "GifSavePanel.h"
#define MANY_COLORS (-1) /* must be < 0 */
@implementation ImageSave (SaveGIF)
/* Local Method */
- (char *)getSaveIntlName: (const char *)path
ext: (const char *)ex interlace: (BOOL *)intp
{
GifSavePanel *savePanel;
char *stmp, *sav = NULL;
stmp = [ImageSave mk_tmpname:path ext:ex nopath:YES];
savePanel = [[GifSavePanel new] loadNib];
if ([savePanel runModalForDirectory: saveDir file: stmp]) {
sav = [ImageSave mk_tmpname:
[savePanel filename] ext:ex nopath:NO];
if (sav == NULL || *sav == 0)
return NULL;
strcpy(saveDir, [savePanel directory]);
*intp = [savePanel interlace];
}
return sav;
}
- (int)getPalette:(ColorMap *)colormap info:(commonInfo *)cinf
map:(unsigned char **)map needAlpha:(BOOL)alflag err:(int *)code
{
int cnum, err;
BOOL hasalpha;
err = 0;
if (cinf->palette != NULL) {
if ([colormap allocPalColor] == nil) {
err = Err_MEMORY;
goto EXIT;
}
cnum = [colormap regPalColorWithAlpha: alflag];
if (cnum > FIXcount)
err = MANY_COLORS;
goto EXIT;
}
if ([colormap allocFullColor] == nil) {
err = Err_MEMORY;
goto EXIT;
}
cnum = alflag
? [colormap getAllColor:map limit:FIXcount alpha:&hasalpha]
: [colormap getAllColor:map limit:FIXcount];
if (hasalpha) ++cnum;
if (cnum > FIXcount)
err = MANY_COLORS;
else {
(void)[colormap getNormalmap: &cnum];
cinf->palette = [colormap getPalette];
cinf->palsteps = cnum;
}
EXIT:
if (err) {
*code = err;
return 0;
}
return cinf->palsteps;
}
- (char *)saveAsGif: (char *)gifname
{
char *sav, *result = NULL;
commonInfo *cinf;
ColorMap *colormap = nil;
unsigned char *map[MAXPLANE];
int cnum, err;
static BOOL interl = NO;
cinf = [toyView commonInfo];
if (cinf->cspace == NX_CMYKColorSpace) {
warnAlert([toyWin filename], Err_SAV_IMPL);
return NULL;
}
if (gifname) /* Called after reduction */
sav = gifname;
else {
sav = [self getSaveIntlName: [toyWin filename]
ext: "gif" interlace: &interl];
if (sav == NULL) /* canceled */
return NULL;
}
if ((err = [toyWin getBitmap:map info: &cinf]) != 0)
goto EXIT;
if ((err = initGetPixel(cinf)) != 0)
goto EXIT;
colormap = [[ColorMap alloc] init];
cnum = [self getPalette:colormap
info:cinf map:map needAlpha:YES err:&err];
if (cnum == 0) {
const char *ask, *cancel, *reduce;
if (err != MANY_COLORS)
goto EXIT;
ask = NXLocalizedString(
"Reduction Start", NULL, GIF_Reduction);
cancel = NXLocalizedString("Cancel", NULL, Stop_SAVE);
reduce = NXLocalizedString("Reduce", NULL, BMP_Reduce);
if (NXRunAlertPanel("", ask, reduce, cancel, NULL))
result = sav; /* Save after reduction */
goto EXIT;
}
if (!err) {
FILE *fp;
int transp;
transp = (cinf->alpha && cinf->palette) ? cinf->palsteps : -1;
if ((fp = fopen(sav, "w")) == NULL) {
errAlert(sav, Err_SAVE);
[colormap free];
[toyWin freeTempBitmap];
return NULL; // Don't goto EXIT.
}
GIFEncode(fp, cinf, map, cnum, transp, interl, cinf->palette);
(void)fclose(fp);
[toyWin resetFilename:sav];
}
EXIT:
if (colormap) [colormap free];
[toyWin freeTempBitmap];
if (err) {
errAlert(sav, err);
(void)unlink(sav);
}
/* result != NULL --> This method is called again after Reduction */
return result;
}
- saveAsPng: sender
{
commonInfo *cinf;
commonInfo copyinf;
FILE *fp;
ColorMap *colormap = nil;
char *sav;
unsigned char *map[MAXPLANE];
int err;
static BOOL interl = NO;
cinf = [toyView commonInfo];
if (cinf->cspace == NX_CMYKColorSpace) {
warnAlert([toyWin filename], Err_SAV_IMPL);
return NULL;
}
if ((sav = [self getSaveIntlName: [toyWin filename]
ext: "png" interlace: &interl]) == NULL) /* canceled */
return NULL;
if ((fp = fopen(sav, "w")) == NULL) {
errAlert(sav, Err_SAVE);
return self;
}
err = [toyWin getBitmap:map info: &cinf];
if (!err) err = initGetPixel(cinf);
if (err) goto EXIT;
if (cinf->cspace != NX_RGBColorSpace) { /* Monochrome */
copyinf = *cinf;
copyinf.palette = NULL; /* No need to allocate palette */
copyinf.palsteps = 0;
cinf = ©inf;
}else {
colormap = [[ColorMap alloc] init];
(void) [self getPalette:colormap
info:cinf map:map needAlpha:YES err:&err];
err = 0; /* Error is ignored */
}
resetPixel(map, 0);
pngwrite(fp, cinf, appDir, interl);
/* fp is closed in pngwrite */
EXIT:
if (colormap) [colormap free];
[toyWin freeTempBitmap];
if (err) {
errAlert(sav, err);
(void)unlink(sav);
}else
[toyWin resetFilename:sav];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.