pixbufutils 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2031 @@
1
+ #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
2
+ /* Includes */
3
+ #include <ruby.h>
4
+ #include <stdlib.h>
5
+ #include <stdio.h>
6
+ #include <string.h>
7
+ #include "gdk-pixbuf/gdk-pixbuf.h"
8
+ #include "rbglib.h"
9
+ #include "rbgobject.h"
10
+ #include "tiffio.h"
11
+ #include "gdk/gdk.h"
12
+
13
+ /* Setup types */
14
+ /* Try not to clash with other definitions of bool... */
15
+ typedef int rubber_bool;
16
+ #define bool rubber_bool
17
+
18
+ /* Prototypes */
19
+ #include "rbglib.h"
20
+
21
+ static VALUE mPixbufUtils;
22
+ static VALUE
23
+ PixbufUtils_CLASS_remove_alpha(VALUE self, VALUE __v_src, VALUE __v_col);
24
+ static VALUE
25
+ PixbufUtils_CLASS_sharpen(VALUE self, VALUE __v_src, VALUE __v_radius);
26
+ static VALUE
27
+ PixbufUtils_CLASS_extract_alpha(int __p_argc, VALUE *__p_argv, VALUE self);
28
+ static VALUE
29
+ PixbufUtils_CLASS_blur(VALUE self, VALUE __v_src, VALUE __v_radius);
30
+ static VALUE
31
+ PixbufUtils_CLASS_rotate_90(VALUE self, VALUE __v_src, VALUE __v_counter_clockwise);
32
+ static VALUE
33
+ PixbufUtils_CLASS_rotate_cw(VALUE self, VALUE __v_src);
34
+ static VALUE
35
+ PixbufUtils_CLASS_rotate_180(VALUE self, VALUE __v_src);
36
+ static VALUE
37
+ PixbufUtils_CLASS_rotate(VALUE self, VALUE __v_src, VALUE __v_angle);
38
+ static VALUE
39
+ PixbufUtils_CLASS_rotate_ccw(VALUE self, VALUE __v_src);
40
+ static VALUE
41
+ PixbufUtils_CLASS_gamma_pling(VALUE self, VALUE __v_src, VALUE __v_level);
42
+ static VALUE
43
+ PixbufUtils_CLASS_soften_edges_pling(VALUE self, VALUE __v_src, VALUE __v_size);
44
+ static VALUE
45
+ PixbufUtils_CLASS_gamma(VALUE self, VALUE __v_src, VALUE __v_level);
46
+ static VALUE
47
+ PixbufUtils_CLASS_greyscale_pling(VALUE self, VALUE __v_src);
48
+ static VALUE
49
+ PixbufUtils_CLASS_to_tiff(VALUE self, VALUE __v_src, VALUE __v_filename);
50
+ static VALUE
51
+ PixbufUtils_CLASS_greyscale(VALUE self, VALUE __v_src);
52
+ static VALUE
53
+ PixbufUtils_CLASS_greyscale_go_pling(VALUE self, VALUE __v_src);
54
+ static VALUE
55
+ PixbufUtils_CLASS_greyscale_go(VALUE self, VALUE __v_src);
56
+ static VALUE
57
+ PixbufUtils_CLASS_tint(VALUE self, VALUE __v_src, VALUE __v_r, VALUE __v_g, VALUE __v_b);
58
+ static VALUE
59
+ PixbufUtils_CLASS_perspect_v(VALUE self, VALUE __v_src, VALUE __v_top_x1, VALUE __v_top_x2, VALUE __v_bot_x1, VALUE __v_bot_x2);
60
+ static VALUE
61
+ PixbufUtils_CLASS_mask(VALUE self, VALUE __v_src, VALUE __v_mask);
62
+ static VALUE
63
+ PixbufUtils_CLASS_blend5050(VALUE self, VALUE __v_src1, VALUE __v_src2);
64
+ static VALUE
65
+ PixbufUtils_CLASS_mask_area(int __p_argc, VALUE *__p_argv, VALUE self);
66
+ static VALUE
67
+ PixbufUtils_CLASS_scale_max(int __p_argc, VALUE *__p_argv, VALUE self);
68
+ static VALUE
69
+ PixbufUtils_CLASS_draw_scaled(int __p_argc, VALUE *__p_argv, VALUE self);
70
+ static VALUE
71
+ PixbufUtils_CLASS_draw_scaled_clip(int __p_argc, VALUE *__p_argv, VALUE self);
72
+
73
+ /* Inline C code */
74
+
75
+
76
+ extern void Init_pixbufutils(void);
77
+
78
+ #ifndef IGNORE
79
+ #define IGNORE(x) x=x
80
+ #endif
81
+
82
+ static GdkPixbuf *pixbuf_extract_alpha(GdkPixbuf *src, int cutoff, int force_2bit)
83
+ {
84
+ int s_has_alpha, d_has_alpha;
85
+ int s_width, s_height, s_rowstride;
86
+ int d_width, d_height, d_rowstride;
87
+ GdkPixbuf *dest;
88
+ guchar *s_pix, *sp;
89
+ guchar *d_pix, *dp;
90
+ int i, j, pix_width, grey;
91
+
92
+ g_return_val_if_fail(src != NULL, NULL);
93
+
94
+ s_width = gdk_pixbuf_get_width(src);
95
+ s_height = gdk_pixbuf_get_height(src);
96
+ s_has_alpha = gdk_pixbuf_get_has_alpha(src);
97
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
98
+ s_pix = gdk_pixbuf_get_pixels(src);
99
+ g_return_val_if_fail(s_has_alpha, NULL);
100
+
101
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, s_width, s_height);
102
+
103
+ g_return_val_if_fail(dest != NULL, NULL);
104
+
105
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
106
+ d_pix = gdk_pixbuf_get_pixels(dest);
107
+
108
+ d_width = gdk_pixbuf_get_width(dest);
109
+ d_height = gdk_pixbuf_get_height(dest);
110
+ d_has_alpha = gdk_pixbuf_get_has_alpha(dest);
111
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
112
+ d_pix = gdk_pixbuf_get_pixels(dest);
113
+
114
+ g_return_val_if_fail(d_width == s_width, NULL);
115
+ g_return_val_if_fail(d_height == s_height, NULL);
116
+
117
+ pix_width = (s_has_alpha ? 4 : 3);
118
+
119
+ for (i = 0; i < s_height; i++) {
120
+ sp = s_pix;
121
+ dp = d_pix;
122
+
123
+ for (j = 0; j < s_width; j++) {
124
+ grey = sp[3];
125
+
126
+ if (grey < cutoff)
127
+ grey = 0;
128
+
129
+ if (force_2bit)
130
+ grey = (grey >= cutoff ? 255 : 0);
131
+
132
+ dp[0] = grey; /* red */
133
+ dp[1] = grey; /* green */
134
+ dp[2] = grey; /* blue */
135
+
136
+ dp += 3;
137
+ sp += 4;
138
+ }
139
+
140
+ d_pix += d_rowstride;
141
+ s_pix += s_rowstride;
142
+ }
143
+
144
+ return dest;
145
+ }
146
+
147
+
148
+ typedef enum {
149
+ ANGLE_0 = 0,
150
+ ANGLE_90 = 90,
151
+ ANGLE_180 = 180,
152
+ ANGLE_270 = 270
153
+ } rotate_angle_t;
154
+
155
+ static GdkPixbuf *
156
+ pixbuf_blur(GdkPixbuf *src, gint radius)
157
+ {
158
+ /* Pixels and Rowstride To Perform Blur On */
159
+ guchar *pixels;
160
+ GdkPixbuf *pixbuf;
161
+ gint rowstride, width, height;
162
+
163
+ pixbuf = gdk_pixbuf_copy(src);
164
+
165
+ /* Get Pixels and Rowstride Of Image Buffer */
166
+ if (pixbuf)
167
+ {
168
+ pixels = gdk_pixbuf_get_pixels (pixbuf);
169
+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
170
+ width = gdk_pixbuf_get_width(pixbuf);
171
+ height = gdk_pixbuf_get_height(pixbuf);
172
+ /*printf("%i, %i, %i, %i\n", rowstride, width, height, rowstride/width);*/
173
+ }
174
+ else
175
+ {
176
+ return NULL;
177
+ }
178
+ if (radius > 1)
179
+ {
180
+ /* Some Important Consts */
181
+ gint bytes = rowstride/width;
182
+ gboolean alpha = (bytes == 4);
183
+
184
+ gint div = radius+radius+1;
185
+ gint divsum = ((div+1)>>1)*((div+1)>>1);
186
+ gint dv[256*divsum]; /* Table of Const RGBA Values */
187
+
188
+ /* Some Important Variables */
189
+ guchar stack[div][bytes];
190
+ gint stackpointer;
191
+ gint stackstart;
192
+ gint vmin[MAX(width,height)];
193
+ guchar *sir;
194
+ gint rbs;
195
+
196
+ gint current = 0;
197
+
198
+ /* RGBA Sums
199
+ 0 - Sum of Incoming pixels(the radius pixels above the Center/to left of Center)
200
+ 1 - Sum of Outgoing pixels(the Center and the radius pixels below the Center/to right of Center)
201
+ 2 - Sum of All pixels within radius
202
+ */
203
+ gint rgba_sums[3][bytes];
204
+
205
+ /* RGBA Values */
206
+ guchar rgba[bytes][width*height];
207
+
208
+ /* Temp Indexes/Counters */
209
+ gint x, y, i, p, yp, yi=0, yw=0;
210
+
211
+ for (i=0; i<256*divsum; i++)
212
+ {
213
+ dv[i] = (i/divsum);
214
+ }
215
+
216
+ for (y=0; y < height; y++)
217
+ {
218
+ /* initialize sums to zero */
219
+ for (i = 0; i<bytes; i++)
220
+ {
221
+ rgba_sums[0][i] = 0;
222
+ rgba_sums[1][i] = 0;
223
+ rgba_sums[2][i] = 0;
224
+ }
225
+
226
+ /* Calculate Initial Sums For radius */
227
+ for(i=-radius; i<=radius; i++)
228
+ {
229
+ current = (yi + MIN(width - 1, MAX(i,0)))*bytes;
230
+
231
+ sir = stack[i+radius];
232
+
233
+ sir[0] = pixels[current + 0];
234
+ sir[1] = pixels[current + 1];
235
+ sir[2] = pixels[current + 2];
236
+ sir[3] = pixels[current + 3];
237
+
238
+ rbs = (radius + 1) - abs(i);
239
+
240
+ rgba_sums[2][0] += sir[0]*rbs;
241
+ rgba_sums[2][1] += sir[1]*rbs;
242
+ rgba_sums[2][2] += sir[2]*rbs;
243
+ if (alpha)
244
+ {
245
+ rgba_sums[2][3] += sir[3]*rbs;
246
+ }
247
+
248
+ if (i>0)
249
+ {
250
+ rgba_sums[0][0] += sir[0];
251
+ rgba_sums[0][1] += sir[1];
252
+ rgba_sums[0][2] += sir[2];
253
+ if (alpha)
254
+ {
255
+ rgba_sums[0][3] += sir[3];
256
+ }
257
+ }
258
+ else
259
+ {
260
+ rgba_sums[1][0] += sir[0];
261
+ rgba_sums[1][1] += sir[1];
262
+ rgba_sums[1][2] += sir[2];
263
+ if (alpha)
264
+ {
265
+ rgba_sums[1][3] += sir[3];
266
+ }
267
+ }
268
+ }
269
+
270
+ stackpointer = radius;
271
+
272
+ for (x=0; x<width; x++)
273
+ {
274
+ rgba[0][yi] = dv[rgba_sums[2][0]];
275
+ rgba[1][yi] = dv[rgba_sums[2][1]];
276
+ rgba[2][yi] = dv[rgba_sums[2][2]];
277
+ if (alpha)
278
+ {
279
+ rgba[3][yi] = dv[rgba_sums[2][3]];
280
+ }
281
+
282
+ rgba_sums[2][0] -= rgba_sums[1][0];
283
+ rgba_sums[2][1] -= rgba_sums[1][1];
284
+ rgba_sums[2][2] -= rgba_sums[1][2];
285
+ if (alpha)
286
+ {
287
+ rgba_sums[2][3] -= rgba_sums[1][3];
288
+ }
289
+
290
+ stackstart = stackpointer - radius + div;
291
+ sir = stack[stackstart%div];
292
+
293
+ rgba_sums[1][0] -= sir[0];
294
+ rgba_sums[1][1] -= sir[1];
295
+ rgba_sums[1][2] -= sir[2];
296
+ if (alpha)
297
+ {
298
+ rgba_sums[1][3] -= sir[3];
299
+ }
300
+
301
+ if(y==0)
302
+ {
303
+ vmin[x] = MIN(x + radius + 1, width - 1);
304
+ }
305
+
306
+ current = (yw + vmin[x])*bytes;
307
+
308
+ sir[0] = pixels[current + 0];
309
+ sir[1] = pixels[current + 1];
310
+ sir[2] = pixels[current + 2];
311
+ if (alpha)
312
+ {
313
+ sir[3] = pixels[current + 3];
314
+ }
315
+
316
+ rgba_sums[0][0] += sir[0];
317
+ rgba_sums[0][1] += sir[1];
318
+ rgba_sums[0][2] += sir[2];
319
+ if (alpha)
320
+ {
321
+ rgba_sums[0][3] += sir[3];
322
+ }
323
+
324
+ rgba_sums[2][0] += rgba_sums[0][0];
325
+ rgba_sums[2][1] += rgba_sums[0][1];
326
+ rgba_sums[2][2] += rgba_sums[0][2];
327
+ if (alpha)
328
+ {
329
+ rgba_sums[2][3] += rgba_sums[0][3];
330
+ }
331
+
332
+ stackpointer=(stackpointer+1)%div;
333
+ sir=stack[(stackpointer)%div];
334
+
335
+ rgba_sums[1][0] += sir[0];
336
+ rgba_sums[1][1] += sir[1];
337
+ rgba_sums[1][2] += sir[2];
338
+ if (alpha)
339
+ {
340
+ rgba_sums[1][3] += sir[3];
341
+ }
342
+
343
+ rgba_sums[0][0] -= sir[0];
344
+ rgba_sums[0][1] -= sir[1];
345
+ rgba_sums[0][2] -= sir[2];
346
+ if (alpha)
347
+ {
348
+ rgba_sums[0][3] -= sir[3];
349
+ }
350
+
351
+ yi++;
352
+ }
353
+
354
+ yw += width;
355
+ }
356
+
357
+ for (x=0; x<width; x++)
358
+ {
359
+ yp=-radius*width;
360
+
361
+ /* initialize sums to zero */
362
+ for (i = 0; i<bytes; i++)
363
+ {
364
+ rgba_sums[0][i] = 0;
365
+ rgba_sums[1][i] = 0;
366
+ rgba_sums[2][i] = 0;
367
+ }
368
+
369
+ /* Calculate Initial Sums For radius */
370
+ for(i=-radius; i<=radius; i++)
371
+ {
372
+ yi = MAX(0,yp) + x;
373
+
374
+ sir = stack[i+radius];
375
+
376
+ sir[0] = rgba[0][yi];
377
+ sir[1] = rgba[1][yi];
378
+ sir[2] = rgba[2][yi];
379
+ if (alpha)
380
+ {
381
+ sir[3] = rgba[3][yi];
382
+ }
383
+
384
+ rbs = (radius + 1) - abs(i);
385
+
386
+ rgba_sums[2][0] += rgba[0][yi]*rbs;
387
+ rgba_sums[2][1] += rgba[1][yi]*rbs;
388
+ rgba_sums[2][2] += rgba[2][yi]*rbs;
389
+ if (alpha)
390
+ {
391
+ rgba_sums[2][3] += rgba[3][yi]*rbs;
392
+ }
393
+
394
+ if (i>0)
395
+ {
396
+ rgba_sums[0][0] += sir[0];
397
+ rgba_sums[0][1] += sir[1];
398
+ rgba_sums[0][2] += sir[2];
399
+ if (alpha)
400
+ {
401
+ rgba_sums[0][3] += sir[3];
402
+ }
403
+ }
404
+ else
405
+ {
406
+ rgba_sums[1][0] += sir[0];
407
+ rgba_sums[1][1] += sir[1];
408
+ rgba_sums[1][2] += sir[2];
409
+ if (alpha)
410
+ {
411
+ rgba_sums[1][3] += sir[3];
412
+ }
413
+ }
414
+
415
+ if(i < height - 1)
416
+ {
417
+ yp += width;
418
+ }
419
+ }
420
+
421
+ yi = x;
422
+ stackpointer = radius;
423
+
424
+ for (y=0; y<height; y++)
425
+ {
426
+ current = (yi)*bytes;
427
+
428
+ pixels[current + 0] = dv[rgba_sums[2][0]];
429
+ pixels[current + 1] = dv[rgba_sums[2][1]];
430
+ pixels[current + 2] = dv[rgba_sums[2][2]];
431
+ if (alpha)
432
+ {
433
+ pixels[current + 3] = dv[rgba_sums[2][3]];
434
+ }
435
+
436
+ rgba_sums[2][0] -= rgba_sums[1][0];
437
+ rgba_sums[2][1] -= rgba_sums[1][1];
438
+ rgba_sums[2][2] -= rgba_sums[1][2];
439
+ if (alpha)
440
+ {
441
+ rgba_sums[2][3] -= rgba_sums[1][3];
442
+ }
443
+
444
+ stackstart = stackpointer - radius + div;
445
+ sir = stack[stackstart%div];
446
+
447
+ rgba_sums[1][0] -= sir[0];
448
+ rgba_sums[1][1] -= sir[1];
449
+ rgba_sums[1][2] -= sir[2];
450
+ if (alpha)
451
+ {
452
+ rgba_sums[1][3] -= sir[3];
453
+ }
454
+
455
+ if (x == 0)
456
+ {
457
+ vmin[y] = MIN(y + (radius + 1), height - 1)*width;
458
+ }
459
+
460
+ p = x + vmin[y];
461
+
462
+ sir[0] = rgba[0][p];
463
+ sir[1] = rgba[1][p];
464
+ sir[2] = rgba[2][p];
465
+ if (alpha)
466
+ {
467
+ sir[3] = rgba[3][p];
468
+ }
469
+
470
+ rgba_sums[0][0] += sir[0];
471
+ rgba_sums[0][1] += sir[1];
472
+ rgba_sums[0][2] += sir[2];
473
+ if (alpha)
474
+ {
475
+ rgba_sums[0][3] += sir[3];
476
+ }
477
+
478
+ rgba_sums[2][0] += rgba_sums[0][0];
479
+ rgba_sums[2][1] += rgba_sums[0][1];
480
+ rgba_sums[2][2] += rgba_sums[0][2];
481
+ if (alpha)
482
+ {
483
+ rgba_sums[2][3] += rgba_sums[0][3];
484
+ }
485
+
486
+ stackpointer = (stackpointer+1)%div;
487
+ sir = stack[stackpointer];
488
+
489
+ rgba_sums[1][0] += sir[0];
490
+ rgba_sums[1][1] += sir[1];
491
+ rgba_sums[1][2] += sir[2];
492
+ if (alpha)
493
+ {
494
+ rgba_sums[1][3] += sir[3];
495
+ }
496
+
497
+ rgba_sums[0][0] -= sir[0];
498
+ rgba_sums[0][1] -= sir[1];
499
+ rgba_sums[0][2] -= sir[2];
500
+ if (alpha)
501
+ {
502
+ rgba_sums[0][3] -= sir[3];
503
+ }
504
+
505
+ yi += width;
506
+ }
507
+ }
508
+ }
509
+
510
+ return pixbuf;
511
+ }
512
+
513
+ static GdkPixbuf *
514
+ pixbuf_sharpen(GdkPixbuf *src, int strength)
515
+ {
516
+ GdkPixbuf *dest;
517
+ int has_alpha;
518
+ int s_width, s_height, s_rowstride;
519
+ int d_width, d_height, d_rowstride;
520
+ guchar *s_pix;
521
+ guchar *d_pix;
522
+ guchar *sp;
523
+ guchar *dp;
524
+ int pix_width;
525
+ bool row_only = TRUE;
526
+ int a=0, r, g, b, x, y, mul;
527
+ int b_a=0, b_r, b_g, b_b;
528
+
529
+ if (!src) return NULL;
530
+
531
+ s_width = gdk_pixbuf_get_width(src);
532
+ s_height = gdk_pixbuf_get_height(src);
533
+ has_alpha = gdk_pixbuf_get_has_alpha(src);
534
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
535
+ s_pix = gdk_pixbuf_get_pixels(src);
536
+
537
+ d_width = s_width;
538
+ d_height = s_height;
539
+
540
+ dest = gdk_pixbuf_copy(src);
541
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
542
+ d_pix = gdk_pixbuf_get_pixels(dest);
543
+
544
+ pix_width = (has_alpha ? 4 : 3);
545
+
546
+ mul = (row_only ? 3 : 5);
547
+
548
+ for (y = 0; y < (s_height); y++)
549
+ {
550
+ sp = s_pix + (y * s_rowstride) + pix_width;
551
+ dp = d_pix + (y * d_rowstride) + pix_width;
552
+
553
+ for (x = 1; x < (s_width - 1); x++)
554
+ {
555
+
556
+ b_r = ((int)*(sp));
557
+ b_g = ((int)*(sp+1));
558
+ b_b = ((int)*(sp+2));
559
+ if (has_alpha)
560
+ b_a = ((int)*((sp+3)));
561
+
562
+ r = b_r * mul;
563
+ g = b_g * mul;
564
+ b = b_b * mul;
565
+ if (has_alpha)
566
+ a = b_a * mul;
567
+
568
+ r = ((int)*(sp)) * mul;
569
+ g = ((int)*(sp+1)) * mul;
570
+ b = ((int)*(sp+2)) * mul;
571
+ if (has_alpha)
572
+ a = ((int)*((sp+3))) * mul;
573
+
574
+ r -= (int)*(sp - pix_width);
575
+ g -= (int)*(sp - pix_width + 1);
576
+ b -= (int)*(sp - pix_width + 2);
577
+ if (has_alpha)
578
+ a -= (int)*(sp - pix_width + 3);
579
+
580
+ r -= (int)*(sp + pix_width);
581
+ g -= (int)*(sp + pix_width + 1);
582
+ b -= (int)*(sp + pix_width + 2);
583
+ if (has_alpha)
584
+ a -= (int)*(sp + pix_width + 3);
585
+
586
+ if (row_only == 0)
587
+ {
588
+ r -= (int)*(sp - (s_rowstride));
589
+ g -= (int)*(sp + 1 - (s_rowstride));
590
+ b -= (int)*(sp + 2 - (s_rowstride));
591
+ if (has_alpha)
592
+ a -= (int)*(sp + 3 - (s_rowstride));
593
+
594
+ r -= (int)*(sp + (s_rowstride));
595
+ g -= (int)*(sp + 1 + (s_rowstride));
596
+ b -= (int)*(sp + 2 + (s_rowstride));
597
+ if (has_alpha)
598
+ a -= (int)*(sp + 3 + (s_rowstride));
599
+ }
600
+
601
+ r = (r & ((~r) >> 16));
602
+ r = ((r | ((r & 256) - ((r & 256) >> 8))));
603
+ g = (g & ((~g) >> 16));
604
+ g = ((g | ((g & 256) - ((g & 256) >> 8))));
605
+ b = (b & ((~b) >> 16));
606
+ b = ((b | ((b & 256) - ((b & 256) >> 8))));
607
+ a = (a & ((~a) >> 16));
608
+ a = ((a | ((a & 256) - ((a & 256) >> 8))));
609
+
610
+ r = 0xff & (MAX(r,0));
611
+ g = 0xff & (MAX(g,0));
612
+ b = 0xff & (MAX(b,0));
613
+ if (has_alpha)
614
+ a = 0xff & (MAX(a,0));
615
+
616
+ r = ((r * strength) + b_r) / (strength + 1);
617
+ g = ((g * strength) + b_g) / (strength + 1);
618
+ b = ((b * strength) + b_b) / (strength + 1);
619
+ if (has_alpha)
620
+ a = ((a * strength) + b_a) / (strength + 1);
621
+
622
+ *(dp++) = r;
623
+ *(dp++) = g;
624
+ *(dp++) = b;
625
+ if (has_alpha)
626
+ *(dp++) = a;
627
+
628
+ sp += pix_width;
629
+ }
630
+ }
631
+ return dest;
632
+ } // */
633
+
634
+ static GdkPixbuf *
635
+ pixbuf_rotate(GdkPixbuf *src, rotate_angle_t angle)
636
+ {
637
+ GdkPixbuf *dest;
638
+ int has_alpha;
639
+ int s_width, s_height, s_rowstride;
640
+ int d_width, d_height, d_rowstride;
641
+ guchar *s_pix;
642
+ guchar *d_pix;
643
+ guchar *sp;
644
+ guchar *dp;
645
+ int i, j, pix_width;
646
+
647
+ if (!src) return NULL;
648
+
649
+ if (angle == ANGLE_0)
650
+ return gdk_pixbuf_copy(src);
651
+
652
+ s_width = gdk_pixbuf_get_width(src);
653
+ s_height = gdk_pixbuf_get_height(src);
654
+ has_alpha = gdk_pixbuf_get_has_alpha(src);
655
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
656
+ s_pix = gdk_pixbuf_get_pixels(src);
657
+
658
+ switch (angle)
659
+ {
660
+ case ANGLE_90:
661
+ case ANGLE_270:
662
+ d_width = s_height;
663
+ d_height = s_width;
664
+ break;
665
+ default:
666
+ case ANGLE_0:/* Avoid compiler warnings... */
667
+ case ANGLE_180:
668
+ d_width = s_width;
669
+ d_height = s_height;
670
+ break;
671
+ }
672
+
673
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8, d_width, d_height);
674
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
675
+ d_pix = gdk_pixbuf_get_pixels(dest);
676
+
677
+ pix_width = (has_alpha ? 4 : 3);
678
+
679
+ for (i = 0; i < s_height; i++) {
680
+ sp = s_pix + (i * s_rowstride);
681
+ for (j = 0; j < s_width; j++) {
682
+ switch (angle)
683
+ {
684
+ case ANGLE_180:
685
+ dp = d_pix + ((d_height - i - 1) * d_rowstride) + ((d_width - j - 1) * pix_width);
686
+ break;
687
+ case ANGLE_90:
688
+ dp = d_pix + (j * d_rowstride) + ((d_width - i - 1) * pix_width);
689
+ break;
690
+ case ANGLE_270:
691
+ dp = d_pix + ((d_height - j - 1) * d_rowstride) + (i * pix_width);
692
+ break;
693
+ default:
694
+ case ANGLE_0:/* Avoid compiler warnings... */
695
+ dp = d_pix + (i * d_rowstride) + (j * pix_width);
696
+ break;
697
+ }
698
+
699
+ *(dp++) = *(sp++); /* red */
700
+ *(dp++) = *(sp++); /* green */
701
+ *(dp++) = *(sp++); /* blue */
702
+ if (has_alpha) *(dp) = *(sp++); /* alpha */
703
+ }
704
+ }
705
+
706
+ return dest;
707
+ }
708
+
709
+ #include <unistd.h>
710
+
711
+ static gboolean pixbuf_save_tiff(GdkPixbuf *pixbuf, char *filename)
712
+ {
713
+ long row;
714
+ TIFF *tif;
715
+ struct tm *ct;
716
+ time_t t;
717
+ int width,
718
+ height,
719
+ rowstride;
720
+ guchar *pixels;
721
+ short photometric;
722
+ short samplesperpixel;
723
+ short bitspersample;
724
+ static char datetime[40] = "";
725
+ char hostname[256] = "";
726
+
727
+ time(&t);
728
+ ct = localtime(&t);
729
+ sprintf(datetime, "%04i:%02i:%02i %02i:%02i:%02i",
730
+ 1900 + ct->tm_year, ct->tm_mon + 1, ct->tm_mday,
731
+ ct->tm_hour, ct->tm_min, ct->tm_sec);
732
+
733
+ tif = TIFFOpen(filename, "w");
734
+
735
+ width = gdk_pixbuf_get_width(pixbuf);
736
+ height = gdk_pixbuf_get_height(pixbuf);
737
+ samplesperpixel = gdk_pixbuf_get_has_alpha(pixbuf) ? 4 : 3;
738
+ bitspersample = gdk_pixbuf_get_bits_per_sample(pixbuf);
739
+ photometric = PHOTOMETRIC_RGB;
740
+ rowstride = gdk_pixbuf_get_rowstride(pixbuf);
741
+ pixels = gdk_pixbuf_get_pixels(pixbuf);
742
+
743
+
744
+ TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
745
+ TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
746
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
747
+ TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
748
+ TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
749
+ TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric);
750
+ /*#TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, inf);*/
751
+ TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Saved from a Gdk::Pixbuf");
752
+ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
753
+ TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
754
+ TIFFSetField(tif, TIFFTAG_SOFTWARE, "LiveLink Photo Kiosk 1.0");
755
+ TIFFSetField(tif, TIFFTAG_DATETIME, datetime);
756
+ if(gethostname((char*)&hostname,sizeof(hostname))==0)
757
+ TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, hostname);
758
+
759
+ for (row = 0; row < height; row++) {
760
+ if (TIFFWriteScanline(tif, (u_char *) pixels, row, 0) < 0) {
761
+ fprintf(stderr, "failed a scanline write (%li)\n", row);
762
+ break;
763
+ }
764
+ pixels = GINT_TO_POINTER(GPOINTER_TO_INT(pixels) + rowstride);
765
+ }
766
+ TIFFFlushData(tif);
767
+ TIFFClose(tif);
768
+
769
+ return TRUE;
770
+ }
771
+
772
+ #include <math.h>
773
+
774
+ static GdkPixbuf *pixbuf_gamma(GdkPixbuf *src, GdkPixbuf *dest, double gamma)
775
+ {
776
+ int has_alpha;
777
+ int s_width, s_height, s_rowstride;
778
+ int d_width, d_height, d_rowstride;
779
+ guchar *s_pix;
780
+ guchar *d_pix;
781
+ guchar *sp;
782
+ guchar *dp;
783
+ int i, j, pix_width;
784
+ double map[256] = {0.0,};
785
+
786
+ for (i=0; i < 256; i++)
787
+ map[i] = 255 * pow((double) i/255, 1.0/gamma);
788
+
789
+ g_return_val_if_fail(src != NULL, NULL);
790
+ g_return_val_if_fail(dest != NULL, NULL);
791
+
792
+ s_width = gdk_pixbuf_get_width(src);
793
+ s_height = gdk_pixbuf_get_height(src);
794
+ has_alpha = gdk_pixbuf_get_has_alpha(src);
795
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
796
+ s_pix = gdk_pixbuf_get_pixels(src);
797
+
798
+ d_width = gdk_pixbuf_get_width(dest);
799
+ d_height = gdk_pixbuf_get_height(dest);
800
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
801
+ d_pix = gdk_pixbuf_get_pixels(dest);
802
+
803
+ g_return_val_if_fail(d_width == s_width, NULL);
804
+ g_return_val_if_fail(d_height == s_height, NULL);
805
+ g_return_val_if_fail(has_alpha == gdk_pixbuf_get_has_alpha(dest), NULL);
806
+
807
+ pix_width = (has_alpha ? 4 : 3);
808
+
809
+ for (i = 0; i < s_height; i++) {
810
+ sp = s_pix + (i * s_rowstride);
811
+ dp = d_pix + (i * d_rowstride);
812
+ for (j = 0; j < s_width; j++) {
813
+ *(dp++) = map[*(sp++)]; /* red */
814
+ *(dp++) = map[*(sp++)]; /* green */
815
+ *(dp++) = map[*(sp++)]; /* blue */
816
+ if (has_alpha) *(dp++) = map[*(sp++)]; /* alpha */
817
+ }
818
+ }
819
+
820
+ return dest;
821
+ }
822
+
823
+ #define PIXEL(row, channels, x) ((pixel_t)(row + (channels * x)))
824
+
825
+ typedef struct {
826
+ unsigned char r,g,b,a;
827
+ } * pixel_t;
828
+
829
+ #define RLUM (0.3086)
830
+ #define GLUM (0.6094)
831
+ #define BLUM (0.0820)
832
+
833
+ // Graphica Obscure
834
+ #define GO_RGB_TO_GREY(r,g,b) ((int)((RLUM * (double)r) + (GLUM * (double)g) + (BLUM * (double)b)))
835
+
836
+ // Gimp Values
837
+ #define GIMP_RGB_TO_GREY(r,g,b) (((77 * r) + (151 * g) + (28 * b)) >> 8)
838
+
839
+ static GdkPixbuf *pixbuf_mask(GdkPixbuf *src, GdkPixbuf *mask)
840
+ {
841
+ int s_has_alpha, m_has_alpha;
842
+ int s_width, s_height, s_rowstride;
843
+ int d_width, d_height, d_rowstride;
844
+ int m_width, m_height, m_rowstride;
845
+ guchar *s_pix, *sp;
846
+ guchar *d_pix, *dp;
847
+ guchar *m_pix, *mp;
848
+ int i, j, pix_width, alpha, grey;
849
+ pixel_t pix;
850
+ GdkPixbuf *dest;
851
+
852
+ g_return_val_if_fail(src != NULL, NULL);
853
+
854
+ s_width = gdk_pixbuf_get_width(src);
855
+ s_height = gdk_pixbuf_get_height(src);
856
+ s_has_alpha = gdk_pixbuf_get_has_alpha(src);
857
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
858
+ s_pix = gdk_pixbuf_get_pixels(src);
859
+
860
+ g_return_val_if_fail(mask != NULL, NULL);
861
+
862
+ m_width = gdk_pixbuf_get_width(mask);
863
+ m_height = gdk_pixbuf_get_height(mask);
864
+ m_has_alpha = gdk_pixbuf_get_has_alpha(mask);
865
+ m_rowstride = gdk_pixbuf_get_rowstride(mask);
866
+ m_pix = gdk_pixbuf_get_pixels(mask);
867
+
868
+ g_return_val_if_fail(m_width <= s_width, NULL);
869
+ g_return_val_if_fail(m_height <= s_height, NULL);
870
+
871
+ d_width = m_width;
872
+ d_height = m_height;
873
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, d_width, d_height);
874
+
875
+ g_return_val_if_fail(dest != NULL, NULL);
876
+
877
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
878
+ d_pix = gdk_pixbuf_get_pixels(dest);
879
+
880
+ pix_width = (m_has_alpha ? 4 : 3);
881
+
882
+
883
+
884
+ for (i = 0; i < m_height; i++) {
885
+ sp = s_pix + (i * s_rowstride);
886
+ dp = d_pix + (i * d_rowstride);
887
+ mp = m_pix + (i * m_rowstride);
888
+
889
+ for (j = 0; j < m_width; j++) {
890
+ *(dp++) = *(sp++); /* red */
891
+ *(dp++) = *(sp++); /* green */
892
+ *(dp++) = *(sp++); /* blue */
893
+
894
+ if (s_has_alpha)
895
+ {
896
+ alpha = *(sp++); /* alpha */
897
+ }
898
+ else
899
+ {
900
+ alpha = 0xff;
901
+ }
902
+
903
+ pix = PIXEL(mp, pix_width, j);
904
+ grey = GIMP_RGB_TO_GREY(pix->r, pix->g, pix->b);
905
+
906
+ *(dp++) = sqrt(alpha * (255 - grey)); /* alpha */
907
+ }
908
+ }
909
+
910
+ return dest;
911
+ }
912
+
913
+ static GdkPixbuf *pixbuf_blend5050(GdkPixbuf *src1, GdkPixbuf *src2)
914
+ {
915
+ int s1_has_alpha, s2_has_alpha;
916
+ int s1_width, s1_height, s1_rowstride;
917
+ int d_width, d_height, d_rowstride;
918
+ int s2_width, s2_height, s2_rowstride;
919
+ guchar *s1_pix, *sp;
920
+ guchar *d_pix, *dp;
921
+ guchar *s2_pix, *mp;
922
+ int i, j;
923
+ GdkPixbuf *dest;
924
+
925
+ g_return_val_if_fail(src1 != NULL, NULL);
926
+
927
+ s1_width = gdk_pixbuf_get_width(src1);
928
+ s1_height = gdk_pixbuf_get_height(src1);
929
+ s1_has_alpha = gdk_pixbuf_get_has_alpha(src1);
930
+ s1_rowstride = gdk_pixbuf_get_rowstride(src1);
931
+ s1_pix = gdk_pixbuf_get_pixels(src1);
932
+
933
+ g_return_val_if_fail(src2 != NULL, NULL);
934
+
935
+ s2_width = gdk_pixbuf_get_width(src2);
936
+ s2_height = gdk_pixbuf_get_height(src2);
937
+ s2_has_alpha = gdk_pixbuf_get_has_alpha(src2);
938
+ s2_rowstride = gdk_pixbuf_get_rowstride(src2);
939
+ s2_pix = gdk_pixbuf_get_pixels(src2);
940
+
941
+ g_return_val_if_fail(s2_width == s1_width, NULL);
942
+ g_return_val_if_fail(s2_height == s1_height, NULL);
943
+ g_return_val_if_fail(s2_has_alpha == s1_has_alpha, NULL);
944
+
945
+ d_width = s2_width;
946
+ d_height = s2_height;
947
+
948
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, d_width, d_height);
949
+
950
+ g_return_val_if_fail(dest != NULL, NULL);
951
+
952
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
953
+ d_pix = gdk_pixbuf_get_pixels(dest);
954
+
955
+ for (i = 0; i < s2_height; i++) {
956
+ sp = s1_pix + (i * s1_rowstride);
957
+ mp = s2_pix + (i * s2_rowstride);
958
+ dp = d_pix + (i * d_rowstride);
959
+
960
+ for (j = 0; j < s2_width; j++) {
961
+ *(dp++) = ((*(sp++)) >> 1) + ((*(mp++)) >> 1); /* red */
962
+ *(dp++) = ((*(sp++)) >> 1) + ((*(mp++)) >> 1); /* green */
963
+ *(dp++) = ((*(sp++)) >> 1) + ((*(mp++)) >> 1); /* blue */
964
+
965
+ if (s1_has_alpha)
966
+ *(dp++) = ((*(sp++)) >> 1) + ((*(mp++)) >> 1); /* alpha */
967
+ else
968
+ *(dp++) = 0xff; /* alpha */
969
+
970
+ }
971
+ }
972
+
973
+ return dest;
974
+ }
975
+
976
+
977
+ static GdkPixbuf *pixbuf_greyscale(GdkPixbuf *src, GdkPixbuf *dest)
978
+ {
979
+ int s_has_alpha, d_has_alpha;
980
+ int s_width, s_height, s_rowstride;
981
+ int d_width, d_height, d_rowstride;
982
+ guchar *s_pix, *sp;
983
+ guchar *d_pix, *dp;
984
+ int i, j, pix_width, grey;
985
+
986
+ g_return_val_if_fail(src != NULL, NULL);
987
+ g_return_val_if_fail(dest != NULL, NULL);
988
+
989
+ s_width = gdk_pixbuf_get_width(src);
990
+ s_height = gdk_pixbuf_get_height(src);
991
+ s_has_alpha = gdk_pixbuf_get_has_alpha(src);
992
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
993
+ s_pix = gdk_pixbuf_get_pixels(src);
994
+
995
+ d_width = gdk_pixbuf_get_width(dest);
996
+ d_height = gdk_pixbuf_get_height(dest);
997
+ d_has_alpha = gdk_pixbuf_get_has_alpha(dest);
998
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
999
+ d_pix = gdk_pixbuf_get_pixels(dest);
1000
+
1001
+ g_return_val_if_fail(d_width == s_width, NULL);
1002
+ g_return_val_if_fail(d_height == s_height, NULL);
1003
+ g_return_val_if_fail(d_has_alpha == s_has_alpha, NULL);
1004
+
1005
+ pix_width = (s_has_alpha ? 4 : 3);
1006
+
1007
+
1008
+ for (i = 0; i < s_height; i++) {
1009
+ sp = s_pix;
1010
+ dp = d_pix;
1011
+
1012
+ for (j = 0; j < s_width; j++) {
1013
+ grey = GIMP_RGB_TO_GREY(sp[0], sp[1], sp[2]);
1014
+
1015
+ dp[0] = grey; /* red */
1016
+ dp[1] = grey; /* green */
1017
+ dp[2] = grey; /* blue */
1018
+
1019
+ if (s_has_alpha)
1020
+ {
1021
+ dp[3] = sp[3]; /* alpha */
1022
+ }
1023
+
1024
+ dp += pix_width;
1025
+ sp += pix_width;
1026
+ }
1027
+
1028
+ d_pix += d_rowstride;
1029
+ s_pix += s_rowstride;
1030
+ }
1031
+
1032
+ return dest;
1033
+ }
1034
+
1035
+ static GdkPixbuf *pixbuf_greyscale_go(GdkPixbuf *src, GdkPixbuf *dest)
1036
+ {
1037
+ int s_has_alpha, d_has_alpha;
1038
+ int s_width, s_height, s_rowstride;
1039
+ int d_width, d_height, d_rowstride;
1040
+ guchar *s_pix, *sp;
1041
+ guchar *d_pix, *dp;
1042
+ int i, j, pix_width, grey;
1043
+
1044
+ g_return_val_if_fail(src != NULL, NULL);
1045
+ g_return_val_if_fail(dest != NULL, NULL);
1046
+
1047
+ s_width = gdk_pixbuf_get_width(src);
1048
+ s_height = gdk_pixbuf_get_height(src);
1049
+ s_has_alpha = gdk_pixbuf_get_has_alpha(src);
1050
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
1051
+ s_pix = gdk_pixbuf_get_pixels(src);
1052
+
1053
+ d_width = gdk_pixbuf_get_width(dest);
1054
+ d_height = gdk_pixbuf_get_height(dest);
1055
+ d_has_alpha = gdk_pixbuf_get_has_alpha(dest);
1056
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
1057
+ d_pix = gdk_pixbuf_get_pixels(dest);
1058
+
1059
+ g_return_val_if_fail(d_width == s_width, NULL);
1060
+ g_return_val_if_fail(d_height == s_height, NULL);
1061
+ g_return_val_if_fail(d_has_alpha == s_has_alpha, NULL);
1062
+
1063
+ pix_width = (s_has_alpha ? 4 : 3);
1064
+
1065
+ for (i = 0; i < s_height; i++) {
1066
+ sp = s_pix;
1067
+ dp = d_pix;
1068
+
1069
+ for (j = 0; j < s_width; j++) {
1070
+ grey = GO_RGB_TO_GREY(sp[0], sp[1], sp[2]);
1071
+
1072
+ dp[0] = grey; /* red */
1073
+ dp[1] = grey; /* green */
1074
+ dp[2] = grey; /* blue */
1075
+
1076
+ if (s_has_alpha)
1077
+ {
1078
+ dp[3] = sp[3]; /* alpha */
1079
+ }
1080
+
1081
+ dp += pix_width;
1082
+ sp += pix_width;
1083
+ }
1084
+
1085
+ d_pix += d_rowstride;
1086
+ s_pix += s_rowstride;
1087
+ }
1088
+
1089
+ return dest;
1090
+ }
1091
+
1092
+ static inline char pu_clamp(int x, int min, int max)
1093
+ {
1094
+ return (x > max) ? max : (x < min ? min : x);
1095
+ }
1096
+
1097
+ static GdkPixbuf *pixbuf_tint(GdkPixbuf *src, GdkPixbuf *dest, int r, int g, int b)
1098
+ {
1099
+ int s_has_alpha, d_has_alpha;
1100
+ int s_width, s_height, s_rowstride;
1101
+ int d_width, d_height, d_rowstride;
1102
+ guchar *s_pix, *sp;
1103
+ guchar *d_pix, *dp;
1104
+ int i, j, pix_width, grey;
1105
+
1106
+ g_return_val_if_fail(src != NULL, NULL);
1107
+ g_return_val_if_fail(dest != NULL, NULL);
1108
+
1109
+ s_width = gdk_pixbuf_get_width(src);
1110
+ s_height = gdk_pixbuf_get_height(src);
1111
+ s_has_alpha = gdk_pixbuf_get_has_alpha(src);
1112
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
1113
+ s_pix = gdk_pixbuf_get_pixels(src);
1114
+
1115
+ d_width = gdk_pixbuf_get_width(dest);
1116
+ d_height = gdk_pixbuf_get_height(dest);
1117
+ d_has_alpha = gdk_pixbuf_get_has_alpha(dest);
1118
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
1119
+ d_pix = gdk_pixbuf_get_pixels(dest);
1120
+
1121
+ g_return_val_if_fail(d_width == s_width, NULL);
1122
+ g_return_val_if_fail(d_height == s_height, NULL);
1123
+ g_return_val_if_fail(d_has_alpha == s_has_alpha, NULL);
1124
+
1125
+ pix_width = (s_has_alpha ? 4 : 3);
1126
+
1127
+ for (i = 0; i < s_height; i++) {
1128
+ sp = s_pix;
1129
+ dp = d_pix;
1130
+
1131
+ for (j = 0; j < s_width; j++) {
1132
+ grey = GO_RGB_TO_GREY(sp[0], sp[1], sp[2]);
1133
+
1134
+ dp[0] = pu_clamp(grey + r, 0, 255); /* red */
1135
+ dp[1] = pu_clamp(grey + g, 0, 255); /* green */
1136
+ dp[2] = pu_clamp(grey + b, 0, 255); /* blue */
1137
+
1138
+ if (s_has_alpha)
1139
+ {
1140
+ dp[3] = sp[3]; /* alpha */
1141
+ }
1142
+
1143
+ dp += pix_width;
1144
+ sp += pix_width;
1145
+ }
1146
+
1147
+ d_pix += d_rowstride;
1148
+ s_pix += s_rowstride;
1149
+ }
1150
+
1151
+ return dest;
1152
+ }
1153
+
1154
+ static GdkPixbuf *pixbuf_soften_edges(GdkPixbuf *dest, int size)
1155
+ {
1156
+ int d_has_alpha;
1157
+ int d_width, d_height, d_rowstride;
1158
+ guchar *d_pix, *dp;
1159
+ int i, j, pix_width;
1160
+
1161
+ g_return_val_if_fail(dest != NULL, NULL);
1162
+
1163
+ d_width = gdk_pixbuf_get_width(dest);
1164
+ d_height = gdk_pixbuf_get_height(dest);
1165
+ d_has_alpha = gdk_pixbuf_get_has_alpha(dest);
1166
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
1167
+ d_pix = gdk_pixbuf_get_pixels(dest);
1168
+
1169
+ g_return_val_if_fail(d_has_alpha, NULL);
1170
+
1171
+ pix_width = (d_has_alpha ? 4 : 3);
1172
+
1173
+ for (i = 0; i < MIN(size,d_height); i++) {
1174
+ dp = d_pix + (i * d_rowstride);
1175
+ //pix = (pixel_t)dp;
1176
+ for (j = 0; j < d_width; j++) {
1177
+ dp[3] = (dp[3] * i) / size; /* alpha */
1178
+ dp += pix_width;
1179
+ }
1180
+
1181
+ dp = d_pix + ((d_height - i - 1) * d_rowstride);
1182
+ for (j = 0; j < d_width; j++) {
1183
+ dp[3] = (dp[3] * i) / size; /* alpha */
1184
+ dp += pix_width;
1185
+ }
1186
+
1187
+ }
1188
+ for (j = 0; j < d_height; j++) {
1189
+ //pix = (pixel_t)GINT_TO_POINTER(GPOINTER_TO_INT(d_pix) + (j * d_rowstride));
1190
+ dp = d_pix + ((d_height - i - 1) * d_rowstride);
1191
+ for (i = 0; i < MIN(size, d_width); i++) {
1192
+ dp[3] = (dp[3] * i) / size; /* alpha */
1193
+ dp += pix_width;
1194
+ }
1195
+
1196
+ dp = d_pix + (j * d_rowstride) + (pix_width * d_width);
1197
+ for (i = 0; i < MIN(size, d_width); i++) {
1198
+ dp[3] = (dp[3] * i) / size; /* alpha */
1199
+ dp -= pix_width;
1200
+ }
1201
+ }
1202
+
1203
+ return dest;
1204
+ }
1205
+
1206
+
1207
+
1208
+ /*
1209
+ GdkPixbuf *pixbuf_op(GdkPixbuf *src, GdkPixbuf *dest,
1210
+ */
1211
+
1212
+ static GdkPixbuf *pixbuf_perspect_v(GdkPixbuf *src, int top_x1, int top_x2, int bot_x1, int bot_x2)
1213
+ {
1214
+ int s_width, s_height, s_rowstride;
1215
+ int d_width, d_height, d_rowstride;
1216
+ guchar *s_pix;
1217
+ guchar *d_pix;
1218
+ guchar *sp;
1219
+ guchar *dp;
1220
+ gboolean has_alpha;
1221
+ GdkPixbuf *dest;
1222
+ int min_x, max_x, top_width, bot_width;
1223
+ int x,y,alpha,channels,s_channels;
1224
+ int row_width;
1225
+ double row_offset, row_end;
1226
+ double row_offset2, row_end2;
1227
+ double left_theta, right_theta;
1228
+ pixel_t spx[3];
1229
+ double ex;
1230
+
1231
+ s_width = gdk_pixbuf_get_width(src);
1232
+ s_height = gdk_pixbuf_get_height(src);
1233
+ has_alpha = gdk_pixbuf_get_has_alpha(src);
1234
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
1235
+ s_pix = gdk_pixbuf_get_pixels(src);
1236
+
1237
+
1238
+ g_return_val_if_fail((top_x2 - top_x1) <= s_width, NULL);
1239
+ g_return_val_if_fail((bot_x2 - bot_x1) <= s_width, NULL);
1240
+
1241
+ d_width = s_width;
1242
+ d_height = s_height;
1243
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, d_width, d_height);
1244
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
1245
+ d_pix = gdk_pixbuf_get_pixels(dest);
1246
+
1247
+ // Shortcut ... should be harmless?
1248
+ // We should really only touch info
1249
+ // Within the range d_pix + (d_rowstride * y) + ((has_alpha ? 4 : 3) * x)
1250
+ bzero(d_pix, (d_rowstride * d_height));
1251
+
1252
+ top_width = top_x2 - top_x1;
1253
+ bot_width = bot_x2 - bot_x1;
1254
+
1255
+ min_x = MIN(top_x1, bot_x1);
1256
+ max_x = MAX(top_x2, bot_x2);
1257
+
1258
+ s_channels = has_alpha ? 4 : 3;
1259
+ channels = 4;
1260
+
1261
+ left_theta = ((double)(min_x == bot_x1 ? top_x1 : bot_x1) - min_x) / (double)d_height;
1262
+ right_theta = ((double)max_x - ((max_x == bot_x2) ? top_x2 : bot_x2)) / (double)d_height;
1263
+
1264
+
1265
+ for (y = 0; y < d_height; y++) {
1266
+ sp = s_pix + (y * s_rowstride);
1267
+
1268
+ row_offset = min_x;
1269
+ row_end = max_x;
1270
+
1271
+ row_offset2 = min_x;
1272
+ row_end2 = max_x;
1273
+
1274
+ row_offset += (left_theta * ((min_x == bot_x1) ? (d_height - y - 1) : y));
1275
+ row_end -= (right_theta * ((max_x == bot_x2) ? (d_height - y - 1) : y));
1276
+
1277
+ row_offset2 += (left_theta * ((min_x == bot_x1) ? (d_height - y) : y+1));
1278
+ row_end2 -= (right_theta * ((max_x == bot_x2) ? (d_height - y) : y+1));
1279
+
1280
+ row_width = ceil(row_end) - floor(row_offset);
1281
+
1282
+ dp = d_pix + (y * d_rowstride) + ((int)floor(row_offset) * channels);
1283
+
1284
+ for (x = (int)floor(row_offset); x < (int)ceil(row_end); x++)
1285
+ {
1286
+ ex = x - floor(row_offset);
1287
+
1288
+ if ((x < ceil(row_offset)))
1289
+ {
1290
+ alpha = ((int) ((double)255 * (ceil(row_offset) - row_offset)));
1291
+ alpha = MAX(alpha,0);
1292
+ }
1293
+ else if ((x >= floor(row_end)))
1294
+ {
1295
+ alpha = ((int) ((double)255 * (row_end - floor(row_end))));
1296
+ alpha = MAX(alpha,0);
1297
+ }
1298
+ else
1299
+ {
1300
+ alpha = 0xff;
1301
+ }
1302
+
1303
+ spx[0] = PIXEL(sp, s_channels, (int)floor(((ex - 1) * (double)s_width) / (double)row_width));
1304
+ spx[1] = PIXEL(sp, s_channels, (int)floor((ex * (double)s_width) / (double)row_width));
1305
+ spx[2] = PIXEL(sp, s_channels, (int)floor(((ex + 1) * (double)s_width) / (double)row_width));
1306
+
1307
+ *(dp++) = ((spx[1]->r * 14) + ((spx[0]->r + spx[2]->r))) >> 4; /* red */
1308
+ *(dp++) = ((spx[1]->g * 14) + ((spx[0]->g + spx[2]->g))) >> 4; /* green */
1309
+ *(dp++) = ((spx[1]->b * 14) + ((spx[0]->b + spx[2]->b))) >> 4; /* blue */
1310
+ if (has_alpha)
1311
+ *(dp++) = sqrt(alpha * (((spx[1]->a * 14) + ((spx[0]->a + spx[2]->a))) >> 4)); /* alpha */
1312
+ else
1313
+ *(dp++) = alpha; /* alpha */
1314
+ }
1315
+
1316
+ }
1317
+
1318
+ return dest;
1319
+ }
1320
+
1321
+ static VALUE pixbuf_mask_area(GdkPixbuf *mask, double cutoff)
1322
+ {
1323
+ long int x0 = 0, x1 = 0, y0 = 0, y1=0;
1324
+ long int m_has_alpha;
1325
+ long int m_width, m_height, m_rowstride;
1326
+ guchar *m_pix, *mp;
1327
+ long int y, x;
1328
+ long pix_width;
1329
+ volatile
1330
+ double grey;
1331
+
1332
+ g_return_val_if_fail(mask != NULL, Qnil);
1333
+
1334
+ m_width = gdk_pixbuf_get_width(mask);
1335
+ m_height = gdk_pixbuf_get_height(mask);
1336
+ m_has_alpha = gdk_pixbuf_get_has_alpha(mask);
1337
+ m_rowstride = gdk_pixbuf_get_rowstride(mask);
1338
+ m_pix = gdk_pixbuf_get_pixels(mask);
1339
+
1340
+ pix_width = (m_has_alpha ? 4 : 3);
1341
+
1342
+
1343
+ x1 = m_width;
1344
+ y1 = m_height;
1345
+
1346
+ for (y = 0; y < m_height; y++)
1347
+ {
1348
+ mp = m_pix;
1349
+ for (x = 0; x < m_width; x++)
1350
+ {
1351
+ grey = GIMP_RGB_TO_GREY(mp[0], mp[1], mp[2]);
1352
+ if (grey < cutoff)// ie. darker than cutoff
1353
+ {
1354
+ if (x0 == 0)
1355
+ {
1356
+ x0 = MAX(x0, x);
1357
+ x1 = MIN(x1, x);
1358
+ }
1359
+ else
1360
+ {
1361
+ x0 = MIN(x0, x);
1362
+ x1 = MAX(x1, x);
1363
+ }
1364
+
1365
+ if (y0 == 0)
1366
+ {
1367
+ y0 = MAX(y0, y);
1368
+ y1 = MIN(y1, y);
1369
+ }
1370
+ else
1371
+ {
1372
+ y0 = MIN(y0, y);
1373
+ y1 = MAX(y1, y);
1374
+ }
1375
+ }
1376
+
1377
+ mp += pix_width;
1378
+ }
1379
+ m_pix += m_rowstride;
1380
+ }
1381
+
1382
+ return rb_ary_new3(4, INT2NUM(x0), INT2NUM(y0), INT2NUM(x1), INT2NUM(y1));
1383
+ }
1384
+
1385
+ static inline VALUE
1386
+ unref_pixbuf(GdkPixbuf *pixbuf)
1387
+ {
1388
+ volatile VALUE pb = Qnil;
1389
+
1390
+ pb = GOBJ2RVAL(pixbuf);
1391
+
1392
+ g_object_unref(pixbuf);
1393
+
1394
+ return pb;
1395
+ }
1396
+
1397
+
1398
+ /* Code */
1399
+ static VALUE
1400
+ PixbufUtils_CLASS_remove_alpha(VALUE self, VALUE __v_src, VALUE __v_col)
1401
+ {
1402
+ VALUE __p_retval = Qnil;
1403
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1404
+ GdkColor * col; GdkColor * __orig_col;
1405
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1406
+ __orig_col = col = RVAL2BOXED(__v_col, GDK_TYPE_COLOR);
1407
+
1408
+ #line 1360 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1409
+
1410
+ do {
1411
+ GdkPixbuf * dest ;
1412
+ uint w,h, pixcol;
1413
+ IGNORE(self);
1414
+ pixcol = (((col->red >> 8)&0xff) << 24) | (((col->green >> 8)&0xff) << 16) | (((col->blue >> 8)&0xff) << 8) | 0xFF;
1415
+ w=gdk_pixbuf_get_width(src);
1416
+ h=gdk_pixbuf_get_height(src);
1417
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, w, h);
1418
+ if(!dest) rb_raise(rb_eNoMemError, "Unable to allocate memory for pixbuf");
1419
+ gdk_pixbuf_fill(dest, pixcol);
1420
+ gdk_pixbuf_composite(src, dest, 0, 0, w, h, 0, 0, 1.0, 1.0, GDK_INTERP_NEAREST, 0xff);
1421
+ do { __p_retval = unref_pixbuf((dest)); goto out; } while(0);
1422
+
1423
+ } while(0);
1424
+
1425
+ out:
1426
+ ;
1427
+ ;
1428
+ return __p_retval;
1429
+ }
1430
+
1431
+ static VALUE
1432
+ PixbufUtils_CLASS_sharpen(VALUE self, VALUE __v_src, VALUE __v_radius)
1433
+ {
1434
+ VALUE __p_retval = Qnil;
1435
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1436
+ int radius; int __orig_radius;
1437
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1438
+ __orig_radius = radius = NUM2INT(__v_radius);
1439
+
1440
+ #line 1381 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1441
+ IGNORE(self);
1442
+ do { __p_retval = unref_pixbuf((pixbuf_sharpen(src, radius))); goto out; } while(0);
1443
+ out:
1444
+ ;
1445
+ return __p_retval;
1446
+ }
1447
+
1448
+ static VALUE
1449
+ PixbufUtils_CLASS_extract_alpha(int __p_argc, VALUE *__p_argv, VALUE self)
1450
+ {
1451
+ VALUE __p_retval = Qnil;
1452
+ VALUE __v_src = Qnil;
1453
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1454
+ VALUE __v_cutoff = Qnil;
1455
+ int cutoff; int __orig_cutoff;
1456
+ VALUE __v_force_2bit = Qnil;
1457
+ bool force_2bit; bool __orig_force_2bit;
1458
+
1459
+ /* Scan arguments */
1460
+ rb_scan_args(__p_argc, __p_argv, "12",&__v_src, &__v_cutoff, &__v_force_2bit);
1461
+
1462
+ /* Set defaults */
1463
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1464
+
1465
+ if (__p_argc > 1)
1466
+ __orig_cutoff = cutoff = NUM2INT(__v_cutoff);
1467
+ else
1468
+ cutoff = 127;
1469
+
1470
+ if (__p_argc > 2)
1471
+ __orig_force_2bit = force_2bit = RTEST(__v_force_2bit);
1472
+ else
1473
+ force_2bit = FALSE;
1474
+
1475
+
1476
+ #line 1385 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1477
+ IGNORE(self);
1478
+ do { __p_retval = unref_pixbuf((pixbuf_extract_alpha(src, cutoff, force_2bit))); goto out; } while(0);
1479
+ out:
1480
+ ;
1481
+ return __p_retval;
1482
+ }
1483
+
1484
+ static VALUE
1485
+ PixbufUtils_CLASS_blur(VALUE self, VALUE __v_src, VALUE __v_radius)
1486
+ {
1487
+ VALUE __p_retval = Qnil;
1488
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1489
+ int radius; int __orig_radius;
1490
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1491
+ __orig_radius = radius = NUM2INT(__v_radius);
1492
+
1493
+ #line 1389 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1494
+ IGNORE(self);
1495
+ do { __p_retval = unref_pixbuf((pixbuf_blur(gdk_pixbuf_copy(src), radius))); goto out; } while(0);
1496
+ out:
1497
+ ;
1498
+ return __p_retval;
1499
+ }
1500
+
1501
+ static VALUE
1502
+ PixbufUtils_CLASS_rotate_90(VALUE self, VALUE __v_src, VALUE __v_counter_clockwise)
1503
+ {
1504
+ VALUE __p_retval = Qnil;
1505
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1506
+ bool counter_clockwise; bool __orig_counter_clockwise;
1507
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1508
+ __orig_counter_clockwise = counter_clockwise = RTEST(__v_counter_clockwise);
1509
+
1510
+ #line 1393 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1511
+ IGNORE(self);
1512
+ do { __p_retval = unref_pixbuf((pixbuf_rotate(src, counter_clockwise ? ANGLE_270 : ANGLE_90))); goto out; } while(0);
1513
+ out:
1514
+ ;
1515
+ return __p_retval;
1516
+ }
1517
+
1518
+ static VALUE
1519
+ PixbufUtils_CLASS_rotate_cw(VALUE self, VALUE __v_src)
1520
+ {
1521
+ VALUE __p_retval = Qnil;
1522
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1523
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1524
+
1525
+ #line 1397 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1526
+ IGNORE(self);
1527
+ do { __p_retval = unref_pixbuf((pixbuf_rotate(src, ANGLE_90))); goto out; } while(0);
1528
+ out:
1529
+ ;
1530
+ return __p_retval;
1531
+ }
1532
+
1533
+ static VALUE
1534
+ PixbufUtils_CLASS_rotate_180(VALUE self, VALUE __v_src)
1535
+ {
1536
+ VALUE __p_retval = Qnil;
1537
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1538
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1539
+
1540
+ #line 1401 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1541
+ IGNORE(self);
1542
+ do { __p_retval = unref_pixbuf((pixbuf_rotate(src, ANGLE_180))); goto out; } while(0);
1543
+ out:
1544
+ ;
1545
+ return __p_retval;
1546
+ }
1547
+
1548
+ static VALUE
1549
+ PixbufUtils_CLASS_rotate(VALUE self, VALUE __v_src, VALUE __v_angle)
1550
+ {
1551
+ VALUE __p_retval = Qnil;
1552
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1553
+ int angle; int __orig_angle;
1554
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1555
+ __orig_angle = angle = NUM2INT(__v_angle);
1556
+
1557
+ #line 1405 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1558
+ IGNORE(self);
1559
+ g_assert(angle == 0 || angle == 90 || angle == 180 || angle == 270);
1560
+ do { __p_retval = unref_pixbuf((pixbuf_rotate(src, (rotate_angle_t)angle))); goto out; } while(0);
1561
+ out:
1562
+ ;
1563
+ return __p_retval;
1564
+ }
1565
+
1566
+ static VALUE
1567
+ PixbufUtils_CLASS_rotate_ccw(VALUE self, VALUE __v_src)
1568
+ {
1569
+ VALUE __p_retval = Qnil;
1570
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1571
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1572
+
1573
+ #line 1410 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1574
+ IGNORE(self);
1575
+ do { __p_retval = unref_pixbuf((pixbuf_rotate(src, ANGLE_270))); goto out; } while(0);
1576
+ out:
1577
+ ;
1578
+ return __p_retval;
1579
+ }
1580
+
1581
+ static VALUE
1582
+ PixbufUtils_CLASS_gamma_pling(VALUE self, VALUE __v_src, VALUE __v_level)
1583
+ {
1584
+ VALUE __p_retval = Qnil;
1585
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1586
+ double level; double __orig_level;
1587
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1588
+ __orig_level = level = NUM2DBL(__v_level);
1589
+
1590
+ #line 1414 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1591
+ IGNORE(self);
1592
+ do { __p_retval = GOBJ2RVAL(pixbuf_gamma(src, src, level)); goto out; } while(0);
1593
+ out:
1594
+ ;
1595
+ return __p_retval;
1596
+ }
1597
+
1598
+ static VALUE
1599
+ PixbufUtils_CLASS_soften_edges_pling(VALUE self, VALUE __v_src, VALUE __v_size)
1600
+ {
1601
+ VALUE __p_retval = Qnil;
1602
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1603
+ int size; int __orig_size;
1604
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1605
+ __orig_size = size = NUM2INT(__v_size);
1606
+
1607
+ #line 1418 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1608
+ IGNORE(self);
1609
+ do { __p_retval = GOBJ2RVAL(pixbuf_soften_edges(src, size)); goto out; } while(0);
1610
+ out:
1611
+ ;
1612
+ return __p_retval;
1613
+ }
1614
+
1615
+ static VALUE
1616
+ PixbufUtils_CLASS_gamma(VALUE self, VALUE __v_src, VALUE __v_level)
1617
+ {
1618
+ VALUE __p_retval = Qnil;
1619
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1620
+ double level; double __orig_level;
1621
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1622
+ __orig_level = level = NUM2DBL(__v_level);
1623
+
1624
+ #line 1422 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1625
+ IGNORE(self);
1626
+ do { __p_retval = unref_pixbuf((pixbuf_gamma(src, gdk_pixbuf_copy(src), level))); goto out; } while(0);
1627
+ out:
1628
+ ;
1629
+ return __p_retval;
1630
+ }
1631
+
1632
+ static VALUE
1633
+ PixbufUtils_CLASS_greyscale_pling(VALUE self, VALUE __v_src)
1634
+ {
1635
+ VALUE __p_retval = Qnil;
1636
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1637
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1638
+
1639
+ #line 1426 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1640
+ IGNORE(self);
1641
+ do { __p_retval = GOBJ2RVAL(pixbuf_greyscale(src, src)); goto out; } while(0);
1642
+ out:
1643
+ ;
1644
+ return __p_retval;
1645
+ }
1646
+
1647
+ static VALUE
1648
+ PixbufUtils_CLASS_to_tiff(VALUE self, VALUE __v_src, VALUE __v_filename)
1649
+ {
1650
+ VALUE __p_retval = Qnil;
1651
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1652
+ char * filename; char * __orig_filename;
1653
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1654
+ __orig_filename = filename = ( NIL_P(__v_filename) ? NULL : StringValuePtr(__v_filename) );
1655
+
1656
+ #line 1430 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1657
+ IGNORE(self);
1658
+ do { __p_retval = ((pixbuf_save_tiff(src, filename)) ? Qtrue : Qfalse); goto out; } while(0);
1659
+ out:
1660
+ ;
1661
+ return __p_retval;
1662
+ }
1663
+
1664
+ static VALUE
1665
+ PixbufUtils_CLASS_greyscale(VALUE self, VALUE __v_src)
1666
+ {
1667
+ VALUE __p_retval = Qnil;
1668
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1669
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1670
+
1671
+ #line 1434 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1672
+ IGNORE(self);
1673
+ do { __p_retval = unref_pixbuf((pixbuf_greyscale(src, gdk_pixbuf_copy(src)))); goto out; } while(0);
1674
+ out:
1675
+ ;
1676
+ return __p_retval;
1677
+ }
1678
+
1679
+ static VALUE
1680
+ PixbufUtils_CLASS_greyscale_go_pling(VALUE self, VALUE __v_src)
1681
+ {
1682
+ VALUE __p_retval = Qnil;
1683
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1684
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1685
+
1686
+ #line 1438 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1687
+ IGNORE(self);
1688
+ do { __p_retval = GOBJ2RVAL(pixbuf_greyscale_go(src, src)); goto out; } while(0);
1689
+ out:
1690
+ ;
1691
+ return __p_retval;
1692
+ }
1693
+
1694
+ static VALUE
1695
+ PixbufUtils_CLASS_greyscale_go(VALUE self, VALUE __v_src)
1696
+ {
1697
+ VALUE __p_retval = Qnil;
1698
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1699
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1700
+
1701
+ #line 1442 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1702
+ IGNORE(self);
1703
+ do { __p_retval = unref_pixbuf((pixbuf_greyscale_go(src, gdk_pixbuf_copy(src)))); goto out; } while(0);
1704
+ out:
1705
+ ;
1706
+ return __p_retval;
1707
+ }
1708
+
1709
+ static VALUE
1710
+ PixbufUtils_CLASS_tint(VALUE self, VALUE __v_src, VALUE __v_r, VALUE __v_g, VALUE __v_b)
1711
+ {
1712
+ VALUE __p_retval = Qnil;
1713
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1714
+ int r; int __orig_r;
1715
+ int g; int __orig_g;
1716
+ int b; int __orig_b;
1717
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1718
+ __orig_r = r = NUM2INT(__v_r);
1719
+ __orig_g = g = NUM2INT(__v_g);
1720
+ __orig_b = b = NUM2INT(__v_b);
1721
+
1722
+ #line 1446 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1723
+ IGNORE(self);
1724
+ do { __p_retval = unref_pixbuf((pixbuf_tint(src, gdk_pixbuf_copy(src), r, g, b))); goto out; } while(0);
1725
+ out:
1726
+ ;
1727
+ return __p_retval;
1728
+ }
1729
+
1730
+ static VALUE
1731
+ PixbufUtils_CLASS_perspect_v(VALUE self, VALUE __v_src, VALUE __v_top_x1, VALUE __v_top_x2, VALUE __v_bot_x1, VALUE __v_bot_x2)
1732
+ {
1733
+ VALUE __p_retval = Qnil;
1734
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1735
+ int top_x1; int __orig_top_x1;
1736
+ int top_x2; int __orig_top_x2;
1737
+ int bot_x1; int __orig_bot_x1;
1738
+ int bot_x2; int __orig_bot_x2;
1739
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1740
+ __orig_top_x1 = top_x1 = NUM2INT(__v_top_x1);
1741
+ __orig_top_x2 = top_x2 = NUM2INT(__v_top_x2);
1742
+ __orig_bot_x1 = bot_x1 = NUM2INT(__v_bot_x1);
1743
+ __orig_bot_x2 = bot_x2 = NUM2INT(__v_bot_x2);
1744
+
1745
+ #line 1450 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1746
+ IGNORE(self);
1747
+ do { __p_retval = unref_pixbuf((pixbuf_perspect_v(src, top_x1, top_x2, bot_x1, bot_x2))); goto out; } while(0);
1748
+ out:
1749
+ ;
1750
+ return __p_retval;
1751
+ }
1752
+
1753
+ static VALUE
1754
+ PixbufUtils_CLASS_mask(VALUE self, VALUE __v_src, VALUE __v_mask)
1755
+ {
1756
+ VALUE __p_retval = Qnil;
1757
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1758
+ GdkPixbuf * mask; GdkPixbuf * __orig_mask;
1759
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1760
+ __orig_mask = mask = GDK_PIXBUF(RVAL2GOBJ(__v_mask));
1761
+
1762
+ #line 1454 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1763
+ IGNORE(self);
1764
+ do { __p_retval = unref_pixbuf((pixbuf_mask(src, mask))); goto out; } while(0);
1765
+ out:
1766
+ ;
1767
+ ;
1768
+ return __p_retval;
1769
+ }
1770
+
1771
+ static VALUE
1772
+ PixbufUtils_CLASS_blend5050(VALUE self, VALUE __v_src1, VALUE __v_src2)
1773
+ {
1774
+ VALUE __p_retval = Qnil;
1775
+ GdkPixbuf * src1; GdkPixbuf * __orig_src1;
1776
+ GdkPixbuf * src2; GdkPixbuf * __orig_src2;
1777
+ __orig_src1 = src1 = GDK_PIXBUF(RVAL2GOBJ(__v_src1));
1778
+ __orig_src2 = src2 = GDK_PIXBUF(RVAL2GOBJ(__v_src2));
1779
+
1780
+ #line 1458 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1781
+ IGNORE(self);
1782
+ do { __p_retval = unref_pixbuf((pixbuf_blend5050(src1, src2))); goto out; } while(0);
1783
+ out:
1784
+ ;
1785
+ ;
1786
+ return __p_retval;
1787
+ }
1788
+
1789
+ static VALUE
1790
+ PixbufUtils_CLASS_mask_area(int __p_argc, VALUE *__p_argv, VALUE self)
1791
+ {
1792
+ VALUE __p_retval = Qnil;
1793
+ VALUE __v_mask = Qnil;
1794
+ GdkPixbuf * mask; GdkPixbuf * __orig_mask;
1795
+ VALUE __v_cutoff = Qnil;
1796
+ int cutoff; int __orig_cutoff;
1797
+
1798
+ /* Scan arguments */
1799
+ rb_scan_args(__p_argc, __p_argv, "11",&__v_mask, &__v_cutoff);
1800
+
1801
+ /* Set defaults */
1802
+ __orig_mask = mask = GDK_PIXBUF(RVAL2GOBJ(__v_mask));
1803
+
1804
+ if (__p_argc > 1)
1805
+ __orig_cutoff = cutoff = NUM2INT(__v_cutoff);
1806
+ else
1807
+ cutoff = 127;
1808
+
1809
+
1810
+ #line 1462 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1811
+ IGNORE(self);
1812
+ do { __p_retval = pixbuf_mask_area(mask, cutoff); goto out; } while(0);
1813
+ out:
1814
+ ;
1815
+ return __p_retval;
1816
+ }
1817
+
1818
+ static VALUE
1819
+ PixbufUtils_CLASS_scale_max(int __p_argc, VALUE *__p_argv, VALUE self)
1820
+ {
1821
+ VALUE __p_retval = Qnil;
1822
+ VALUE __v_src = Qnil;
1823
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1824
+ VALUE __v_max = Qnil;
1825
+ gulong max; gulong __orig_max;
1826
+ VALUE __v_interp = Qnil;
1827
+ GdkInterpType interp; GdkInterpType __orig_interp;
1828
+
1829
+ /* Scan arguments */
1830
+ rb_scan_args(__p_argc, __p_argv, "21",&__v_src, &__v_max, &__v_interp);
1831
+
1832
+ /* Set defaults */
1833
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1834
+
1835
+ __orig_max = max = NUM2UINT(__v_max);
1836
+
1837
+ if (__p_argc > 2)
1838
+ __orig_interp = interp = RVAL2GENUM(__v_interp, GDK_TYPE_INTERP_TYPE);
1839
+ else
1840
+ interp = GDK_INTERP_BILINEAR;
1841
+
1842
+
1843
+ #line 1466 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1844
+
1845
+ do {
1846
+ gulong width, height, largest;
1847
+ gdouble scale ;
1848
+ IGNORE(self);
1849
+ width = gdk_pixbuf_get_width(src);
1850
+ height = gdk_pixbuf_get_height(src);
1851
+ largest = MAX(width, height);
1852
+ if (max > largest) { do { __p_retval = unref_pixbuf((gdk_pixbuf_copy(src))); goto out; } while(0); } scale = (double)(max) / (double)(largest);
1853
+ do { __p_retval = unref_pixbuf((gdk_pixbuf_scale_simple(src, (int)(scale * width), (int)(scale * height), interp))); goto out; } while(0);
1854
+
1855
+ } while(0);
1856
+
1857
+ out:
1858
+ ;
1859
+ ;
1860
+ ;
1861
+ return __p_retval;
1862
+ }
1863
+
1864
+ static VALUE
1865
+ PixbufUtils_CLASS_draw_scaled(int __p_argc, VALUE *__p_argv, VALUE self)
1866
+ {
1867
+ VALUE __p_retval = Qnil;
1868
+ VALUE __v_drawable = Qnil;
1869
+ GdkDrawable * drawable; GdkDrawable * __orig_drawable;
1870
+ VALUE __v_src = Qnil;
1871
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1872
+ VALUE __v_x = Qnil;
1873
+ int x; int __orig_x;
1874
+ VALUE __v_y = Qnil;
1875
+ int y; int __orig_y;
1876
+ VALUE __v_width = Qnil;
1877
+ int width; int __orig_width;
1878
+ VALUE __v_height = Qnil;
1879
+ int height; int __orig_height;
1880
+ VALUE __v_interp = Qnil;
1881
+ GdkInterpType interp; GdkInterpType __orig_interp;
1882
+
1883
+ /* Scan arguments */
1884
+ rb_scan_args(__p_argc, __p_argv, "61",&__v_drawable, &__v_src, &__v_x, &__v_y, &__v_width, &__v_height, &__v_interp);
1885
+
1886
+ /* Set defaults */
1887
+ __orig_drawable = drawable = RVAL2GOBJ(__v_drawable);
1888
+
1889
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1890
+
1891
+ __orig_x = x = NUM2INT(__v_x);
1892
+
1893
+ __orig_y = y = NUM2INT(__v_y);
1894
+
1895
+ __orig_width = width = NUM2INT(__v_width);
1896
+
1897
+ __orig_height = height = NUM2INT(__v_height);
1898
+
1899
+ if (__p_argc > 6)
1900
+ __orig_interp = interp = RVAL2GENUM(__v_interp, GDK_TYPE_INTERP_TYPE);
1901
+ else
1902
+ interp = GDK_INTERP_BILINEAR;
1903
+
1904
+
1905
+ #line 1484 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1906
+
1907
+ do {
1908
+ GdkPixbuf * tmp ;
1909
+ IGNORE(self);
1910
+ if((width == gdk_pixbuf_get_width(src)) && (height == gdk_pixbuf_get_height(src))) { tmp = src;
1911
+ } else if (((tmp = (GdkPixbuf*)g_object_get_data(G_OBJECT(src), "pixbuf_utils_scaled")) == NULL) || ((width != gdk_pixbuf_get_width(tmp)) || (height != gdk_pixbuf_get_height(tmp)))) { if (tmp) fprintf(stderr, "Old pixbuf is %i,%i\n", gdk_pixbuf_get_width(tmp), gdk_pixbuf_get_height(tmp));
1912
+ fprintf(stderr, "Scaling pixbuf to %i,%i\n", width, height);
1913
+ tmp = gdk_pixbuf_scale_simple(src, width, height, interp);
1914
+ g_object_set_data_full(G_OBJECT(src), "pixbuf_utils_scaled", tmp, g_object_unref);
1915
+ } g_return_val_if_fail(tmp != NULL, Qfalse);
1916
+ gdk_draw_pixbuf(/* GdkDrawable *drawable */ drawable, /* GdkGC *gc */ NULL, /* GdkPixbuf *pixbuf */ tmp, /* gint src_x */ 0, /* gint src_y */ 0, /* gint dest_x */ x, /* gint dest_y */ y, /* gint width */ width, /* gint height */ height, /* GdkRgbDither dither */ GDK_RGB_DITHER_NORMAL, /* gint x_dither */ 0, /* gint y_dither */ 0);
1917
+ do { __p_retval = Qtrue; goto out; } while(0);
1918
+
1919
+ } while(0);
1920
+
1921
+ out:
1922
+ ;
1923
+ ;
1924
+ ;
1925
+ return __p_retval;
1926
+ }
1927
+
1928
+ static VALUE
1929
+ PixbufUtils_CLASS_draw_scaled_clip(int __p_argc, VALUE *__p_argv, VALUE self)
1930
+ {
1931
+ VALUE __p_retval = Qnil;
1932
+ VALUE __v_drawable = Qnil;
1933
+ GdkDrawable * drawable; GdkDrawable * __orig_drawable;
1934
+ VALUE __v_src = Qnil;
1935
+ GdkPixbuf * src; GdkPixbuf * __orig_src;
1936
+ VALUE __v_x = Qnil;
1937
+ int x; int __orig_x;
1938
+ VALUE __v_y = Qnil;
1939
+ int y; int __orig_y;
1940
+ VALUE __v_width = Qnil;
1941
+ int width; int __orig_width;
1942
+ VALUE __v_height = Qnil;
1943
+ int height; int __orig_height;
1944
+ VALUE __v_clip_area = Qnil;
1945
+ GdkRectangle * clip_area; GdkRectangle * __orig_clip_area;
1946
+ VALUE __v_interp = Qnil;
1947
+ GdkInterpType interp; GdkInterpType __orig_interp;
1948
+
1949
+ /* Scan arguments */
1950
+ rb_scan_args(__p_argc, __p_argv, "71",&__v_drawable, &__v_src, &__v_x, &__v_y, &__v_width, &__v_height, &__v_clip_area, &__v_interp);
1951
+
1952
+ /* Set defaults */
1953
+ __orig_drawable = drawable = RVAL2GOBJ(__v_drawable);
1954
+
1955
+ __orig_src = src = GDK_PIXBUF(RVAL2GOBJ(__v_src));
1956
+
1957
+ __orig_x = x = NUM2INT(__v_x);
1958
+
1959
+ __orig_y = y = NUM2INT(__v_y);
1960
+
1961
+ __orig_width = width = NUM2INT(__v_width);
1962
+
1963
+ __orig_height = height = NUM2INT(__v_height);
1964
+
1965
+ __orig_clip_area = clip_area = RVAL2BOXED(__v_clip_area, GDK_TYPE_RECTANGLE);
1966
+
1967
+ if (__p_argc > 7)
1968
+ __orig_interp = interp = RVAL2GENUM(__v_interp, GDK_TYPE_INTERP_TYPE);
1969
+ else
1970
+ interp = GDK_INTERP_BILINEAR;
1971
+
1972
+
1973
+ #line 1520 "/home/geoff/Projects/pixbufutils/ext/pixbufutils/pixbufutils.cr"
1974
+
1975
+ do {
1976
+ GdkPixbuf * tmp ;
1977
+ GdkGC * gc ;
1978
+ IGNORE(self);
1979
+ if((width == gdk_pixbuf_get_width(src)) && (height == gdk_pixbuf_get_height(src))) { tmp = src;
1980
+ } else if (((tmp = (GdkPixbuf*)g_object_get_data(G_OBJECT(src), "pixbuf_utils_scaled")) == NULL) || ((width != gdk_pixbuf_get_width(tmp)) || (height != gdk_pixbuf_get_height(tmp)))) { if (tmp) fprintf(stderr, "Old pixbuf is %i,%i\n", gdk_pixbuf_get_width(tmp), gdk_pixbuf_get_height(tmp));
1981
+ fprintf(stderr, "Scaling pixbuf to %i,%i\n", width, height);
1982
+ tmp = gdk_pixbuf_scale_simple(src, width, height, interp);
1983
+ g_object_set_data_full(G_OBJECT(src), "pixbuf_utils_scaled", tmp, g_object_unref);
1984
+ } g_return_val_if_fail(tmp != NULL, Qfalse);
1985
+ gc = gdk_gc_new(drawable);
1986
+ gdk_gc_set_clip_rectangle(GDK_GC(gc), clip_area);
1987
+ gdk_draw_pixbuf(/* GdkDrawable *drawable */ drawable, /* GdkGC *gc */ gc, /* GdkPixbuf *pixbuf */ tmp, /* gint src_x */ clip_area->x, /* gint src_y */ clip_area->y, /* gint dest_x */ x + clip_area->x, /* gint dest_y */ y + clip_area->y, /* gint width */ clip_area->width, /* gint height */ clip_area->height, /* GdkRgbDither dither */ GDK_RGB_DITHER_NORMAL, /* gint x_dither */ 0, /* gint y_dither */ 0);
1988
+ g_object_unref(gc);
1989
+ do { __p_retval = Qtrue; goto out; } while(0);
1990
+
1991
+ } while(0);
1992
+
1993
+ out:
1994
+ ;
1995
+ ;
1996
+ ;
1997
+ ;
1998
+ return __p_retval;
1999
+ }
2000
+
2001
+ /* Init */
2002
+ void
2003
+ Init_pixbufutils(void)
2004
+ {
2005
+ mPixbufUtils = rb_define_module("PixbufUtils");
2006
+ rb_define_singleton_method(mPixbufUtils, "remove_alpha", PixbufUtils_CLASS_remove_alpha, 2);
2007
+ rb_define_singleton_method(mPixbufUtils, "sharpen", PixbufUtils_CLASS_sharpen, 2);
2008
+ rb_define_singleton_method(mPixbufUtils, "extract_alpha", PixbufUtils_CLASS_extract_alpha, -1);
2009
+ rb_define_singleton_method(mPixbufUtils, "blur", PixbufUtils_CLASS_blur, 2);
2010
+ rb_define_singleton_method(mPixbufUtils, "rotate_90", PixbufUtils_CLASS_rotate_90, 2);
2011
+ rb_define_singleton_method(mPixbufUtils, "rotate_cw", PixbufUtils_CLASS_rotate_cw, 1);
2012
+ rb_define_singleton_method(mPixbufUtils, "rotate_180", PixbufUtils_CLASS_rotate_180, 1);
2013
+ rb_define_singleton_method(mPixbufUtils, "rotate", PixbufUtils_CLASS_rotate, 2);
2014
+ rb_define_singleton_method(mPixbufUtils, "rotate_ccw", PixbufUtils_CLASS_rotate_ccw, 1);
2015
+ rb_define_singleton_method(mPixbufUtils, "gamma!", PixbufUtils_CLASS_gamma_pling, 2);
2016
+ rb_define_singleton_method(mPixbufUtils, "soften_edges!", PixbufUtils_CLASS_soften_edges_pling, 2);
2017
+ rb_define_singleton_method(mPixbufUtils, "gamma", PixbufUtils_CLASS_gamma, 2);
2018
+ rb_define_singleton_method(mPixbufUtils, "greyscale!", PixbufUtils_CLASS_greyscale_pling, 1);
2019
+ rb_define_singleton_method(mPixbufUtils, "to_tiff", PixbufUtils_CLASS_to_tiff, 2);
2020
+ rb_define_singleton_method(mPixbufUtils, "greyscale", PixbufUtils_CLASS_greyscale, 1);
2021
+ rb_define_singleton_method(mPixbufUtils, "greyscale_go!", PixbufUtils_CLASS_greyscale_go_pling, 1);
2022
+ rb_define_singleton_method(mPixbufUtils, "greyscale_go", PixbufUtils_CLASS_greyscale_go, 1);
2023
+ rb_define_singleton_method(mPixbufUtils, "tint", PixbufUtils_CLASS_tint, 4);
2024
+ rb_define_singleton_method(mPixbufUtils, "perspect_v", PixbufUtils_CLASS_perspect_v, 5);
2025
+ rb_define_singleton_method(mPixbufUtils, "mask", PixbufUtils_CLASS_mask, 2);
2026
+ rb_define_singleton_method(mPixbufUtils, "blend5050", PixbufUtils_CLASS_blend5050, 2);
2027
+ rb_define_singleton_method(mPixbufUtils, "mask_area", PixbufUtils_CLASS_mask_area, -1);
2028
+ rb_define_singleton_method(mPixbufUtils, "scale_max", PixbufUtils_CLASS_scale_max, -1);
2029
+ rb_define_singleton_method(mPixbufUtils, "draw_scaled", PixbufUtils_CLASS_draw_scaled, -1);
2030
+ rb_define_singleton_method(mPixbufUtils, "draw_scaled_clip", PixbufUtils_CLASS_draw_scaled_clip, -1);
2031
+ }