This is ImageCChange.m in view mode; [Download] [Up]
#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
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.