home *** CD-ROM | disk | FTP | other *** search
- #import "../ImageOpr.h"
- #import <appkit/Application.h>
- #import <appkit/publicWraps.h>
- #import <appkit/NXBitmapImageRep.h>
- #import <appkit/Control.h>
- #import <appkit/Panel.h>
- #import <appkit/TextField.h>
- #import <stdio.h>
- #import <stdlib.h>
- #import <string.h>
- #import <libc.h>
- #import <streams/streams.h>
- #import "../TVController.h"
- #import "../ToyWin.h"
- #import "../ToyWinEPS.h"
- #import "../ToyView.h"
- #import "../common.h"
- #import "../getpixel.h"
- #import "../strfunc.h"
- #import "../ColorMap.h"
- #import "imageOperation.h"
- #ifdef _REDUCE_BY_MDA
- # import "MDAmethod.h"
- # define DitherCLASS MDAmethod
- #else
- # import "Dither.h"
- # define DitherCLASS Dither
- #endif
-
- @implementation ImageOpr (ReduceColor)
-
- static short tagColors[] = { /* Recude into N colors */
- 256, 256, 64, 16, 8
- };
-
- /* Local Method */
- - (int)reduceColor:(ColorMap *)colormap info:(commonInfo *)cinf
- map:(unsigned char **)map newmap:(unsigned char **)newmap
- alpha:(BOOL)alpha tag:(int)tag
- {
- id msgtext;
- paltype *pal = NULL;
- int i, x, y, idx;
- int trial, cnum;
- id <Dithering> dither[3];
- char msgbuf[80];
- unsigned char *rr, *gg, *bb;
- int elm[MAXPLANE];
- unsigned char apool[MAXWidth];
- unsigned char *alp;
- static short tagOpr[] = {
- /* initial value of 'trial'... index for dthbits[][] */
- 2, /* MCA (default reduction) */
- 5, /* Dither + MCA 256 colors */
- 7, /* Dither + MCA 64 colors */
- 5, /* Dither + MCA 16 colors */
- 5 /* Dither + MCA 8 colors */
- };
- static short dthbits[][3] = {
- {7, 7, 7}, {7, 7, 6}, {6, 6, 6}, {6, 6, 5},
- {5, 5, 5}, {5, 5, 4}, {4, 4, 4}, {4, 4, 3},
- {3, 3, 3}, {3, 3, 2}, {2, 2, 2 /* never */ }};
-
- msgtext = [theController messageDisplay:"Starting Reduction..."];
-
- cnum = 0;
- for (i = 0; i < 3; i++)
- dither[i] = nil;
- for (i = 0; i < 3; i++) {
- dither[i] = [DitherCLASS alloc];
- if (dither[i] == nil
- || [dither[i] init:128 width:cinf->width] == nil)
- goto ErrEXIT;
- }
-
- resetPixel(map, 0);
- idx = 0;
- for (y = 0; y < cinf->height; y++) {
- alp = alpha ? &newmap[ALPHA][idx] : apool;
- for (x = 0; x < cinf->width; x++, idx++) {
- getPixel(&elm[0], &elm[1], &elm[2], &elm[3]);
- if ((alp[x] = elm[ALPHA]) == AlphaTransp) {
- for (i = 0; i < 3; i++)
- newmap[i][idx] = 255;
- }else {
- for (i = 0; i < 3; i++)
- newmap[i][idx] = elm[i];
- }
- }
- }
-
- for (trial = tagOpr[tag]; ; trial++) {
- sprintf(msgbuf, "Trying Reduction: RGB=%d:%d:%d",
- dthbits[trial][0], dthbits[trial][1], dthbits[trial][2]);
- [msgtext setStringValue: msgbuf];
- NXPing();
-
- for (i = 0; i < 3; i++)
- [dither[i] reset:(1 << dthbits[trial][i])];
- [colormap init_regColor];
- for (y = 0; y < cinf->height; y++) {
- for (i = 0; i < 3; i++) {
- rr = [dither[i] buffer];
- gg = &newmap[i][y * cinf->width];
- for (x = 0; x < cinf->width; x++)
- *rr++ = *gg++;
- }
- rr = [dither[RED] getNewLine];
- gg = [dither[GREEN] getNewLine];
- bb = [dither[BLUE] getNewLine];
- for (x = 0; x < cinf->width; x++) {
- if ([colormap regColorToMap:*rr++:*gg++:*bb++] < 0)
- goto ReTRY; /* Too Many Color */
- }
- }
- break; /* OK */
- ReTRY: ;
- }
-
- [msgtext setStringValue: "Making Palette..."];
- NXPing();
- cnum = tagColors[tag];
- pal = [colormap getReducedMap: &cnum alpha:alpha];
- [msgtext setStringValue: "Writing Image..."];
- NXPing();
-
- for (i = 0; i < 3; i++)
- [dither[i] reset:(1 << dthbits[trial][i])];
- idx = 0;
- for (y = 0; y < cinf->height; y++) {
- for (i = 0; i < 3; i++) {
- rr = [dither[i] buffer];
- gg = &newmap[i][idx];
- for (x = 0; x < cinf->width; x++)
- *rr++ = *gg++;
- }
- rr = [dither[RED] getNewLine];
- gg = [dither[GREEN] getNewLine];
- bb = [dither[BLUE] getNewLine];
- for (x = 0; x < cinf->width; x++, idx++) {
- unsigned char *p = pal[mapping(*rr, *gg, *bb)];
- for (i = 0; i < 3; i++)
- newmap[i][idx] = p[i];
- rr++, gg++, bb++;
- }
- }
-
- ErrEXIT:
- for (i = 0; i < 3; i++)
- if (dither[i]) [dither[i] free];
- [theController messageDisplay:NULL];
- return cnum;
- }
-
-
- /* Local Method */
- - (commonInfo *)reducedBitmap:(unsigned char **)newmap
- from:(ToyWin *)tw with:(commonInfo *)cinf tag:(int)tag
- {
- commonInfo *newinfo = NULL;
- ColorMap *colormap = nil;
- unsigned char *map[MAXPLANE];
- int cnum = 0, pl, err = 0;
- BOOL hasalpha = NO;
- const char *fnam;
-
- newmap[0] = NULL;
- fnam = [tw filename];
- if ((err = [tw getBitmap:map info: &cinf]) == 0)
- err = initGetPixel(cinf);
- if (err) {
- errAlert(fnam, err);
- return NULL;
- }
-
- colormap = [[ColorMap alloc] init];
- if ([colormap allocFullColor] == nil) {
- err = Err_MEMORY;
- goto ErrEXIT;
- }else {
- cnum = [colormap getAllColor:map limit:0 alpha:&hasalpha];
- if (hasalpha) ++cnum;
- if (cnum <= tagColors[tag]) {
- (void)[self needReduce:fnam colors:cnum ask:NO];
- goto ErrEXIT;
- }
- }
- pl = hasalpha ? 4 : 3;
- err = allocImage(newmap, cinf->width, cinf->height, 8, pl);
- newinfo = (commonInfo *)malloc(sizeof(commonInfo));
- if (!newinfo)
- err = Err_MEMORY;
- if (err) goto ErrEXIT;
-
- cnum = [self reduceColor:colormap info:cinf
- map:map newmap:newmap alpha:hasalpha tag:tag];
- if (cnum <= 0) {
- err = Err_MEMORY;
- goto ErrEXIT;
- }
- *newinfo = *cinf;
- newinfo->xbytes = newinfo->width;
- newinfo->palsteps = cnum;
- newinfo->bits = 8;
- newinfo->numcolors = 3;
- newinfo->isplanar = YES;
- newinfo->alpha = hasalpha;
- newinfo->palette = [colormap getPalette];
- sprintf(newinfo->memo, "%d x %d %dcolors%s",
- newinfo->width, newinfo->height, cnum,
- (newinfo->alpha ? " Alpha" : ""));
- comment_copy(newinfo->memo, cinf->memo);
-
- if (colormap) [colormap free];
- [tw freeTempBitmap];
- return newinfo;
-
- ErrEXIT:
- if (err) errAlert(fnam, err);
- [tw freeTempBitmap];
- if (newmap[0]) free((void *)newmap[0]);
- if (newinfo) free((void *)newinfo);
- if (colormap) [colormap free];
- return NULL;
- }
-
-
- - reduceUsing: (int)tag
- {
- ToyWin *tw, *newtw;
- commonInfo *cinf;
- unsigned char *map[MAXPLANE];
- const char *fnam;
- char fn[256];
-
- if ((tw = [self keyParentWindow: Reduction]) == nil) {
- NXBeep();
- return self;
- }
- fnam = [tw filename];
- cinf = [[tw toyView] commonInfo];
- if (![self checkCommonInfo:cinf filename:fnam])
- return self;
-
- if (cinf->numcolors == 1) {
- warnAlert(fnam, Err_OPR_IMPL);
- return NULL;
- }
- if (cinf->palette && cinf->palsteps <= tagColors[tag]) {
- (void)[self needReduce:fnam colors:cinf->palsteps ask:NO];
- return NULL;
- }
-
- if ((cinf = [self reducedBitmap:map from:tw with:cinf tag:tag]) == NULL)
- return self;
- newtw = [[ToyWin alloc] init:tw by:Reduction];
- if (tag == 0)
- sprintf(fn, "%s(Reduce)", fnam);
- else
- sprintf(fn, "%s(Reduce%d)", fnam, tagColors[tag]);
- [newtw initLocateWindow:fn width:cinf->width height:cinf->height];
- if ([newtw drawView:map info: cinf] == nil) {
- errAlert(fnam, Err_MEMORY);
- [newtw free];
- free((void *)map[0]);
- free((void *)cinf);
- }else
- [theController newWindow: newtw];
- return self;
- }
-
-
- - (BOOL)needReduce:(const char *)fn colors:(int)cnum ask:(BOOL)ask
- {
- const char *qust, *title, *cancel, *reduce;
-
- qust = NXLocalizedString("No Need to Reduce", NULL, NO_Need_Reduction);
- title = NXLocalizedString("WARNING", NULL, WARNING);
- if (ask) {
- cancel = NXLocalizedString("Cancel", NULL, Stop_SAVE);
- reduce = NXLocalizedString("Reduce", NULL, BMP_Reduce);
- if (NXRunAlertPanel(title, qust, cancel, reduce, NULL, fn, cnum))
- return NO;
- }else
- NXRunAlertPanel(title, qust, NULL, NULL, NULL, fn, cnum);
- return YES;
- }
-
- @end
-