pixbufutils 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }