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 "imageOperation.h"
-
-
- @implementation ImageOpr (ColorReplace)
-
-
- #define CLR_THRESHOLD (32 * 32 * 3)
- #define BRT_THRESHOLD (64 * 3)
- #define MONO_THRESHOLD 128
-
- static BOOL isMono;
- static const int *origClr;
- static int origbrite, cthresh, bthreshm, bthreshp;
-
- static void initNearColor(const int *orig, float comparison, int cnum)
- {
- origClr = orig;
- if (cnum < 3) {
- isMono = YES;
- origbrite = orig[0];
- bthreshm = orig[0] - MONO_THRESHOLD * comparison;
- bthreshp = orig[0] + MONO_THRESHOLD * comparison;
- }else {
- isMono = NO;
- origbrite = Bright255(orig[RED], orig[GREEN], orig[BLUE]);
- bthreshm = origbrite - BRT_THRESHOLD * comparison;
- bthreshp = origbrite + BRT_THRESHOLD * comparison;
- cthresh = CLR_THRESHOLD * comparison;
- }
- }
-
- static BOOL isNearColor(const int *elm)
- {
- int i, brt;
- double dif, d, fr;
-
- if (isMono)
- return (elm[0] < bthreshp && elm[0] > bthreshm);
-
- brt = Bright255(elm[RED], elm[GREEN], elm[BLUE]);
- if (brt > bthreshp || brt < bthreshm) /* compare brightness */
- return NO;
- if (brt == 0 || brt == 255 * 3)
- return YES; /* White/Black within allowed brightness */
- fr = (float)origbrite / brt;
- for (dif = 0, i = 0; i < 3; i++) {
- d = fr * elm[i] - origClr[i];
- dif += d * d;
- }
- if (dif < cthresh)
- return YES;
- fr = (255.0 * 3 - origClr[GREEN]) / (255.0 * 3 - elm[GREEN]);
- for (dif = 0, i = 0; i < 3; i++) {
- d = fr * (255.0 - elm[i]) - (255.0 - origClr[i]);
- dif += d * d;
- }
- if (dif < cthresh)
- return YES;
- return NO;
- }
-
- static commonInfo *makeClrChangeMap(const int *origclr, const int *newclr,
- float comparison, BOOL uniform, BOOL outside,
- commonInfo *cinf, NXRect *selrect,
- const unsigned char *map[], unsigned char *newmap[])
- {
- commonInfo *newinf = NULL;
- int pn, alp, cn;
- int x, y, i;
- int xorg=0, yorg=0, xend=0, yend=0;
-
- newmap[0] = NULL;
- if (selrect == NULL
- || selrect->size.width <= 0 || selrect->size.height <= 0
- || (selrect->size.width >= cinf->width &&
- selrect->size.height >= cinf->height))
- selrect = NULL;
- else {
- xorg = selrect->origin.x;
- xend = selrect->size.width + xorg - 1;
- yorg = cinf->height -
- (selrect->origin.y + selrect->size.height);
- yend = cinf->height - selrect->origin.y - 1;
- }
- if ((newinf = (commonInfo *)malloc(sizeof(commonInfo))) == NULL)
- goto ErrEXIT;
- *newinf = *cinf;
- newinf->palette = NULL;
- newinf->palsteps = 0;
- newinf->isplanar = YES;
- newinf->bits = 8;
- newinf->xbytes = newinf->width;
- if (cinf->alpha && origclr[ALPHA] == AlphaTransp && selrect == NULL)
- newinf->alpha = NO;
- if (newclr[ALPHA] == AlphaTransp)
- newinf->alpha = YES;
- if (cinf->numcolors == 1) {
- if (newclr[RED] != newclr[GREEN]
- || newclr[RED] != newclr[BLUE]) {
- newinf->numcolors = 3;
- newinf->cspace = NX_RGBColorSpace;
- }else
- newinf->cspace = NX_OneIsWhiteColorSpace;
- }
- pn = cn = (newinf->numcolors == 1) ? 1 : 3;
- if (newinf->alpha) alp = pn++;
- else alp = 0;
- initNearColor(origclr, comparison, cn);
- if (allocImage(newmap, newinf->width, newinf->height, 8, pn))
- goto ErrEXIT;
- if (initGetPixel(cinf) != 0)
- goto ErrEXIT;
- resetPixel(map, 0);
- for (y = 0; y < newinf->height; y++) {
- int elm[MAXPLANE], gen[MAXPLANE];
- const int *cp;
- BOOL selflag = selrect ? (yorg <= y && y <= yend) : NO;
- int ptr = newinf->width * y;
- for (x = 0; x < newinf->width; x++, ptr++) {
- getPixel(&elm[RED], &elm[GREEN], &elm[BLUE], &elm[ALPHA]);
- if (selrect == NULL ||
- (outside ^ (selflag && xorg <= x && x <= xend))) {
- if (origclr[ALPHA] == AlphaTransp)
- cp = (elm[ALPHA] == AlphaTransp) ? newclr : elm;
- else if (elm[ALPHA] == AlphaTransp)
- cp = elm; /* origclr[ALPHA] != AlphaTransp */
- else if (comparison == 0.0) {
- for (i = 0; i < cn; i++)
- if (origclr[i] != elm[i]) break;
- cp = (i >= cn) ? newclr : elm;
- }else if (isNearColor(elm)) {
- if (uniform) cp = newclr;
- else {
- int d;
- for (i = 0; i < cn; i++) {
- d = elm[i] - origclr[i] + newclr[i];
- gen[i] = (d>255)? 255: ((d<0)? 0: d);
- }
- if (alp) gen[ALPHA] = newclr[ALPHA];
- cp = gen;
- }
- }else
- cp = elm;
- }else
- cp = elm;
- for (i = 0; i < cn; i++)
- newmap[i][ptr] = cp[i];
- if (alp)
- newmap[alp][ptr] = cp[ALPHA];
- }
- }
- return newinf;
-
- ErrEXIT:
- if (newinf)
- free((void *)newinf);
- if (newmap[0]) free((void *)newmap[0]);
- return NULL;
- }
-
-
- - colorChange:(int *)origclr to:(int *)newclr with:(float)comparison
- uniformly:(BOOL)uniform area:(BOOL)outside
- {
- ToyWin *tw, *newtw = nil;
- ToyView *tv = nil;
- commonInfo *cinf, *newinf;
- const char *fnam;
- char fn[256];
- NXBitmapImageRep *rep;
- unsigned char *map[MAXPLANE], *newmap[MAXPLANE];
- int i;
-
- for (i = 0; i < 4; i++)
- if (origclr[i] != newclr[i]) break;
- if (i >= 4 /* Same Color */
- || (tw = [theController keyWindow]) == nil) {
- NXBeep();
- return self;
- }
- tv = [tw toyView];
- cinf = [tv commonInfo];
- if (!cinf->alpha && origclr[ALPHA] == AlphaTransp) {
- NXBeep();
- return self;
- }
- fnam = [tw filename];
- if (![self checkCommonInfo:cinf filename:fnam])
- return self;
- sprintf(fn, "%s(ColorChange)", fnam);
- rep = (NXBitmapImageRep *)[[tv image] bestRepresentation];
- [rep getDataPlanes: map];
- newinf = makeClrChangeMap(origclr, newclr, comparison,
- uniform, outside, cinf, [tv selectedScaledRect], map, newmap);
- if (newinf == NULL) {
- warnAlert(fnam, Err_MEMORY);
- return self;
- }
- newtw = [[ToyWin alloc] init:tw by:ColorChange];
- [newtw initLocateWindow:fn width:newinf->width height:newinf->height];
- [newtw makeComment: newinf from: cinf];
- [newtw drawView:newmap info: newinf];
-
- [theController newWindow: newtw];
- return self;
- }
-
- @end
-