home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / gbmsrc.zip / gbmpgm.c < prev    next >
C/C++ Source or Header  |  1999-01-22  |  5KB  |  240 lines

  1. /*
  2.  
  3. gbmpgm.C - Poskanzers PGM format
  4.  
  5. Reads as 8 bit grey image.
  6. Writes grey equivelent of passed in 8 bit colour data (no palette written).
  7. Output options: r,g,b,k (default: k)
  8.  
  9. */
  10.  
  11. /*...sincludes:0:*/
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. #include <stddef.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <memory.h>
  18. #include <malloc.h>
  19. #include "gbm.h"
  20. #include "gbmhelp.h"
  21.  
  22. /*...vgbm\46\h:0:*/
  23. /*...vgbmhelp\46\h:0:*/
  24. /*...e*/
  25.  
  26. /*...suseful:0:*/
  27. #define    low_byte(w)    ((byte)  ((w)&0x00ff)    )
  28. #define    high_byte(w)    ((byte) (((w)&0xff00)>>8))
  29. #define    make_word(a,b)    (((word)a) + (((word)b) << 8))
  30. /*...e*/
  31. /*...smake_output_palette:0:*/
  32. #define    SW4(a,b,c,d)    ((a)*8+(b)*4+(c)*2+(d))
  33.  
  34. static BOOLEAN make_output_palette(const GBMRGB gbmrgb[], byte grey[], const char *opt)
  35.     {
  36.     BOOLEAN    k = ( gbm_find_word(opt, "k") != NULL );
  37.     BOOLEAN    r = ( gbm_find_word(opt, "r") != NULL );
  38.     BOOLEAN    g = ( gbm_find_word(opt, "g") != NULL );
  39.     BOOLEAN    b = ( gbm_find_word(opt, "b") != NULL );
  40.     int i;
  41.  
  42.     switch ( SW4(k,r,g,b) )
  43.         {
  44.         case SW4(0,0,0,0):
  45.             /* Default is the same as "k" */
  46.         case SW4(1,0,0,0):
  47.             for ( i = 0; i < 0x100; i++ )
  48.                 grey[i] = (byte) ( ((word) gbmrgb[i].r *  77U +
  49.                             (word) gbmrgb[i].g * 150U +
  50.                             (word) gbmrgb[i].b *  29U) >> 8 );
  51.             return TRUE;
  52.         case SW4(0,1,0,0):
  53.             for ( i = 0; i < 0x100; i++ )
  54.                 grey[i] = gbmrgb[i].r;
  55.             return TRUE;
  56.         case SW4(0,0,1,0):
  57.             for ( i = 0; i < 0x100; i++ )
  58.                 grey[i] = gbmrgb[i].g;
  59.             return TRUE;
  60.         case SW4(0,0,0,1):
  61.             for ( i = 0; i < 0x100; i++ )
  62.                 grey[i] = gbmrgb[i].b;
  63.             return TRUE;
  64.         }
  65.     return FALSE;
  66.     }
  67. /*...e*/
  68. /*...sposk stuff:0:*/
  69. /*...sread_byte:0:*/
  70. static byte read_byte(int fd)
  71.     {
  72.     byte b = 0;
  73.     gbm_file_read(fd, (char *) &b, 1);
  74.     return b;
  75.     }
  76. /*...e*/
  77. /*...sread_char:0:*/
  78. static char read_char(int fd)
  79.     {
  80.     char c;
  81.     while ( (c = read_byte(fd)) == '#' )
  82.         /* Discard to end of line */
  83.         while ( (c = read_byte(fd)) != '\n' )
  84.             ;
  85.     return c;
  86.     }
  87. /*...e*/
  88. /*...sread_num:0:*/
  89. static int read_num(int fd)
  90.     {
  91.     char c;
  92.     int num;
  93.  
  94.     while ( isspace(c = read_char(fd)) )
  95.         ;
  96.     num = c - '0';
  97.     while ( isdigit(c = read_char(fd)) )
  98.         num = num * 10 + (c - '0');
  99.     return num;
  100.     }
  101. /*...e*/
  102. /*...sread_posk_header:0:*/
  103. static void read_posk_header(int fd, int *h1, int *h2, int *w, int *h, int *m)
  104.     {
  105.     gbm_file_lseek(fd, 0, SEEK_SET);
  106.     *h1 = read_byte(fd);
  107.     *h2 = read_byte(fd);
  108.     *w  = read_num(fd);
  109.     *h  = read_num(fd);
  110.     *m  = read_num(fd);
  111.     }
  112. /*...e*/
  113. /*...e*/
  114.  
  115. static GBMFT pgm_gbmft =
  116.     {
  117.     "Greymap",
  118.     "Portable Greyscale-map (binary P5 type)",
  119.     "PGM",
  120.     GBM_FT_R8|
  121.     GBM_FT_W8,
  122.     };
  123.  
  124. #define    GBM_ERR_PGM_BAD_M    ((GBM_ERR) 100)
  125.  
  126. /*...spgm_qft:0:*/
  127. GBM_ERR pgm_qft(GBMFT *gbmft)
  128.     {
  129.     *gbmft = pgm_gbmft;
  130.     return GBM_ERR_OK;
  131.     }
  132. /*...e*/
  133. /*...spgm_rhdr:0:*/
  134. GBM_ERR pgm_rhdr(const char *fn, int fd, GBM *gbm, const char *opt)
  135.     {
  136.     int    h1, h2, w, h, m;
  137.  
  138.     fn=fn; opt=opt; /* Suppress 'unref arg' compiler warnings */
  139.  
  140.     read_posk_header(fd, &h1, &h2, &w, &h, &m);
  141.     if ( h1 != 'P' || h2 != '5' )
  142.         return GBM_ERR_BAD_MAGIC;
  143.  
  144.     if ( w <= 0 || h <= 0 )
  145.         return GBM_ERR_BAD_SIZE;
  146.  
  147.     if ( m <= 1 || m >= 0x100 )
  148.         return GBM_ERR_PGM_BAD_M;
  149.  
  150.     gbm->w   = w;
  151.     gbm->h   = h;
  152.     gbm->bpp = 8;
  153.  
  154.     return GBM_ERR_OK;
  155.     }
  156. /*...e*/
  157. /*...spgm_rpal:0:*/
  158. GBM_ERR pgm_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
  159.     {
  160.     int    h1, h2, w, h, m, i;
  161.  
  162.     gbm=gbm; /* Suppress 'unref arg' compiler warning */
  163.  
  164.     read_posk_header(fd, &h1, &h2, &w, &h, &m);
  165.     for ( i = 0; i <= m; i++ )
  166.         gbmrgb[i].r =
  167.         gbmrgb[i].g =
  168.         gbmrgb[i].b = (byte) (i * 0xff / m);
  169.  
  170.     return GBM_ERR_OK;
  171.     }
  172. /*...e*/
  173. /*...spgm_rdata:0:*/
  174. GBM_ERR pgm_rdata(int fd, GBM *gbm, byte *data)
  175.     {
  176.     int    h1, h2, w, h, m, i, stride;
  177.     byte    *p;
  178.  
  179.     read_posk_header(fd, &h1, &h2, &w, &h, &m);
  180.  
  181.     stride = ((gbm->w + 3) & ~3);
  182.     p = data + ((gbm->h - 1) * stride);
  183.     for ( i = gbm->h - 1; i >= 0; i-- )
  184.         {
  185.         gbm_file_read(fd, p, gbm->w);
  186.         p -= stride;
  187.         }
  188.     return GBM_ERR_OK;
  189.     }
  190. /*...e*/
  191. /*...spgm_w:0:*/
  192. GBM_ERR pgm_w(const char *fn, int fd, const GBM *gbm, const GBMRGB *gbmrgb, const byte *data, const char *opt)
  193.     {
  194.     char s[100+1];
  195.     int i, j, stride;
  196.     byte grey[0x100];
  197.     const byte *p;
  198.     byte *linebuf;
  199.  
  200.     fn=fn; opt=opt; /* Suppress 'unref arg' compiler warnings */
  201.  
  202.     if ( gbm->bpp != 8 )
  203.         return GBM_ERR_NOT_SUPP;
  204.  
  205.     if ( !make_output_palette(gbmrgb, grey, opt) )
  206.         return GBM_ERR_BAD_OPTION;
  207.  
  208.     if ( (linebuf = malloc((size_t) gbm->w)) == NULL )
  209.         return GBM_ERR_MEM;
  210.  
  211.     sprintf(s, "P5\n%d %d\n255\n", gbm->w, gbm->h);
  212.     gbm_file_write(fd, s, (int) strlen(s));
  213.  
  214.     stride = ((gbm->w + 3) & ~3);
  215.     p = data + ((gbm->h - 1) * stride);
  216.     for ( i = gbm->h - 1; i >= 0; i-- )
  217.         {
  218.         for ( j = 0; j < gbm->w; j++ )
  219.             linebuf[j] = grey[p[j]];
  220.         gbm_file_write(fd, linebuf, gbm->w);
  221.         p -= stride;
  222.         }
  223.  
  224.     free(linebuf);
  225.  
  226.     return GBM_ERR_OK;
  227.     }
  228. /*...e*/
  229. /*...spgm_err:0:*/
  230. const char *pgm_err(GBM_ERR rc)
  231.     {
  232.     switch ( (int) rc )
  233.         {
  234.         case GBM_ERR_PGM_BAD_M:
  235.             return "bad maximum pixel intensity";
  236.         }
  237.     return NULL;
  238.     }
  239. /*...e*/
  240.