home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Graphics / ToyViewer-2.6a / src / ImageOpr.bproj / ImageCChange.m < prev    next >
Encoding:
Text File  |  1997-01-22  |  5.9 KB  |  227 lines

  1. #import "../ImageOpr.h"
  2. #import <appkit/Application.h>
  3. #import <appkit/publicWraps.h>
  4. #import <appkit/NXBitmapImageRep.h>
  5. #import <appkit/Control.h>
  6. #import <appkit/Panel.h>
  7. #import <appkit/TextField.h>
  8. #import <stdio.h>
  9. #import <stdlib.h>
  10. #import <string.h>
  11. #import <libc.h>
  12. #import <streams/streams.h>
  13. #import "../TVController.h"
  14. #import "../ToyWin.h"
  15. #import "../ToyWinEPS.h"
  16. #import "../ToyView.h"
  17. #import "../common.h"
  18. #import "../getpixel.h"
  19. #import "imageOperation.h"
  20.  
  21.  
  22. @implementation ImageOpr (ColorReplace)
  23.  
  24.  
  25. #define  CLR_THRESHOLD    (32 * 32 * 3)
  26. #define  BRT_THRESHOLD    (64 * 3)
  27. #define  MONO_THRESHOLD    128
  28.  
  29. static BOOL isMono;
  30. static const int *origClr;
  31. static int origbrite, cthresh, bthreshm, bthreshp;
  32.  
  33. static void initNearColor(const int *orig, float comparison, int cnum)
  34. {
  35.     origClr = orig;
  36.     if (cnum < 3) {
  37.     isMono = YES;
  38.     origbrite = orig[0];
  39.     bthreshm = orig[0] - MONO_THRESHOLD * comparison;
  40.     bthreshp = orig[0] + MONO_THRESHOLD * comparison;
  41.     }else {
  42.     isMono = NO;
  43.     origbrite = Bright255(orig[RED], orig[GREEN], orig[BLUE]);
  44.     bthreshm = origbrite - BRT_THRESHOLD * comparison;
  45.     bthreshp = origbrite + BRT_THRESHOLD * comparison;
  46.     cthresh = CLR_THRESHOLD * comparison;
  47.     }
  48. }
  49.  
  50. static BOOL isNearColor(const int *elm)
  51. {
  52.     int i, brt;
  53.     double dif, d, fr;
  54.  
  55.     if (isMono)
  56.         return (elm[0] < bthreshp && elm[0] > bthreshm);
  57.  
  58.     brt = Bright255(elm[RED], elm[GREEN], elm[BLUE]);
  59.     if (brt > bthreshp || brt < bthreshm)    /* compare brightness */
  60.         return NO;
  61.     if (brt == 0 || brt == 255 * 3)
  62.         return YES;    /* White/Black within allowed brightness */
  63.     fr = (float)origbrite / brt;
  64.     for (dif = 0, i = 0; i < 3; i++) {
  65.         d = fr * elm[i] - origClr[i];
  66.         dif += d * d;
  67.     }
  68.     if (dif < cthresh)
  69.         return YES;
  70.     fr = (255.0 * 3 - origClr[GREEN]) / (255.0 * 3 - elm[GREEN]);
  71.     for (dif = 0, i = 0; i < 3; i++) {
  72.         d = fr * (255.0 - elm[i]) - (255.0 - origClr[i]);
  73.         dif += d * d;
  74.     }
  75.     if (dif < cthresh)
  76.         return YES;
  77.     return NO;
  78. }
  79.  
  80. static commonInfo *makeClrChangeMap(const int *origclr, const int *newclr,
  81.     float comparison, BOOL uniform, BOOL outside,
  82.     commonInfo *cinf, NXRect *selrect,
  83.     const unsigned char *map[], unsigned char *newmap[])
  84. {
  85.     commonInfo *newinf = NULL;
  86.     int pn, alp, cn;
  87.     int x, y, i;
  88.     int xorg=0, yorg=0, xend=0, yend=0;
  89.  
  90.     newmap[0] = NULL;
  91.     if (selrect == NULL
  92.         || selrect->size.width <= 0 || selrect->size.height <= 0
  93.         || (selrect->size.width >= cinf->width &&
  94.             selrect->size.height >= cinf->height))
  95.         selrect = NULL;
  96.     else {
  97.         xorg = selrect->origin.x;
  98.         xend = selrect->size.width + xorg - 1;
  99.         yorg = cinf->height -
  100.             (selrect->origin.y + selrect->size.height);
  101.         yend = cinf->height - selrect->origin.y - 1;
  102.     }
  103.     if ((newinf = (commonInfo *)malloc(sizeof(commonInfo))) == NULL)
  104.         goto ErrEXIT;
  105.     *newinf = *cinf;
  106.     newinf->palette = NULL;
  107.     newinf->palsteps = 0;
  108.     newinf->isplanar = YES;
  109.     newinf->bits = 8;
  110.     newinf->xbytes = newinf->width;
  111.     if (cinf->alpha && origclr[ALPHA] == AlphaTransp && selrect == NULL)
  112.         newinf->alpha = NO;
  113.     if (newclr[ALPHA] == AlphaTransp)
  114.         newinf->alpha = YES;
  115.     if (cinf->numcolors == 1) {
  116.         if (newclr[RED] != newclr[GREEN]
  117.                 || newclr[RED] != newclr[BLUE]) {
  118.             newinf->numcolors = 3;
  119.             newinf->cspace = NX_RGBColorSpace;
  120.         }else
  121.             newinf->cspace = NX_OneIsWhiteColorSpace;
  122.     }
  123.     pn = cn = (newinf->numcolors == 1) ? 1 : 3;
  124.     if (newinf->alpha) alp = pn++;
  125.     else alp = 0;
  126.     initNearColor(origclr, comparison, cn);
  127.     if (allocImage(newmap, newinf->width, newinf->height, 8, pn))
  128.         goto ErrEXIT;
  129.     if (initGetPixel(cinf) != 0)
  130.         goto ErrEXIT;
  131.     resetPixel(map, 0);
  132.     for (y = 0; y < newinf->height; y++) {
  133.         int elm[MAXPLANE], gen[MAXPLANE];
  134.         const int *cp;
  135.         BOOL selflag = selrect ? (yorg <= y && y <= yend) : NO;
  136.         int ptr = newinf->width * y;
  137.         for (x = 0; x < newinf->width; x++, ptr++) {
  138.         getPixel(&elm[RED], &elm[GREEN], &elm[BLUE], &elm[ALPHA]);
  139.         if (selrect == NULL ||
  140.             (outside ^ (selflag && xorg <= x && x <= xend))) {
  141.             if (origclr[ALPHA] == AlphaTransp)
  142.             cp = (elm[ALPHA] == AlphaTransp) ? newclr : elm;
  143.             else if (elm[ALPHA] == AlphaTransp)
  144.             cp = elm;    /* origclr[ALPHA] != AlphaTransp */
  145.             else if (comparison == 0.0) {
  146.             for (i = 0; i < cn; i++)
  147.                 if (origclr[i] != elm[i]) break;
  148.             cp = (i >= cn) ? newclr : elm;
  149.             }else if (isNearColor(elm)) {
  150.                 if (uniform) cp = newclr;
  151.                 else {
  152.                     int d;
  153.                     for (i = 0; i < cn; i++) {
  154.                     d = elm[i] - origclr[i] + newclr[i];
  155.                     gen[i] = (d>255)? 255: ((d<0)? 0: d);
  156.                     }
  157.                     if (alp) gen[ALPHA] = newclr[ALPHA];
  158.                     cp = gen;
  159.                 }
  160.             }else
  161.                 cp = elm;
  162.         }else
  163.             cp = elm;
  164.         for (i = 0; i < cn; i++)
  165.             newmap[i][ptr] = cp[i];
  166.         if (alp)
  167.             newmap[alp][ptr] = cp[ALPHA];
  168.         }
  169.     }
  170.     return newinf;
  171.  
  172. ErrEXIT:
  173.     if (newinf)
  174.         free((void *)newinf);
  175.     if (newmap[0]) free((void *)newmap[0]);
  176.     return NULL;
  177. }
  178.  
  179.  
  180. - colorChange:(int *)origclr to:(int *)newclr with:(float)comparison
  181.         uniformly:(BOOL)uniform area:(BOOL)outside
  182. {
  183.     ToyWin    *tw, *newtw = nil;
  184.     ToyView    *tv = nil;
  185.     commonInfo    *cinf, *newinf;
  186.     const char *fnam;
  187.     char fn[256];
  188.     NXBitmapImageRep *rep;
  189.     unsigned char *map[MAXPLANE], *newmap[MAXPLANE];
  190.     int i;
  191.  
  192.     for (i = 0; i < 4; i++)
  193.         if (origclr[i] != newclr[i]) break;
  194.     if (i >= 4 /* Same Color */
  195.         || (tw = [theController keyWindow]) == nil) {
  196.         NXBeep();
  197.         return self;
  198.     }
  199.     tv = [tw toyView];
  200.     cinf = [tv commonInfo];
  201.     if (!cinf->alpha && origclr[ALPHA] == AlphaTransp) {
  202.         NXBeep();
  203.         return self;
  204.     }
  205.     fnam = [tw filename];
  206.     if (![self checkCommonInfo:cinf filename:fnam])
  207.         return self;
  208.     sprintf(fn, "%s(ColorChange)", fnam);
  209.     rep = (NXBitmapImageRep *)[[tv image] bestRepresentation];
  210.     [rep getDataPlanes: map];
  211.     newinf = makeClrChangeMap(origclr, newclr, comparison,
  212.         uniform, outside, cinf, [tv selectedScaledRect], map, newmap);
  213.     if (newinf == NULL) {
  214.         warnAlert(fnam, Err_MEMORY);
  215.         return self;
  216.     }
  217.     newtw = [[ToyWin alloc] init:tw by:ColorChange];
  218.     [newtw initLocateWindow:fn width:newinf->width height:newinf->height];
  219.     [newtw makeComment: newinf from: cinf];
  220.     [newtw drawView:newmap info: newinf];
  221.  
  222.     [theController newWindow: newtw];
  223.     return self;
  224. }
  225.  
  226. @end
  227.