home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / xv310a / xvpm.c < prev    next >
C/C++ Source or Header  |  1995-06-12  |  16KB  |  413 lines

  1. /*
  2.  * xvpm.c - load routine for 'pm' format pictures
  3.  *
  4.  * LoadPM();
  5.  * WritePM(fp, pic, ptype, w, h, r,g,b, numcols, style, comment)
  6.  */
  7.  
  8. #include "copyright.h"
  9.  
  10. #include "xv.h"
  11.  
  12.  
  13. /**** PM.H ******/
  14. #define    PM_MAGICNO    0x56494557        /* Hex for VIEW */
  15. #define    PM_A        0x8000
  16. #define    PM_C        0x8001
  17. #define    PM_S        0x8002
  18. #define    PM_I        0x8004
  19. #define PM_F        0xc004
  20.  
  21. #define PM_IOHDR_SIZE    (sizeof(pmpic)-(2*sizeof(char*)))
  22.  
  23. typedef struct {
  24.     int    pm_id;        /* Magic number for pm format files.    */
  25.     int    pm_np;        /* Number of planes. Normally 1.    */
  26.     int    pm_nrow;    /* Number of rows. 1 - MAXNELM.        */
  27.     int    pm_ncol;    /* Number of columns. 1 - MAXNELM.    */
  28.     int    pm_nband;    /* Number of bands.            */
  29.     int    pm_form;    /* Pixel format.            */
  30.     int    pm_cmtsize;    /* Number comment bytes. Includes NULL. */
  31.     char    *pm_image;    /* The image itself.            */
  32.     char    *pm_cmt;    /* Transforms performed.        */
  33. } pmpic;
  34.  
  35.  
  36. #define pm_nelm(p)    ((p)->pm_ncol * (p)->pm_nrow)
  37. #define pm_nbelm(p)    (pm_nelm(p) * (p)->pm_nband)
  38. #define pm_psize(p)    (pm_nbelm(p) * (((p)->pm_form)&0xff))
  39. #define pm_isize(p)    ((p)->pm_np * pm_psize(p))
  40. #define pm_npix(p)      (pm_nbelm(p) * (p)->pm_np)
  41.  
  42. /***** end PM.H *****/
  43.  
  44.  
  45. pmpic  thePic;
  46.  
  47. static int  pmError  PARM((char *, char *));
  48. static int  flip4    PARM((int));
  49. static int  getint32 PARM((FILE *));
  50. static void putint32 PARM((int, FILE *));
  51.  
  52.  
  53. /*******************************************/
  54. int LoadPM(fname, pinfo)
  55.      char    *fname;
  56.      PICINFO *pinfo;
  57. /*******************************************/
  58. {
  59.   /* returns '1' on success */
  60.  
  61.   FILE  *fp;
  62.   byte  *pic8;
  63.   int    isize,i,flipit,w,h;
  64.   char  *bname;
  65.  
  66.   bname = BaseName(fname);
  67.   thePic.pm_image = (char *) NULL;
  68.   thePic.pm_cmt   = (char *) NULL;
  69.  
  70.   pinfo->pic = (byte *) NULL;
  71.   pinfo->comment = (char *) NULL;
  72.  
  73.  
  74.   fp = xv_fopen(fname,"r");
  75.   if (!fp) return( pmError(bname, "unable to open file") );
  76.  
  77.   /* read in the pmpic struct, one byte at a time */
  78.   thePic.pm_id      = getint32(fp);
  79.   thePic.pm_np      = getint32(fp);
  80.   thePic.pm_nrow    = getint32(fp);
  81.   thePic.pm_ncol    = getint32(fp);
  82.   thePic.pm_nband   = getint32(fp);
  83.   thePic.pm_form    = getint32(fp);
  84.   thePic.pm_cmtsize = getint32(fp);
  85.  
  86.   if (ferror(fp) || feof(fp)) return(pmError(bname, "error reading header"));
  87.  
  88.   flipit = 0;
  89.  
  90.   if (thePic.pm_id != PM_MAGICNO) {
  91.     thePic.pm_id = flip4(thePic.pm_id);
  92.     if (thePic.pm_id == PM_MAGICNO) flipit = 1;
  93.     else thePic.pm_id = flip4(thePic.pm_id);
  94.   }
  95.   if (thePic.pm_id != PM_MAGICNO) return( pmError(bname, "not a PM file") );
  96.  
  97.   if (flipit) {
  98.     thePic.pm_np      = flip4(thePic.pm_np);
  99.     thePic.pm_nrow    = flip4(thePic.pm_nrow);
  100.     thePic.pm_ncol    = flip4(thePic.pm_ncol);
  101.     thePic.pm_nband   = flip4(thePic.pm_nband);
  102.     thePic.pm_form    = flip4(thePic.pm_form);
  103.     thePic.pm_cmtsize = flip4(thePic.pm_cmtsize);
  104.     }
  105.  
  106.   w = thePic.pm_ncol;  h = thePic.pm_nrow;
  107.  
  108.   /* make sure that the input picture can be dealt with */
  109.   if ( thePic.pm_nband!=1 || 
  110.       (thePic.pm_form!=PM_I && thePic.pm_form!=PM_C) ||
  111.       (thePic.pm_form==PM_I && thePic.pm_np>1) ||
  112.       (thePic.pm_form==PM_C && (thePic.pm_np==2 || thePic.pm_np>4)) ) {
  113.     fprintf(stderr,"PM picture not in a displayable format.\n");
  114.     fprintf(stderr,"(ie, 1-plane PM_I, or 1-, 3-, or 4-plane PM_C)\n");
  115.  
  116.     return pmError(bname, "PM file in unsupported format");
  117.   }    
  118.  
  119.  
  120.   isize = pm_isize(&thePic);
  121.  
  122.   if (DEBUG) 
  123.     fprintf(stderr,"%s: LoadPM() - loading a %dx%d %s pic, %d planes\n",
  124.         cmd, w, h, (thePic.pm_form==PM_I) ? "PM_I" : "PM_C", 
  125.         thePic.pm_np);
  126.  
  127.           
  128.   /* allocate memory for picture and read it in */
  129.   thePic.pm_image = (char *) malloc((size_t) isize);
  130.   if (thePic.pm_image == NULL) 
  131.     return( pmError(bname, "unable to malloc PM picture") );
  132.  
  133.   if (fread(thePic.pm_image, (size_t) isize, (size_t) 1, fp) != 1)   {
  134.     free(thePic.pm_image);
  135.     return( pmError(bname, "file read error") );
  136.   }
  137.  
  138.  
  139.   /* alloc and read in comment, if any */
  140.   if (thePic.pm_cmtsize>0) {
  141.     thePic.pm_cmt = (char *) malloc((size_t) thePic.pm_cmtsize+1);
  142.     if (thePic.pm_cmt) {
  143.       thePic.pm_cmt[thePic.pm_cmtsize] = '\0';  /* to be safe */
  144.       if (fread(thePic.pm_cmt,(size_t) thePic.pm_cmtsize,(size_t) 1,fp) != 1) {
  145.     free(thePic.pm_cmt);
  146.     thePic.pm_cmt = (char *) NULL;
  147.       }
  148.     }
  149.   }
  150.    
  151.   fclose(fp);
  152.  
  153.  
  154.   if (thePic.pm_form == PM_I) {
  155.     int  *intptr;
  156.     byte *pic24, *picptr;
  157.  
  158.     if ((pic24 = (byte *) malloc((size_t) w*h*3))==NULL) {
  159.       if (thePic.pm_cmt) free(thePic.pm_cmt);
  160.       return( pmError(bname, "unable to malloc 24-bit picture") );
  161.     }
  162.       
  163.     intptr = (int *) thePic.pm_image;
  164.     picptr = pic24;
  165.  
  166.     if (flipit) {    /* if flipit, integer is RRGGBBAA instead of AABBGGRR */
  167.       for (i=w*h; i>0; i--, intptr++) {
  168.     if ((i & 0x3fff) == 0) WaitCursor();
  169.     *picptr++ = (*intptr>>24) & 0xff;
  170.     *picptr++ = (*intptr>>16) & 0xff;
  171.     *picptr++ = (*intptr>>8)  & 0xff;
  172.       }
  173.     }
  174.     else {
  175.       for (i=w*h; i>0; i--, intptr++) {
  176.     if ((i & 0x3fff) == 0) WaitCursor();
  177.     *picptr++ = (*intptr)     & 0xff;
  178.     *picptr++ = (*intptr>>8)  & 0xff;
  179.     *picptr++ = (*intptr>>16) & 0xff;
  180.       }
  181.     }
  182.  
  183.     free(thePic.pm_image);
  184.  
  185.     pinfo->pic  = pic24;
  186.     pinfo->type = PIC24;
  187.   }
  188.  
  189.  
  190.   else if (thePic.pm_form == PM_C && thePic.pm_np>1) {
  191.     byte *pic24, *picptr, *rptr, *gptr, *bptr;
  192.  
  193.     if ((pic24 = (byte *) malloc((size_t) w*h*3))==NULL) {
  194.       if (thePic.pm_cmt) free(thePic.pm_cmt);
  195.       return( pmError(bname, "unable to malloc 24-bit picture") );
  196.     }
  197.  
  198.     rptr = (byte *) thePic.pm_image;
  199.     gptr = rptr + w*h;
  200.     bptr = rptr + w*h*2;
  201.     picptr = pic24;
  202.     for (i=w*h; i>0; i--) {
  203.       if ((i & 0x3fff) == 0) WaitCursor();
  204.       *picptr++ = *rptr++;
  205.       *picptr++ = *gptr++;
  206.       *picptr++ = *bptr++;
  207.     }
  208.     free(thePic.pm_image);
  209.  
  210.     pinfo->pic  = pic24;
  211.     pinfo->type = PIC24;
  212.   }
  213.   
  214.  
  215.   else if (thePic.pm_form == PM_C && thePic.pm_np==1) {
  216.     /* don't have to convert, just point pic at thePic.pm_image */
  217.     pic8 = (byte *) thePic.pm_image;
  218.     for (i=0; i<256; i++) 
  219.       pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i;  /* build mono cmap */
  220.  
  221.     pinfo->pic  = pic8;
  222.     pinfo->type = PIC8;
  223.   }
  224.  
  225.  
  226.   /* load up remaining pinfo fields */
  227.   pinfo->w = thePic.pm_ncol;  pinfo->h = thePic.pm_nrow;
  228.   pinfo->normw = pinfo->w;   pinfo->normh = pinfo->h;
  229.  
  230.   pinfo->frmType = F_PM;
  231.   pinfo->colType = (thePic.pm_form==PM_I || thePic.pm_np>1) 
  232.                          ? F_FULLCOLOR : F_GREYSCALE;
  233.   sprintf(pinfo->fullInfo,"PM, %s.  (%d plane %s)  (%ld bytes)",
  234.       (thePic.pm_form==PM_I || thePic.pm_np>1) 
  235.             ? "24-bit color" : "8-bit greyscale",
  236.       thePic.pm_np, (thePic.pm_form==PM_I) ? "PM_I" : "PM_C",
  237.       isize + PM_IOHDR_SIZE + thePic.pm_cmtsize);
  238.  
  239.   sprintf(pinfo->shrtInfo, "%dx%d PM.", w,h);
  240.   pinfo->comment = thePic.pm_cmt;
  241.  
  242.   return 1;
  243. }
  244.  
  245.  
  246. /*******************************************/
  247. int WritePM(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle,
  248.         comment)
  249.      FILE *fp;
  250.      byte *pic;
  251.      int   ptype,w,h;
  252.      byte *rmap, *gmap, *bmap;
  253.      int   numcols, colorstyle;
  254.      char *comment;
  255. {
  256.   /* writes a PM file to the already open stream
  257.      'colorstyle' single-handedly determines the type of PM pic written
  258.      if colorstyle==0, (Full Color) a 3-plane PM_C pic is written
  259.      if colorstyle==1, (Greyscal) a 1-plane PM_C pic is written
  260.      if colorstyle==0, (B/W stipple) a 1-plane PM_C pic is written */
  261.  
  262.   char  foo[256];
  263.   int   i;
  264.   byte *p;
  265.  
  266.   /* create 'comment' field */
  267.   sprintf(foo,"CREATOR: XV %s\n", REVDATE);
  268.  
  269.   /* fill in fields of a pmheader */
  270.   thePic.pm_id = PM_MAGICNO;
  271.   thePic.pm_np = (colorstyle==0) ? 3 : 1;
  272.   thePic.pm_ncol = w;
  273.   thePic.pm_nrow = h;
  274.   thePic.pm_nband = 1;
  275.   thePic.pm_form  = PM_C;
  276.   thePic.pm_cmtsize = (strlen(foo) + 1);   /* +1 to write trailing '\0' */
  277.   if (comment) thePic.pm_cmtsize += (strlen(comment) + 1);
  278.  
  279.   putint32(thePic.pm_id, fp);
  280.   putint32(thePic.pm_np, fp);
  281.   putint32(thePic.pm_nrow, fp);
  282.   putint32(thePic.pm_ncol, fp);
  283.   putint32(thePic.pm_nband, fp);
  284.   putint32(thePic.pm_form, fp);
  285.   putint32(thePic.pm_cmtsize, fp);
  286.  
  287.   /* write the picture data */
  288.   if (colorstyle == 0) {         /* 24bit RGB, organized as 3 8bit planes */
  289.  
  290.     if (ptype == PIC8) {
  291.       WaitCursor();
  292.       for (i=0,p=pic; i<w*h; i++, p++) putc(rmap[*p], fp);
  293.  
  294.       WaitCursor();
  295.       for (i=0,p=pic; i<w*h; i++, p++) putc(gmap[*p], fp);
  296.  
  297.       WaitCursor();
  298.       for (i=0,p=pic; i<w*h; i++, p++) putc(bmap[*p], fp);
  299.     }
  300.  
  301.     else {  /* PIC24 */
  302.       WaitCursor();
  303.       for (i=0,p=pic; i<w*h; i++, p+=3) putc(*p, fp);
  304.  
  305.       WaitCursor();
  306.       for (i=0,p=pic+1; i<w*h; i++, p+=3) putc(*p, fp);
  307.  
  308.       WaitCursor();
  309.       for (i=0,p=pic+2; i<w*h; i++, p+=3) putc(*p, fp);
  310.     }
  311.   }
  312.  
  313.  
  314.   else if (colorstyle == 1) {    /* GreyScale: 8 bits per pixel */
  315.     byte rgb[256];
  316.     
  317.     if (ptype == PIC8) {
  318.       for (i=0; i<numcols; i++) rgb[i] = MONO(rmap[i],gmap[i],bmap[i]);
  319.       for (i=0, p=pic; i<w*h; i++, p++) {
  320.     if ((i & 0x3fff) == 0) WaitCursor();
  321.     putc(rgb[*p],fp);
  322.       }
  323.     }
  324.     else {  /* PIC24 */
  325.       for (i=0, p=pic; i<w*h; i++, p+=3) {
  326.     if ((i & 0x3fff) == 0) WaitCursor();
  327.     putc( MONO(p[0],p[1],p[2]), fp);
  328.       }
  329.     }
  330.   }
  331.  
  332.   else /* (colorstyle == 2) */ { /* B/W stipple.  pic is 1's and 0's */
  333.     /* note: pic has already been dithered into 8-bit image */
  334.     for (i=0, p=pic; i<w*h; i++, p++) {
  335.       if ((i & 0x3fff) == 0) WaitCursor();
  336.       putc(*p ? 255 : 0,fp);
  337.     }
  338.   }
  339.  
  340.   if (comment) {
  341.     fwrite(comment, (size_t) strlen(comment), (size_t) 1, fp);
  342.     fwrite("\n",    (size_t) 1,               (size_t) 1, fp);
  343.   }
  344.   fwrite(foo, strlen(foo) + 1, (size_t) 1, fp);  /* +1 for trailing '\0' */
  345.  
  346.   if (ferror(fp)) return -1;
  347.  
  348.   return 0;
  349. }
  350.  
  351.  
  352. /*****************************/
  353. static int pmError(fname, st)
  354.      char *fname, *st;
  355. {
  356.   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
  357.   if (thePic.pm_image != NULL) free(thePic.pm_image);
  358.   return 0;
  359. }
  360.  
  361.  
  362. /*****************************/
  363. static int flip4(i)
  364.      int i;
  365. {
  366.   /* flips low-order 4 bytes around in integer */
  367.  
  368.   byte b0, b1, b2, b3;
  369.   int  rv;
  370.  
  371.   b0 = (((u_long) i)) & 0xff;
  372.   b1 = (((u_long) i) >>  8) & 0xff;
  373.   b2 = (((u_long) i) >> 16) & 0xff;
  374.   b3 = (((u_long) i) >> 24) & 0xff;
  375.  
  376.   rv = (((u_long) b0) << 24) |
  377.        (((u_long) b1) << 16) |
  378.        (((u_long) b2) <<  8) |
  379.        (((u_long) b3));
  380.  
  381.   return rv;
  382. }
  383.  
  384.  
  385.  
  386. static int getint32(fp)
  387.      FILE *fp;
  388. {
  389.   int i;
  390.  
  391.   i  = (getc(fp) & 0xff) << 24;
  392.   i |= (getc(fp) & 0xff) << 16;
  393.   i |= (getc(fp) & 0xff) << 8;
  394.   i |= (getc(fp) & 0xff);
  395.  
  396.   return i;
  397. }
  398.  
  399.  
  400.  
  401. static void putint32(i, fp)
  402.      int   i;
  403.      FILE *fp;
  404. {
  405.   putc( ((i>>24) & 0xff), fp);
  406.   putc( ((i>>16) & 0xff), fp);
  407.   putc( ((i>> 8) & 0xff), fp);
  408.   putc( ((i) & 0xff), fp);
  409. }
  410.  
  411.  
  412.