home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Viewers / aa_m68k_Intel_Only / ToyViewer1.2 / Source / TVrotate.m < prev    next >
Encoding:
Text File  |  1995-11-12  |  8.5 KB  |  343 lines

  1. #import "TVController.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 <stdio.h>
  8. #import <stdlib.h>
  9. #import <string.h>
  10. #import <streams/streams.h>
  11. #import "ToyWin.h"
  12. #import "ToyWinEPS.h"
  13. #import "ToyView.h"
  14. #import "save.h"
  15. #import "common.h"
  16.  
  17. #define  Width45(x,y)    ((((x)+1) >> 1) + (((y)+1) >> 1))
  18. #define  NewLoc        13
  19.  
  20. @implementation TVController (Rotate)
  21.  
  22. static void packWorkingImage(const commonInfo *newinf, int pl,
  23.     unsigned char **working, unsigned char **planes)
  24. {
  25.     int    pn, y;
  26.     unsigned char *pp, *ww;
  27.  
  28.     for (pn = 0; pn < pl; pn++) {
  29.         for (y = 0; y < newinf->height; y++) {
  30.         ww = working[pn] + y * newinf->width;
  31.         pp = planes[pn] + y * newinf->xbytes;
  32.         packImage(pp, ww, newinf->width, newinf->bits);
  33.         }
  34.     }
  35. }
  36.  
  37. /* Local Method */
  38. - doBitmap: (const char *)fn info:(commonInfo *)cinf
  39.         to:(int)angle rect:(NXRect *)select
  40. {
  41.     ToyWin    *tw;
  42.     commonInfo *newinf = NULL;
  43.     unsigned char *working[5], *planes[5];
  44.     int    i, pidx, ptr, x, y, w, pl;
  45.     int    pix[5], idx[5];
  46.  
  47.     working[0] = planes[0] = NULL;
  48.     tw = NULL;
  49.     if ((newinf = (commonInfo *)malloc(sizeof(commonInfo))) == NULL)
  50.         goto ErrEXIT;
  51.     *newinf = *cinf;
  52.     if (cinf->cspace == NX_OneIsBlackColorSpace)
  53.         newinf->cspace = NX_OneIsWhiteColorSpace;
  54.         /* getPixel() fixes 0 as Black */
  55.     newinf->isplanar = YES;
  56.     if (angle == 90 || angle == 270) {
  57.         newinf->width = cinf->height;
  58.         newinf->height = cinf->width;
  59.     }else if (angle == 45) {
  60.         newinf->width = newinf->height
  61.             = Width45(cinf->width, cinf->height);
  62.     }else if (angle == Clip) {
  63.         newinf->width = select->size.width;
  64.         newinf->height = select->size.height;
  65.     }
  66.     newinf->xbytes = byte_length(newinf->bits, newinf->width);
  67.     newinf->palette = NULL;
  68.     if (cinf->palette) {
  69.         w = sizeof(paltype) * newinf->palsteps;
  70.         if ((newinf->palette = (paltype *)malloc(w)) == NULL)
  71.             goto ErrEXIT;
  72.         memcpy((void *)newinf->palette, (void *)cinf->palette, w);
  73.     }
  74.  
  75.     pl = newinf->numcolors;
  76.     for (i = 0; i < pl; i++) idx[i] = i;
  77.     for (i = pl; i < 5; i++) idx[i] = -1;
  78.     if (newinf->alpha) idx[ALPHA] = pl++;
  79.     w = newinf->width * newinf->height;
  80.     if ((working[0] = (unsigned char *)calloc(w * pl, 1)) == NULL)
  81.         goto ErrEXIT;
  82.     for (i = 1; i < pl; i++)
  83.         working[i] = working[i - 1] + w;
  84.     if (newinf->bits < 8) {
  85.         w = newinf->xbytes * newinf->height;
  86.         if ((planes[0] = (unsigned char *)malloc(w * pl)) == NULL)
  87.             goto ErrEXIT;
  88.         for (i = 1; i < pl; i++)
  89.             planes[i] = planes[i - 1] + w;
  90.     }
  91.  
  92.     tw = [[ToyWin alloc] init: self];
  93.     [tw initLocateWindow:fn
  94.         Width:newinf->width Height:newinf->height Num:NewLoc];
  95.  
  96.     if (angle == 45) {
  97.         int yorg = (cinf->width + 1) >> 1;
  98.         int xt, yt;
  99.         for (y = 0; y < cinf->height; y++) {
  100.             for (x = 0; x < cinf->width; x++) {
  101.             getPixelA(pix);
  102.             if (((xt = x + y) & 1) == 0) {
  103.                 xt >>= 1;
  104.                 yt = yorg + ((y - x) >> 1);
  105.                 ptr = yt * newinf->width;
  106.                 for (i = 0; i <= ALPHA; i++) {
  107.                     if ((pidx = idx[i]) < 0) continue;
  108.                     working[pidx][ptr + xt] = pix[i];
  109.                 }
  110.             }
  111.             }
  112.         }
  113.     }else if (angle == 90) {
  114.         for (x = 0; x < newinf->width; x++) {
  115.             for (y = newinf->height - 1; y >= 0; y--) {
  116.                 ptr = y * newinf->width;
  117.                 getPixelA(pix);
  118.                 for (i = 0; i <= ALPHA; i++) {
  119.                     if ((pidx = idx[i]) < 0) continue;
  120.                     working[pidx][ptr + x] = pix[i];
  121.                 }
  122.             }
  123.         }
  124.     }else if (angle == 270) {
  125.         for (x = newinf->width - 1; x >= 0; x--) {
  126.             for (y = 0; y < newinf->height; y++) {
  127.                 ptr = y * newinf->width;
  128.                 getPixelA(pix);
  129.                 for (i = 0; i <= ALPHA; i++) {
  130.                     if ((pidx = idx[i]) < 0) continue;
  131.                     working[pidx][ptr + x] = pix[i];
  132.                 }
  133.             }
  134.         }
  135.     }else if (angle == 180) {
  136.         for (y = newinf->height - 1; y >= 0; y--) {
  137.             ptr = y * newinf->width;
  138.             for (x = newinf->width - 1; x >= 0; x--) {
  139.                 getPixelA(pix);
  140.                 for (i = 0; i <= ALPHA; i++) {
  141.                     if ((pidx = idx[i]) < 0) continue;
  142.                     working[pidx][ptr + x] = pix[i];
  143.                 }
  144.             }
  145.         }
  146.     }else if (angle == Horizontal) {
  147.         for (y = 0; y < newinf->height; y++) {
  148.             ptr = y * newinf->width;
  149.             for (x = newinf->width - 1; x >= 0; x--) {
  150.                 getPixelA(pix);
  151.                 for (i = 0; i <= ALPHA; i++) {
  152.                     if ((pidx = idx[i]) < 0) continue;
  153.                     working[pidx][ptr + x] = pix[i];
  154.                 }
  155.             }
  156.         }
  157.     }else if (angle == Vertical) {
  158.         for (y = newinf->height - 1; y >= 0; y--) {
  159.             ptr = y * newinf->width;
  160.             for (x = 0; x < newinf->width; x++) {
  161.                 getPixelA(pix);
  162.                 for (i = 0; i <= ALPHA; i++) {
  163.                     if ((pidx = idx[i]) < 0) continue;
  164.                     working[pidx][ptr + x] = pix[i];
  165.                 }
  166.             }
  167.         }
  168.     }else if (angle == Clip) {
  169.         int skipx = select->origin.x;
  170.         int skipt = cinf->width - (skipx + select->size.width);
  171.         int skipy = cinf->height
  172.             - (select->origin.y + select->size.height);
  173.         for (y = 0; y < skipy; y++) {
  174.             for (x = 0; x < cinf->width; x++)
  175.                 getPixelA(pix);
  176.         }
  177.         for (y = 0; y < newinf->height; y++) {
  178.             ptr = y * newinf->width;
  179.             for (x = 0; x < skipx; x++)
  180.                 getPixelA(pix);
  181.             for (x = 0; x < newinf->width; x++) {
  182.                 getPixelA(pix);
  183.                 for (i = 0; i <= ALPHA; i++) {
  184.                     if ((pidx = idx[i]) < 0) continue;
  185.                     working[pidx][ptr + x] = pix[i];
  186.                 }
  187.             }
  188.             for (x = 0; x < skipt; x++)
  189.                 getPixelA(pix);
  190.         }
  191.     }else /* Negative */ {
  192.         for (y = 0; y < newinf->height; y++) {
  193.             ptr = y * newinf->width;
  194.             for (x = 0; x < newinf->width; x++) {
  195.                 getPixelA(pix);
  196.                 for (i = 0; i <= ALPHA; i++) {
  197.                     if ((pidx = idx[i]) < 0) continue;
  198.                     working[pidx][ptr + x] = 0xff - pix[i];
  199.                 }
  200.             }
  201.         }
  202.         if (newinf->palette) {
  203.             unsigned char *p;
  204.             paltype *pal = newinf->palette;
  205.             for (x = 0; x < newinf->palsteps; x++) {
  206.                 p = pal[x];
  207.                 for (i = 0; i < 3; i++)
  208.                     p[i] = 0xff - p[i];
  209.             }
  210.         }
  211.     }
  212.  
  213.     sprintf(newinf->memo, "%d x %d  %dbit%s",
  214.         newinf->width, newinf->height, newinf->bits,
  215.         ((newinf->bits > 1) ? "s" : ""));
  216.     if (newinf->bits < 8) {
  217.         packWorkingImage(newinf, pl, working, planes);
  218.         if ([tw drawView:planes info: newinf] == nil)
  219.             goto ErrEXIT;
  220.         free((void *)working[0]);
  221.     }else {
  222.         if ([tw drawView:working info: newinf] == nil)
  223.             goto ErrEXIT;
  224.     }
  225.     [self newWindow: tw];
  226.     return self;
  227.  
  228. ErrEXIT:
  229.     if (working[0]) free((void *)working[0]);
  230.     if (planes[0]) free((void *)planes[0]);
  231.     if (newinf) {
  232.         if (newinf->palette) free((void *)newinf->palette);
  233.         free((void *)newinf);
  234.     }
  235.     if (tw) [tw free];
  236.     return nil;
  237. }
  238.  
  239.  
  240. - doRotateFlipClip: (int)angle
  241. {
  242.     ToyWin    *tw;
  243.     ToyView    *tv = NULL;
  244.     NXImageRep    *rep;
  245.     commonInfo    *cinf;
  246.     NXRect        *select = NULL, rct;
  247.     unsigned char    *map[5];
  248.     char    *ex = NULL, fn[256];
  249.     float    sf;
  250.     int    err;
  251.  
  252.     if ((tw = [self keyWindow]) != nil) {
  253.         tv = [tw toyView];
  254.         if (angle == Clip) {
  255.         select = [tv selectedRect];
  256.         sf = [tv scaleFactor];
  257.         if (sf != 1.0) {
  258.             rct.size.width = (int)(select->size.width / sf + 0.5);
  259.             rct.size.height = (int)(select->size.height / sf + 0.5);
  260.             rct.origin.x = (int)(select->origin.x / sf + 0.5);
  261.             rct.origin.y = (int)(select->origin.y / sf + 0.5);
  262.             select = &rct;
  263.         }
  264.         if (select->size.width < 1.0 || select->size.height < 1.0)
  265.             tw = nil;
  266.         }
  267.     }
  268.     if (tw == nil) {
  269.         NXBeep();
  270.         return self;
  271.     }
  272.  
  273.     cinf = [tv commonInfo];
  274.     if (cinf->width >= MAXWidth || cinf->height >= MAXWidth
  275.     || (angle == 45 && Width45(cinf->width, cinf->height) >= MAXWidth)) {
  276.         errAlert([tw filename], Err_MEMORY);
  277.         return self;
  278.     }
  279.     if (angle > 0) ex = "Rotate";
  280.     else if (angle == Clip) ex = "Clip";
  281.     else if (angle == Negative) ex = "Negative";
  282.     else ex = "Flip";
  283.     sprintf(fn, "%s(%s)", [tw filename], ex);
  284.  
  285.     if (cinf->type == Type_eps) {
  286.         NXStream    *stream;
  287.         ToyWinEPS    *newtw;
  288.  
  289.         if (angle == Negative) {
  290.             errAlert([tw filename], Err_EPS_IMPL);
  291.             return self;
  292.         }
  293.         stream = (angle == Clip)
  294.             ? [(ToyWinEPS *)tw clipEPS:select error:&err]
  295.             : [(ToyWinEPS *)tw rotateEPS:angle name:fn error:&err];
  296.         if (stream == NULL) {
  297.             errAlert(fn, err);
  298.             return self;
  299.         }
  300.         newtw = [[ToyWinEPS alloc] init: self];
  301.         err = [newtw drawFromFile:(const char *)fn or:stream Num:NewLoc];
  302.         NXCloseMemory(stream, NX_FREEBUFFER);
  303.         if (err) {
  304.             errAlert(fn, err);
  305.             [newtw free];
  306.         }else
  307.             [self newWindow: newtw];
  308.         return self;
  309.     }
  310.  
  311.     if (cinf->cspace == NX_CMYKColorSpace) {
  312.         errAlert(fn, Err_IMPLEMENT);
  313.         return self;
  314.     }
  315.  
  316.     rep = [[tv image] bestRepresentation];
  317.     [(NXBitmapImageRep *)rep getDataPlanes: map];
  318.     if ((err = initGetPixel(cinf)) != 0) {
  319.         errAlert(fn, err);
  320.         return self;
  321.     }
  322.     resetPixel(map, 0);
  323.     if ([self doBitmap:fn info:cinf to:angle rect:select] == nil)
  324.         errAlert(fn, Err_MEMORY);
  325.  
  326.     return self;
  327. }
  328.  
  329. - rotate: sender
  330. {
  331.     static int tagAngles[] = { 45, 90, 270, 180 };
  332.     return [self doRotateFlipClip: tagAngles[[sender selectedTag]]];
  333. }
  334.  
  335. - flip: sender
  336. {
  337.     static int flipkind[]
  338.         = { Horizontal, Vertical, Negative, Clip };
  339.     return [self doRotateFlipClip: flipkind[[sender selectedTag]]];
  340. }
  341.  
  342. @end
  343.