home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / rexx / library2 / gbmrexx / gbm / gbmpix.c < prev    next >
C/C++ Source or Header  |  1993-02-19  |  9KB  |  369 lines

  1. /*
  2.  
  3. GBMPIX.C  Per-Pixel manipulation of General Bitmap
  4.  
  5. */
  6.  
  7. /*...sincludes:0:*/
  8. #include <stdio.h>
  9. #include <ctype.h>
  10. #include <math.h>
  11. #include <string.h>
  12. #include <stddef.h>
  13. #include <stdlib.h>
  14. #include <stdarg.h>
  15. #include <memory.h>
  16. #include <malloc.h>
  17. #ifdef AIX
  18. #include <unistd.h>
  19. #else
  20. #include <io.h>
  21. #endif
  22. #include <fcntl.h>
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #ifndef O_BINARY
  26. #define    O_BINARY    0
  27. #endif
  28. #include "standard.h"
  29. #include "gbm.h"
  30.  
  31. /*...vgbm\46\h:0:*/
  32. /*...e*/
  33.  
  34. static char progname [] = "gbmpix";
  35. static char sccs_id [] = "@(#)Per-Pixel Manipulation of General Bitmap  1/3/93";
  36.  
  37. /*...sfatal:0:*/
  38. static void fatal(const char *fmt, ...)
  39.     {
  40.     va_list    vars;
  41.     char    s [256+1];
  42.  
  43.     va_start(vars, fmt);
  44.     vsprintf(s, fmt, vars);
  45.     va_end(vars);
  46.     fprintf(stderr, "%s: %s\n", progname, s);
  47.     exit(1);
  48.     }
  49. /*...e*/
  50. /*...susage:0:*/
  51. static void usage(void)
  52.     {
  53.     int    ft, n_ft;
  54.  
  55.     fprintf(stderr, "usage: %s [-m map] fn1.ext{,opt} [fn2.ext{,opt}]\n", progname);
  56.     fprintf(stderr, "flags: -m map         mapping to perform per-pixel\n");
  57.     fprintf(stderr, "                      invert    pixel colours are inverted (default)\n");
  58.     fprintf(stderr, "                      mulR:G:B  multiply red by R, green by G, blue by B\n");
  59.     fprintf(stderr, "                      l  L* cyclometric linear perceived intensitys (as in PM)\n");
  60.     fprintf(stderr, "       fn1.ext{,opt}  input filename (with any format specific options)\n");
  61.     fprintf(stderr, "       fn2.ext{,opt}  optional output filename (or will use fn1 if not present)\n");
  62.     fprintf(stderr, "                      ext's are used to deduce desired bitmap file formats\n");
  63.  
  64.     gbm_init();
  65.     gbm_query_n_filetypes(&n_ft);
  66.     for ( ft = 0; ft < n_ft; ft++ )
  67.         {
  68.         GBMFT gbmft;
  69.  
  70.         gbm_query_filetype(ft, &gbmft);
  71.         fprintf(stderr, "                      %s when ext in [%s]\n",
  72.             gbmft.short_name, gbmft.extensions);
  73.         }
  74.     gbm_deinit();
  75.  
  76.     fprintf(stderr, "       opt's          bitmap format specific options\n");
  77.  
  78.     exit(1);
  79.     }
  80. /*...e*/
  81. /*...sget_opt_double:0:*/
  82. static double get_opt_double(char *s, char *name)
  83.     {
  84.     double    v;
  85.  
  86.     if ( s == NULL )
  87.         fatal("missing %s argument", name);
  88.     sscanf(s, "%lf", &v);
  89.  
  90.     return ( v );
  91.     }
  92. /*...e*/
  93. /*...ssame:0:*/
  94. static BOOLEAN same(char *s1, char *s2, int n)
  95.     {
  96.     for ( ; n--; s1++, s2++ )
  97.         if ( tolower(*s1) != tolower(*s2) )
  98.             return ( FALSE );
  99.     return ( TRUE );
  100.     }
  101. /*...e*/
  102. /*...smain:0:*/
  103. /*...smapinfos:0:*/
  104. #define    CVT_NONE    0
  105. #define    CVT_I_TO_P    1
  106. #define    CVT_P_TO_I    2
  107. #define    CVT_I_TO_L    3
  108. #define    CVT_L_TO_I    4
  109. #define    CVT_P_TO_L    5
  110. #define    CVT_L_TO_P    6
  111.  
  112. typedef struct { char *name; int m; } MAPINFO;
  113.  
  114. static MAPINFO mapinfos [] =
  115.     {
  116.     "none",        CVT_NONE,
  117.     "i_to_p",    CVT_I_TO_P,
  118.     "p_to_i",    CVT_P_TO_I,
  119.     "i_to_l",    CVT_I_TO_L,
  120.     "l_to_i",    CVT_L_TO_I,
  121.     "p_to_l",    CVT_P_TO_L,
  122.     "l_to_p",    CVT_L_TO_P,
  123.     };
  124.  
  125. #define    N_MAPINFOS    (sizeof(mapinfos)/sizeof(mapinfos [0]))
  126. /*...e*/
  127.  
  128. /*...smap_compute:0:*/
  129. /*...slstar_from_i:0:*/
  130. static double lstar_from_i(double y)
  131.     {
  132.     y = pow(1.16 * y, 1.0/3.0) - 0.16;
  133.  
  134.     if ( y < 0.0 ) y = 0.0; else if ( y > 1.0 ) y = 1.0;
  135.  
  136.     return ( y );
  137.     }
  138. /*...e*/
  139. /*...si_from_lstar:0:*/
  140. static double i_from_lstar(double y)
  141.     {
  142.     y = pow(y + 0.16, 3.0) / 1.16;
  143.  
  144.     if ( y < 0.0 ) y = 0.0; else if ( y > 1.0 ) y = 1.0;
  145.  
  146.     return ( y );
  147.     }
  148. /*...e*/
  149. /*...spal_from_i:0:*/
  150. static double pal_from_i(double y, double gam, double shelf)
  151.     {
  152.     y = pow(y,1.0 / gam) * (1.0 - shelf) + shelf;
  153.  
  154.     if ( y < 0.0 ) y = 0.0; else if ( y > 1.0 ) y = 1.0;
  155.  
  156.     return ( y );
  157.     }
  158. /*...e*/
  159. /*...si_from_pal:0:*/
  160. static double i_from_pal(double y, double gam, double shelf)
  161.     {
  162.     if ( y >= shelf )
  163.         y = pow((y - shelf) / (1.0 - shelf), gam);
  164.     else
  165.         y = 0.0;
  166.  
  167.     if ( y < 0.0 ) y = 0.0; else if ( y > 1.0 ) y = 1.0;
  168.  
  169.     return ( y );
  170.     }
  171. /*...e*/
  172.  
  173. static void map_compute(int m, byte remap [], double gam, double shelf)
  174.     {
  175.     int    i;
  176.  
  177.     for ( i = 0; i < 0x100; i++ )
  178.         {
  179.         double y = (double) i / 255.0;
  180.  
  181.         switch ( m )
  182.             {
  183.             case CVT_I_TO_P: y = pal_from_i(y, gam, shelf); break;
  184.             case CVT_P_TO_I: y = i_from_pal(y, gam, shelf); break;
  185.             case CVT_I_TO_L: y = lstar_from_i(y); break;
  186.             case CVT_L_TO_I: y = i_from_lstar(y); break;
  187.             case CVT_P_TO_L: y = lstar_from_i(i_from_pal(y, gam, shelf)); break;
  188.             case CVT_L_TO_P: y = pal_from_i(i_from_lstar(y), gam, shelf); break;
  189.             }
  190.  
  191.         remap [i] = (byte) (y * 255.0);
  192.         }
  193.     }
  194. /*...e*/
  195. /*...smap_data:0:*/
  196. static void map_data(byte *data, int w, int h, byte remap [])
  197.     {
  198.     int stride = ((w * 3 + 3) & ~3);
  199.     int x, y;
  200.  
  201.     for ( y = 0; y < h; y++, data += stride )
  202.         for ( x = 0; x < w * 3; x++ )
  203.             data [x] = remap [data [x]];
  204.     }
  205. /*...e*/
  206. /*...smap_palette:0:*/
  207. static void map_palette(GBMRGB *gbmrgb, int npals, byte remap [])
  208.     {
  209.     for ( ; npals--; gbmrgb++ )
  210.         {
  211.         gbmrgb -> b = remap [gbmrgb -> b];
  212.         gbmrgb -> g = remap [gbmrgb -> g];
  213.         gbmrgb -> r = remap [gbmrgb -> r];
  214.         }
  215.     }
  216. /*...e*/
  217.  
  218. int    main(int argc, char *argv [])
  219.     {
  220.     char    fn_src [500+1], fn_dst [500+1], *opt_src, *opt_dst;
  221.     int    fd, ft_src, ft_dst, i, stride, bytes, flag, m;
  222.     GBM_ERR    rc;
  223.     GBMFT    gbmft;
  224.     GBM    gbm;
  225.     GBMRGB    gbmrgb [0x100];
  226.     byte    *data;
  227.     char    *map = "none";
  228.     byte    remap [0x100];
  229.     double gam = 2.1, shelf = 0.0;
  230.  
  231. /*...scommand line arguments:8:*/
  232. for ( i = 1; i < argc; i++ )
  233.     {
  234.     if ( argv [i][0] != '-' )
  235.         break;
  236.     switch ( argv [i][1] )
  237.         {
  238.         case 'm':
  239.             if ( ++i == argc )
  240.                 fatal("expected map argument");
  241.             map = argv [i];
  242.             break;
  243.         case 'g':
  244.             if ( ++i == argc ) usage();
  245.             gam = get_opt_double(argv [i], "gam");
  246.             if ( gam < 0.1 || gam > 10.0 )
  247.                 fatal("only gammas in the range 0.1 to 10.0 are sensible");
  248.             break;
  249.         case 's':
  250.             if ( ++i == argc ) usage();
  251.             shelf = get_opt_double(argv [i], "shelf");
  252.             break;
  253.         default:
  254.             usage();
  255.             break;
  256.         }
  257.     }
  258. /*...e*/
  259.  
  260. /*...sdeduce mapping and bits per pixel etc\46\:8:*/
  261. {
  262. int    j;
  263.  
  264. for ( j = 0; j < N_MAPINFOS; j++ )
  265.     if ( same(map, mapinfos [j].name, strlen(map) + 1) )
  266.         break;
  267. if ( j == N_MAPINFOS )
  268.     fatal("unrecognised mapping %s", map);
  269. m = mapinfos [j].m;
  270. }
  271. /*...e*/
  272.  
  273.     if ( i == argc )
  274.         usage();
  275.     strcpy(fn_src, argv [i++]);
  276.     strcpy(fn_dst, ( i == argc ) ? fn_src : argv [i++]);
  277.     if ( i < argc )
  278.         usage();
  279.  
  280.     if ( (opt_src = strchr(fn_src, ',')) != NULL )
  281.         *opt_src++ = '\0';
  282.     else
  283.         opt_src = "";
  284.  
  285.     if ( (opt_dst = strchr(fn_dst, ',')) != NULL )
  286.         *opt_dst++ = '\0';
  287.     else
  288.         opt_dst = "";
  289.  
  290.     gbm_init();
  291.  
  292.     if ( gbm_guess_filetype(fn_src, &ft_src) != GBM_ERR_OK )
  293.         fatal("can't guess bitmap file format for %s", fn_src);
  294.  
  295.     if ( gbm_guess_filetype(fn_dst, &ft_dst) != GBM_ERR_OK )
  296.         fatal("can't guess bitmap file format for %s", fn_dst);
  297.  
  298.     if ( (fd = open(fn_src, O_RDONLY | O_BINARY)) == -1 )
  299.         fatal("can't open %s", fn_src);
  300.  
  301.     if ( (rc = gbm_read_header(fn_src, fd, ft_src, &gbm, opt_src)) != GBM_ERR_OK )
  302.         {
  303.         close(fd);
  304.         fatal("can't read header of %s: %s", fn_src, gbm_err(rc));
  305.         }
  306.  
  307.     gbm_query_filetype(ft_dst, &gbmft);
  308.     switch ( gbm.bpp )
  309.         {
  310.         case 24:    flag = GBM_FT_W24;    break;
  311.         case 8:        flag = GBM_FT_W8;    break;
  312.         case 4:        flag = GBM_FT_W4;    break;
  313.         case 1:        flag = GBM_FT_W1;    break;
  314.         }
  315.     if ( (gbmft.flags & flag) == 0 )
  316.         {
  317.         close(fd);
  318.         fatal("output bitmap format %s does not support writing %d bpp data",
  319.             gbmft.short_name, gbm.bpp);
  320.         }
  321.  
  322.     if ( (rc = gbm_read_palette(fd, ft_src, &gbm, gbmrgb)) != GBM_ERR_OK )
  323.         {
  324.         close(fd);
  325.         fatal("can't read palette of %s: %s", fn_src, gbm_err(rc));
  326.         }
  327.  
  328.     stride = ( ((gbm.w * gbm.bpp + 31)/32) * 4 );
  329.     bytes = stride * gbm.h;
  330.     if ( (data = malloc(bytes)) == NULL )
  331.         {
  332.         close(fd);
  333.         fatal("out of memory allocating %d bytes for bitmap", bytes);
  334.         }
  335.  
  336.     if ( (rc = gbm_read_data(fd, ft_src, &gbm, data)) != GBM_ERR_OK )
  337.         {
  338.         close(fd);
  339.         fatal("can't read bitmap data of %s: %s", fn_src, gbm_err(rc));
  340.         }
  341.  
  342.     close(fd);
  343.  
  344.     map_compute(m, remap, gam, shelf);
  345.  
  346.     if ( gbm.bpp == 24 )
  347.         map_data(data, gbm.w, gbm.h, remap);
  348.     else
  349.         map_palette(gbmrgb, 1 << gbm.bpp, remap);
  350.  
  351.     if ( (fd = open(fn_dst, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, S_IREAD | S_IWRITE)) == -1 )
  352.         fatal("can't create %s", fn_dst);
  353.  
  354.     if ( (rc = gbm_write(fn_dst, fd, ft_dst, &gbm, gbmrgb, data, opt_dst)) != GBM_ERR_OK )
  355.         {
  356.         close(fd);
  357.         fatal("can't write %s: %s", fn_dst, gbm_err(rc));
  358.         }
  359.  
  360.     close(fd);
  361.  
  362.     free(data);
  363.  
  364.     gbm_deinit();
  365.  
  366.     return ( 0 );
  367.     }
  368. /*...e*/
  369.