home *** CD-ROM | disk | FTP | other *** search
/ MACD 9 / MACD9.iso / Datatypes / MacPict2 / extras / dt2macpict.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-01  |  8.6 KB  |  419 lines

  1. /*
  2.     dt2macpict
  3.  
  4.     Reads a picture (by the datatypes system) and 
  5.     writes a 256 colors picture in Macintosh Pict2 format.
  6.  
  7.     Made by Erik Engdahl 1998. The code is FREEWARE.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12.  
  13.     v1.0 Initial version, 1998-02-28
  14. */
  15.  
  16. #include <exec/types.h>
  17. #include <exec/memory.h>
  18. #include <dos/dos.h>
  19. #include <dos/rdargs.h>
  20. #include <graphics/gfx.h>
  21. #include <datatypes/datatypes.h>
  22. #include <datatypes/datatypesclass.h>
  23. #include <datatypes/pictureclass.h>
  24. #include <proto/exec.h>
  25. #include <proto/dos.h>
  26. #include <proto/graphics.h>
  27. #include <proto/datatypes.h>
  28. #include <string.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31.  
  32. #define HEADER_SIZE            512
  33. #define PICT_clipRgn        0x01
  34. #define PICT_picVersion        0x11
  35. #define PICT_PackBitsRect    0x98
  36. #define PICT_EndOfPicture    0xFF
  37. #define    PICT_headerOp        0x0C00
  38.  
  39. int  openLibs(void);
  40. void closeLibs(void);
  41.  
  42. struct Library* DosBase = NULL;
  43. struct GfxBase *GfxBase = NULL;
  44. struct Library *DataTypesBase = NULL;
  45.  
  46. static char *verstr="$VER: dt2macpict 1.0 by Erik Engdahl\0";
  47.  
  48. struct {
  49.     char *from;
  50.     char *to;
  51.     BOOL nopack;
  52. } args;
  53.  
  54. #define NUM_OPTS 3
  55.  
  56. #define TEMPLATE "INFILE/A,OUTFILE/A,NOPACK/S"
  57.  
  58. UWORD headdata[26] = {
  59.     0, 0, 0, 2, 16, PICT_picVersion, 0x02ff, PICT_headerOp,
  60.     0xffff, 0xffff, 0, 0, 0, 0, 16, 0, 
  61.     2, 0, 0, 0, PICT_clipRgn, 10, 0, 0, 
  62.     16, 2
  63. };
  64.  
  65. UWORD pbdata[27] = {
  66.     PICT_PackBitsRect, 0x8016, 0, 0, 2, 16, 0, 0, 
  67.     0, 0, 72, 0, 72, 0, 0, 8,
  68.     1, 8, 0, 0, 0, 0, 0, 0,
  69.     0, 0, 0
  70. };
  71.  
  72.  
  73. void putWord(BPTR fh, UWORD data, UWORD num)
  74. {
  75.     UWORD i;
  76.  
  77.     for(i = 0; i < num; i++)
  78.     {
  79.         FWrite(fh, &data, sizeof(UWORD), 1);
  80.     }
  81. } /* putWord */
  82.  
  83. UWORD packrow(UBYTE *inbuf, ULONG width, UBYTE *outbuf, BOOL nopack)
  84. {
  85.     UWORD outlen, inpos;
  86.     UWORD i, imax;
  87.     UBYTE n, len;
  88.     
  89.     outlen = 0;
  90.     inpos = 0;
  91.  
  92.     /* Should we pack the row? */
  93.     if(!nopack)
  94.     {
  95.         while(inpos < width)
  96.         {
  97.             if((imax = width - inpos)> 0x7f)
  98.             {
  99.                 imax = 0x7f;
  100.             }
  101.  
  102.             /* Possible to pack? */
  103.             len = 0;
  104.             for(i = 1; (i < imax); i++)
  105.             {
  106.                 if(inbuf[inpos] == inbuf[inpos + i])
  107.                 {
  108.                     len = i;
  109.                 }
  110.                 else break;
  111.             }
  112.  
  113.             /* OK pack */
  114.             if(len > 0x2)
  115.             {
  116.                 len++;
  117.                 n = (len^255) + 2;
  118.                 outbuf[outlen++] = n;
  119.                 outbuf[outlen++] = inbuf[inpos];
  120.                 inpos += len;
  121.             }
  122.             /* NO packing */
  123.             else
  124.             {
  125.                 len = 0;
  126.                 for(i = 1; (i < imax); i++)
  127.                 {
  128.                     if(inbuf[inpos + i] != inbuf[inpos + i + 1]) 
  129.                     {
  130.                         len = i;
  131.                     }
  132.                     else 
  133.                     {
  134.                         /* if there are just 2 identical bytes breaking
  135.                             a series of different bytes then ignore it 
  136.                             ex "a b c c d a c b"
  137.                         */
  138.                         if(inbuf[inpos + i] == inbuf[inpos + i + 2]) 
  139.                         {
  140.                             break;
  141.                         }
  142.                     }
  143.                 }
  144.                 outbuf[outlen++] = len;
  145.                 imax = (UWORD) (len + 1);
  146.                 for(i = 0; i < imax; i++)
  147.                 {
  148.                     outbuf[outlen++] = inbuf[inpos++];
  149.                 }
  150.             }
  151.         }
  152.     }
  153.     /* No packing requested, simple */
  154.     else
  155.     {
  156.         while(inpos < width)
  157.         {
  158.             n = width - inpos;
  159.             if(n >= 0x80) 
  160.             {
  161.                 n = 0x7f;
  162.             }
  163.             outbuf[outlen++] = n;
  164.  
  165.             for(i = 0; i <= n; i++)
  166.             {
  167.                 outbuf[outlen++] = inbuf[inpos++];
  168.             }
  169.         }
  170.     }
  171.     return outlen;
  172. } /* packrow */
  173.  
  174. int savebody(BPTR fh, struct BitMap *bm, 
  175.             ULONG width, ULONG height, ULONG depth)
  176. {
  177.     struct BitMap *tbm;
  178.     struct RastPort __aligned trp;
  179.     struct RastPort __aligned rp;
  180.     UBYTE *buf, *outbuf;
  181.     LONG count;
  182.     ULONG row;
  183.     UWORD rowlen;
  184.     UBYTE shortrow;
  185.     int res;
  186.     
  187.   
  188.     buf = (UBYTE *) AllocVec(width + 0x80UL, (MEMF_CHIP | MEMF_CLEAR));
  189.     outbuf = (UBYTE *) AllocVec(width + 0x200UL, MEMF_CLEAR);
  190.  
  191.     tbm = AllocBitMap(    width + 16UL, 1UL, depth, BMF_CLEAR, NULL);
  192.     
  193.     if(tbm && buf && outbuf)
  194.     {
  195.         InitRastPort (&trp);
  196.         trp.BitMap = tbm;
  197.         InitRastPort (&rp);
  198.         rp.BitMap = bm;
  199.  
  200.         /* Source and Destination Rectangle + Mode */
  201.         putWord(fh, 0, 2); 
  202.         putWord(fh, (UWORD)height, 1);
  203.         putWord(fh, (UWORD)width, 1);
  204.         putWord(fh, 0, 2); 
  205.         putWord(fh, (UWORD)height, 1);
  206.         putWord(fh, (UWORD)width, 1);
  207.         putWord(fh, 0, 1); 
  208.  
  209.         for(row = 0; row < height; row++)
  210.         {
  211.             count = ReadPixelLine8(&rp, 0, row, width, buf, &trp);
  212.             rowlen = packrow(buf, count, outbuf, args.nopack);
  213.  
  214.             /* Write number of (packed) bytes in this row */
  215.             if(width > 250)
  216.             {
  217.                 putWord(fh, rowlen, 1);
  218.             }
  219.             else
  220.             {
  221.                 shortrow = (UBYTE) rowlen;
  222.                 FWrite(fh, &shortrow, sizeof(UBYTE), 1);
  223.             }
  224.  
  225.             /* Write the bytes */
  226.             FWrite(fh, outbuf, sizeof(UBYTE), (ULONG)(rowlen));
  227.  
  228.         }
  229.  
  230.         /* Word align */
  231.         count = Seek(fh, 0, OFFSET_CURRENT);
  232.         if(count & 1)
  233.         {
  234.             FWrite(fh, buf, sizeof(UBYTE), 1);
  235.         }
  236.  
  237.         res = (int) row;
  238.     }
  239.     else
  240.     {
  241.         printf("Couldn't allocate memory and/or bitmap\n");
  242.         res = -1;
  243.     }
  244.  
  245.     /* Free the memory */
  246.     if(tbm)    FreeBitMap(tbm);
  247.     if(buf)    FreeVec(buf);
  248.     if(outbuf)    FreeVec(outbuf);
  249.     
  250.     return res;
  251. } /* savebody */
  252.  
  253. /* Open the libraries and return TRUE if ok */
  254. int openLibs(void)
  255. {
  256.     if((DosBase = OpenLibrary("dos.library", 39)) == NULL)
  257.     {
  258.         fprintf(stderr, "Sorry, couldn't open dos.library\n");
  259.         return FALSE;
  260.     }
  261.     if((GfxBase = (struct GfxBase *) 
  262.         OpenLibrary("graphics.library", 39)) == NULL)
  263.     {
  264.         fprintf(stderr, "Sorry, couldn't open graphics.library\n");
  265.         return FALSE;
  266.     }
  267.     if((DataTypesBase = OpenLibrary("datatypes.library", 39)) == NULL)
  268.     {
  269.         fprintf(stderr, "Sorry, couldn't open datatypes.library\n");
  270.         return FALSE;
  271.     }
  272.     return TRUE;
  273. } /* openLibs */
  274.  
  275. /* Close libraries */
  276. void closeLibs(void)
  277. {
  278.     CloseLibrary(DosBase);
  279.     CloseLibrary((struct Library *)GfxBase);
  280.     CloseLibrary(DataTypesBase);
  281. } /* closeLibs */
  282.  
  283.  
  284. int main(int argc, char *argv[])
  285. {
  286.     Object *pic;
  287.     struct BitMapHeader *bmhd;
  288.     struct BitMap *bm;
  289.     struct gpLayout dtlayout;
  290.     ULONG *cregs, tlong;
  291.     UWORD i, numcolors;
  292.     BPTR fh;
  293.     int exitstatus = EXIT_SUCCESS;
  294.     struct RDArgs *rdargs = NULL;
  295.     LONG options[NUM_OPTS];
  296.  
  297.     if(argc == 0)
  298.     {
  299.         fprintf(stderr, "Must be started from Shell\n");
  300.         return EXIT_FAILURE;
  301.     }
  302.  
  303.     if(!openLibs())
  304.     {
  305.         closeLibs();
  306.         return EXIT_FAILURE;
  307.     }
  308.  
  309.     memset(options, 0, sizeof(options));
  310.  
  311.     if(rdargs = ReadArgs(TEMPLATE, options, NULL))
  312.     {
  313.         if(options[0]) args.from = (char *)options[0];
  314.         if(options[1]) args.to = (char *)options[1];
  315.         if(options[2]) args.nopack = TRUE;
  316.  
  317.         if(pic = NewDTObject(    args.from, 
  318.                                 DTA_SourceType, DTST_FILE, 
  319.                                 DTA_GroupID, GID_PICTURE, 
  320.                                 PDTA_Remap, FALSE, 
  321.                                 TAG_END))
  322.         {
  323.             /* Make sure the object is rendered */
  324.             dtlayout.MethodID = DTM_PROCLAYOUT;
  325.             dtlayout.gpl_GInfo = NULL;
  326.             dtlayout.gpl_Initial = TRUE;
  327.  
  328.             if (DoDTMethodA(pic, NULL, NULL, (Msg)&dtlayout))
  329.             {
  330.                 /* Get bitmap and colors */
  331.                 if (GetDTAttrs( pic,
  332.                                 PDTA_BitMapHeader, &bmhd,
  333.                                 PDTA_BitMap, &bm,
  334.                                 PDTA_CRegs, &cregs,
  335.                                 PDTA_NumColors, &tlong,
  336.                                 TAG_DONE) == 4)
  337.                 {
  338.                     numcolors = (UWORD) tlong;
  339.  
  340.                     printf("Colors: %d\n",numcolors);
  341.                     printf("Size: %d x %d\n", bmhd->bmh_Width, bmhd->bmh_Height);
  342.                     printf("Wait a while, this can take some time...\n");
  343.  
  344.                     fh = Open(args.to, MODE_NEWFILE);
  345.                     if(fh)
  346.                     {
  347.                         /* Save file header */
  348.                         putWord(fh, 0, (HEADER_SIZE/2));
  349.  
  350.                         /* Fill in dimensions and write picture header */
  351.                         headdata[4] = headdata[14] = headdata[24] = 
  352.                             bmhd->bmh_Width;
  353.                         headdata[3] = headdata[16] = headdata[25] = 
  354.                             bmhd->bmh_Height;
  355.  
  356.                         FWrite(fh, headdata, sizeof(UWORD), 26);
  357.  
  358.                         /* Save bitmap packbits header */
  359.                         pbdata[1] = bmhd->bmh_Width | 0x8000;
  360.                         pbdata[4] = bmhd->bmh_Height;
  361.                         pbdata[5] = bmhd->bmh_Width;
  362.                         FWrite(fh, pbdata, sizeof(UWORD), 27);
  363.  
  364.                         /* Save colormap */
  365.                         putWord(fh, (numcolors - 1), 1);
  366.                         for(i = 0; i < numcolors; i++)
  367.                         {
  368.                             putWord(fh, i, 1);
  369.                             tlong = cregs[3 * i    ] >> 16;
  370.                             putWord(fh, (UWORD)(tlong), 1);
  371.                             tlong = cregs[3 * i + 1] >> 16;
  372.                             putWord(fh, (UWORD)(tlong), 1);
  373.                             tlong = cregs[3 * i + 2] >> 16;
  374.                             putWord(fh, (UWORD)(tlong), 1);
  375.                         }
  376.  
  377.                         /* Save the bitmap */
  378.                         savebody(fh, bm, (ULONG) bmhd->bmh_Width,
  379.                                     (ULONG) bmhd->bmh_Height,
  380.                                     (ULONG) bmhd->bmh_Depth);
  381.  
  382.                         /* Put end-mark in file */
  383.                         putWord(fh, PICT_EndOfPicture, 1);
  384.  
  385.                         /* Write size (excluding empty header) */
  386.                         tlong = Seek(fh, 0, OFFSET_CURRENT);
  387.                         i = (UWORD)(tlong - HEADER_SIZE);
  388.                         Seek(fh, HEADER_SIZE, OFFSET_BEGINNING);
  389.                         putWord(fh, i, 1);
  390.  
  391.                         /* Done! */
  392.                         Close(fh);
  393.                     }
  394.                     else
  395.                     {
  396.                         printf("Couldn't open file %s for writing\n", 
  397.                             args.to);
  398.                         exitstatus = EXIT_FAILURE;
  399.                     }
  400.                 }
  401.                 else 
  402.                 {
  403.                     printf("Couldn't get information about the picture\n");
  404.                     exitstatus = EXIT_FAILURE;
  405.                 }
  406.             }
  407.             DisposeDTObject(pic);
  408.         }
  409.         FreeArgs (rdargs);
  410.         rdargs = NULL;
  411.     }
  412.     else {
  413.         printf("%s\n", &verstr[6]);
  414.         printf("Usage: %s " TEMPLATE "\n", argv[0]);
  415.     }
  416.  
  417.     closeLibs();
  418.     return exitstatus;
  419. }