lighting-image.c 8.04 KB
Newer Older
Manish Singh's avatar
Manish Singh committed
1 2 3 4
/*************************************/
/* GIMP image manipulation routines. */
/*************************************/

5
#include "config.h"
6

7
#include <gtk/gtk.h>
8

9
#include <libgimp/gimp.h>
10

11 12 13 14
#include "lighting-main.h"
#include "lighting-image.h"
#include "lighting-preview.h"
#include "lighting-ui.h"
Manish Singh's avatar
Manish Singh committed
15

16

17 18
GimpDrawable *input_drawable,*output_drawable;
GimpPixelRgn  source_region, dest_region;
Manish Singh's avatar
Manish Singh committed
19

20 21
GimpDrawable *bump_drawable = NULL;
GimpPixelRgn  bump_region;
Manish Singh's avatar
Manish Singh committed
22

23 24
GimpDrawable *env_drawable = NULL;
GimpPixelRgn  env_region;
Manish Singh's avatar
Manish Singh committed
25

26 27 28
guchar          *preview_rgb_data = NULL;
gint             preview_rgb_stride;
cairo_surface_t *preview_surface = NULL;
Manish Singh's avatar
Manish Singh committed
29

30 31
glong  maxcounter;
gint   imgtype, width, height, env_width, env_height, in_channels, out_channels;
32
GimpRGB background;
Manish Singh's avatar
Manish Singh committed
33

34
gint border_x1, border_y1, border_x2, border_y2;
Manish Singh's avatar
Manish Singh committed
35

36
guchar sinemap[256], spheremap[256], logmap[256];
Manish Singh's avatar
Manish Singh committed
37 38 39 40 41

/******************/
/* Implementation */
/******************/

42
guchar
43
peek_map (GimpPixelRgn *region,
44 45
	  gint       x,
	  gint       y)
Manish Singh's avatar
Manish Singh committed
46
{
47 48 49 50 51
  guchar data[4];
  guchar ret_val;


  gimp_pixel_rgn_get_pixel (region, data, x, y);
Manish Singh's avatar
Manish Singh committed
52

53
  if (region->bpp == 1)
54
  {
55 56 57 58 59
    ret_val = data[0];
  } else
  {
    ret_val = (guchar)((float)((data[0] + data[1] + data[2])/3.0));
  }
60

61
  return ret_val;
Manish Singh's avatar
Manish Singh committed
62 63
}

64
GimpRGB
65 66
peek (gint x,
      gint y)
Manish Singh's avatar
Manish Singh committed
67 68
{
  guchar data[4];
69
  GimpRGB color;
Manish Singh's avatar
Manish Singh committed
70

71
  gimp_pixel_rgn_get_pixel (&source_region,data, x, y);
Manish Singh's avatar
Manish Singh committed
72

73 74 75
  color.r = (gdouble) (data[0]) / 255.0;
  color.g = (gdouble) (data[1]) / 255.0;
  color.b = (gdouble) (data[2]) / 255.0;
Manish Singh's avatar
Manish Singh committed
76

77
  if (input_drawable->bpp == 4)
Manish Singh's avatar
Manish Singh committed
78
    {
79 80
      if (in_channels == 4)
        color.a = (gdouble) (data[3]) / 255.0;
Manish Singh's avatar
Manish Singh committed
81
      else
82
        color.a = 1.0;
Manish Singh's avatar
Manish Singh committed
83 84
    }
  else
85 86 87
    {
      color.a = 1.0;
    }
Manish Singh's avatar
Manish Singh committed
88

89
  return color;
Manish Singh's avatar
Manish Singh committed
90 91
}

92
GimpRGB
93 94
peek_env_map (gint x,
	      gint y)
Manish Singh's avatar
Manish Singh committed
95 96
{
  guchar data[4];
97
  GimpRGB color;
Manish Singh's avatar
Manish Singh committed
98

99 100 101 102 103 104 105 106
  if (x < 0)
    x = 0;
  else if (x >= env_width)
    x = env_width - 1;
  if (y < 0)
    y = 0;
  else if (y >= env_height)
    y = env_height - 1;
Manish Singh's avatar
Manish Singh committed
107

108
  gimp_pixel_rgn_get_pixel (&env_region, data, x, y);
Manish Singh's avatar
Manish Singh committed
109

110 111 112 113
  color.r = (gdouble) (data[0]) / 255.0;
  color.g = (gdouble) (data[1]) / 255.0;
  color.b = (gdouble) (data[2]) / 255.0;
  color.a = 1.0;
Manish Singh's avatar
Manish Singh committed
114

115
  return color;
Manish Singh's avatar
Manish Singh committed
116 117
}

118 119 120
void
poke (gint    x,
      gint    y,
121
      GimpRGB *color)
Manish Singh's avatar
Manish Singh committed
122 123 124
{
  static guchar data[4];

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
  if (x < 0)
    x = 0;
  else if (x >= width)
    x = width - 1;
  if (y < 0)
    y = 0;
  else if (y >= height)
    y = height - 1;

  data[0] = (guchar) (color->r * 255.0);
  data[1] = (guchar) (color->g * 255.0);
  data[2] = (guchar) (color->b * 255.0);
  data[3] = (guchar) (color->a * 255.0);

  gimp_pixel_rgn_set_pixel (&dest_region, data, x, y);
Manish Singh's avatar
Manish Singh committed
140 141
}

142 143 144
gint
check_bounds (gint x,
	      gint y)
Manish Singh's avatar
Manish Singh committed
145
{
146 147
  if (x < border_x1 || y < border_y1 || x >= border_x2 || y >= border_y2)
    return FALSE;
Manish Singh's avatar
Manish Singh committed
148
  else
149
    return TRUE;
Manish Singh's avatar
Manish Singh committed
150 151
}

152 153 154
GimpVector3
int_to_pos (gint x,
	    gint y)
Manish Singh's avatar
Manish Singh committed
155
{
156
  GimpVector3 pos;
Manish Singh's avatar
Manish Singh committed
157

158
  if (width >= height)
Manish Singh's avatar
Manish Singh committed
159
    {
160 161
      pos.x = (gdouble) x / (gdouble) width;
      pos.y = (gdouble) y / (gdouble) width;
Manish Singh's avatar
Manish Singh committed
162

163
      pos.y += 0.5 * (1.0 - (gdouble) height / (gdouble) width);
Manish Singh's avatar
Manish Singh committed
164 165 166
    }
  else
    {
167 168
      pos.x = (gdouble) x / (gdouble) height;
      pos.y = (gdouble) y / (gdouble) height;
Manish Singh's avatar
Manish Singh committed
169

170
      pos.x += 0.5 * (1.0 - (gdouble) width / (gdouble) height);
Manish Singh's avatar
Manish Singh committed
171
    }
172 173 174

  pos.z = 0.0;
  return pos;
Manish Singh's avatar
Manish Singh committed
175 176
}

177 178 179
GimpVector3
int_to_posf (gdouble x,
	     gdouble y)
Manish Singh's avatar
Manish Singh committed
180
{
181
  GimpVector3 pos;
Manish Singh's avatar
Manish Singh committed
182

183
  if (width >= height)
Manish Singh's avatar
Manish Singh committed
184
    {
185 186
      pos.x = x / (gdouble) width;
      pos.y = y / (gdouble) width;
Manish Singh's avatar
Manish Singh committed
187

188
      pos.y += 0.5 * (1.0 - (gdouble) height / (gdouble) width);
Manish Singh's avatar
Manish Singh committed
189 190 191
    }
  else
    {
192 193
      pos.x = x / (gdouble) height;
      pos.y = y / (gdouble) height;
Manish Singh's avatar
Manish Singh committed
194

195
      pos.x += 0.5 * (1.0 - (gdouble) width / (gdouble) height);
Manish Singh's avatar
Manish Singh committed
196
    }
197 198 199

  pos.z = 0.0;
  return pos;
Manish Singh's avatar
Manish Singh committed
200 201
}

202 203 204 205
void
pos_to_int (gdouble  x,
	    gdouble  y,
	    gint    *scr_x,
206
	    gint    *scr_y)
Manish Singh's avatar
Manish Singh committed
207
{
208
  if (width >= height)
Manish Singh's avatar
Manish Singh committed
209
    {
210
      y -= 0.5 * (1.0 - (gdouble) height / (gdouble) width);
211 212
      *scr_x = RINT ((x * (gdouble) width));
      *scr_y = RINT ((y * (gdouble) width));
Manish Singh's avatar
Manish Singh committed
213 214 215
    }
  else
    {
216
      x -= 0.5 * (1.0 - (gdouble) width / (gdouble) height);
Manish Singh's avatar
Manish Singh committed
217

218 219
      *scr_x = RINT ((x * (gdouble) height));
      *scr_y = RINT ((y  *(gdouble) height));
Manish Singh's avatar
Manish Singh committed
220 221 222
    }
}

223 224 225 226 227
void
pos_to_float (gdouble  x,
	      gdouble  y,
	      gdouble *xf,
	      gdouble *yf)
Manish Singh's avatar
Manish Singh committed
228
{
229
  if (width >= height)
Manish Singh's avatar
Manish Singh committed
230
    {
231 232
      y -= 0.5 * (1.0 - (gdouble) height / (gdouble) width);

233 234
      *xf = x * (gdouble) (width-1);
      *yf = y * (gdouble) (width-1);
Manish Singh's avatar
Manish Singh committed
235 236 237
    }
  else
    {
238
      x -= 0.5 * (1.0 - (gdouble) width / (gdouble) height);
Manish Singh's avatar
Manish Singh committed
239

240 241
      *xf = x * (gdouble) (height-1);
      *yf = y * (gdouble) (height-1);
Manish Singh's avatar
Manish Singh committed
242 243 244 245 246 247 248 249
    }
}

/**********************************************/
/* Compute the image color at pos (u,v) using */
/* Quartics bilinear interpolation stuff.     */
/**********************************************/

250
GimpRGB
251 252 253
get_image_color (gdouble  u,
		 gdouble  v,
		 gint    *inside)
Manish Singh's avatar
Manish Singh committed
254
{
255
  gint    x1, y1, x2, y2;
256
  GimpRGB p[4];
257

258 259
  x1 = RINT (u);
  y1 = RINT (v);
Manish Singh's avatar
Manish Singh committed
260

261
  if (check_bounds (x1, y1) == FALSE)
Manish Singh's avatar
Manish Singh committed
262
    {
263 264
      *inside = FALSE;
      return background;
Manish Singh's avatar
Manish Singh committed
265 266 267 268 269
    }

  x2 = (x1 + 1);
  y2 = (y1 + 1);

270 271 272 273 274
  if (check_bounds (x2, y2) == FALSE)
    {
      *inside = TRUE;
      return peek (x1, y1);
    }
Manish Singh's avatar
Manish Singh committed
275

276 277 278 279 280
  *inside = TRUE;
  p[0] = peek (x1, y1);
  p[1] = peek (x2, y1);
  p[2] = peek (x1, y2);
  p[3] = peek (x2, y2);
Manish Singh's avatar
Manish Singh committed
281

282
  return gimp_bilinear_rgba (u, v, p);
Manish Singh's avatar
Manish Singh committed
283 284
}

285
gdouble
286
get_map_value (GimpPixelRgn *region,
287 288 289
	       gdouble    u,
	       gdouble    v,
	       gint      *inside)
Manish Singh's avatar
Manish Singh committed
290 291 292
{
  gint    x1, y1, x2, y2;
  gdouble p[4];
293

294 295
  x1 = RINT (u);
  y1 = RINT (v);
296

Manish Singh's avatar
Manish Singh committed
297 298 299
  x2 = (x1 + 1);
  y2 = (y1 + 1);

300 301 302 303 304
  if (check_bounds (x2, y2) == FALSE)
    {
      *inside = TRUE;
      return (gdouble) peek_map (region, x1, y1);
    }
Manish Singh's avatar
Manish Singh committed
305

306 307 308 309 310
  *inside = TRUE;
  p[0] = (gdouble) peek_map (region, x1, y1);
  p[1] = (gdouble) peek_map (region, x2, y1);
  p[2] = (gdouble) peek_map (region, x1, y2);
  p[3] = (gdouble) peek_map (region, x2, y2);
Manish Singh's avatar
Manish Singh committed
311

312
  return gimp_bilinear (u, v, p);
Manish Singh's avatar
Manish Singh committed
313 314
}

315
static void
316
compute_maps (void)
Manish Singh's avatar
Manish Singh committed
317
{
318 319
  gint    x;
  gdouble val, c, d;
Manish Singh's avatar
Manish Singh committed
320

321
  /* Compute Sine, Log and Spherical transfer function maps */
Manish Singh's avatar
Manish Singh committed
322 323
  /* ====================================================== */

324 325 326 327
  c = 1.0  / 255.0;
  d = 1.15 * 255.0;

  for (x = 0; x < 256; x++)
Manish Singh's avatar
Manish Singh committed
328
    {
329 330 331 332 333 334 335 336 337 338
      sinemap[x] = (guchar) (255.0 * (0.5 * (sin ((G_PI * c * (gdouble) x) -
						  0.5 * G_PI) +
					     1.0)));
      spheremap[x] = (guchar) (255.0 * (sqrt (sin (G_PI * (gdouble) x /
						   512.0))));
      val = (d * exp (-1.0 / (8.0 * c * ((gdouble) x + 5.0))));

      if (val > 255.0)
        val = 255.0;
      logmap[x] = (guchar) val;
Manish Singh's avatar
Manish Singh committed
339 340 341 342 343 344 345
    }
}

/****************************************/
/* Allocate memory for temporary images */
/****************************************/

346
gint
347
image_setup (GimpDrawable *drawable,
348
	     gint          interactive)
Manish Singh's avatar
Manish Singh committed
349
{
350 351 352
  gint		w, h;
  gboolean      ret;

353 354
  compute_maps ();

Manish Singh's avatar
Manish Singh committed
355 356 357
  /* Get some useful info on the input drawable */
  /* ========================================== */

358
  input_drawable  = drawable;
359
  output_drawable = drawable;
Manish Singh's avatar
Manish Singh committed
360

361 362 363 364 365 366 367 368
  ret = gimp_drawable_mask_intersect (drawable->drawable_id,
                                      &border_x1, &border_y1, &w, &h);

  border_x2 = border_x1 + w;
  border_y2 = border_y1 + h;

  if (! ret)
    return FALSE;
Manish Singh's avatar
Manish Singh committed
369

370
  width  = input_drawable->width;
371
  height = input_drawable->height;
Manish Singh's avatar
Manish Singh committed
372

373 374
  gimp_pixel_rgn_init (&source_region, input_drawable,
		       0, 0, width, height, FALSE, FALSE);
Manish Singh's avatar
Manish Singh committed
375

376
  maxcounter = (glong) width * (glong) height;
Manish Singh's avatar
Manish Singh committed
377 378 379 380

  /* Assume at least RGB */
  /* =================== */

381
  in_channels = 3;
382
  if (gimp_drawable_has_alpha (input_drawable->drawable_id) == TRUE)
Manish Singh's avatar
Manish Singh committed
383 384
    in_channels++;

385
  if (interactive)
Manish Singh's avatar
Manish Singh committed
386
    {
387 388 389 390 391 392 393 394
      preview_rgb_stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24,
                                                          PREVIEW_WIDTH);
      preview_rgb_data = g_new0 (guchar, preview_rgb_stride * PREVIEW_HEIGHT);
      preview_surface = cairo_image_surface_create_for_data (preview_rgb_data,
                                                             CAIRO_FORMAT_RGB24,
                                                             PREVIEW_WIDTH,
                                                             PREVIEW_HEIGHT,
                                                             preview_rgb_stride);
Manish Singh's avatar
Manish Singh committed
395 396
    }

397
  return TRUE;
Manish Singh's avatar
Manish Singh committed
398
}