home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / Lighting / lighting_image.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-24  |  8.0 KB  |  387 lines

  1. /*************************************/
  2. /* GIMP image manipulation routines. */
  3. /*************************************/
  4.  
  5. #include <gtk/gtk.h>
  6.  
  7. #include <libgimp/gimp.h>
  8.  
  9. #include <gck/gck.h>
  10.  
  11. #include "lighting_main.h"
  12. #include "lighting_image.h"
  13. #include "lighting_preview.h"
  14. #include "lighting_ui.h"
  15.  
  16. GimpDrawable *input_drawable,*output_drawable;
  17. GimpPixelRgn  source_region, dest_region;
  18.  
  19. GimpDrawable *bump_drawable = NULL;
  20. GimpPixelRgn  bump_region;
  21.  
  22. GimpDrawable *env_drawable = NULL;
  23. GimpPixelRgn  env_region;
  24.  
  25. guchar   *preview_rgb_data = NULL;
  26. GdkImage *image = NULL;
  27.  
  28. glong  maxcounter;
  29. gint   imgtype, width, height, env_width, env_height, in_channels, out_channels;
  30. GckRGB background;
  31.  
  32. gint border_x1, border_y1, border_x2, border_y2;
  33.  
  34. guchar sinemap[256], spheremap[256], logmap[256];
  35.  
  36. /******************/
  37. /* Implementation */
  38. /******************/
  39.  
  40. guchar
  41. peek_map (GimpPixelRgn *region,
  42.       gint       x,
  43.       gint       y)
  44. {
  45.   guchar data;
  46.  
  47.   gimp_pixel_rgn_get_pixel (region, &data, x, y);
  48.  
  49.   return data;
  50. }
  51.  
  52. GckRGB
  53. peek (gint x,
  54.       gint y)
  55. {
  56.   guchar data[4];
  57.   GckRGB color;
  58.  
  59.   gimp_pixel_rgn_get_pixel (&source_region,data, x, y);
  60.  
  61.   color.r = (gdouble) (data[0]) / 255.0;
  62.   color.g = (gdouble) (data[1]) / 255.0;
  63.   color.b = (gdouble) (data[2]) / 255.0;
  64.  
  65.   if (input_drawable->bpp == 4)
  66.     {
  67.       if (in_channels == 4)
  68.         color.a = (gdouble) (data[3]) / 255.0;
  69.       else
  70.         color.a = 1.0;
  71.     }
  72.   else
  73.     color.a = 1.0;
  74.  
  75.   return color;
  76. }
  77.  
  78. GckRGB
  79. peek_env_map (gint x,
  80.           gint y)
  81. {
  82.   guchar data[4];
  83.   GckRGB color;
  84.  
  85.   if (x < 0)
  86.     x = 0;
  87.   else if (x >= env_width)
  88.     x = env_width - 1;
  89.   if (y < 0)
  90.     y = 0;
  91.   else if (y >= env_height)
  92.     y = env_height - 1;
  93.  
  94.   gimp_pixel_rgn_get_pixel (&env_region, data, x, y);
  95.  
  96.   color.r = (gdouble) (data[0]) / 255.0;
  97.   color.g = (gdouble) (data[1]) / 255.0;
  98.   color.b = (gdouble) (data[2]) / 255.0;
  99.   color.a = 1.0;
  100.  
  101.   return color;
  102. }
  103.  
  104. void
  105. poke (gint    x,
  106.       gint    y,
  107.       GckRGB *color)
  108. {
  109.   static guchar data[4];
  110.  
  111.   if (x < 0)
  112.     x = 0;
  113.   else if (x >= width)
  114.     x = width - 1;
  115.   if (y < 0)
  116.     y = 0;
  117.   else if (y >= height)
  118.     y = height - 1;
  119.  
  120.   data[0] = (guchar) (color->r * 255.0);
  121.   data[1] = (guchar) (color->g * 255.0);
  122.   data[2] = (guchar) (color->b * 255.0);
  123.   data[3] = (guchar) (color->a * 255.0);
  124.  
  125.   gimp_pixel_rgn_set_pixel (&dest_region, data, x, y);
  126. }
  127.  
  128. gint
  129. check_bounds (gint x,
  130.           gint y)
  131. {
  132.   if (x < border_x1 || y < border_y1 || x >= border_x2 || y >= border_y2)
  133.     return FALSE;
  134.   else
  135.     return TRUE;
  136. }
  137.  
  138. GimpVector3
  139. int_to_pos (gint x,
  140.         gint y)
  141. {
  142.   GimpVector3 pos;
  143.  
  144.   if (width >= height)
  145.     {
  146.       pos.x = (gdouble) x / (gdouble) width;
  147.       pos.y = (gdouble) y / (gdouble) width;
  148.  
  149.       pos.y += 0.5 * (1.0 - (gdouble) height / (gdouble) width); 
  150.     }
  151.   else
  152.     {
  153.       pos.x = (gdouble) x / (gdouble) height;
  154.       pos.y = (gdouble) y / (gdouble) height;
  155.  
  156.       pos.x += 0.5 * (1.0 - (gdouble) width / (gdouble) height);
  157.     }
  158.  
  159.   pos.z = 0.0;
  160.   return pos;
  161. }
  162.  
  163. GimpVector3
  164. int_to_posf (gdouble x,
  165.          gdouble y)
  166. {
  167.   GimpVector3 pos;
  168.  
  169.   if (width >= height)
  170.     {
  171.       pos.x = x / (gdouble) width;
  172.       pos.y = y / (gdouble) width;
  173.  
  174.       pos.y += 0.5 * (1.0 - (gdouble) height / (gdouble) width); 
  175.     }
  176.   else
  177.     {
  178.       pos.x = x / (gdouble) height;
  179.       pos.y = y / (gdouble) height;
  180.  
  181.       pos.x += 0.5 * (1.0 - (gdouble) width / (gdouble) height);
  182.     }
  183.  
  184.   pos.z = 0.0;
  185.   return pos;
  186. }
  187.  
  188. void
  189. pos_to_int (gdouble  x,
  190.         gdouble  y,
  191.         gint    *scr_x,
  192.         gint *scr_y)
  193. {
  194.   if (width >= height)
  195.     {
  196.       y -= 0.5 * (1.0 - (gdouble) height / (gdouble) width);
  197.       *scr_x = (gint) ((x * (gdouble) width) + 0.5);
  198.       *scr_y = (gint) ((y * (gdouble) width) + 0.5);
  199.     }
  200.   else
  201.     {
  202.       x -= 0.5 * (1.0 - (gdouble) width / (gdouble) height);
  203.  
  204.       *scr_x = (gint) ((x * (gdouble) height) + 0.5);
  205.       *scr_y = (gint) ((y  *(gdouble) height) + 0.5);
  206.     }
  207. }
  208.  
  209. void
  210. pos_to_float (gdouble  x,
  211.           gdouble  y,
  212.           gdouble *xf,
  213.           gdouble *yf)
  214. {
  215.   if (width >= height)
  216.     {
  217.       y -= 0.5 * (1.0 - (gdouble) height / (gdouble) width);
  218.  
  219.       *xf = x * (gdouble) width;
  220.       *yf = y * (gdouble) width;
  221.     }
  222.   else
  223.     {
  224.       x -= 0.5 * (1.0 - (gdouble) width / (gdouble) height);
  225.  
  226.       *xf = x * (gdouble) height;
  227.       *yf = y * (gdouble) height;
  228.     }
  229. }
  230.  
  231. /**********************************************/
  232. /* Compute the image color at pos (u,v) using */
  233. /* Quartics bilinear interpolation stuff.     */
  234. /**********************************************/
  235.  
  236. GckRGB
  237. get_image_color (gdouble  u,
  238.          gdouble  v,
  239.          gint    *inside)
  240. {
  241.   gint   x1, y1, x2, y2;
  242.   GckRGB p[4];
  243.  
  244.   x1 = (gint) (u + 0.5);
  245.   y1 = (gint) (v + 0.5);
  246.  
  247.   if (check_bounds (x1, y1) == FALSE)
  248.     {
  249.       *inside = FALSE;
  250.       return background;
  251.     }
  252.  
  253.   x2 = (x1 + 1);
  254.   y2 = (y1 + 1);
  255.  
  256.   if (check_bounds (x2, y2) == FALSE)
  257.     {
  258.       *inside = TRUE;
  259.       return peek (x1, y1);
  260.     }
  261.  
  262.   *inside = TRUE;
  263.   p[0] = peek (x1, y1);
  264.   p[1] = peek (x2, y1);
  265.   p[2] = peek (x1, y2);
  266.   p[3] = peek (x2, y2);
  267.  
  268.   return gck_bilinear_rgba (u, v, p);
  269. }
  270.  
  271. gdouble
  272. get_map_value (GimpPixelRgn *region,
  273.            gdouble    u,
  274.            gdouble    v,
  275.            gint      *inside)
  276. {
  277.   gint    x1, y1, x2, y2;
  278.   gdouble p[4];
  279.  
  280.   x1 = (gint) (u + 0.5);
  281.   y1 = (gint) (v + 0.5);
  282.  
  283.   x2 = (x1 + 1);
  284.   y2 = (y1 + 1);
  285.  
  286.   if (check_bounds (x2, y2) == FALSE)
  287.     {
  288.       *inside = TRUE;
  289.       return (gdouble) peek_map (region, x1, y1);
  290.     }
  291.  
  292.   *inside = TRUE;
  293.   p[0] = (gdouble) peek_map (region, x1, y1);
  294.   p[1] = (gdouble) peek_map (region, x2, y1);
  295.   p[2] = (gdouble) peek_map (region, x1, y2);
  296.   p[3] = (gdouble) peek_map (region, x2, y2);
  297.  
  298.   return gck_bilinear (u, v, p);
  299. }
  300.  
  301. static void
  302. compute_maps (void)
  303. {
  304.   gint    x;
  305.   gdouble val, c, d;
  306.  
  307.   /* Compute Sine, Log ans Spherical transfer function maps */
  308.   /* ====================================================== */
  309.  
  310.   c = 1.0  / 255.0;
  311.   d = 1.15 * 255.0;
  312.  
  313.   for (x = 0; x < 256; x++)
  314.     {
  315.       sinemap[x] = (guchar) (255.0 * (0.5 * (sin ((G_PI * c * (gdouble) x) -
  316.                           0.5 * G_PI) +
  317.                          1.0)));
  318.       spheremap[x] = (guchar) (255.0 * (sqrt (sin (G_PI * (gdouble) x /
  319.                            512.0))));
  320.       val = (d * exp (-1.0 / (8.0 * c * ((gdouble) x + 5.0))));
  321.  
  322.       if (val > 255.0)
  323.         val = 255.0;
  324.       logmap[x] = (guchar) val;
  325.     }
  326. }
  327.  
  328. /****************************************/
  329. /* Allocate memory for temporary images */
  330. /****************************************/
  331.  
  332. gint
  333. image_setup (GimpDrawable *drawable,
  334.          gint       interactive)
  335. {
  336.   glong numbytes;
  337.  
  338.   compute_maps ();
  339.  
  340.   /* Get some useful info on the input drawable */
  341.   /* ========================================== */
  342.  
  343.   input_drawable = drawable;
  344.   output_drawable = drawable;
  345.  
  346.   gimp_drawable_mask_bounds (drawable->id,
  347.                  &border_x1, &border_y1, &border_x2, &border_y2);
  348.  
  349.   width = input_drawable->width;
  350.   height = input_drawable->height;
  351.  
  352.   gimp_pixel_rgn_init (&source_region, input_drawable,
  353.                0, 0, width, height, FALSE, FALSE);
  354.  
  355.   maxcounter = (glong) width * (glong) height;
  356.  
  357.   /* Assume at least RGB */
  358.   /* =================== */
  359.  
  360.   in_channels = 3;
  361.   if (gimp_drawable_has_alpha (input_drawable->id) == TRUE)
  362.     in_channels++;
  363.  
  364.   if (interactive == TRUE)
  365.     {
  366.       /* Allocate memory for temp. images */
  367.       /* ================================ */
  368.  
  369.       image = gdk_image_new (GDK_IMAGE_FASTEST, visinfo->visual,
  370.                  PREVIEW_WIDTH, PREVIEW_HEIGHT);
  371.  
  372.       if (image == NULL)
  373.         return FALSE;
  374.  
  375.       numbytes = (glong) PREVIEW_WIDTH * (glong) PREVIEW_HEIGHT * 3;
  376.       preview_rgb_data = g_new0 (guchar, numbytes);
  377.  
  378.       /* Convert from raw RGB to GdkImage */
  379.       /* ================================ */
  380.  
  381.       gck_rgb_to_gdkimage (visinfo, preview_rgb_data, image,
  382.                PREVIEW_WIDTH, PREVIEW_HEIGHT);
  383.     }
  384.  
  385.   return TRUE;
  386. }
  387.