home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / bomb.tar.gz / bomb.tar / bomb / image.c < prev    next >
C/C++ Source or Header  |  1997-04-25  |  10KB  |  453 lines

  1. /*
  2.     bomb - automatic interactive visual stimulation
  3.     Copyright (C) 1994  Scott Draves <spot@cs.cmu.edu>
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. #include "defs.h"
  21. #include "image.h"
  22.  
  23. void
  24. image_fill(Image *image, Pixel v)
  25. {
  26.    int w = image->width;
  27.    int h = image->height;
  28.    Pixel *p = image->pixels;
  29.    int s = image->stride;
  30.    int i, j;
  31.    
  32.    for (i = 0; i < h; i++)
  33.       for (j = 0; j < w; j++)
  34.      p[i * s + j] = v;
  35. }
  36.  
  37. void
  38. image_random(Image *image)
  39. {
  40.    int w = image->width;
  41.    int h = image->height;
  42.    Pixel *p = image->pixels;
  43.    int s = image->stride;
  44.    int i, j;
  45.    
  46.    for (i = 0; i < h; i++)
  47.       for (j = 0; j < w; j++) {
  48.      Pixel x;
  49.      x.r = R; x.g = R; x.b = R;
  50.      x.a = 255;
  51.      p[i * s + j] = x;
  52.       }
  53. }
  54.  
  55.  
  56. /* next two functions stolen from readppm.c from photo widget.
  57.    shouldn't the dll of graphics formats have something for this,
  58.    then we can handle jpg too... */
  59.  
  60. static char *
  61. ppm_fgets(line, len, fp)
  62.     char *line;
  63.     int len;
  64.     FILE *fp;
  65. {
  66.     int incomment = 0;
  67.     int s, i = 0;
  68.     for(;;){
  69.         if (i == len - 1) {
  70.           line[i] = 0;
  71.           break;
  72.         }
  73.     if( -1 == (s = fgetc(fp))) {
  74.         return NULL;
  75.      }
  76.      if (s == '\n' || s == '\r') {
  77.         line[i] = 0;
  78.         break;
  79.       }
  80.       line[i++] = s;
  81.       
  82.     }
  83.     if ('#' == line[0])
  84.        return ppm_fgets(line, len, fp);
  85.     return line;
  86. }
  87.  
  88. static int
  89. read_hdr(fp, wp, hp)
  90.    FILE *fp;
  91.    int *wp, *hp;
  92. {
  93.     int pmax;
  94.     char line[64];
  95.     if (0 == fp) {
  96.        printf("bad file\n");
  97.        return 0;
  98.     }
  99.     if( ppm_fgets(line, sizeof(line), fp) == NULL
  100.        || strcmp(line, "P6") != 0 ) {
  101.     return 0;
  102.        }
  103.     if( ppm_fgets(line, sizeof(line), fp) == NULL
  104.        || sscanf(line, "%d%d", wp, hp) != 2 ) {
  105.     return 0;
  106.      }
  107.     if( ppm_fgets(line, sizeof(line), fp) == NULL
  108.        || sscanf(line, "%d", &pmax) != 1
  109.        || pmax != 255 ) {
  110.     return 0;
  111.       }
  112.     return 1;
  113. }
  114.  
  115. #define file_type_unknown 0
  116. #define file_type_ppm     1
  117. #define file_type_gif     2
  118. #define file_type_jpeg    3
  119. #define file_type_tiff    4
  120.  
  121. int
  122. file_type(FILE *fp)
  123. {
  124.    int r = file_type_unknown;
  125.    char buf[4];
  126.  
  127.    if (4 != fread(buf, 1, 4, fp))
  128.       goto done;
  129.    if (!strncmp("GIF", buf, 3))
  130.       r = file_type_gif;
  131.    else if (!strncmp("P6", buf, 2))
  132.       r = file_type_ppm;
  133.    else if (!strncmp("II", buf, 2) ||
  134.         !strncmp("JJ", buf, 2))
  135.       r = file_type_tiff;
  136.    else
  137.       r = file_type_jpeg; /* just guessing now */
  138.  done:
  139.    fseek(fp, 0, SEEK_SET);
  140.    return r;
  141. }
  142.  
  143. #include "tiffio.h"
  144.    
  145. /* should support jpeg */
  146.  
  147. int
  148. image_read(Image *image, char *file)
  149. {
  150.    FILE *fp;
  151.    int width, height;
  152.    int bytes_read;
  153.    int total_bytes;
  154.    int gifLoadBomb(Image *image, char *filename);
  155.  
  156.    fp = fopen(file, "r");
  157.    if (fp == NULL)
  158.       return TCL_ERROR;
  159.    switch (file_type(fp)) {
  160.  
  161.     case file_type_ppm:
  162.       if (!read_hdr(fp, &width, &height)) {
  163.          printf("bad header %s\n", file);
  164.      goto fail;
  165.     }
  166.       /* note ppm stores 3 bytes per pixel, we store 4.
  167.      so after we read it in, we have to insert gaps
  168.      for the alpha */
  169.       total_bytes = width * height * 3;
  170.       image = image_allocate(image, width, height);
  171.       if (NULL == image)
  172.          goto fail;
  173.       if (total_bytes != fread(image->pixels, 1, total_bytes, fp)) {
  174.          printf("short file %s\n", file);
  175.      goto fail;
  176.        }
  177.       fclose(fp);
  178.       
  179.       /* insert gaps, be careful at last pixel */
  180.       if (1) {
  181.      char *p = (char *) image->pixels;
  182.      int scan_ppm = total_bytes;
  183.      int scan_rgba = width * height * sizeof(Pixel);
  184.      while (scan_ppm) {
  185.         p[scan_rgba - 1] = alpha_solid;
  186.         p[scan_rgba - 2] = p[scan_ppm - 1];
  187.         p[scan_rgba - 3] = p[scan_ppm - 2];
  188.         p[scan_rgba - 4] = p[scan_ppm - 3];
  189.         scan_rgba -= 4;
  190.         scan_ppm -= 3;
  191.      }
  192.       }
  193.       break;
  194.       
  195.     case file_type_gif:
  196.       fclose(fp);
  197.       return gifLoadBomb(image, file);
  198.  
  199.     case file_type_tiff:
  200.       fclose(fp);
  201.       if (1) {
  202.      uint32 w, h;
  203.      uint32* raster;
  204.      size_t npixels;
  205. #if win_bomb
  206.      TIFF* tif = TIFFOpen(file, "rm");
  207. #else
  208.      TIFF* tif = TIFFOpen(file, "r");
  209. #endif
  210.      if (NULL == tif)
  211.         goto fail;
  212.  
  213.      TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
  214.      TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
  215.      image = image_allocate(image, w, h);
  216.      if (NULL == image)
  217.        goto fail;
  218.      npixels = w * h;
  219.      /* _TIFFmalloc(npixels * sizeof (uint32)); */
  220.      raster = (uint32*) image->pixels;
  221.      if (0 == TIFFReadRGBAImage(tif, w, h, raster, 0))
  222.         goto fail;
  223.        TIFFClose(tif); 
  224.      if (1) {
  225.         /* mirror top-bottom, permute channels */
  226.         int i, j;
  227.         for (j = 0; j < h/2; j++) {
  228.            Pixel *p1 = image->pixels + (j * image->stride);
  229.            Pixel *p2 = image->pixels + (((h-1) - j) * image->stride);
  230.            for (i = 0; i < w; i++) {
  231.           Pixel s, r, t;
  232.           t = p1[i];
  233.           s.r = t.g;
  234.           s.g = t.b;
  235.           s.b = t.a;
  236.           s.a = t.r;
  237.           t = p2[i];
  238.           r.r = t.g;
  239.           r.g = t.b;
  240.           r.b = t.a;
  241.           r.a = t.r;
  242.           p1[i] = r;
  243.           p2[i] = s;
  244.            }
  245.         }
  246.      }
  247.       }
  248.       break;
  249.  
  250.     case file_type_unknown:
  251.     case file_type_jpeg:
  252.       goto fail;
  253.    }
  254.       
  255.    return TCL_OK;
  256.  fail:
  257.    fclose(fp);
  258.    fprintf(stderr, "unable to read image: %s\n", file);
  259.    return TCL_ERROR;
  260. }
  261.  
  262. void
  263. image_destroy(Image* image)
  264. {
  265.    if (NULL != image->pixels &&
  266.        NULL == image->parent)
  267.       free(image->pixels);
  268.    free(image);
  269. }
  270.  
  271. void
  272. image_init(Image *image)
  273. {
  274.    image->width =
  275.       image->height = 0;
  276.    image->pixels = 0;
  277.    image->parent = 0;
  278. }
  279.  
  280. /* recycle passed in image and its storage if possible.
  281.    never returns a subimage */
  282. Image *
  283. image_allocate(Image *image, int w, int h)
  284. {
  285.    int total_bytes = (sizeof(Pixel)) * w * h;
  286.    if (NULL == image) {
  287.       image = (Image *) malloc(sizeof(Image));
  288.       image->pixels = (Pixel *) malloc(total_bytes);
  289.    } else if (w != image->width ||
  290.           h != image->height ||
  291.           NULL != image->parent) {
  292.       /* ugh, complex XXX */
  293.       if (NULL != image->pixels &&
  294.       NULL == image->parent)
  295.      free(image->pixels);
  296.       image->pixels = (Pixel *) malloc(total_bytes);
  297.    }
  298.    if (NULL == image->pixels)
  299.      return NULL;
  300.    image->width = w;
  301.    image->height = h;
  302.    image->stride = w;
  303.    image->origin_x = 0;
  304.    image->origin_y = 0;
  305.    return image;
  306. }
  307.  
  308. Image *
  309. image_subimage(Image *image, Image *of, int x, int y, int w, int h)
  310. {
  311.    if (NULL == image)
  312.       image = (Image *) malloc(sizeof(Image));
  313.    image->width = w;
  314.    image->height = h;
  315.    image->stride = of->stride;
  316.    image->pixels = of->pixels + of->stride * y + x;
  317.    /* eliminate hierarchy */
  318.    if (NULL == of->parent) {
  319.       image->origin_x = x;
  320.       image->origin_y = y;
  321.       image->parent = of;
  322.    } else {
  323.       image->origin_x = of->origin_x + x;
  324.       image->origin_y = of->origin_y + y;
  325.       image->parent = of->parent;
  326.    }
  327. #if 1
  328.    if (x + w > of->width)
  329.       fprintf(stderr, "x + w > of->width (%d + %d > %d)\n",
  330.           x, w, of->width);
  331.    if (y + h > of->height)
  332.       fprintf(stderr, "y + h > of->height (%d + %d > %d)\n",
  333.           y, h, of->height);
  334. #endif
  335.    return image;
  336. }
  337.  
  338.  
  339. /* if the requested size is larger than the image itself, then
  340.    the tile is silently truncated to fit */
  341.  
  342. Image *
  343. image_random_tile(Image *image, Image *of, int size)
  344. {
  345.    int x, y;
  346.    if (size >= of->width) {
  347.       size = of->width;
  348.       x = 0;
  349.    } else
  350.       x = R % (of->width - size);
  351.    if (size >= of->height) {
  352.       size = of->height;
  353.       y = 0;
  354.    } else
  355.       y = R % (of->height - size);
  356.    if (NULL == image)
  357.       image = (Image *) malloc(sizeof(Image));
  358.    image->width = size;
  359.    image->height = size;
  360.    image->stride = of->stride;
  361.    image->pixels = of->pixels + of->stride * y + x;
  362.    /* eliminate hierarchy */
  363.    if (NULL == of->parent) {
  364.       image->origin_x = x;
  365.       image->origin_y = y;
  366.       image->parent = of;
  367.    } else {
  368.       image->origin_x = of->origin_x + x;
  369.       image->origin_y = of->origin_y + y;
  370.       image->parent = of->parent;
  371.    }
  372.    return image;
  373. }
  374.  
  375. void
  376. image_mean_pixel(Image *img, Pixel *pix)
  377. {
  378.    int r, g, b, a;
  379.    Pixel p;
  380.    unsigned char *bytes = (unsigned char *) &p;
  381.    int i, j;
  382.    int npix;
  383.  
  384.    a = r = g = b = 0;
  385.    for (i = 0; i < img->height; i++)
  386.       for (j = 0; j < img->width; j++) {
  387.      p = img->pixels[img->stride * i + j];
  388.      r += bytes[0];
  389.      g += bytes[1];
  390.      b += bytes[2];
  391.      a += bytes[3];
  392.       }
  393.  
  394.    npix = img->width * img->height;
  395.  
  396.    bytes[0] = r / npix;
  397.    bytes[1] = g / npix;
  398.    bytes[2] = b / npix;
  399.    bytes[3] = a / npix;
  400.  
  401.    *pix = p;
  402. }
  403.    
  404.    
  405.  
  406. void
  407. image_filter_down(Image *from, Image *to)
  408. {
  409.    int h_scale = from->height / to->height;
  410.    int w_scale = from->width / to->width;
  411.    int i, j;
  412.    Pixel p;
  413.    int npix;
  414.  
  415.    npix = h_scale * w_scale;
  416.  
  417.    for (i = 0; i < to->height; i++)
  418.       for (j = 0; j < to->width; j++) {
  419.      int ii, jj;
  420.      int r, g, b, a;
  421.      a = r = g = b = 0;
  422.      for (ii = 0; ii < h_scale; ii++)
  423.         for (jj = 0; jj < w_scale; jj++) {
  424.            p = from->pixels[from->stride * (i * h_scale + ii) +
  425.                 (j * w_scale + jj)];
  426.            a += p.a;
  427.            r += p.r;
  428.            g += p.g;
  429.            b += p.b;
  430.         }
  431.      p.a = a / npix;
  432.      p.r = r / npix;
  433.      p.g = g / npix;
  434.      p.b = b / npix;
  435.      to->pixels[to->stride * i + j] = p;
  436.       }
  437. }
  438.   
  439.  
  440. /* and more complex arithmetic versions, with alpha */
  441. /* no overlap */
  442. void
  443. image_blit(Image *from, Image *to)
  444. {
  445.    Image f = *from;
  446.    Image t = *to;
  447.    int i, j;
  448.    for (i = 0; i < f.height; i++)
  449.       for (j = 0; j < f.width; j++)
  450.      t.pixels[t.stride * i + j] =
  451.         f.pixels[f.stride * i + j];
  452. }
  453.