home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / asupsample.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  9.2 KB  |  342 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * General, non-jittered adaptive supersampling library
  5.  * Copyright (C) 1997 Federico Mena Quintero
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20.  *
  21.  */
  22.  
  23.  
  24. /* This code is *largely* based on the sources for POV-Ray 3.0.  I am
  25.  * grateful to the POV-Team for such a great program and for making
  26.  * their sources available.  All comments / bug reports /
  27.  * etc. regarding this library should be addressed to me, not to the
  28.  * POV-Ray team.  Any bugs are my responsibility, not theirs.
  29.  */
  30.  
  31. #include "config.h"
  32.  
  33. #include <math.h>
  34. #include <stdlib.h>
  35.  
  36. #include <gtk/gtk.h>
  37.  
  38. #include "apptypes.h"
  39.  
  40. #include "appenv.h"
  41. #include "asupsample.h"
  42.  
  43.  
  44. /***** Types *****/
  45.  
  46. typedef struct {
  47.     char    ready;
  48.     color_t color;
  49. } sample_t;
  50.  
  51.  
  52. /***** Local functions *****/
  53.  
  54. static unsigned long render_sub_pixel(int max_depth, int depth, sample_t **block,
  55.                       int x, int y, int x1, int y1, int x3, int y3,
  56.                       double threshold, int sub_pixel_size, render_func_t render_func,
  57.                       color_t *color, void *render_data);
  58.  
  59. static double color_dist(color_t c1, color_t c2);
  60.  
  61.  
  62. /***** Functions *****/
  63.  
  64. /*****/
  65.  
  66. unsigned long
  67. adaptive_supersample_area(int x1, int y1, int x2, int y2, int max_depth, double threshold,
  68.               render_func_t render_func, void *render_data,
  69.               put_pixel_func_t put_pixel_func, void *put_pixel_data,
  70.               progress_func_t progress_func, void *progress_data)
  71. {
  72.     int              x, y, width;                 /* Counters, width of region */
  73.     int              xt, xtt, yt;                 /* Temporary counters */
  74.     int              sub_pixel_size;              /* Numbe of samples per pixel (1D) */
  75.     size_t           row_size;                    /* Memory needed for one row */
  76.      color_t          color;                       /* Rendered pixel's color */
  77.     sample_t         tmp_sample;                  /* For swapping samples */
  78.     sample_t       *top_row, *bot_row, *tmp_row; /* Sample rows */
  79.     sample_t      **block;                       /* Sample block matrix */
  80.     unsigned long   num_samples;
  81.  
  82.     /* Initialize color */
  83.  
  84.     color.r = 0.0;
  85.     color.g = 0.0;
  86.     color.b = 0.0;
  87.     color.a = 0.0;
  88.  
  89.     /* Calculate sub-pixel size */
  90.  
  91.     sub_pixel_size = 1 << max_depth; /* 2**max_depth */
  92.  
  93.     /* Create row arrays */
  94.  
  95.     width = x2 - x1 + 1;
  96.  
  97.     row_size = (sub_pixel_size * width + 1) * sizeof(sample_t);
  98.  
  99.     top_row = g_malloc(row_size);
  100.     bot_row = g_malloc(row_size);
  101.  
  102.     for (x = 0; x < (sub_pixel_size * width + 1); x++) {
  103.         top_row[x].ready   = 0;
  104.         
  105.         top_row[x].color.r = 0.0;
  106.         top_row[x].color.g = 0.0;
  107.         top_row[x].color.b = 0.0;
  108.         top_row[x].color.a = 0.0;
  109.  
  110.         bot_row[x].ready   = 0;
  111.         
  112.         bot_row[x].color.r = 0.0;
  113.         bot_row[x].color.g = 0.0;
  114.         bot_row[x].color.b = 0.0;
  115.         bot_row[x].color.a = 0.0;
  116.     } /* for */
  117.  
  118.     /* Allocate block matrix */
  119.  
  120.     block = g_malloc((sub_pixel_size + 1) * sizeof(sample_t *)); /* Rows */
  121.  
  122.     for (y = 0; y < (sub_pixel_size + 1); y++) {
  123.         block[y] = g_malloc((sub_pixel_size + 1) * sizeof(sample_t)); /* Columns */
  124.  
  125.         for (x = 0; x < (sub_pixel_size + 1); x++) {
  126.             block[y][x].ready = 0;
  127.  
  128.             block[y][x].color.r = 0;
  129.             block[y][x].color.g = 0;
  130.             block[y][x].color.b = 0;
  131.             block[y][x].color.a = 0;
  132.         }
  133.     }
  134.  
  135.     /* Render region */
  136.  
  137.     num_samples = 0;
  138.  
  139.     for (y = y1; y <= y2; y++) {
  140.         /* Clear the bottom row */
  141.  
  142.         for (xt = 0; xt < (sub_pixel_size * width + 1); xt++)
  143.             bot_row[xt].ready = 0;
  144.  
  145.         /* Clear first column */
  146.  
  147.         for (yt = 0; yt < (sub_pixel_size + 1); yt++)
  148.             block[yt][0].ready = 0;
  149.  
  150.         /* Render row */
  151.  
  152.         for (x = x1; x <= x2; x++) {
  153.             /* Initialize block by clearing all but first row/column */
  154.  
  155.             for (yt = 1; yt < (sub_pixel_size + 1); yt++)
  156.                 for (xt = 1; xt < (sub_pixel_size + 1); xt++)
  157.                     block[yt][xt].ready = 0;
  158.  
  159.             /* Copy samples from top row to block */
  160.  
  161.             for (xtt = 0, xt = (x - x1) * sub_pixel_size;
  162.                  xtt < (sub_pixel_size + 1);
  163.                  xtt++, xt++)
  164.                 block[0][xtt] = top_row[xt];
  165.  
  166.             /* Render pixel on (x, y) */
  167.  
  168.             num_samples += render_sub_pixel(max_depth, 1, block, x, y, 0, 0,
  169.                             sub_pixel_size, sub_pixel_size,
  170.                             threshold, sub_pixel_size, render_func, &color,
  171.                             render_data);
  172.  
  173.             if (put_pixel_func)
  174.                 (*put_pixel_func)(x, y, color, put_pixel_data);
  175.  
  176.             /* Copy block information to rows */
  177.  
  178.             top_row[((x - x1) + 1) * sub_pixel_size] = block[0][sub_pixel_size];
  179.  
  180.             for (xtt = 0, xt = (x - x1) * sub_pixel_size;
  181.                  xtt < (sub_pixel_size + 1);
  182.                  xtt++, xt++)
  183.                 bot_row[xt] = block[sub_pixel_size][xtt];
  184.  
  185.             /* Swap first and last columns */
  186.  
  187.             for (yt = 0; yt < (sub_pixel_size + 1); yt++) {
  188.                 tmp_sample             = block[yt][0];
  189.                 block[yt][0]           = block[yt][sub_pixel_size];
  190.                 block[yt][sub_pixel_size] = tmp_sample;
  191.             } /* for */
  192.         } /* for */
  193.  
  194.         /* Swap rows */
  195.  
  196.         tmp_row = top_row;
  197.         top_row = bot_row;
  198.         bot_row = tmp_row;
  199.  
  200.         /* Call progress display function */
  201.  
  202.         if (progress_func && !(y & 0xf))
  203.             (*progress_func)(y1, y2, y, progress_data);
  204.     } /* for */
  205.  
  206.     /* Free memory */
  207.  
  208.     for (y = 0; y < (sub_pixel_size + 1); y++)
  209.         g_free(block[y]);
  210.  
  211.     g_free(block);
  212.     g_free(top_row);
  213.     g_free(bot_row);
  214.  
  215.     return num_samples;
  216. } /* adaptive_supersample_area */
  217.  
  218.  
  219. /*****/
  220.  
  221. static unsigned long
  222. render_sub_pixel(int max_depth, int depth, sample_t **block,
  223.          int x, int y, int x1, int y1, int x3, int y3,
  224.          double threshold, int sub_pixel_size, render_func_t render_func,
  225.          color_t *color, void *render_data)
  226. {
  227.     int           x2, y2;   /* Coords of center sample */
  228.     double        dx1, dy1; /* Delta to upper left sample */
  229.     double        dx3, dy3; /* Delta to lower right sample */
  230.     color_t       c1, c2, c3, c4; /* Sample colors */
  231.     unsigned long num_samples;
  232.  
  233.     /* Get offsets for corners */
  234.  
  235.     dx1 = (double) (x1 - sub_pixel_size / 2) / sub_pixel_size;
  236.     dx3 = (double) (x3 - sub_pixel_size / 2) / sub_pixel_size;
  237.  
  238.     dy1 = (double) (y1 - sub_pixel_size / 2) / sub_pixel_size;
  239.     dy3 = (double) (y3 - sub_pixel_size / 2) / sub_pixel_size;
  240.  
  241.     num_samples = 0;
  242.  
  243.     /* Render upper left sample */
  244.  
  245.     if (!block[y1][x1].ready) {
  246.         num_samples++;
  247.         (*render_func)(x + dx1, y + dy1, &c1, render_data);
  248.  
  249.         block[y1][x1].ready = 1;
  250.         block[y1][x1].color = c1;
  251.     } else
  252.         c1 = block[y1][x1].color;
  253.  
  254.     /* Render upper right sample */
  255.  
  256.     if (!block[y1][x3].ready) {
  257.         num_samples++;
  258.         (*render_func)(x + dx3, y + dy1, &c2, render_data);
  259.  
  260.         block[y1][x3].ready = 1;
  261.         block[y1][x3].color = c2;
  262.     } else
  263.         c2 = block[y1][x3].color;
  264.  
  265.     /* Render lower left sample */
  266.  
  267.     if (!block[y3][x1].ready) {
  268.         num_samples++;
  269.         (*render_func)(x + dx1, y + dy3, &c3, render_data);
  270.  
  271.         block[y3][x1].ready = 1;
  272.         block[y3][x1].color = c3;
  273.     } else
  274.         c3 = block[y3][x1].color;
  275.  
  276.     /* Render lower right sample */
  277.  
  278.     if (!block[y3][x3].ready) {
  279.         num_samples++;
  280.         (*render_func)(x + dx3, y + dy3, &c4, render_data);
  281.  
  282.         block[y3][x3].ready = 1;
  283.         block[y3][x3].color = c4;
  284.     } else
  285.         c4 = block[y3][x3].color;
  286.  
  287.     /* Check for supersampling */
  288.  
  289.     if (depth <= max_depth) {
  290.         /* Check whether we have tu supersample */
  291.  
  292.         if ((color_dist(c1, c2) >= threshold) ||
  293.             (color_dist(c1, c3) >= threshold) ||
  294.             (color_dist(c1, c4) >= threshold) ||
  295.             (color_dist(c2, c3) >= threshold) ||
  296.             (color_dist(c2, c4) >= threshold) ||
  297.             (color_dist(c3, c4) >= threshold)) {
  298.             /* Calc coordinates of center subsample */
  299.  
  300.             x2 = (x1 + x3) / 2;
  301.             y2 = (y1 + y3) / 2;
  302.  
  303.             /* Render sub-blocks */
  304.  
  305.             num_samples += render_sub_pixel(max_depth, depth + 1, block, x, y, x1, y1, x2, y2,
  306.                             threshold, sub_pixel_size, render_func, &c1,
  307.                             render_data);
  308.  
  309.             num_samples += render_sub_pixel(max_depth, depth + 1, block, x, y, x2, y1, x3, y2,
  310.                             threshold, sub_pixel_size, render_func, &c2,
  311.                             render_data);
  312.  
  313.             num_samples += render_sub_pixel(max_depth, depth + 1, block, x, y, x1, y2, x2, y3,
  314.                             threshold, sub_pixel_size, render_func, &c3,
  315.                             render_data);
  316.  
  317.             num_samples += render_sub_pixel(max_depth, depth + 1, block, x, y, x2, y2, x3, y3,
  318.                             threshold, sub_pixel_size, render_func, &c4,
  319.                             render_data);
  320.         } /* if */
  321.     } /* if */
  322.  
  323.     color->r = 0.25 * (c1.r + c2.r + c3.r + c4.r);
  324.     color->g = 0.25 * (c1.g + c2.g + c3.g + c4.g);
  325.     color->b = 0.25 * (c1.b + c2.b + c3.b + c4.b);
  326.     color->a = 0.25 * (c1.a + c2.a + c3.a + c4.a);
  327.  
  328.     return num_samples;
  329. } /* render_sub_pixel */
  330.  
  331.  
  332. /*****/
  333.  
  334. static double
  335. color_dist(color_t c1, color_t c2)
  336. {
  337.     return fabs(c1.r - c2.r) +
  338.            fabs(c1.g - c2.g) +
  339.            fabs(c1.b - c2.b) +
  340.            fabs(c1.a - c2.a);
  341. } /* color_dist */
  342.