home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Libraries / PixMaps 1.1 / PixMap.c next >
Encoding:
C/C++ Source or Header  |  1997-07-12  |  31.1 KB  |  1,120 lines  |  [TEXT/MPS ]

  1. /* File PixMap.c
  2.     PixMap manipulation routines, implementation.
  3.     Copyright (c) 1996, 1997 by John Montbriand.  All Rights Reserved.
  4.     Permission hereby granted for public use.
  5.         Distribute freely in areas where the laws of copyright apply.
  6.     USE AT YOUR OWN RISK.
  7.     DO NOT DISTRIBUTE MODIFIED COPIES.
  8.     Comments/questions/postcards* to the author at the address:
  9.       John Montbriand
  10.       P.O. Box. 1133
  11.       Saskatoon Saskatchewan Canada
  12.       S7K 3N2
  13.     or by email at:
  14.       tinyjohn@sk.sympatico.ca
  15.     *if you mail a postcard, then I will provide you with technical support
  16.     regarding questions you may have about this file.
  17.  
  18. */
  19.  
  20.  
  21. #include "PixMap.h"
  22. #include <Memory.h>
  23. #include <OSUtils.h>
  24. #include <ToolUtils.h>
  25. #include <FixMath.h>
  26. #include <Math.h>
  27. #include <Gestalt.h>
  28. #include <ImageCompression.h>
  29. #include <PictUtils.h>
  30. #include <String.h>
  31.  
  32.  
  33. PixMapHandle MakePixMap(short width, short height, CTabHandle clut) {
  34.     long row_bytes, depth;
  35.     Ptr raster_data;
  36.     long bytecount;
  37.     CTabHandle colours;
  38.     PixMapHandle newpix;
  39.     PixMapPtr pixptr;
  40.     
  41.         /* calculate required depth */
  42.     if (clut == NULL)
  43.         depth = 8;
  44.     else if ((*clut)->ctSize < 2)
  45.         depth = 1;
  46.     else if ((*clut)->ctSize < 4)
  47.         depth = 2;
  48.     else if ((*clut)->ctSize < 16)
  49.         depth = 4;
  50.     else depth = 8;
  51.     
  52.         /* set up initial values for locals */
  53.     row_bytes = ((depth * ((long) width) + 31) >> 5) << 2;
  54.     bytecount = row_bytes * ((long) height);
  55.     colours = NULL;
  56.     raster_data = NULL;
  57.     newpix = NULL;
  58.     
  59.         /* check for valid rowbytes */
  60.     if (row_bytes > 0x00003FFF) goto bail;
  61.  
  62.         /* allocate the raster data */
  63.     raster_data = NewPtrClear(bytecount);
  64.     if (raster_data == NULL) goto bail;
  65.  
  66.         /* copy the colour table */
  67.     if (clut == NULL) {
  68.         colours = GetCTable(8);
  69.         if (colours == NULL) goto bail;
  70.     } else {
  71.         colours = clut;
  72.         if (HandToHand((Handle*) &colours) != noErr) {
  73.             colours = NULL;
  74.             goto bail;
  75.         }
  76.     }
  77.         /* create the pixmap handle */
  78.     newpix = (PixMapHandle) NewHandleClear(sizeof(PixMap));
  79.     if (newpix == NULL) goto bail;
  80.     
  81.         /* set up the pixmap fields */
  82.     pixptr = *newpix;
  83.     pixptr->baseAddr = raster_data;
  84.     pixptr->rowBytes = (row_bytes | 0x8000);
  85.     pixptr->bounds.right = width;
  86.     pixptr->bounds.bottom = height;
  87.     pixptr->hRes = 0x00480000; /* resolution = 72 dots per inch */
  88.     pixptr->vRes = 0x00480000;
  89.     pixptr->pixelSize = depth;
  90.     pixptr->cmpCount = 1;
  91.     pixptr->cmpSize = depth;
  92.     pixptr->pmTable = colours;
  93.  
  94.         /* done */
  95.     return newpix;
  96.  
  97. bail:
  98.     if (raster_data != NULL) DisposePtr(raster_data);
  99.     if (newpix != NULL) DisposeHandle((Handle) newpix);
  100.     if (colours != NULL) DisposeHandle((Handle) colours);
  101.     return NULL;
  102. }
  103.  
  104. PixMapHandle Make16BitPixMap(short width, short height) {
  105.     long row_bytes;
  106.     Ptr raster_data;
  107.     long bytecount, response;
  108.     CTabHandle colours;
  109.     PixMapHandle newpix;
  110.     PixMapPtr pixptr;
  111.     unsigned char *rowptr;
  112.     unsigned short *pixelptr;
  113.     short y, x;
  114.  
  115.         /* is it possible? */
  116.     if (Gestalt(gestaltQuickdrawVersion, &response) != noErr) response = 0;
  117.     if (response < gestalt32BitQD) return NULL;
  118.  
  119.         /* set up initial values for locals */
  120.     row_bytes = ((16 * ((long) width) + 31) >> 5) << 2;
  121.     bytecount = row_bytes * ((long) height);
  122.     colours = NULL;
  123.     raster_data = NULL;
  124.     newpix = NULL;
  125.     
  126.         /* check for valid rowbytes */
  127.     if (row_bytes > 0x00003FFF) goto bail;
  128.     
  129.         /* allocate the raster data */
  130.     raster_data = NewPtr(bytecount);
  131.     if (raster_data == NULL) goto bail;
  132.     rowptr = (unsigned char *) raster_data;
  133.     for (y=0; y< height; y++, rowptr += row_bytes)
  134.         for (pixelptr = (unsigned short *) rowptr, x=0; x<width; x++)
  135.             *pixelptr++ = 0x7FFF;
  136.  
  137.         /* dummy colour table */
  138.     colours = (CTabHandle) NewHandleClear(8);
  139.     if (colours == NULL) goto bail;
  140.     (*colours)->ctSeed = 15;
  141.     (*colours)->ctSize = -1;
  142.  
  143.         /* create the pixmap handle */
  144.     newpix = (PixMapHandle) NewHandleClear(sizeof(PixMap));
  145.     if (newpix == NULL) goto bail;
  146.     
  147.         /* set up the pixmap fields */
  148.     pixptr = *newpix;
  149.     pixptr->baseAddr = raster_data;
  150.     pixptr->rowBytes = (row_bytes | 0x8000);
  151.     pixptr->bounds.right = width;
  152.     pixptr->bounds.bottom = height;
  153.     pixptr->hRes = 0x00480000; /* resolution = 72 dots per inch */
  154.     pixptr->vRes = 0x00480000;
  155.     pixptr->pixelSize = 16;
  156.     pixptr->pixelType = RGBDirect;
  157.     pixptr->cmpCount = 3;
  158.     pixptr->cmpSize = 5;
  159.     pixptr->pmTable = colours;
  160.  
  161.         /* done */
  162.     return newpix;
  163.  
  164. bail:
  165.     if (raster_data != NULL) DisposePtr(raster_data);
  166.     if (newpix != NULL) DisposeHandle((Handle) newpix);
  167.     if (colours != NULL) DisposeHandle((Handle) colours);
  168.     return NULL;
  169. }
  170.  
  171.  
  172. PixMapHandle Make32BitPixMap(short width, short height) {
  173.     long row_bytes;
  174.     Ptr raster_data;
  175.     long bytecount, response;
  176.     CTabHandle colours;
  177.     PixMapHandle newpix;
  178.     PixMapPtr pixptr;
  179.     unsigned char *rowptr;
  180.     unsigned long *pixelptr;
  181.     short y, x;
  182.  
  183.         /* is it possible? */
  184.     if (Gestalt(gestaltQuickdrawVersion, &response) != noErr) response = 0;
  185.     if (response < gestalt32BitQD) return NULL;
  186.  
  187.         /* set up initial values for locals */
  188.     row_bytes = ((32 * ((long) width) + 31) >> 5) << 2;
  189.     bytecount = row_bytes * ((long) height);
  190.     colours = NULL;
  191.     raster_data = NULL;
  192.     newpix = NULL;
  193.     
  194.         /* check for valid rowbytes */
  195.     if (row_bytes > 0x00003FFF) goto bail;
  196.  
  197.         /* allocate the raster data */
  198.     raster_data = NewPtr(bytecount);
  199.     if (raster_data == NULL) goto bail;
  200.     rowptr = (unsigned char *) raster_data;
  201.     for (y=0; y< height; y++, rowptr += row_bytes)
  202.         for (pixelptr = (unsigned long *) rowptr, x=0; x<width; x++)
  203.             *pixelptr++ = 0x00FFFFFF;
  204.  
  205.         /* dummy colour table */
  206.     colours = (CTabHandle) NewHandleClear(8);
  207.     if (colours == NULL) goto bail;
  208.     (*colours)->ctSeed = 24;
  209.     (*colours)->ctSize = -1;
  210.  
  211.         /* create the pixmap handle */
  212.     newpix = (PixMapHandle) NewHandleClear(sizeof(PixMap));
  213.     if (newpix == NULL) goto bail;
  214.     
  215.         /* set up the pixmap fields */
  216.     pixptr = *newpix;
  217.     pixptr->baseAddr = raster_data;
  218.     pixptr->rowBytes = (row_bytes | 0x8000);
  219.     pixptr->bounds.right = width;
  220.     pixptr->bounds.bottom = height;
  221.     pixptr->hRes = 0x00480000; /* resolution = 72 dots per inch */
  222.     pixptr->vRes = 0x00480000;
  223.     pixptr->pixelSize = 32;
  224.     pixptr->pixelType = RGBDirect;
  225.     pixptr->cmpCount = 3;
  226.     pixptr->cmpSize = 8;
  227.     pixptr->pmTable = colours;
  228.  
  229.         /* done */
  230.     return newpix;
  231.  
  232. bail:
  233.     if (raster_data != NULL) DisposePtr(raster_data);
  234.     if (newpix != NULL) DisposeHandle((Handle) newpix);
  235.     if (colours != NULL) DisposeHandle((Handle) colours);
  236.     return NULL;
  237. }
  238.  
  239.  
  240. PixMapHandle MakeScreenLikePixMap(Rect *globalRect) {
  241.     long maxArea, area;
  242.     PixMapHandle device_pix;
  243.     GDHandle device;
  244.     short width, height;
  245.     Rect sect, device_box;
  246.         /* search for maximum intersecting device */
  247.     device_pix = NULL;
  248.     maxArea = 0;
  249.     for (device = GetDeviceList(); device; device = GetNextDevice(device)) {
  250.         device_box = (*device)->gdRect;
  251.         if (TestDeviceAttribute(device, screenDevice)
  252.           && TestDeviceAttribute(device, screenActive)
  253.           && SectRect(globalRect, &device_box, §)) {
  254.             area = (sect.right - sect.left) * (sect.bottom - sect.top);
  255.             if (area > maxArea) {
  256.                 device_pix = (*device)->gdPMap;
  257.                 maxArea = area;
  258.             }
  259.         }
  260.     }
  261.         /* create a pixmap */
  262.     if (device_pix != NULL) {
  263.         width = globalRect->right - globalRect->left;
  264.         height = globalRect->bottom - globalRect->top;
  265.         if ((*device_pix)->pixelSize <= 8)
  266.             return MakePixMap(width, height, (*device_pix)->pmTable);
  267.         else if ((*device_pix)->pixelSize == 16)
  268.             return Make16BitPixMap(width, height);
  269.         else if ((*device_pix)->pixelSize == 32)
  270.             return Make32BitPixMap(width, height);
  271.     }
  272.     return NULL;
  273. }
  274.  
  275.  
  276. void KillPixMap(PixMapHandle pix) {
  277.     DisposePtr((*pix)->baseAddr);
  278.     DisposeHandle((Handle) (*pix)->pmTable);
  279.     DisposeHandle((Handle) pix);
  280. }
  281.  
  282. long PixMapSize(PixMapHandle pix) {
  283.     if (pix == NULL) return 0;
  284.     return GetPtrSize((*pix)->baseAddr)
  285.         + GetHandleSize((Handle) (*pix)->pmTable)
  286.         + GetHandleSize((Handle) pix);
  287. }
  288.  
  289. void SetPixMapPixel(PixMapHandle pix, short h, short v, long value) {
  290.     long row_bytes;
  291.     unsigned char *dst;
  292.     row_bytes = (*pix)->rowBytes & 0x00003FFF;
  293.     dst = (unsigned char *) (*pix)->baseAddr;
  294.     switch ((*pix)->pixelSize) {
  295.         case 1:
  296.             dst += ((long) v) * row_bytes;
  297.             if (value != 0) BitSet(dst, h); else BitClr(dst, h);
  298.             break;
  299.         case 2:
  300.             dst += ((long) v) * row_bytes + ((long) (h>>2));
  301.             switch (h&3) {
  302.                 case 0:
  303.                     *dst = ((*dst) & 0x3F) | (value<<6);
  304.                     break;
  305.                 case 1:
  306.                     *dst = ((*dst) & 0xCF) | ((value&0x03)<<4);
  307.                     break;
  308.                 case 2:
  309.                     *dst = ((*dst) & 0xF3) | ((value&0x03)<<2);
  310.                     break;
  311.                 case 3:
  312.                     *dst = ((*dst) & 0xFC) | (value&0x03);
  313.                     break;
  314.             }
  315.             break;
  316.         case 4:
  317.             dst += ((long) v) * row_bytes + ((long) (h>>1));
  318.             if ((h&1) == 0) {
  319.                 *dst = ((*dst) & 0x0F) | (value<<4);
  320.             } else {
  321.                 *dst = ((*dst) & 0xF0) | (value & 0x0F);
  322.             }
  323.             break;
  324.         case 8:
  325.             dst += ((long) v) * row_bytes + ((long) h);
  326.             *dst = (unsigned char) value;
  327.             break;
  328.         case 16:
  329.             dst += ((long) v) * row_bytes + (((long) h) * 2);
  330.             * ((short*) dst) = (short) value;
  331.             break;
  332.         case 32:
  333.             dst += ((long) v) * row_bytes + (((long) h) * 4);
  334.             * ((long*) dst) = value;
  335.             break;
  336.     }
  337. }
  338.  
  339.  
  340. long GetPixMapPixel(PixMapHandle pix, short h, short v) {
  341.     long row_bytes, the_value;
  342.     unsigned char *src;
  343.     row_bytes = ((*pix)->rowBytes & 0x00003FFF);
  344.     src = (unsigned char *) (*pix)->baseAddr;
  345.     switch ((*pix)->pixelSize) {
  346.         case 1:
  347.             src += ((long) v) * row_bytes;
  348.             if (BitTst(src, h)) the_value = 1; else the_value = 0;
  349.             break;
  350.         case 2:
  351.             src += ((long) v) * row_bytes + (((long) h) >> 2);
  352.             switch (h&3) {
  353.                 case 0:
  354.                     the_value = (long) (((*src) >> 6) & 0x03);
  355.                     break;
  356.                 case 1:
  357.                     the_value = (long) (((*src) >> 4) & 0x03);
  358.                     break;
  359.                 case 2:
  360.                     the_value = (long) (((*src) >> 2) & 0x03);
  361.                     break;
  362.                 case 3:
  363.                     the_value = (long) ((*src) & 0x03);
  364.                     break;
  365.             }
  366.             break;
  367.         case 4:
  368.             src += ((long) v) * row_bytes + (((long) h) >> 1);
  369.             if ((h&1) == 0) {
  370.                 the_value = (long) (((*src) >> 4) & 0x0F);
  371.             } else {
  372.                 the_value = (long) ((*src) & 0x0F);
  373.             }
  374.             break;
  375.         case 8:
  376.             src += ((long) v) * row_bytes + ((long) h);
  377.             the_value = (long) ((*src) & 0x000000FF);
  378.             break;
  379.         case 16:
  380.             src += ((long) v) * row_bytes + (((long) h) << 1);
  381.             the_value = (long) ((* ((short*) src)) & 0x0000FFFF);
  382.             break;
  383.         case 32:
  384.             src += ((long) v) * row_bytes + (((long) h) << 2);
  385.             the_value = * ((long*) src);
  386.             break;
  387.     }
  388.     return the_value;
  389. }
  390.  
  391.  
  392. #if defined(powerc) || defined(__powerc)
  393.  
  394. static short pixround(float x) {
  395.     float low, high;
  396.     low = floor(x);
  397.     high = ceil(x);
  398.     if (fabs(low - x) < fabs(high - x))
  399.         return (short) low;
  400.     else return (short) high;
  401. }
  402.  
  403. PixMapHandle RotatePixMap(PixMapHandle pix, short cx, short cy, float angle) {
  404.     unsigned long srcrow, dstrow;
  405.     long x, y, width, height;
  406.     unsigned char *srcbase, *dstbase, *d;
  407.     float rad, crad, srad, zx, zy;
  408.     short hpos, vpos;
  409.     PixMapHandle new_pix;
  410.     if ((*pix)->pixelSize <= 8)
  411.         new_pix = MakePixMap((*pix)->bounds.right, (*pix)->bounds.bottom, (*pix)->pmTable);
  412.     else if ((*pix)->pixelSize == 16)
  413.         new_pix = Make16BitPixMap((*pix)->bounds.right, (*pix)->bounds.bottom);
  414.     else if ((*pix)->pixelSize == 32)
  415.         new_pix = Make32BitPixMap((*pix)->bounds.right, (*pix)->bounds.bottom);
  416.     else return NULL;
  417.     if (new_pix != NULL) {
  418.         rad = 0.017453 * angle;
  419.         crad = cos(rad);
  420.         srad = sin(rad);
  421.         srcrow = ((*pix)->rowBytes & 0x3FFF);
  422.         dstrow = ((*new_pix)->rowBytes & 0x3FFF);
  423.         srcbase = (unsigned char*) (*pix)->baseAddr;
  424.         dstbase = (unsigned char*) (*new_pix)->baseAddr;
  425.         height = (*pix)->bounds.bottom;
  426.         width = (*pix)->bounds.right;
  427.         switch ((*pix)->pixelSize) {
  428.             case 1:
  429.             case 2:
  430.             case 4:
  431.                 for (y = 0; y < height; y++)
  432.                     for (x = 0; x < width; x++) {
  433.                         zx = (float) (x - cx);
  434.                         zy = (float) (y - cy);
  435.                         vpos = pixround((zy*crad) - (zx*srad) + ((float) cy));
  436.                         if (vpos >= 0 && vpos < height) {
  437.                             hpos = pixround((zx*crad) + (zy*srad) + ((float) cx));
  438.                             if (hpos >= 0 && hpos < width)
  439.                                 SetPixMapPixel(new_pix, x, y, GetPixMapPixel(pix, hpos, vpos));
  440.                         }
  441.                     }
  442.                 break;
  443.             case 8:
  444.                 for (y = 0; y < height; y++, dstbase += dstrow)
  445.                     for (d = dstbase, x = 0; x < width; x++, d++) {
  446.                         zx = (float) (x - cx);
  447.                         zy = (float) (y - cy);
  448.                         vpos = pixround((zy*crad) - (zx*srad) + ((float) cy));
  449.                         if (vpos >= 0 && vpos < height) {
  450.                             hpos = pixround((zx*crad) + (zy*srad) + ((float) cx));
  451.                             if (hpos >= 0 && hpos < width)
  452.                                 *d = *(srcbase + vpos * srcrow + hpos);
  453.                         }
  454.                     }
  455.                 break;
  456.             case 16:
  457.                 for (y = 0; y < height; y++, dstbase += dstrow)
  458.                     for (d = dstbase, x = 0; x < width; x++, d += 2) {
  459.                         zx = (float) (x - cx);
  460.                         zy = (float) (y - cy);
  461.                         vpos = pixround((zy * crad) - (zx * srad) + ((float) cy));
  462.                         if (vpos >= 0 && vpos < height) {
  463.                             hpos = pixround((zx * crad) + (zy * srad) + ((float) cx));
  464.                             if (hpos >= 0 && hpos < width)
  465.                                 * ((short*) d) = * ((short*) (srcbase + vpos * srcrow + (hpos<<1)));
  466.                         }
  467.                     }
  468.                 break;
  469.             case 32:
  470.                 for (y = 0; y < height; y++, dstbase += dstrow)
  471.                     for (d = dstbase, x = 0; x < width; x++, d += 4) {
  472.                         zx = (float) (x - cx);
  473.                         zy = (float) (y - cy);
  474.                         vpos = pixround((zy * crad) - (zx * srad) + ((float) cy));
  475.                         if (vpos >= 0 && vpos < height) {
  476.                             hpos = pixround((zx * crad) + (zy * srad) + ((float) cx));
  477.                             if (hpos >= 0 && hpos < width)
  478.                                 * ((long*) d) = * ((long*) (srcbase + vpos * srcrow + (hpos<<2)));
  479.                         }
  480.                     }
  481.                 break;
  482.         }
  483.     }
  484.     return new_pix;
  485. }
  486.  
  487. #else
  488.  
  489. PixMapHandle RotatePixMap(PixMapHandle pix, short cx, short cy, float angle) {
  490.     unsigned long srcrow, dstrow;
  491.     long x, y, i, width, height;
  492.     unsigned char *srcbase, *dstbase, *d, *s;
  493.     Fixed rad, crad, srad, zx, zy, cxx, cyy;
  494.     short hpos, vpos;
  495.     PixMapHandle new_pix;
  496.     if ((*pix)->pixelSize <= 8)
  497.         new_pix = MakePixMap((*pix)->bounds.right, (*pix)->bounds.bottom, (*pix)->pmTable);
  498.     else if ((*pix)->pixelSize == 16)
  499.         new_pix = Make16BitPixMap((*pix)->bounds.right, (*pix)->bounds.bottom);
  500.     else if ((*pix)->pixelSize == 32)
  501.         new_pix = Make32BitPixMap((*pix)->bounds.right, (*pix)->bounds.bottom);
  502.     else return NULL;
  503.     if (new_pix != NULL) {
  504.         rad = FixMul(0x00000478, X2Fix(angle));
  505.         crad = FracCos(rad);
  506.         srad = FracSin(rad);
  507.         srcrow = ((*pix)->rowBytes & 0x3FFF);
  508.         dstrow = ((*new_pix)->rowBytes & 0x3FFF);
  509.         srcbase = (unsigned char*) (*pix)->baseAddr;
  510.         dstbase = (unsigned char*) (*new_pix)->baseAddr;
  511.         height = (*pix)->bounds.bottom;
  512.         width = (*pix)->bounds.right;
  513.         cxx = FixRatio(cx, 1);
  514.         cyy = FixRatio(cy, 1);
  515.         switch ((*pix)->pixelSize) {
  516.             case 1:
  517.             case 2:
  518.             case 4:
  519.                 for (y = 0; y < height; y++)
  520.                     for (x = 0; x < width; x++) {
  521.                         zx = FixRatio(x, 1) - cxx;
  522.                         zy = FixRatio(y, 1) - cyy;
  523.                         vpos = FixRound(FracMul(zy, crad) - FracMul(zx, srad) + cyy);
  524.                         if (vpos >= 0 && vpos < height) {
  525.                             hpos = FixRound(FracMul(zx, crad) + FracMul(zy, srad) + cxx);
  526.                             if (hpos >= 0 && hpos < width)
  527.                                 SetPixMapPixel(new_pix, x, y, GetPixMapPixel(pix, hpos, vpos));
  528.                         }
  529.                     }
  530.                 break;
  531.             case 8:
  532.                 for (y = 0; y < height; y++, dstbase += dstrow)
  533.                     for (d = dstbase, x = 0; x < width; x++, d++) {
  534.                         zx = FixRatio(x, 1) - cxx;
  535.                         zy = FixRatio(y, 1) - cyy;
  536.                         vpos = FixRound(FracMul(zy, crad) - FracMul(zx, srad) + cyy);
  537.                         if (vpos >= 0 && vpos < height) {
  538.                             hpos = FixRound(FracMul(zx, crad) + FracMul(zy, srad) + cxx);
  539.                             if (hpos >= 0 && hpos < width)
  540.                                 *d = *(srcbase + vpos * srcrow + hpos);
  541.                         }
  542.                     }
  543.                 break;
  544.             case 16:
  545.                 for (y = 0; y < height; y++, dstbase += dstrow)
  546.                     for (d = dstbase, x = 0; x < width; x++, d += 2) {
  547.                         zx = FixRatio(x, 1) - cxx;
  548.                         zy = FixRatio(y, 1) - cyy;
  549.                         vpos = FixRound(FracMul(zy, crad) - FracMul(zx, srad) + cyy);
  550.                         if (vpos >= 0 && vpos < height) {
  551.                             hpos = FixRound(FracMul(zx, crad) + FracMul(zy, srad) + cxx);
  552.                             if (hpos >= 0 && hpos < width)
  553.                                 * ((short*) d) = * ((short*) (srcbase + vpos * srcrow + (hpos<<1)));
  554.                         }
  555.                     }
  556.                 break;
  557.             case 32:
  558.                 for (y = 0; y < height; y++, dstbase += dstrow)
  559.                     for (d = dstbase, x = 0; x < width; x++, d += 4) {
  560.                         zx = FixRatio(x, 1) - cxx;
  561.                         zy = FixRatio(y, 1) - cyy;
  562.                         vpos = FixRound(FracMul(zy, crad) - FracMul(zx, srad) + cyy);
  563.                         if (vpos >= 0 && vpos < height) {
  564.                             hpos = FixRound(FracMul(zx, crad) + FracMul(zy, srad) + cxx);
  565.                             if (hpos >= 0 && hpos < width)
  566.                                 * ((long*) d) = * ((long*) (srcbase + vpos * srcrow + (hpos<<2)));
  567.                         }
  568.                     }
  569.                 break;
  570.         }
  571.     }
  572.     return new_pix;
  573. }
  574.  
  575. #endif
  576.  
  577.  
  578. PixMapHandle RotatePixRight(PixMapHandle pix) {
  579.     unsigned long srcrow, dstrow, x, y, dstcol, width, height;
  580.     unsigned char *srcbase, *dstbase, *s, *d;
  581.     PixMapHandle new_pix;
  582.         
  583.         /* establish the next pixmap */
  584.     if ((*pix)->pixelSize <= 8)
  585.         new_pix = MakePixMap((*pix)->bounds.bottom, (*pix)->bounds.right, (*pix)->pmTable);
  586.     else if ((*pix)->pixelSize == 16)
  587.         new_pix = Make16BitPixMap((*pix)->bounds.bottom, (*pix)->bounds.right);
  588.     else if ((*pix)->pixelSize == 32)
  589.         new_pix = Make32BitPixMap((*pix)->bounds.bottom, (*pix)->bounds.right);
  590.     else return NULL;
  591.     
  592.     if (new_pix == NULL) return NULL;
  593.     
  594.         /* set up locals */
  595.     srcrow = ((*pix)->rowBytes & 0x3FFF);
  596.     dstrow = ((*new_pix)->rowBytes & 0x3FFF);
  597.     srcbase = (unsigned char*) (*pix)->baseAddr;
  598.     dstbase = (unsigned char*) (*new_pix)->baseAddr;
  599.     dstcol = height = (*pix)->bounds.bottom;
  600.     width = (*pix)->bounds.right;
  601.         
  602.         /* rotate the image */
  603.     switch ((*pix)->pixelSize) {
  604.         case 1:
  605.         case 2:
  606.         case 4:
  607.             for (y = 0; y < height; y++)
  608.                 for (x=0; x < width; x++)
  609.                     SetPixMapPixel(new_pix, height - y - 1, x, GetPixMapPixel(pix, x, y));
  610.             break;
  611.         case 8:
  612.             for (y = 0; y < height; y++, srcbase += srcrow)
  613.                 for (s = srcbase, d = dstbase + (--dstcol), x=0; x < width; x++, d += dstrow)
  614.                     *d = *s++;
  615.             break;
  616.         case 16:
  617.             for (y = 0; y < height; y++, srcbase += srcrow)
  618.                 for (s = srcbase, d = dstbase + ((--dstcol) << 1), x=0; x < width; x++, s += 2, d += dstrow)
  619.                     * ((short*) d) = * ((short*) s);
  620.             break;
  621.         case 32:
  622.             for (y = 0; y < height; y++, srcbase += srcrow)
  623.                 for (s = srcbase, d = dstbase + ((--dstcol) << 2), x=0; x < width; x++, s += 4, d += dstrow)
  624.                     * ((long*) d) = * ((long*) s);
  625.             break;
  626.     }
  627.     
  628.         /* done */
  629.     return new_pix;
  630. }
  631.  
  632.  
  633. PixMapHandle RotatePixLeft(PixMapHandle pix) {
  634.     unsigned long srcrow, dstrow, x, y, dstcol, width, height;
  635.     unsigned char *srcbase, *dstbase, *s, *d, *dststart;
  636.     PixMapHandle new_pix;
  637.         
  638.         /* get the next pixmap */
  639.     if ((*pix)->pixelSize <= 8)
  640.         new_pix = MakePixMap((*pix)->bounds.bottom, (*pix)->bounds.right, (*pix)->pmTable);
  641.     else if ((*pix)->pixelSize == 16)
  642.         new_pix = Make16BitPixMap((*pix)->bounds.bottom, (*pix)->bounds.right);
  643.     else if ((*pix)->pixelSize == 32)
  644.         new_pix = Make32BitPixMap((*pix)->bounds.bottom, (*pix)->bounds.right);
  645.     else return NULL;
  646.     if (new_pix == NULL) return NULL;
  647.     
  648.         /* set up the locals */
  649.     srcrow = ((*pix)->rowBytes & 0x3FFF);
  650.     dstrow = ((*new_pix)->rowBytes & 0x3FFF);
  651.     srcbase = (unsigned char*) (*pix)->baseAddr;
  652.     dstbase = (unsigned char*) (*new_pix)->baseAddr;
  653.     height = (*pix)->bounds.bottom;
  654.     width = (*pix)->bounds.right;
  655.     dststart = dstbase + ((width-1) * dstrow);
  656.     dstcol = 0;
  657.     
  658.         /* rotate the image */
  659.     switch ((*pix)->pixelSize) {
  660.         case 1:
  661.         case 2:
  662.         case 4:
  663.             for (y = 0; y < height; y++)
  664.                 for (x=0; x < width; x++)
  665.                     SetPixMapPixel(new_pix, y, width - x - 1, GetPixMapPixel(pix, x, y));
  666.             break;
  667.         case 8:
  668.             for (y = 0; y < height; y++, srcbase += srcrow)
  669.                 for (s = srcbase, d = dststart + (dstcol++), x = 0; x < width; x++, d -= dstrow)
  670.                     *d = *s++;
  671.             break;
  672.         case 16:
  673.             for (y = 0; y < height; y++, srcbase += srcrow)
  674.                 for (s = srcbase, d = dststart + ((dstcol++) << 1), x = 0; x < width; x++, s += 2, d -= dstrow)
  675.                     * ((short*) d) = * ((short*) s);
  676.             break;
  677.         case 32:
  678.             for (y = 0; y < height; y++, srcbase += srcrow)
  679.                 for (s = srcbase, d = dststart + ((dstcol++) << 2), x = 0; x < width; x++, s += 4, d -= dstrow)
  680.                     * ((long*) d) = * ((long*) s);
  681.             break;
  682.     }
  683.     return new_pix;
  684. }
  685.  
  686. PixMapHandle FlipPixVertical(PixMapHandle pix) {
  687.     unsigned long srcrow, dstrow, y, width, height;
  688.     unsigned char *srcbase, *dstbase;
  689.     PixMapHandle new_pix;
  690.     
  691.         /* get the next pixmap */
  692.     if ((*pix)->pixelSize <= 8)
  693.         new_pix = MakePixMap((*pix)->bounds.right, (*pix)->bounds.bottom, (*pix)->pmTable);
  694.     else if ((*pix)->pixelSize == 16)
  695.         new_pix = Make16BitPixMap((*pix)->bounds.right, (*pix)->bounds.bottom);
  696.     else if ((*pix)->pixelSize == 32)
  697.         new_pix = Make32BitPixMap((*pix)->bounds.right, (*pix)->bounds.bottom);
  698.     else return NULL;
  699.     if (new_pix == NULL) return NULL;
  700.     
  701.         /* set up the locals */
  702.     srcrow = ((*pix)->rowBytes & 0x3FFF);
  703.     dstrow = ((*new_pix)->rowBytes & 0x3FFF);
  704.     srcbase = (unsigned char*) (*pix)->baseAddr;
  705.     dstbase = (unsigned char*) (*new_pix)->baseAddr;
  706.     height = (*pix)->bounds.bottom;
  707.     width = (*pix)->bounds.right;
  708.     dstbase += (height * dstrow);
  709.     
  710.         /* flip the image */
  711.     for (y=0; y < height; y++) {
  712.         dstbase -= dstrow;
  713.         BlockMoveData(srcbase, dstbase, dstrow);
  714.         srcbase += srcrow; 
  715.     }
  716.     return new_pix;
  717. }
  718.  
  719. PixMapHandle FlipPixHorizontal(PixMapHandle pix) {
  720.     unsigned long srcrow, dstrow, x, y, width, height;
  721.     unsigned char *srcbase, *dstbase, *s, *d;
  722.     PixMapHandle new_pix;
  723.     
  724.         /* get the next pixmap */
  725.     if ((*pix)->pixelSize <= 8)
  726.         new_pix = MakePixMap((*pix)->bounds.right, (*pix)->bounds.bottom, (*pix)->pmTable);
  727.     else if ((*pix)->pixelSize == 16)
  728.         new_pix = Make16BitPixMap((*pix)->bounds.right, (*pix)->bounds.bottom);
  729.     else if ((*pix)->pixelSize == 32)
  730.         new_pix = Make32BitPixMap((*pix)->bounds.right, (*pix)->bounds.bottom);
  731.     else return NULL;
  732.     if (new_pix == NULL) return NULL;
  733.     
  734.         /* set up the locals */
  735.     srcrow = ((*pix)->rowBytes & 0x3FFF);
  736.     dstrow = ((*new_pix)->rowBytes & 0x3FFF);
  737.     srcbase = (unsigned char*) (*pix)->baseAddr;
  738.     dstbase = (unsigned char*) (*new_pix)->baseAddr;
  739.     height = (*pix)->bounds.bottom;
  740.     width = (*pix)->bounds.right;
  741.     
  742.         /* flip the image */
  743.     switch ((*pix)->pixelSize) {
  744.         case 1:
  745.         case 2:
  746.         case 4:
  747.             for (y = 0; y < height; y++)
  748.                 for (x=0; x < width; x++)
  749.                     SetPixMapPixel(new_pix, width - x - 1, y, GetPixMapPixel(pix, x, y));
  750.             break;
  751.         case 8:
  752.             for (y = 0; y < height; y++, srcbase += srcrow, dstbase += dstrow)
  753.                 for(s = srcbase + width, d = dstbase, x = 0; x < width; x++)
  754.                     *d++ = *--s;
  755.             break;
  756.         case 16:
  757.             for (y = 0; y < height; y++, srcbase += srcrow, dstbase += dstrow)
  758.                 for(s = srcbase + (width << 1) - 2, d = dstbase, x = 0; x < width; x++, d += 2, s -= 2)
  759.                     * ((short*) d) = * ((short*) s);
  760.             break;
  761.         case 32:
  762.             for (y = 0; y < height; y++, srcbase += srcrow, dstbase += dstrow)
  763.                 for(s = srcbase + (width << 2) - 4, d = dstbase, x = 0; x < width; x++, d += 4, s -= 4)
  764.                     * ((long*) d) = * ((long*) s);
  765.             break;
  766.     }
  767.     return new_pix;
  768. }
  769.  
  770.  
  771. PixMapHandle DuplicatePixMap(PixMapHandle pix) {
  772.     unsigned long srcrow, dstrow, y, width, height;
  773.     unsigned char *srcbase, *dstbase;
  774.     PixMapHandle new_pix;
  775.     
  776.         /* get the next pixmap */
  777.     if ((*pix)->pixelSize <= 8)
  778.         new_pix = MakePixMap((*pix)->bounds.right, (*pix)->bounds.bottom, (*pix)->pmTable);
  779.     else if ((*pix)->pixelSize == 16)
  780.         new_pix = Make16BitPixMap((*pix)->bounds.right, (*pix)->bounds.bottom);
  781.     else if ((*pix)->pixelSize == 32)
  782.         new_pix = Make32BitPixMap((*pix)->bounds.right, (*pix)->bounds.bottom);
  783.     else return NULL;
  784.     if (new_pix == NULL) return NULL;
  785.     
  786.         /* set up the locals */
  787.     srcrow = ((*pix)->rowBytes & 0x3FFF);
  788.     dstrow = ((*new_pix)->rowBytes & 0x3FFF);
  789.     srcbase = (unsigned char*) (*pix)->baseAddr;
  790.     dstbase = (unsigned char*) (*new_pix)->baseAddr;
  791.     height = (*pix)->bounds.bottom;
  792.     width = (*pix)->bounds.right;
  793.     
  794.         /* copy the image */
  795.     for (y=0; y < height; y++) {
  796.         BlockMoveData(srcbase, dstbase, dstrow);
  797.         srcbase += srcrow; 
  798.         dstbase += dstrow;
  799.     }
  800.     return new_pix;
  801. }
  802.  
  803.  
  804. PixMapHandle PICTToPixMap(PicHandle pic, CTabHandle clut) {
  805.     Rect bounds;
  806.     PixMapHandle pix;
  807.     PixMapPort *pxmp;
  808.     bounds = (*pic)->picFrame;
  809.     OffsetRect(&bounds, -bounds.left, -bounds.top);
  810.     pix = MakePixMap(bounds.right, bounds.bottom, clut);
  811.     if (pix != NULL)
  812.         WithPixMap(pix, pxmp) {
  813.             DrawPicture(pic, &bounds);
  814.         }
  815.     return pix;
  816. }
  817.  
  818. PixMapHandle PICTTo16BitPixMap(PicHandle pic) {
  819.     Rect bounds;
  820.     PixMapHandle pix;
  821.     PixMapPort *pxmp;
  822.     bounds = (*pic)->picFrame;
  823.     OffsetRect(&bounds, -bounds.left, -bounds.top);
  824.     pix = Make16BitPixMap(bounds.right, bounds.bottom);
  825.     if (pix != NULL)
  826.         WithPixMap(pix, pxmp) {
  827.             DrawPicture(pic, &bounds);
  828.         }
  829.     return pix;
  830. }
  831.  
  832.  
  833. PixMapHandle PICTTo32BitPixMap(PicHandle pic) {
  834.     Rect bounds;
  835.     PixMapHandle pix;
  836.     PixMapPort *pxmp;
  837.     bounds = (*pic)->picFrame;
  838.     OffsetRect(&bounds, -bounds.left, -bounds.top);
  839.     pix = Make32BitPixMap(bounds.right, bounds.bottom);
  840.     if (pix != NULL)
  841.         WithPixMap(pix, pxmp) {
  842.             DrawPicture(pic, &bounds);
  843.         }
  844.     return pix;
  845. }
  846.  
  847.  
  848. PicHandle PixMapToPICT(PixMapHandle pix) {
  849.     PicHandle pic;
  850.     GrafPtr saved;
  851.     CGrafPort port;
  852.     Rect bounds;
  853.     bounds = (*pix)->bounds;
  854.     GetPort(&saved);
  855.     OpenCPort(&port);
  856.     pic = OpenPicture(&bounds);
  857.     ClipRect(&bounds);
  858.     PlotPixMap(pix, 0, 0, srcCopy);
  859.     ClosePicture();
  860.     SetPort(saved);
  861.     ClosePort((GrafPtr) &port);
  862.     if (GetHandleSize((Handle) pic) == sizeof(Picture)) {
  863.         KillPicture(pic);
  864.         pic = NULL;
  865.     }
  866.     return pic;
  867. }
  868.  
  869.  
  870. PicHandle PixMapToCompressedPICT(PixMapHandle pix) {
  871.     GrafPtr saved;
  872.     CGrafPort port;
  873.     PicHandle pic;
  874.     Rect bounds;
  875.     OSErr err;
  876.     long buffersize, response;
  877.     Ptr compBuffer;
  878.     ImageDescriptionHandle iDesc;
  879.     Boolean port_open;
  880.     
  881.         /* can it be done? */
  882.     if (Gestalt(gestaltCompressionMgr, &response) != noErr) return NULL;
  883.     
  884.         /* initial state */
  885.     compBuffer = NULL;
  886.     iDesc = NULL;
  887.     pic = NULL;
  888.     port_open = false;
  889.  
  890.         /* draw the picture, make sure we have a port */
  891.     GetPort(&saved);
  892.     OpenCPort(&port);
  893.     ClipRect(&bounds);
  894.     port_open = true;
  895.     
  896.         /* calculate sizes */
  897.     bounds = (*pix)->bounds;
  898.     err = GetMaxCompressionSize(pix, &bounds, 0, codecHighQuality, 'jpeg', anyCodec, &buffersize);
  899.     if (err != noErr) goto bail;
  900.     
  901.         /* allocate storage */
  902.     compBuffer = NewPtr(buffersize);
  903.     if ((err = MemError()) != noErr) goto bail;
  904.     iDesc = (ImageDescriptionHandle) NewHandleClear(sizeof(ImageDescription));
  905.     if ((err = MemError()) != noErr) goto bail;
  906.     
  907.         /* compress the image */
  908.     err = CompressImage(pix, &bounds, codecHighQuality, 'jpeg', iDesc, compBuffer);
  909.     if (err != noErr) goto bail;
  910.         
  911.         /* put the compressed image in a picture */
  912.     pic = OpenPicture(&bounds);
  913.     ClipRect(&bounds);
  914.     err = DecompressImage(compBuffer, iDesc, pix, &bounds, &bounds, srcCopy, NULL);
  915.     ClosePicture();
  916.     
  917.         /* verify that the picture is ok */
  918.     if (err != noErr || GetHandleSize((Handle) pic) == sizeof(Picture)) goto bail;
  919.     
  920.         /* clean up and go */
  921.     SetPort(saved);
  922.     ClosePort((GrafPtr) &port);
  923.     DisposePtr(compBuffer);
  924.     DisposeHandle((Handle) iDesc);
  925.     return pic;
  926.  
  927. bail:
  928.     if (port_open)  {
  929.         SetPort(saved);
  930.         ClosePort((GrafPtr) &port);
  931.     }
  932.     if (pic != NULL) KillPicture(pic);
  933.     if (compBuffer != NULL) DisposePtr(compBuffer);
  934.     if (iDesc != NULL) DisposeHandle((Handle) iDesc);
  935.     return NULL;
  936. }
  937.  
  938.  
  939. PixMapPort* NewPxMP(PixMapHandle pix) {
  940.     GDHandle the_device;
  941.     ITabHandle inverse_table;
  942.     PixMapPort* pxmp;
  943.     Boolean device_active;
  944.     Rect r;
  945.     
  946.         /* set up initial variable states */
  947.     the_device = NULL;
  948.     inverse_table = NULL;
  949.     pxmp = NULL;
  950.     device_active = false;
  951.     
  952.         /* allocate the pxmp */
  953.     pxmp = (PixMapPort*) NewPtr(sizeof(PixMapPort));
  954.     if (pxmp == NULL) goto bail;
  955.     
  956.         /* create the graphics device */
  957.     inverse_table = (ITabHandle) NewHandleClear(2);
  958.     if (inverse_table == NULL) goto bail;
  959.     if ((*pix)->pixelSize <= 8) { /* set it up only for indexed devices */
  960.         MakeITable((*pix)->pmTable, inverse_table, 4);
  961.         if (QDError() != noErr) goto bail;
  962.     }
  963.     
  964.         /* create the graphics device */
  965.     the_device = (GDHandle) NewHandleClear(sizeof(GDevice));
  966.     if (the_device == NULL) goto bail;
  967.     if ((*pix)->pixelSize <= 8)
  968.         (*the_device)->gdType = clutType;
  969.     else (*the_device)->gdType = directType;
  970.     (*the_device)->gdITable = inverse_table;
  971.     (*the_device)->gdResPref = 4;
  972.     (*the_device)->gdPMap = pix;
  973.     (*the_device)->gdRect = (*pix)->bounds;
  974.     (*the_device)->gdMode = -1;
  975.     SetDeviceAttribute(the_device, gdDevType, true);
  976.     SetDeviceAttribute(the_device, noDriver, true);
  977.  
  978.         /* save the current grafport and device */
  979.     GetPort(&pxmp->saved_port);
  980.     pxmp->saved_device = GetGDevice();
  981.  
  982.         /* set the current device to the new one*/
  983.     SetGDevice((pxmp->pdevice = the_device));
  984.     device_active = true;
  985.  
  986.         /* Open the new grafport*/
  987.     OpenCPort(&pxmp->pport);
  988.     SetPort((GrafPtr) &pxmp->pport);
  989.     r = (*pix)->bounds;
  990.     PortSize(r.right, r.bottom);
  991.     ClipRect(&r);
  992.     RectRgn(pxmp->pport.visRgn, &r);
  993.  
  994.         /* done */
  995.     return pxmp;
  996.  
  997. bail:
  998.     if (device_active) SetGDevice(pxmp->saved_device);
  999.     if (inverse_table != NULL) DisposHandle((Handle) inverse_table);
  1000.     if (the_device != NULL) DisposHandle((Handle) the_device);
  1001.     if (pxmp != NULL) DisposPtr((Ptr) pxmp);
  1002.     return NULL;
  1003. }
  1004.  
  1005. void DisposePxMP(PixMapPort* px) {
  1006.     if (px->pdevice == GetGDevice()) {
  1007.         SetGDevice(px->saved_device);
  1008.         SetPort(px->saved_port);
  1009.     }
  1010.     CloseCPort(&px->pport);
  1011.     DisposeHandle((Handle) ((*px->pdevice)->gdITable));
  1012.     DisposeHandle((Handle) (px->pdevice));
  1013.     DisposPtr((Ptr) px);
  1014. }
  1015.  
  1016. void PlotPixMap(PixMapHandle pix, short h, short v, short mode) {
  1017.     GrafPtr port;
  1018.     Rect src, dst;
  1019.     char hstate;
  1020.     GetPort(&port);
  1021.     hstate = HGetState((Handle) pix);
  1022.     HLock((Handle) pix);
  1023.     src = dst = (*pix)->bounds;
  1024.     OffsetRect(&dst, h, v);
  1025.     CopyBits((BitMap *) (*pix), &port->portBits, &src, &dst, mode, NULL);
  1026.     HSetState((Handle) pix, hstate);
  1027. }
  1028.  
  1029. void PixMapCopy(PixMapHandle pix, Rect *src, Rect *dst, short mode) {
  1030.     GrafPtr port;
  1031.     char hstate;
  1032.     GetPort(&port);
  1033.     hstate = HGetState((Handle) pix);
  1034.     HLock((Handle) pix);
  1035.     CopyBits((BitMap *) (*pix), &port->portBits, src, dst, mode, NULL);
  1036.     HSetState((Handle) pix, hstate);
  1037. }
  1038.  
  1039. PixPatHandle PixMap2PixPat(PixMapHandle pix, Pattern *the_pattern) {
  1040.     PixPat ppat;
  1041.     PixMap pmap;
  1042.     PixPatHandle the_pixpat;
  1043.     long bytecount;
  1044.     char ctstate;
  1045.     short width, height;
  1046.     OSErr err;
  1047.     
  1048.         /* recoverable state */
  1049.     the_pixpat = NULL;
  1050.  
  1051.         /* check parameters */
  1052.     if ((*pix)->pixelSize > 8) goto bail;
  1053.     width = (*pix)->bounds.right;
  1054.     if (width != 8 && width != 16 && width != 32 && width != 64 && width != 128)
  1055.         goto bail;
  1056.     height = (*pix)->bounds.bottom;
  1057.     if (height != 8 && height != 16 && height != 32 && height != 64 && height != 128)
  1058.         goto bail;    
  1059.     
  1060.         /* set variables to correct initial settings */
  1061.     bytecount = ((long) ((*pix)->rowBytes & 0x3FFF)) * ((long) (*pix)->bounds.bottom);
  1062.     ppat.patType = 1;
  1063.     ppat.patMap = (PixMapHandle) sizeof(PixPat);
  1064.     ppat.patData = (Handle) (sizeof(PixPat) + sizeof(PixMap));
  1065.     ppat.patXData = NULL;
  1066.     ppat.patXValid = -1;
  1067.     ppat.patXMap = NULL;
  1068.     ppat.pat1Data = *the_pattern;
  1069.     pmap = **pix;
  1070.     pmap.baseAddr = NULL;
  1071.     pmap.pmTable = (CTabHandle) (sizeof(PixPat) + sizeof(PixMap) + bytecount);
  1072.  
  1073.         /* add the PixPat header */
  1074.     err = PtrToHand(&ppat, (Handle*) &the_pixpat, sizeof(ppat));
  1075.     if (err != noErr) goto bail;
  1076.     
  1077.         /* ... then the PixMap */
  1078.     err = PtrAndHand(&pmap, (Handle) the_pixpat, sizeof(PixMap));
  1079.     if (err != noErr) goto bail;
  1080.     
  1081.         /* ... then the raster data */
  1082.     err = PtrAndHand((*pix)->baseAddr, (Handle) the_pixpat, bytecount);
  1083.     if (err != noErr) goto bail;
  1084.     
  1085.         /* ... and finally the colour table */
  1086.     ctstate = HGetState((Handle) (*pix)->pmTable);
  1087.     HLock((Handle) (*pix)->pmTable);
  1088.     err = PtrAndHand(*((*pix)->pmTable), (Handle) the_pixpat, GetHandleSize((Handle) (*pix)->pmTable));
  1089.     HSetState((Handle) (*pix)->pmTable, ctstate);
  1090.     if (err != noErr) goto bail;
  1091.     
  1092.         /* done */
  1093.     return the_pixpat;
  1094.  
  1095. bail:
  1096.     if (the_pixpat != NULL) DisposeHandle((Handle) the_pixpat);
  1097.     return NULL;
  1098. }
  1099.  
  1100.  
  1101. CTabHandle CalcPixMapColours(PixMapHandle pix) {
  1102.     CTabHandle clut;
  1103.     OSErr err;
  1104.     clut = NULL;
  1105.     if ((*pix)->pixelSize <= 8) {
  1106.         clut = (*pix)->pmTable;
  1107.         if (HandToHand((Handle *) &clut) != noErr) clut = NULL;
  1108.     } else {
  1109.         PictInfo pictinfo;
  1110.         memset(&pictinfo, 0, sizeof(pictinfo));
  1111.         err = GetPixMapInfo(pix, &pictinfo,
  1112.             returnColorTable+suppressBlackAndWhite,
  1113.             254, medianMethod, 0);
  1114.         if (err == noErr) clut = pictinfo.theColorTable;
  1115.     }
  1116.     return clut;
  1117. }
  1118.  
  1119.  
  1120.