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

  1. #import "../ImageOpr.h"
  2. #import <appkit/Application.h>
  3. #import <appkit/publicWraps.h>
  4. #import <appkit/NXEPSImageRep.h>
  5. #import <appkit/NXBitmapImageRep.h>
  6. #import <appkit/Control.h>
  7. #import <appkit/Panel.h>
  8. #import <appkit/TextField.h>
  9. #import <stdio.h>
  10. #import <stdlib.h>
  11. #import <string.h>
  12. #import <streams/streams.h>
  13. #import <sys/types.h>
  14. #import <libc.h>
  15. #import "../TVController.h"
  16. #import "../ToyWin.h"
  17. #import "../ToyWinEPS.h"
  18. #import "../ToyView.h"
  19. #import "../common.h"
  20. #import "../getpixel.h"
  21. #import "imageOperation.h"
  22.  
  23. @implementation ImageOpr
  24.  
  25. - keyParentWindow:(int)op
  26. {
  27.     ToyWin *tw, *win;
  28.  
  29.     if ((tw = [theController keyWindow]) == nil)
  30.         return nil;
  31.     if (op != NoOperation && [tw madeby] == op) {
  32.         win = [tw parent];
  33.         if (win && [theController isOpenedID: win])
  34.             return win;
  35.     }
  36.     return tw;
  37. }
  38.  
  39. - (BOOL)checkCommonInfo:(const commonInfo *)cinf filename:(const char *)fn
  40. {
  41.     if (cinf->type == Type_eps) {
  42.         warnAlert(fn, Err_EPS_IMPL);
  43.         return NO;
  44.     }
  45.     if (cinf->cspace == NX_CMYKColorSpace) {
  46.         warnAlert(fn, Err_IMPLEMENT);
  47.         return NO;
  48.     }
  49.     if (cinf->width >= MAXWidth || cinf->height >= MAXWidth) {
  50.         errAlert(fn, Err_MEMORY);
  51.         return NO;
  52.     }
  53.     return YES;
  54. }
  55.  
  56.  
  57. static void sub_clip(NXRect *select, commonInfo *cinf, commonInfo *newinf,
  58.             int idx[], unsigned char **working)
  59. {
  60.     int    x, y;
  61.     int    i, pidx, ptr;
  62.     int    pix[MAXPLANE];
  63.  
  64.     int skipx = select->origin.x;
  65.     int skipt = cinf->width - (skipx + select->size.width);
  66.     int skipy = cinf->height - (select->origin.y + select->size.height);
  67.     for (y = 0; y < skipy; y++) {
  68.         for (x = 0; x < cinf->width; x++)
  69.             getPixelA(pix);
  70.     }
  71.     for (y = 0; y < newinf->height; y++) {
  72.         ptr = y * newinf->width;
  73.         for (x = 0; x < skipx; x++)
  74.             getPixelA(pix);
  75.         for (x = 0; x < newinf->width; x++) {
  76.             getPixelA(pix);
  77.             for (i = 0; i <= ALPHA; i++) {
  78.                 if ((pidx = idx[i]) < 0) continue;
  79.                 working[pidx][ptr + x] = pix[i];
  80.             }
  81.         }
  82.         for (x = 0; x < skipt; x++)
  83.             getPixelA(pix);
  84.     }
  85. }
  86.  
  87.  
  88. /******* Random Functions ********/
  89. #define  ValBAND    32
  90. #define  BANDMask    0x1f
  91. #define  ValBIAS    16
  92. static int randomFreq = 0, randomMag = 0;
  93.  
  94. - setRandom:(float)freq :(float)mag
  95. {
  96.     if (!randomMag)
  97.         srandom(getpid());
  98.     randomFreq = freq * freq * 256.0;
  99.     randomMag = (int)(mag * mag * (ValBAND - ValBIAS + 256.0)) + ValBIAS;
  100.     return self;
  101. }
  102.  
  103. static int random_value(int pix)
  104. {
  105.     long r, v;
  106.     r = random();
  107.     if ((r & 0xff) >= randomFreq)
  108.         return pix;
  109.     r = random();
  110.     v = randomMag - ((r >> 1) & BANDMask);
  111.     if (r & 1) v += pix;
  112.     else v = pix - v;
  113.     return (v > 255) ? 255 : ((v < 0) ? 0 : v);
  114. }
  115.  
  116. static void sub_negative(int op, NXRect *select, 
  117.         commonInfo *newinf, int idx[], unsigned char **working)
  118. {
  119.     int    x, y;
  120.     int    i, pidx, ptr, alp;
  121.     int    pix[MAXPLANE];
  122.     int    selectflag = NO, yout, xout;
  123.     int    skipx = 0, skipy = 0, yorig = 0;
  124.  
  125.     if (select && select->size.width > 0) {
  126.         skipx = select->origin.x + select->size.width - 1;
  127.         skipy = newinf->height - select->origin.y - 1;
  128.         yorig = skipy - select->size.height + 1;
  129.         selectflag = YES;
  130.     }
  131.  
  132.     if ((alp = idx[ALPHA]) < 0)
  133.         alp = 0;    /* index of Alpha > 0 */
  134.     for (y = 0; y < newinf->height; y++) {
  135.         yout = (selectflag && (y < yorig || y > skipy));
  136.         ptr = y * newinf->width;
  137.         for (x = 0; x < newinf->width; x++) {
  138.             xout = (yout ||
  139.             (selectflag && (x < select->origin.x || x > skipx)));
  140.             getPixelA(pix);
  141.             if (xout) {
  142.                 for (i = 0; i < ALPHA; i++) {
  143.                     if ((pidx = idx[i]) < 0) continue;
  144.                     working[pidx][ptr + x] = pix[i];
  145.                 }
  146.             }else if (op == Negative) {
  147.                 for (i = 0; i < ALPHA; i++) {
  148.                     if ((pidx = idx[i]) < 0) continue;
  149.                     working[pidx][ptr + x] = 0xff - pix[i];
  150.                 }
  151.             }else {
  152.                 for (i = 0; i < ALPHA; i++) {
  153.                     if ((pidx = idx[i]) < 0) continue;
  154.                     working[pidx][ptr + x] = random_value(pix[i]);
  155.                 }
  156.             }
  157.             if (alp) /* Alpha */
  158.                 working[alp][ptr + x] = pix[i];
  159.         }
  160.     }
  161.     if (newinf->palette) {
  162.         unsigned char *p;
  163.         paltype *pal = newinf->palette;
  164.         for (x = 0; x < newinf->palsteps; x++) {
  165.             p = pal[x];
  166.             for (i = 0; i < 3; i++)
  167.                 p[i] = 0xff - p[i];
  168.         }
  169.     }
  170. }
  171.  
  172.  
  173. /* Local Method */
  174. - doBitmap:(int)op parent:parent
  175.         filename:(const char *)fn info:(commonInfo *)cinf
  176.         to:(int)angle rect:(NXRect *)select
  177. {
  178.     ToyWin    *tw;
  179.     commonInfo *newinf = NULL;
  180.     unsigned char *working[MAXPLANE], *planes[MAXPLANE];
  181.     int    i, pl;
  182.     int    idx[MAXPLANE];
  183.     BOOL    rotalpha = NO, hadalpha = NO;
  184.  
  185.     working[0] = planes[0] = NULL;
  186.     tw = NULL;
  187.     if ((newinf = (commonInfo *)malloc(sizeof(commonInfo))) == NULL)
  188.         goto ErrEXIT;
  189.     *newinf = *cinf;
  190.     if (cinf->cspace == NX_OneIsBlackColorSpace)
  191.         newinf->cspace = NX_OneIsWhiteColorSpace;
  192.         /* getPixel() fixes 0 as Black */
  193.     newinf->isplanar = YES;
  194.     if (op == Rotation) {
  195.         rotate_size(angle, cinf, newinf);
  196.         if (newinf->width >= MAXWidth || newinf->height >= MAXWidth)
  197.             goto ErrEXIT;
  198.     }else if (op == Clip) {
  199.         newinf->width = select->size.width;
  200.         newinf->height = select->size.height;
  201.     }
  202.     newinf->xbytes = byte_length(newinf->bits, newinf->width);
  203.  
  204.     /** if rotalpha==YES one color(transparent) is added **/
  205.     if (cinf->palette 
  206.     && (cinf->alpha || !rotalpha || newinf->palsteps < FIXcount)) {
  207.         newinf->palette = copyPalette(cinf->palette, newinf->palsteps);
  208.         if (newinf->palette == NULL)
  209.             goto ErrEXIT;
  210.     }else {
  211.         newinf->palette = NULL;
  212.         newinf->palsteps = 0;
  213.     }
  214.  
  215.     pl = newinf->numcolors;
  216.     for (i = 0; i < pl; i++) idx[i] = i;
  217.     for (i = pl; i < MAXPLANE; i++) idx[i] = -1;
  218.     if (op == Rotation && (angle % 90 != 0))
  219.         newinf->alpha = rotalpha = YES;
  220.     if (newinf->alpha) idx[ALPHA] = pl++;
  221.     if (allocImage(working, newinf->width, newinf->height, 8, pl))
  222.         goto ErrEXIT;
  223.     tw = [[ToyWin alloc] init:parent by:op];
  224.     [tw initLocateWindow:fn width:newinf->width height:newinf->height];
  225.  
  226.     if (op == Clip) {
  227.         sub_clip(select, cinf, newinf, idx, working);
  228.         if (newinf->alpha) {
  229.             int aw = newinf->width * newinf->height;
  230.             unsigned char *ap = working[pl-1];
  231.             for (i = 0; i < aw; i++, ap++)
  232.                 if (isAlphaTransp(*ap)) {
  233.                     hadalpha = YES;
  234.                     break;
  235.                 }
  236.         }
  237.     }else if (op == Negative || op == RandomPttn) {
  238.         sub_negative(op, select, newinf, idx, working);
  239.         if (newinf->alpha) hadalpha = hadAlpha();
  240.     }else /* Rotation | Horizontal | Vertical */ {
  241.         if (sub_rotate(op, angle, cinf, newinf, idx, working))
  242.             goto ErrEXIT;
  243.         if (rotalpha)
  244.             hadalpha = YES;
  245.         else if (newinf->alpha)
  246.             hadalpha = hadAlpha();
  247.     }
  248.  
  249.     if (newinf->alpha && !hadalpha) {
  250.         newinf->alpha = NO;
  251.         working[--pl] = NULL;
  252.     }
  253.     if (newinf->alpha && newinf->palette && newinf->palsteps >= 256) {
  254.         free((void *)newinf->palette);    /* 256 colors are too much */
  255.         newinf->palette = NULL;
  256.         newinf->palsteps = 0;
  257.     }
  258.     [tw makeComment: newinf from: cinf];
  259.     if (newinf->bits < 8) {
  260.         if (allocImage(planes, newinf->width, newinf->height,
  261.             newinf->bits, pl))
  262.             goto ErrEXIT;
  263.         packWorkingImage(newinf, pl, working, planes);
  264.         if ([tw drawView:planes info: newinf] == nil)
  265.             goto ErrEXIT;
  266.         free((void *)working[0]);
  267.     }else {
  268.         if ([tw drawView:working info: newinf] == nil)
  269.             goto ErrEXIT;
  270.     }
  271.     [theController newWindow: tw];
  272.     return self;
  273.  
  274. ErrEXIT:
  275.     if (working[0]) free((void *)working[0]);
  276.     if (planes[0]) free((void *)planes[0]);
  277.     if (newinf) {
  278.         if (newinf->palette) free((void *)newinf->palette);
  279.         free((void *)newinf);
  280.     }
  281.     if (tw) [[tw window] performClose: self];
  282.         /* This call frees tw */
  283.     return nil;
  284. }
  285.  
  286.  
  287. - doRotateFlipClip: (int)op to:(int)angle
  288. {
  289.     ToyWin    *tw;
  290.     ToyView    *tv = NULL;
  291.     NXImageRep    *rep;
  292.     commonInfo    *cinf;
  293.     NXRect        *select = NULL;
  294.     unsigned char    *map[MAXPLANE];
  295.     const char    *ex = NULL, *fnam;
  296.     char    fn[256];
  297.     int    err;
  298.  
  299.     if ((tw = [theController keyWindow]) != nil) {
  300.         tv = [tw toyView];
  301.         if (op == Clip) {
  302.         select = [tv selectedScaledRect];
  303.         if (select->size.width < 1.0 || select->size.height < 1.0)
  304.             tw = nil;
  305.         }else if (op == Negative || op == RandomPttn)
  306.         select = [tv selectedScaledRect];
  307.     }
  308.     if (tw == nil) {
  309.         NXBeep();
  310.         return self;
  311.     }
  312.  
  313.     cinf = [tv commonInfo];
  314.     if (cinf->width >= MAXWidth || cinf->height >= MAXWidth) {
  315.         errAlert([tw filename], Err_MEMORY);
  316.         return self;
  317.     }
  318.     switch (op) {
  319.     case Rotation:    ex = "Rotate"; break;
  320.     case Clip:    ex = "Clip"; break;
  321.     case Negative:    ex = "Negative"; break;
  322.     case RandomPttn: ex = "Random"; break;
  323.     case Horizontal:
  324.     case Vertical:
  325.     default:    ex = "Flip"; break;
  326.     }
  327.     fnam = [tw filename];
  328.     sprintf(fn, "%s(%s)", fnam, ex);
  329.  
  330.     if (cinf->type == Type_eps) {
  331.         NXStream    *stream;
  332.         ToyWinEPS    *newtw;
  333.         commonInfo    info;
  334.  
  335.         if (op == Negative || op == RandomPttn) {
  336.             warnAlert(fnam, Err_EPS_IMPL);
  337.             return self;
  338.         }
  339.         if (op == Clip)
  340.             stream = [(ToyWinEPS *)tw clipEPS:select error:&err];
  341.         else { /* Rotate | Horizontal | Vertical */
  342.             rotate_size(angle, cinf, &info);
  343.             stream = [(ToyWinEPS *)tw rotateEPS:op to:angle
  344.                 width:info.width height:info.height
  345.                 name:fn error:&err];
  346.         }
  347.         if (stream == NULL) {
  348.             errAlert(fnam, err);
  349.             return self;
  350.         }
  351.         newtw = [[ToyWinEPS alloc] init:tw by:op];
  352.         err = [newtw drawFromFile:(const char *)fn or:stream];
  353.         NXCloseMemory(stream, NX_FREEBUFFER);
  354.         if (err) {
  355.             errAlert(fnam, err);
  356.             [newtw free];
  357.         }else
  358.             [theController newWindow: newtw];
  359.         return self;
  360.     }
  361.  
  362.     if (cinf->cspace == NX_CMYKColorSpace) {
  363.         warnAlert(fnam, Err_IMPLEMENT);
  364.         return self;
  365.     }
  366.  
  367.     rep = [[tv image] bestRepresentation];
  368.     [(NXBitmapImageRep *)rep getDataPlanes: map];
  369.     if ((err = initGetPixel(cinf)) != 0) {
  370.         errAlert(fnam, err);
  371.         return self;
  372.     }
  373.     resetPixel(map, 0);
  374.     if ([self doBitmap:op parent:tw
  375.         filename:fn info:cinf to:angle rect:select] == nil)
  376.         errAlert(fn, Err_MEMORY);
  377.     return self;
  378. }
  379.  
  380. @end
  381.