pixbufutils 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1561 @@
1
+ %name pixbufutils
2
+ %pkg-config gdk-pixbuf-2.0
3
+ %include gdk-pixbuf/gdk-pixbuf.h
4
+ %include rbglib.h
5
+ %include rbgobject.h
6
+ %include tiffio.h
7
+
8
+ %include gdk/gdk.h
9
+
10
+ %option gtk=no
11
+ %pkg-config gdk-2.0
12
+ %lib tiff
13
+
14
+ %map GdkPixbuf* > VALUE : GOBJ2RVAL(%%)
15
+ %map VALUE > GdkPixbuf* : GDK_PIXBUF(RVAL2GOBJ(%%))
16
+
17
+ %map GtkWidget* > VALUE : GOBJ2RVAL(%%)
18
+ %map VALUE > GtkWidget* : GTK_WIDGET(RVAL2GOBJ(%%))
19
+ %map VALUE > gulong : NUM2UINT(%%)
20
+
21
+ %{
22
+
23
+ extern void Init_pixbufutils(void);
24
+
25
+ #ifndef IGNORE
26
+ #define IGNORE(x) x=x
27
+ #endif
28
+
29
+ static GdkPixbuf *pixbuf_extract_alpha(GdkPixbuf *src, int cutoff, int force_2bit)
30
+ {
31
+ int s_has_alpha, d_has_alpha;
32
+ int s_width, s_height, s_rowstride;
33
+ int d_width, d_height, d_rowstride;
34
+ GdkPixbuf *dest;
35
+ guchar *s_pix, *sp;
36
+ guchar *d_pix, *dp;
37
+ int i, j, pix_width, grey;
38
+
39
+ g_return_val_if_fail(src != NULL, NULL);
40
+
41
+ s_width = gdk_pixbuf_get_width(src);
42
+ s_height = gdk_pixbuf_get_height(src);
43
+ s_has_alpha = gdk_pixbuf_get_has_alpha(src);
44
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
45
+ s_pix = gdk_pixbuf_get_pixels(src);
46
+ g_return_val_if_fail(s_has_alpha, NULL);
47
+
48
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, s_width, s_height);
49
+
50
+ g_return_val_if_fail(dest != NULL, NULL);
51
+
52
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
53
+ d_pix = gdk_pixbuf_get_pixels(dest);
54
+
55
+ d_width = gdk_pixbuf_get_width(dest);
56
+ d_height = gdk_pixbuf_get_height(dest);
57
+ d_has_alpha = gdk_pixbuf_get_has_alpha(dest);
58
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
59
+ d_pix = gdk_pixbuf_get_pixels(dest);
60
+
61
+ g_return_val_if_fail(d_width == s_width, NULL);
62
+ g_return_val_if_fail(d_height == s_height, NULL);
63
+
64
+ pix_width = (s_has_alpha ? 4 : 3);
65
+
66
+ for (i = 0; i < s_height; i++) {
67
+ sp = s_pix;
68
+ dp = d_pix;
69
+
70
+ for (j = 0; j < s_width; j++) {
71
+ grey = sp[3];
72
+
73
+ if (grey < cutoff)
74
+ grey = 0;
75
+
76
+ if (force_2bit)
77
+ grey = (grey >= cutoff ? 255 : 0);
78
+
79
+ dp[0] = grey; /* red */
80
+ dp[1] = grey; /* green */
81
+ dp[2] = grey; /* blue */
82
+
83
+ dp += 3;
84
+ sp += 4;
85
+ }
86
+
87
+ d_pix += d_rowstride;
88
+ s_pix += s_rowstride;
89
+ }
90
+
91
+ return dest;
92
+ }
93
+
94
+
95
+ typedef enum {
96
+ ANGLE_0 = 0,
97
+ ANGLE_90 = 90,
98
+ ANGLE_180 = 180,
99
+ ANGLE_270 = 270
100
+ } rotate_angle_t;
101
+
102
+ static GdkPixbuf *
103
+ pixbuf_blur(GdkPixbuf *src, gint radius)
104
+ {
105
+ /* Pixels and Rowstride To Perform Blur On */
106
+ guchar *pixels;
107
+ GdkPixbuf *pixbuf;
108
+ gint rowstride, width, height;
109
+
110
+ pixbuf = gdk_pixbuf_copy(src);
111
+
112
+ /* Get Pixels and Rowstride Of Image Buffer */
113
+ if (pixbuf)
114
+ {
115
+ pixels = gdk_pixbuf_get_pixels (pixbuf);
116
+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
117
+ width = gdk_pixbuf_get_width(pixbuf);
118
+ height = gdk_pixbuf_get_height(pixbuf);
119
+ /*printf("%i, %i, %i, %i\n", rowstride, width, height, rowstride/width);*/
120
+ }
121
+ else
122
+ {
123
+ return NULL;
124
+ }
125
+ if (radius > 1)
126
+ {
127
+ /* Some Important Consts */
128
+ gint bytes = rowstride/width;
129
+ gboolean alpha = (bytes == 4);
130
+
131
+ gint div = radius+radius+1;
132
+ gint divsum = ((div+1)>>1)*((div+1)>>1);
133
+ gint dv[256*divsum]; /* Table of Const RGBA Values */
134
+
135
+ /* Some Important Variables */
136
+ guchar stack[div][bytes];
137
+ gint stackpointer;
138
+ gint stackstart;
139
+ gint vmin[MAX(width,height)];
140
+ guchar *sir;
141
+ gint rbs;
142
+
143
+ gint current = 0;
144
+
145
+ /* RGBA Sums
146
+ 0 - Sum of Incoming pixels(the radius pixels above the Center/to left of Center)
147
+ 1 - Sum of Outgoing pixels(the Center and the radius pixels below the Center/to right of Center)
148
+ 2 - Sum of All pixels within radius
149
+ */
150
+ gint rgba_sums[3][bytes];
151
+
152
+ /* RGBA Values */
153
+ guchar rgba[bytes][width*height];
154
+
155
+ /* Temp Indexes/Counters */
156
+ gint x, y, i, p, yp, yi=0, yw=0;
157
+
158
+ for (i=0; i<256*divsum; i++)
159
+ {
160
+ dv[i] = (i/divsum);
161
+ }
162
+
163
+ for (y=0; y < height; y++)
164
+ {
165
+ /* initialize sums to zero */
166
+ for (i = 0; i<bytes; i++)
167
+ {
168
+ rgba_sums[0][i] = 0;
169
+ rgba_sums[1][i] = 0;
170
+ rgba_sums[2][i] = 0;
171
+ }
172
+
173
+ /* Calculate Initial Sums For radius */
174
+ for(i=-radius; i<=radius; i++)
175
+ {
176
+ current = (yi + MIN(width - 1, MAX(i,0)))*bytes;
177
+
178
+ sir = stack[i+radius];
179
+
180
+ sir[0] = pixels[current + 0];
181
+ sir[1] = pixels[current + 1];
182
+ sir[2] = pixels[current + 2];
183
+ sir[3] = pixels[current + 3];
184
+
185
+ rbs = (radius + 1) - abs(i);
186
+
187
+ rgba_sums[2][0] += sir[0]*rbs;
188
+ rgba_sums[2][1] += sir[1]*rbs;
189
+ rgba_sums[2][2] += sir[2]*rbs;
190
+ if (alpha)
191
+ {
192
+ rgba_sums[2][3] += sir[3]*rbs;
193
+ }
194
+
195
+ if (i>0)
196
+ {
197
+ rgba_sums[0][0] += sir[0];
198
+ rgba_sums[0][1] += sir[1];
199
+ rgba_sums[0][2] += sir[2];
200
+ if (alpha)
201
+ {
202
+ rgba_sums[0][3] += sir[3];
203
+ }
204
+ }
205
+ else
206
+ {
207
+ rgba_sums[1][0] += sir[0];
208
+ rgba_sums[1][1] += sir[1];
209
+ rgba_sums[1][2] += sir[2];
210
+ if (alpha)
211
+ {
212
+ rgba_sums[1][3] += sir[3];
213
+ }
214
+ }
215
+ }
216
+
217
+ stackpointer = radius;
218
+
219
+ for (x=0; x<width; x++)
220
+ {
221
+ rgba[0][yi] = dv[rgba_sums[2][0]];
222
+ rgba[1][yi] = dv[rgba_sums[2][1]];
223
+ rgba[2][yi] = dv[rgba_sums[2][2]];
224
+ if (alpha)
225
+ {
226
+ rgba[3][yi] = dv[rgba_sums[2][3]];
227
+ }
228
+
229
+ rgba_sums[2][0] -= rgba_sums[1][0];
230
+ rgba_sums[2][1] -= rgba_sums[1][1];
231
+ rgba_sums[2][2] -= rgba_sums[1][2];
232
+ if (alpha)
233
+ {
234
+ rgba_sums[2][3] -= rgba_sums[1][3];
235
+ }
236
+
237
+ stackstart = stackpointer - radius + div;
238
+ sir = stack[stackstart%div];
239
+
240
+ rgba_sums[1][0] -= sir[0];
241
+ rgba_sums[1][1] -= sir[1];
242
+ rgba_sums[1][2] -= sir[2];
243
+ if (alpha)
244
+ {
245
+ rgba_sums[1][3] -= sir[3];
246
+ }
247
+
248
+ if(y==0)
249
+ {
250
+ vmin[x] = MIN(x + radius + 1, width - 1);
251
+ }
252
+
253
+ current = (yw + vmin[x])*bytes;
254
+
255
+ sir[0] = pixels[current + 0];
256
+ sir[1] = pixels[current + 1];
257
+ sir[2] = pixels[current + 2];
258
+ if (alpha)
259
+ {
260
+ sir[3] = pixels[current + 3];
261
+ }
262
+
263
+ rgba_sums[0][0] += sir[0];
264
+ rgba_sums[0][1] += sir[1];
265
+ rgba_sums[0][2] += sir[2];
266
+ if (alpha)
267
+ {
268
+ rgba_sums[0][3] += sir[3];
269
+ }
270
+
271
+ rgba_sums[2][0] += rgba_sums[0][0];
272
+ rgba_sums[2][1] += rgba_sums[0][1];
273
+ rgba_sums[2][2] += rgba_sums[0][2];
274
+ if (alpha)
275
+ {
276
+ rgba_sums[2][3] += rgba_sums[0][3];
277
+ }
278
+
279
+ stackpointer=(stackpointer+1)%div;
280
+ sir=stack[(stackpointer)%div];
281
+
282
+ rgba_sums[1][0] += sir[0];
283
+ rgba_sums[1][1] += sir[1];
284
+ rgba_sums[1][2] += sir[2];
285
+ if (alpha)
286
+ {
287
+ rgba_sums[1][3] += sir[3];
288
+ }
289
+
290
+ rgba_sums[0][0] -= sir[0];
291
+ rgba_sums[0][1] -= sir[1];
292
+ rgba_sums[0][2] -= sir[2];
293
+ if (alpha)
294
+ {
295
+ rgba_sums[0][3] -= sir[3];
296
+ }
297
+
298
+ yi++;
299
+ }
300
+
301
+ yw += width;
302
+ }
303
+
304
+ for (x=0; x<width; x++)
305
+ {
306
+ yp=-radius*width;
307
+
308
+ /* initialize sums to zero */
309
+ for (i = 0; i<bytes; i++)
310
+ {
311
+ rgba_sums[0][i] = 0;
312
+ rgba_sums[1][i] = 0;
313
+ rgba_sums[2][i] = 0;
314
+ }
315
+
316
+ /* Calculate Initial Sums For radius */
317
+ for(i=-radius; i<=radius; i++)
318
+ {
319
+ yi = MAX(0,yp) + x;
320
+
321
+ sir = stack[i+radius];
322
+
323
+ sir[0] = rgba[0][yi];
324
+ sir[1] = rgba[1][yi];
325
+ sir[2] = rgba[2][yi];
326
+ if (alpha)
327
+ {
328
+ sir[3] = rgba[3][yi];
329
+ }
330
+
331
+ rbs = (radius + 1) - abs(i);
332
+
333
+ rgba_sums[2][0] += rgba[0][yi]*rbs;
334
+ rgba_sums[2][1] += rgba[1][yi]*rbs;
335
+ rgba_sums[2][2] += rgba[2][yi]*rbs;
336
+ if (alpha)
337
+ {
338
+ rgba_sums[2][3] += rgba[3][yi]*rbs;
339
+ }
340
+
341
+ if (i>0)
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
+ else
352
+ {
353
+ rgba_sums[1][0] += sir[0];
354
+ rgba_sums[1][1] += sir[1];
355
+ rgba_sums[1][2] += sir[2];
356
+ if (alpha)
357
+ {
358
+ rgba_sums[1][3] += sir[3];
359
+ }
360
+ }
361
+
362
+ if(i < height - 1)
363
+ {
364
+ yp += width;
365
+ }
366
+ }
367
+
368
+ yi = x;
369
+ stackpointer = radius;
370
+
371
+ for (y=0; y<height; y++)
372
+ {
373
+ current = (yi)*bytes;
374
+
375
+ pixels[current + 0] = dv[rgba_sums[2][0]];
376
+ pixels[current + 1] = dv[rgba_sums[2][1]];
377
+ pixels[current + 2] = dv[rgba_sums[2][2]];
378
+ if (alpha)
379
+ {
380
+ pixels[current + 3] = dv[rgba_sums[2][3]];
381
+ }
382
+
383
+ rgba_sums[2][0] -= rgba_sums[1][0];
384
+ rgba_sums[2][1] -= rgba_sums[1][1];
385
+ rgba_sums[2][2] -= rgba_sums[1][2];
386
+ if (alpha)
387
+ {
388
+ rgba_sums[2][3] -= rgba_sums[1][3];
389
+ }
390
+
391
+ stackstart = stackpointer - radius + div;
392
+ sir = stack[stackstart%div];
393
+
394
+ rgba_sums[1][0] -= sir[0];
395
+ rgba_sums[1][1] -= sir[1];
396
+ rgba_sums[1][2] -= sir[2];
397
+ if (alpha)
398
+ {
399
+ rgba_sums[1][3] -= sir[3];
400
+ }
401
+
402
+ if (x == 0)
403
+ {
404
+ vmin[y] = MIN(y + (radius + 1), height - 1)*width;
405
+ }
406
+
407
+ p = x + vmin[y];
408
+
409
+ sir[0] = rgba[0][p];
410
+ sir[1] = rgba[1][p];
411
+ sir[2] = rgba[2][p];
412
+ if (alpha)
413
+ {
414
+ sir[3] = rgba[3][p];
415
+ }
416
+
417
+ rgba_sums[0][0] += sir[0];
418
+ rgba_sums[0][1] += sir[1];
419
+ rgba_sums[0][2] += sir[2];
420
+ if (alpha)
421
+ {
422
+ rgba_sums[0][3] += sir[3];
423
+ }
424
+
425
+ rgba_sums[2][0] += rgba_sums[0][0];
426
+ rgba_sums[2][1] += rgba_sums[0][1];
427
+ rgba_sums[2][2] += rgba_sums[0][2];
428
+ if (alpha)
429
+ {
430
+ rgba_sums[2][3] += rgba_sums[0][3];
431
+ }
432
+
433
+ stackpointer = (stackpointer+1)%div;
434
+ sir = stack[stackpointer];
435
+
436
+ rgba_sums[1][0] += sir[0];
437
+ rgba_sums[1][1] += sir[1];
438
+ rgba_sums[1][2] += sir[2];
439
+ if (alpha)
440
+ {
441
+ rgba_sums[1][3] += sir[3];
442
+ }
443
+
444
+ rgba_sums[0][0] -= sir[0];
445
+ rgba_sums[0][1] -= sir[1];
446
+ rgba_sums[0][2] -= sir[2];
447
+ if (alpha)
448
+ {
449
+ rgba_sums[0][3] -= sir[3];
450
+ }
451
+
452
+ yi += width;
453
+ }
454
+ }
455
+ }
456
+
457
+ return pixbuf;
458
+ }
459
+
460
+ static GdkPixbuf *
461
+ pixbuf_sharpen(GdkPixbuf *src, int strength)
462
+ {
463
+ GdkPixbuf *dest;
464
+ int has_alpha;
465
+ int s_width, s_height, s_rowstride;
466
+ int d_width, d_height, d_rowstride;
467
+ guchar *s_pix;
468
+ guchar *d_pix;
469
+ guchar *sp;
470
+ guchar *dp;
471
+ int pix_width;
472
+ bool row_only = TRUE;
473
+ int a=0, r, g, b, x, y, mul;
474
+ int b_a=0, b_r, b_g, b_b;
475
+
476
+ if (!src) return NULL;
477
+
478
+ s_width = gdk_pixbuf_get_width(src);
479
+ s_height = gdk_pixbuf_get_height(src);
480
+ has_alpha = gdk_pixbuf_get_has_alpha(src);
481
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
482
+ s_pix = gdk_pixbuf_get_pixels(src);
483
+
484
+ d_width = s_width;
485
+ d_height = s_height;
486
+
487
+ dest = gdk_pixbuf_copy(src);
488
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
489
+ d_pix = gdk_pixbuf_get_pixels(dest);
490
+
491
+ pix_width = (has_alpha ? 4 : 3);
492
+
493
+ mul = (row_only ? 3 : 5);
494
+
495
+ for (y = 0; y < (s_height); y++)
496
+ {
497
+ sp = s_pix + (y * s_rowstride) + pix_width;
498
+ dp = d_pix + (y * d_rowstride) + pix_width;
499
+
500
+ for (x = 1; x < (s_width - 1); x++)
501
+ {
502
+
503
+ b_r = ((int)*(sp));
504
+ b_g = ((int)*(sp+1));
505
+ b_b = ((int)*(sp+2));
506
+ if (has_alpha)
507
+ b_a = ((int)*((sp+3)));
508
+
509
+ r = b_r * mul;
510
+ g = b_g * mul;
511
+ b = b_b * mul;
512
+ if (has_alpha)
513
+ a = b_a * mul;
514
+
515
+ r = ((int)*(sp)) * mul;
516
+ g = ((int)*(sp+1)) * mul;
517
+ b = ((int)*(sp+2)) * mul;
518
+ if (has_alpha)
519
+ a = ((int)*((sp+3))) * mul;
520
+
521
+ r -= (int)*(sp - pix_width);
522
+ g -= (int)*(sp - pix_width + 1);
523
+ b -= (int)*(sp - pix_width + 2);
524
+ if (has_alpha)
525
+ a -= (int)*(sp - pix_width + 3);
526
+
527
+ r -= (int)*(sp + pix_width);
528
+ g -= (int)*(sp + pix_width + 1);
529
+ b -= (int)*(sp + pix_width + 2);
530
+ if (has_alpha)
531
+ a -= (int)*(sp + pix_width + 3);
532
+
533
+ if (row_only == 0)
534
+ {
535
+ r -= (int)*(sp - (s_rowstride));
536
+ g -= (int)*(sp + 1 - (s_rowstride));
537
+ b -= (int)*(sp + 2 - (s_rowstride));
538
+ if (has_alpha)
539
+ a -= (int)*(sp + 3 - (s_rowstride));
540
+
541
+ r -= (int)*(sp + (s_rowstride));
542
+ g -= (int)*(sp + 1 + (s_rowstride));
543
+ b -= (int)*(sp + 2 + (s_rowstride));
544
+ if (has_alpha)
545
+ a -= (int)*(sp + 3 + (s_rowstride));
546
+ }
547
+
548
+ r = (r & ((~r) >> 16));
549
+ r = ((r | ((r & 256) - ((r & 256) >> 8))));
550
+ g = (g & ((~g) >> 16));
551
+ g = ((g | ((g & 256) - ((g & 256) >> 8))));
552
+ b = (b & ((~b) >> 16));
553
+ b = ((b | ((b & 256) - ((b & 256) >> 8))));
554
+ a = (a & ((~a) >> 16));
555
+ a = ((a | ((a & 256) - ((a & 256) >> 8))));
556
+
557
+ r = 0xff & (MAX(r,0));
558
+ g = 0xff & (MAX(g,0));
559
+ b = 0xff & (MAX(b,0));
560
+ if (has_alpha)
561
+ a = 0xff & (MAX(a,0));
562
+
563
+ r = ((r * strength) + b_r) / (strength + 1);
564
+ g = ((g * strength) + b_g) / (strength + 1);
565
+ b = ((b * strength) + b_b) / (strength + 1);
566
+ if (has_alpha)
567
+ a = ((a * strength) + b_a) / (strength + 1);
568
+
569
+ *(dp++) = r;
570
+ *(dp++) = g;
571
+ *(dp++) = b;
572
+ if (has_alpha)
573
+ *(dp++) = a;
574
+
575
+ sp += pix_width;
576
+ }
577
+ }
578
+ return dest;
579
+ } // */
580
+
581
+ static GdkPixbuf *
582
+ pixbuf_rotate(GdkPixbuf *src, rotate_angle_t angle)
583
+ {
584
+ GdkPixbuf *dest;
585
+ int has_alpha;
586
+ int s_width, s_height, s_rowstride;
587
+ int d_width, d_height, d_rowstride;
588
+ guchar *s_pix;
589
+ guchar *d_pix;
590
+ guchar *sp;
591
+ guchar *dp;
592
+ int i, j, pix_width;
593
+
594
+ if (!src) return NULL;
595
+
596
+ if (angle == ANGLE_0)
597
+ return gdk_pixbuf_copy(src);
598
+
599
+ s_width = gdk_pixbuf_get_width(src);
600
+ s_height = gdk_pixbuf_get_height(src);
601
+ has_alpha = gdk_pixbuf_get_has_alpha(src);
602
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
603
+ s_pix = gdk_pixbuf_get_pixels(src);
604
+
605
+ switch (angle)
606
+ {
607
+ case ANGLE_90:
608
+ case ANGLE_270:
609
+ d_width = s_height;
610
+ d_height = s_width;
611
+ break;
612
+ default:
613
+ case ANGLE_0:/* Avoid compiler warnings... */
614
+ case ANGLE_180:
615
+ d_width = s_width;
616
+ d_height = s_height;
617
+ break;
618
+ }
619
+
620
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8, d_width, d_height);
621
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
622
+ d_pix = gdk_pixbuf_get_pixels(dest);
623
+
624
+ pix_width = (has_alpha ? 4 : 3);
625
+
626
+ for (i = 0; i < s_height; i++) {
627
+ sp = s_pix + (i * s_rowstride);
628
+ for (j = 0; j < s_width; j++) {
629
+ switch (angle)
630
+ {
631
+ case ANGLE_180:
632
+ dp = d_pix + ((d_height - i - 1) * d_rowstride) + ((d_width - j - 1) * pix_width);
633
+ break;
634
+ case ANGLE_90:
635
+ dp = d_pix + (j * d_rowstride) + ((d_width - i - 1) * pix_width);
636
+ break;
637
+ case ANGLE_270:
638
+ dp = d_pix + ((d_height - j - 1) * d_rowstride) + (i * pix_width);
639
+ break;
640
+ default:
641
+ case ANGLE_0:/* Avoid compiler warnings... */
642
+ dp = d_pix + (i * d_rowstride) + (j * pix_width);
643
+ break;
644
+ }
645
+
646
+ *(dp++) = *(sp++); /* red */
647
+ *(dp++) = *(sp++); /* green */
648
+ *(dp++) = *(sp++); /* blue */
649
+ if (has_alpha) *(dp) = *(sp++); /* alpha */
650
+ }
651
+ }
652
+
653
+ return dest;
654
+ }
655
+
656
+ #include <unistd.h>
657
+
658
+ static gboolean pixbuf_save_tiff(GdkPixbuf *pixbuf, char *filename)
659
+ {
660
+ long row;
661
+ TIFF *tif;
662
+ struct tm *ct;
663
+ time_t t;
664
+ int width,
665
+ height,
666
+ rowstride;
667
+ guchar *pixels;
668
+ short photometric;
669
+ short samplesperpixel;
670
+ short bitspersample;
671
+ static char datetime[40] = "";
672
+ char hostname[256] = "";
673
+
674
+ time(&t);
675
+ ct = localtime(&t);
676
+ sprintf(datetime, "%04i:%02i:%02i %02i:%02i:%02i",
677
+ 1900 + ct->tm_year, ct->tm_mon + 1, ct->tm_mday,
678
+ ct->tm_hour, ct->tm_min, ct->tm_sec);
679
+
680
+ tif = TIFFOpen(filename, "w");
681
+
682
+ width = gdk_pixbuf_get_width(pixbuf);
683
+ height = gdk_pixbuf_get_height(pixbuf);
684
+ samplesperpixel = gdk_pixbuf_get_has_alpha(pixbuf) ? 4 : 3;
685
+ bitspersample = gdk_pixbuf_get_bits_per_sample(pixbuf);
686
+ photometric = PHOTOMETRIC_RGB;
687
+ rowstride = gdk_pixbuf_get_rowstride(pixbuf);
688
+ pixels = gdk_pixbuf_get_pixels(pixbuf);
689
+
690
+
691
+ TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
692
+ TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
693
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
694
+ TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
695
+ TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
696
+ TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric);
697
+ /*#TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, inf);*/
698
+ TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Saved from a Gdk::Pixbuf");
699
+ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
700
+ TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
701
+ TIFFSetField(tif, TIFFTAG_SOFTWARE, "LiveLink Photo Kiosk 1.0");
702
+ TIFFSetField(tif, TIFFTAG_DATETIME, datetime);
703
+ if(gethostname((char*)&hostname,sizeof(hostname))==0)
704
+ TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, hostname);
705
+
706
+ for (row = 0; row < height; row++) {
707
+ if (TIFFWriteScanline(tif, (u_char *) pixels, row, 0) < 0) {
708
+ fprintf(stderr, "failed a scanline write (%li)\n", row);
709
+ break;
710
+ }
711
+ pixels = GINT_TO_POINTER(GPOINTER_TO_INT(pixels) + rowstride);
712
+ }
713
+ TIFFFlushData(tif);
714
+ TIFFClose(tif);
715
+
716
+ return TRUE;
717
+ }
718
+
719
+ #include <math.h>
720
+
721
+ static GdkPixbuf *pixbuf_gamma(GdkPixbuf *src, GdkPixbuf *dest, double gamma)
722
+ {
723
+ int has_alpha;
724
+ int s_width, s_height, s_rowstride;
725
+ int d_width, d_height, d_rowstride;
726
+ guchar *s_pix;
727
+ guchar *d_pix;
728
+ guchar *sp;
729
+ guchar *dp;
730
+ int i, j, pix_width;
731
+ double map[256] = {0.0,};
732
+
733
+ for (i=0; i < 256; i++)
734
+ map[i] = 255 * pow((double) i/255, 1.0/gamma);
735
+
736
+ g_return_val_if_fail(src != NULL, NULL);
737
+ g_return_val_if_fail(dest != NULL, NULL);
738
+
739
+ s_width = gdk_pixbuf_get_width(src);
740
+ s_height = gdk_pixbuf_get_height(src);
741
+ has_alpha = gdk_pixbuf_get_has_alpha(src);
742
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
743
+ s_pix = gdk_pixbuf_get_pixels(src);
744
+
745
+ d_width = gdk_pixbuf_get_width(dest);
746
+ d_height = gdk_pixbuf_get_height(dest);
747
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
748
+ d_pix = gdk_pixbuf_get_pixels(dest);
749
+
750
+ g_return_val_if_fail(d_width == s_width, NULL);
751
+ g_return_val_if_fail(d_height == s_height, NULL);
752
+ g_return_val_if_fail(has_alpha == gdk_pixbuf_get_has_alpha(dest), NULL);
753
+
754
+ pix_width = (has_alpha ? 4 : 3);
755
+
756
+ for (i = 0; i < s_height; i++) {
757
+ sp = s_pix + (i * s_rowstride);
758
+ dp = d_pix + (i * d_rowstride);
759
+ for (j = 0; j < s_width; j++) {
760
+ *(dp++) = map[*(sp++)]; /* red */
761
+ *(dp++) = map[*(sp++)]; /* green */
762
+ *(dp++) = map[*(sp++)]; /* blue */
763
+ if (has_alpha) *(dp++) = map[*(sp++)]; /* alpha */
764
+ }
765
+ }
766
+
767
+ return dest;
768
+ }
769
+
770
+ #define PIXEL(row, channels, x) ((pixel_t)(row + (channels * x)))
771
+
772
+ typedef struct {
773
+ unsigned char r,g,b,a;
774
+ } * pixel_t;
775
+
776
+ #define RLUM (0.3086)
777
+ #define GLUM (0.6094)
778
+ #define BLUM (0.0820)
779
+
780
+ // Graphica Obscure
781
+ #define GO_RGB_TO_GREY(r,g,b) ((int)((RLUM * (double)r) + (GLUM * (double)g) + (BLUM * (double)b)))
782
+
783
+ // Gimp Values
784
+ #define GIMP_RGB_TO_GREY(r,g,b) (((77 * r) + (151 * g) + (28 * b)) >> 8)
785
+
786
+ static GdkPixbuf *pixbuf_mask(GdkPixbuf *src, GdkPixbuf *mask)
787
+ {
788
+ int s_has_alpha, m_has_alpha;
789
+ int s_width, s_height, s_rowstride;
790
+ int d_width, d_height, d_rowstride;
791
+ int m_width, m_height, m_rowstride;
792
+ guchar *s_pix, *sp;
793
+ guchar *d_pix, *dp;
794
+ guchar *m_pix, *mp;
795
+ int i, j, pix_width, alpha, grey;
796
+ pixel_t pix;
797
+ GdkPixbuf *dest;
798
+
799
+ g_return_val_if_fail(src != NULL, NULL);
800
+
801
+ s_width = gdk_pixbuf_get_width(src);
802
+ s_height = gdk_pixbuf_get_height(src);
803
+ s_has_alpha = gdk_pixbuf_get_has_alpha(src);
804
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
805
+ s_pix = gdk_pixbuf_get_pixels(src);
806
+
807
+ g_return_val_if_fail(mask != NULL, NULL);
808
+
809
+ m_width = gdk_pixbuf_get_width(mask);
810
+ m_height = gdk_pixbuf_get_height(mask);
811
+ m_has_alpha = gdk_pixbuf_get_has_alpha(mask);
812
+ m_rowstride = gdk_pixbuf_get_rowstride(mask);
813
+ m_pix = gdk_pixbuf_get_pixels(mask);
814
+
815
+ g_return_val_if_fail(m_width <= s_width, NULL);
816
+ g_return_val_if_fail(m_height <= s_height, NULL);
817
+
818
+ d_width = m_width;
819
+ d_height = m_height;
820
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, d_width, d_height);
821
+
822
+ g_return_val_if_fail(dest != NULL, NULL);
823
+
824
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
825
+ d_pix = gdk_pixbuf_get_pixels(dest);
826
+
827
+ pix_width = (m_has_alpha ? 4 : 3);
828
+
829
+
830
+
831
+ for (i = 0; i < m_height; i++) {
832
+ sp = s_pix + (i * s_rowstride);
833
+ dp = d_pix + (i * d_rowstride);
834
+ mp = m_pix + (i * m_rowstride);
835
+
836
+ for (j = 0; j < m_width; j++) {
837
+ *(dp++) = *(sp++); /* red */
838
+ *(dp++) = *(sp++); /* green */
839
+ *(dp++) = *(sp++); /* blue */
840
+
841
+ if (s_has_alpha)
842
+ {
843
+ alpha = *(sp++); /* alpha */
844
+ }
845
+ else
846
+ {
847
+ alpha = 0xff;
848
+ }
849
+
850
+ pix = PIXEL(mp, pix_width, j);
851
+ grey = GIMP_RGB_TO_GREY(pix->r, pix->g, pix->b);
852
+
853
+ *(dp++) = sqrt(alpha * (255 - grey)); /* alpha */
854
+ }
855
+ }
856
+
857
+ return dest;
858
+ }
859
+
860
+ static GdkPixbuf *pixbuf_blend5050(GdkPixbuf *src1, GdkPixbuf *src2)
861
+ {
862
+ int s1_has_alpha, s2_has_alpha;
863
+ int s1_width, s1_height, s1_rowstride;
864
+ int d_width, d_height, d_rowstride;
865
+ int s2_width, s2_height, s2_rowstride;
866
+ guchar *s1_pix, *sp;
867
+ guchar *d_pix, *dp;
868
+ guchar *s2_pix, *mp;
869
+ int i, j;
870
+ GdkPixbuf *dest;
871
+
872
+ g_return_val_if_fail(src1 != NULL, NULL);
873
+
874
+ s1_width = gdk_pixbuf_get_width(src1);
875
+ s1_height = gdk_pixbuf_get_height(src1);
876
+ s1_has_alpha = gdk_pixbuf_get_has_alpha(src1);
877
+ s1_rowstride = gdk_pixbuf_get_rowstride(src1);
878
+ s1_pix = gdk_pixbuf_get_pixels(src1);
879
+
880
+ g_return_val_if_fail(src2 != NULL, NULL);
881
+
882
+ s2_width = gdk_pixbuf_get_width(src2);
883
+ s2_height = gdk_pixbuf_get_height(src2);
884
+ s2_has_alpha = gdk_pixbuf_get_has_alpha(src2);
885
+ s2_rowstride = gdk_pixbuf_get_rowstride(src2);
886
+ s2_pix = gdk_pixbuf_get_pixels(src2);
887
+
888
+ g_return_val_if_fail(s2_width == s1_width, NULL);
889
+ g_return_val_if_fail(s2_height == s1_height, NULL);
890
+ g_return_val_if_fail(s2_has_alpha == s1_has_alpha, NULL);
891
+
892
+ d_width = s2_width;
893
+ d_height = s2_height;
894
+
895
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, d_width, d_height);
896
+
897
+ g_return_val_if_fail(dest != NULL, NULL);
898
+
899
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
900
+ d_pix = gdk_pixbuf_get_pixels(dest);
901
+
902
+ for (i = 0; i < s2_height; i++) {
903
+ sp = s1_pix + (i * s1_rowstride);
904
+ mp = s2_pix + (i * s2_rowstride);
905
+ dp = d_pix + (i * d_rowstride);
906
+
907
+ for (j = 0; j < s2_width; j++) {
908
+ *(dp++) = ((*(sp++)) >> 1) + ((*(mp++)) >> 1); /* red */
909
+ *(dp++) = ((*(sp++)) >> 1) + ((*(mp++)) >> 1); /* green */
910
+ *(dp++) = ((*(sp++)) >> 1) + ((*(mp++)) >> 1); /* blue */
911
+
912
+ if (s1_has_alpha)
913
+ *(dp++) = ((*(sp++)) >> 1) + ((*(mp++)) >> 1); /* alpha */
914
+ else
915
+ *(dp++) = 0xff; /* alpha */
916
+
917
+ }
918
+ }
919
+
920
+ return dest;
921
+ }
922
+
923
+
924
+ static GdkPixbuf *pixbuf_greyscale(GdkPixbuf *src, GdkPixbuf *dest)
925
+ {
926
+ int s_has_alpha, d_has_alpha;
927
+ int s_width, s_height, s_rowstride;
928
+ int d_width, d_height, d_rowstride;
929
+ guchar *s_pix, *sp;
930
+ guchar *d_pix, *dp;
931
+ int i, j, pix_width, grey;
932
+
933
+ g_return_val_if_fail(src != NULL, NULL);
934
+ g_return_val_if_fail(dest != NULL, NULL);
935
+
936
+ s_width = gdk_pixbuf_get_width(src);
937
+ s_height = gdk_pixbuf_get_height(src);
938
+ s_has_alpha = gdk_pixbuf_get_has_alpha(src);
939
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
940
+ s_pix = gdk_pixbuf_get_pixels(src);
941
+
942
+ d_width = gdk_pixbuf_get_width(dest);
943
+ d_height = gdk_pixbuf_get_height(dest);
944
+ d_has_alpha = gdk_pixbuf_get_has_alpha(dest);
945
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
946
+ d_pix = gdk_pixbuf_get_pixels(dest);
947
+
948
+ g_return_val_if_fail(d_width == s_width, NULL);
949
+ g_return_val_if_fail(d_height == s_height, NULL);
950
+ g_return_val_if_fail(d_has_alpha == s_has_alpha, NULL);
951
+
952
+ pix_width = (s_has_alpha ? 4 : 3);
953
+
954
+
955
+ for (i = 0; i < s_height; i++) {
956
+ sp = s_pix;
957
+ dp = d_pix;
958
+
959
+ for (j = 0; j < s_width; j++) {
960
+ grey = GIMP_RGB_TO_GREY(sp[0], sp[1], sp[2]);
961
+
962
+ dp[0] = grey; /* red */
963
+ dp[1] = grey; /* green */
964
+ dp[2] = grey; /* blue */
965
+
966
+ if (s_has_alpha)
967
+ {
968
+ dp[3] = sp[3]; /* alpha */
969
+ }
970
+
971
+ dp += pix_width;
972
+ sp += pix_width;
973
+ }
974
+
975
+ d_pix += d_rowstride;
976
+ s_pix += s_rowstride;
977
+ }
978
+
979
+ return dest;
980
+ }
981
+
982
+ static GdkPixbuf *pixbuf_greyscale_go(GdkPixbuf *src, GdkPixbuf *dest)
983
+ {
984
+ int s_has_alpha, d_has_alpha;
985
+ int s_width, s_height, s_rowstride;
986
+ int d_width, d_height, d_rowstride;
987
+ guchar *s_pix, *sp;
988
+ guchar *d_pix, *dp;
989
+ int i, j, pix_width, grey;
990
+
991
+ g_return_val_if_fail(src != NULL, NULL);
992
+ g_return_val_if_fail(dest != NULL, NULL);
993
+
994
+ s_width = gdk_pixbuf_get_width(src);
995
+ s_height = gdk_pixbuf_get_height(src);
996
+ s_has_alpha = gdk_pixbuf_get_has_alpha(src);
997
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
998
+ s_pix = gdk_pixbuf_get_pixels(src);
999
+
1000
+ d_width = gdk_pixbuf_get_width(dest);
1001
+ d_height = gdk_pixbuf_get_height(dest);
1002
+ d_has_alpha = gdk_pixbuf_get_has_alpha(dest);
1003
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
1004
+ d_pix = gdk_pixbuf_get_pixels(dest);
1005
+
1006
+ g_return_val_if_fail(d_width == s_width, NULL);
1007
+ g_return_val_if_fail(d_height == s_height, NULL);
1008
+ g_return_val_if_fail(d_has_alpha == s_has_alpha, NULL);
1009
+
1010
+ pix_width = (s_has_alpha ? 4 : 3);
1011
+
1012
+ for (i = 0; i < s_height; i++) {
1013
+ sp = s_pix;
1014
+ dp = d_pix;
1015
+
1016
+ for (j = 0; j < s_width; j++) {
1017
+ grey = GO_RGB_TO_GREY(sp[0], sp[1], sp[2]);
1018
+
1019
+ dp[0] = grey; /* red */
1020
+ dp[1] = grey; /* green */
1021
+ dp[2] = grey; /* blue */
1022
+
1023
+ if (s_has_alpha)
1024
+ {
1025
+ dp[3] = sp[3]; /* alpha */
1026
+ }
1027
+
1028
+ dp += pix_width;
1029
+ sp += pix_width;
1030
+ }
1031
+
1032
+ d_pix += d_rowstride;
1033
+ s_pix += s_rowstride;
1034
+ }
1035
+
1036
+ return dest;
1037
+ }
1038
+
1039
+ static inline char pu_clamp(int x, int min, int max)
1040
+ {
1041
+ return (x > max) ? max : (x < min ? min : x);
1042
+ }
1043
+
1044
+ static GdkPixbuf *pixbuf_tint(GdkPixbuf *src, GdkPixbuf *dest, int r, int g, int b)
1045
+ {
1046
+ int s_has_alpha, d_has_alpha;
1047
+ int s_width, s_height, s_rowstride;
1048
+ int d_width, d_height, d_rowstride;
1049
+ guchar *s_pix, *sp;
1050
+ guchar *d_pix, *dp;
1051
+ int i, j, pix_width, grey;
1052
+
1053
+ g_return_val_if_fail(src != NULL, NULL);
1054
+ g_return_val_if_fail(dest != NULL, NULL);
1055
+
1056
+ s_width = gdk_pixbuf_get_width(src);
1057
+ s_height = gdk_pixbuf_get_height(src);
1058
+ s_has_alpha = gdk_pixbuf_get_has_alpha(src);
1059
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
1060
+ s_pix = gdk_pixbuf_get_pixels(src);
1061
+
1062
+ d_width = gdk_pixbuf_get_width(dest);
1063
+ d_height = gdk_pixbuf_get_height(dest);
1064
+ d_has_alpha = gdk_pixbuf_get_has_alpha(dest);
1065
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
1066
+ d_pix = gdk_pixbuf_get_pixels(dest);
1067
+
1068
+ g_return_val_if_fail(d_width == s_width, NULL);
1069
+ g_return_val_if_fail(d_height == s_height, NULL);
1070
+ g_return_val_if_fail(d_has_alpha == s_has_alpha, NULL);
1071
+
1072
+ pix_width = (s_has_alpha ? 4 : 3);
1073
+
1074
+ for (i = 0; i < s_height; i++) {
1075
+ sp = s_pix;
1076
+ dp = d_pix;
1077
+
1078
+ for (j = 0; j < s_width; j++) {
1079
+ grey = GO_RGB_TO_GREY(sp[0], sp[1], sp[2]);
1080
+
1081
+ dp[0] = pu_clamp(grey + r, 0, 255); /* red */
1082
+ dp[1] = pu_clamp(grey + g, 0, 255); /* green */
1083
+ dp[2] = pu_clamp(grey + b, 0, 255); /* blue */
1084
+
1085
+ if (s_has_alpha)
1086
+ {
1087
+ dp[3] = sp[3]; /* alpha */
1088
+ }
1089
+
1090
+ dp += pix_width;
1091
+ sp += pix_width;
1092
+ }
1093
+
1094
+ d_pix += d_rowstride;
1095
+ s_pix += s_rowstride;
1096
+ }
1097
+
1098
+ return dest;
1099
+ }
1100
+
1101
+ static GdkPixbuf *pixbuf_soften_edges(GdkPixbuf *dest, int size)
1102
+ {
1103
+ int d_has_alpha;
1104
+ int d_width, d_height, d_rowstride;
1105
+ guchar *d_pix, *dp;
1106
+ int i, j, pix_width;
1107
+
1108
+ g_return_val_if_fail(dest != NULL, NULL);
1109
+
1110
+ d_width = gdk_pixbuf_get_width(dest);
1111
+ d_height = gdk_pixbuf_get_height(dest);
1112
+ d_has_alpha = gdk_pixbuf_get_has_alpha(dest);
1113
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
1114
+ d_pix = gdk_pixbuf_get_pixels(dest);
1115
+
1116
+ g_return_val_if_fail(d_has_alpha, NULL);
1117
+
1118
+ pix_width = (d_has_alpha ? 4 : 3);
1119
+
1120
+ for (i = 0; i < MIN(size,d_height); i++) {
1121
+ dp = d_pix + (i * d_rowstride);
1122
+ //pix = (pixel_t)dp;
1123
+ for (j = 0; j < d_width; j++) {
1124
+ dp[3] = (dp[3] * i) / size; /* alpha */
1125
+ dp += pix_width;
1126
+ }
1127
+
1128
+ dp = d_pix + ((d_height - i - 1) * d_rowstride);
1129
+ for (j = 0; j < d_width; j++) {
1130
+ dp[3] = (dp[3] * i) / size; /* alpha */
1131
+ dp += pix_width;
1132
+ }
1133
+
1134
+ }
1135
+ for (j = 0; j < d_height; j++) {
1136
+ //pix = (pixel_t)GINT_TO_POINTER(GPOINTER_TO_INT(d_pix) + (j * d_rowstride));
1137
+ dp = d_pix + ((d_height - i - 1) * d_rowstride);
1138
+ for (i = 0; i < MIN(size, d_width); i++) {
1139
+ dp[3] = (dp[3] * i) / size; /* alpha */
1140
+ dp += pix_width;
1141
+ }
1142
+
1143
+ dp = d_pix + (j * d_rowstride) + (pix_width * d_width);
1144
+ for (i = 0; i < MIN(size, d_width); i++) {
1145
+ dp[3] = (dp[3] * i) / size; /* alpha */
1146
+ dp -= pix_width;
1147
+ }
1148
+ }
1149
+
1150
+ return dest;
1151
+ }
1152
+
1153
+
1154
+
1155
+ /*
1156
+ GdkPixbuf *pixbuf_op(GdkPixbuf *src, GdkPixbuf *dest,
1157
+ */
1158
+
1159
+ static GdkPixbuf *pixbuf_perspect_v(GdkPixbuf *src, int top_x1, int top_x2, int bot_x1, int bot_x2)
1160
+ {
1161
+ int s_width, s_height, s_rowstride;
1162
+ int d_width, d_height, d_rowstride;
1163
+ guchar *s_pix;
1164
+ guchar *d_pix;
1165
+ guchar *sp;
1166
+ guchar *dp;
1167
+ gboolean has_alpha;
1168
+ GdkPixbuf *dest;
1169
+ int min_x, max_x, top_width, bot_width;
1170
+ int x,y,alpha,channels,s_channels;
1171
+ int row_width;
1172
+ double row_offset, row_end;
1173
+ double row_offset2, row_end2;
1174
+ double left_theta, right_theta;
1175
+ pixel_t spx[3];
1176
+ double ex;
1177
+
1178
+ s_width = gdk_pixbuf_get_width(src);
1179
+ s_height = gdk_pixbuf_get_height(src);
1180
+ has_alpha = gdk_pixbuf_get_has_alpha(src);
1181
+ s_rowstride = gdk_pixbuf_get_rowstride(src);
1182
+ s_pix = gdk_pixbuf_get_pixels(src);
1183
+
1184
+
1185
+ g_return_val_if_fail((top_x2 - top_x1) <= s_width, NULL);
1186
+ g_return_val_if_fail((bot_x2 - bot_x1) <= s_width, NULL);
1187
+
1188
+ d_width = s_width;
1189
+ d_height = s_height;
1190
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, d_width, d_height);
1191
+ d_rowstride = gdk_pixbuf_get_rowstride(dest);
1192
+ d_pix = gdk_pixbuf_get_pixels(dest);
1193
+
1194
+ // Shortcut ... should be harmless?
1195
+ // We should really only touch info
1196
+ // Within the range d_pix + (d_rowstride * y) + ((has_alpha ? 4 : 3) * x)
1197
+ bzero(d_pix, (d_rowstride * d_height));
1198
+
1199
+ top_width = top_x2 - top_x1;
1200
+ bot_width = bot_x2 - bot_x1;
1201
+
1202
+ min_x = MIN(top_x1, bot_x1);
1203
+ max_x = MAX(top_x2, bot_x2);
1204
+
1205
+ s_channels = has_alpha ? 4 : 3;
1206
+ channels = 4;
1207
+
1208
+ left_theta = ((double)(min_x == bot_x1 ? top_x1 : bot_x1) - min_x) / (double)d_height;
1209
+ right_theta = ((double)max_x - ((max_x == bot_x2) ? top_x2 : bot_x2)) / (double)d_height;
1210
+
1211
+
1212
+ for (y = 0; y < d_height; y++) {
1213
+ sp = s_pix + (y * s_rowstride);
1214
+
1215
+ row_offset = min_x;
1216
+ row_end = max_x;
1217
+
1218
+ row_offset2 = min_x;
1219
+ row_end2 = max_x;
1220
+
1221
+ row_offset += (left_theta * ((min_x == bot_x1) ? (d_height - y - 1) : y));
1222
+ row_end -= (right_theta * ((max_x == bot_x2) ? (d_height - y - 1) : y));
1223
+
1224
+ row_offset2 += (left_theta * ((min_x == bot_x1) ? (d_height - y) : y+1));
1225
+ row_end2 -= (right_theta * ((max_x == bot_x2) ? (d_height - y) : y+1));
1226
+
1227
+ row_width = ceil(row_end) - floor(row_offset);
1228
+
1229
+ dp = d_pix + (y * d_rowstride) + ((int)floor(row_offset) * channels);
1230
+
1231
+ for (x = (int)floor(row_offset); x < (int)ceil(row_end); x++)
1232
+ {
1233
+ ex = x - floor(row_offset);
1234
+
1235
+ if ((x < ceil(row_offset)))
1236
+ {
1237
+ alpha = ((int) ((double)255 * (ceil(row_offset) - row_offset)));
1238
+ alpha = MAX(alpha,0);
1239
+ }
1240
+ else if ((x >= floor(row_end)))
1241
+ {
1242
+ alpha = ((int) ((double)255 * (row_end - floor(row_end))));
1243
+ alpha = MAX(alpha,0);
1244
+ }
1245
+ else
1246
+ {
1247
+ alpha = 0xff;
1248
+ }
1249
+
1250
+ spx[0] = PIXEL(sp, s_channels, (int)floor(((ex - 1) * (double)s_width) / (double)row_width));
1251
+ spx[1] = PIXEL(sp, s_channels, (int)floor((ex * (double)s_width) / (double)row_width));
1252
+ spx[2] = PIXEL(sp, s_channels, (int)floor(((ex + 1) * (double)s_width) / (double)row_width));
1253
+
1254
+ *(dp++) = ((spx[1]->r * 14) + ((spx[0]->r + spx[2]->r))) >> 4; /* red */
1255
+ *(dp++) = ((spx[1]->g * 14) + ((spx[0]->g + spx[2]->g))) >> 4; /* green */
1256
+ *(dp++) = ((spx[1]->b * 14) + ((spx[0]->b + spx[2]->b))) >> 4; /* blue */
1257
+ if (has_alpha)
1258
+ *(dp++) = sqrt(alpha * (((spx[1]->a * 14) + ((spx[0]->a + spx[2]->a))) >> 4)); /* alpha */
1259
+ else
1260
+ *(dp++) = alpha; /* alpha */
1261
+ }
1262
+
1263
+ }
1264
+
1265
+ return dest;
1266
+ }
1267
+
1268
+ static VALUE pixbuf_mask_area(GdkPixbuf *mask, double cutoff)
1269
+ {
1270
+ long int x0 = 0, x1 = 0, y0 = 0, y1=0;
1271
+ long int m_has_alpha;
1272
+ long int m_width, m_height, m_rowstride;
1273
+ guchar *m_pix, *mp;
1274
+ long int y, x;
1275
+ long pix_width;
1276
+ volatile
1277
+ double grey;
1278
+
1279
+ g_return_val_if_fail(mask != NULL, Qnil);
1280
+
1281
+ m_width = gdk_pixbuf_get_width(mask);
1282
+ m_height = gdk_pixbuf_get_height(mask);
1283
+ m_has_alpha = gdk_pixbuf_get_has_alpha(mask);
1284
+ m_rowstride = gdk_pixbuf_get_rowstride(mask);
1285
+ m_pix = gdk_pixbuf_get_pixels(mask);
1286
+
1287
+ pix_width = (m_has_alpha ? 4 : 3);
1288
+
1289
+
1290
+ x1 = m_width;
1291
+ y1 = m_height;
1292
+
1293
+ for (y = 0; y < m_height; y++)
1294
+ {
1295
+ mp = m_pix;
1296
+ for (x = 0; x < m_width; x++)
1297
+ {
1298
+ grey = GIMP_RGB_TO_GREY(mp[0], mp[1], mp[2]);
1299
+ if (grey < cutoff)// ie. darker than cutoff
1300
+ {
1301
+ if (x0 == 0)
1302
+ {
1303
+ x0 = MAX(x0, x);
1304
+ x1 = MIN(x1, x);
1305
+ }
1306
+ else
1307
+ {
1308
+ x0 = MIN(x0, x);
1309
+ x1 = MAX(x1, x);
1310
+ }
1311
+
1312
+ if (y0 == 0)
1313
+ {
1314
+ y0 = MAX(y0, y);
1315
+ y1 = MIN(y1, y);
1316
+ }
1317
+ else
1318
+ {
1319
+ y0 = MIN(y0, y);
1320
+ y1 = MAX(y1, y);
1321
+ }
1322
+ }
1323
+
1324
+ mp += pix_width;
1325
+ }
1326
+ m_pix += m_rowstride;
1327
+ }
1328
+
1329
+ return rb_ary_new3(4, INT2NUM(x0), INT2NUM(y0), INT2NUM(x1), INT2NUM(y1));
1330
+ }
1331
+
1332
+ static inline VALUE
1333
+ unref_pixbuf(GdkPixbuf *pixbuf)
1334
+ {
1335
+ volatile VALUE pb = Qnil;
1336
+
1337
+ pb = GOBJ2RVAL(pixbuf);
1338
+
1339
+ g_object_unref(pixbuf);
1340
+
1341
+ return pb;
1342
+ }
1343
+
1344
+ %}
1345
+
1346
+ %map GdkInterpType > VALUE : GENUM2RVAL(%%, GDK_TYPE_INTERP_TYPE)
1347
+ %map VALUE > GdkInterpType : RVAL2GENUM(%%, GDK_TYPE_INTERP_TYPE)
1348
+ %map GdkRectangle* > VALUE : GBOXED2RVAL(%%, GDK_TYPE_RECTANGLE)
1349
+ %map unref_pixbuf > VALUE : unref_pixbuf((%%))
1350
+
1351
+ %map GdkColor* > VALUE : GBOXED2RVAL(%%, GDK_TYPE_COLOR)
1352
+ %map VALUE > GdkColor* : RVAL2BOXED(%%, GDK_TYPE_COLOR)
1353
+
1354
+ %map VALUE > GdkDrawable* : RVAL2GOBJ(%%)
1355
+ %map VALUE > GdkGC* : RVAL2BOXED(%%, GDK_TYPE_GC)
1356
+ %map VALUE > GdkRectangle* : RVAL2BOXED(%%, GDK_TYPE_RECTANGLE)
1357
+
1358
+ module PixbufUtils
1359
+ %% module methods
1360
+ def unref_pixbuf:self.remove_alpha(GdkPixbuf *src, GdkColor *col)
1361
+ GdkPixbuf *dest;
1362
+ uint w,h, pixcol;
1363
+
1364
+ IGNORE(self);
1365
+ pixcol = (((col->red >> 8)&0xff) << 24) |
1366
+ (((col->green >> 8)&0xff) << 16) |
1367
+ (((col->blue >> 8)&0xff) << 8) | 0xFF;
1368
+
1369
+ w=gdk_pixbuf_get_width(src);
1370
+ h=gdk_pixbuf_get_height(src);
1371
+
1372
+ dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, w, h);
1373
+ if(!dest)
1374
+ rb_raise(rb_eNoMemError, "Unable to allocate memory for pixbuf");
1375
+
1376
+ gdk_pixbuf_fill(dest, pixcol);
1377
+ gdk_pixbuf_composite(src, dest, 0, 0, w, h, 0, 0, 1.0, 1.0, GDK_INTERP_NEAREST, 0xff);
1378
+
1379
+ return dest;
1380
+ end
1381
+ def unref_pixbuf:self.sharpen(GdkPixbuf *src, int radius)
1382
+ IGNORE(self);
1383
+ return pixbuf_sharpen(src, radius);
1384
+ end
1385
+ def unref_pixbuf:self.extract_alpha(GdkPixbuf *src, int cutoff = 127, bool force_2bit = FALSE)
1386
+ IGNORE(self);
1387
+ return pixbuf_extract_alpha(src, cutoff, force_2bit);
1388
+ end
1389
+ def unref_pixbuf:self.blur(GdkPixbuf *src, int radius)
1390
+ IGNORE(self);
1391
+ return pixbuf_blur(gdk_pixbuf_copy(src), radius);
1392
+ end
1393
+ def unref_pixbuf:self.rotate_90(GdkPixbuf *src, bool counter_clockwise)
1394
+ IGNORE(self);
1395
+ return pixbuf_rotate(src, counter_clockwise ? ANGLE_270 : ANGLE_90);
1396
+ end
1397
+ def unref_pixbuf:self.rotate_cw(GdkPixbuf *src)
1398
+ IGNORE(self);
1399
+ return pixbuf_rotate(src, ANGLE_90);
1400
+ end
1401
+ def unref_pixbuf:self.rotate_180(GdkPixbuf *src)
1402
+ IGNORE(self);
1403
+ return pixbuf_rotate(src, ANGLE_180);
1404
+ end
1405
+ def unref_pixbuf:self.rotate(GdkPixbuf *src, int angle)
1406
+ IGNORE(self);
1407
+ g_assert(angle == 0 || angle == 90 || angle == 180 || angle == 270);
1408
+ return pixbuf_rotate(src, (rotate_angle_t)angle);
1409
+ end
1410
+ def unref_pixbuf:self.rotate_ccw(GdkPixbuf *src)
1411
+ IGNORE(self);
1412
+ return pixbuf_rotate(src, ANGLE_270);
1413
+ end
1414
+ def GdkPixbuf*:self.gamma!(GdkPixbuf *src, double level)
1415
+ IGNORE(self);
1416
+ return pixbuf_gamma(src, src, level);
1417
+ end
1418
+ def GdkPixbuf*:self.soften_edges!(GdkPixbuf *src, int size)
1419
+ IGNORE(self);
1420
+ return pixbuf_soften_edges(src, size);
1421
+ end
1422
+ def unref_pixbuf:self.gamma(GdkPixbuf *src, double level)
1423
+ IGNORE(self);
1424
+ return pixbuf_gamma(src, gdk_pixbuf_copy(src), level);
1425
+ end
1426
+ def GdkPixbuf*:self.greyscale!(GdkPixbuf *src)
1427
+ IGNORE(self);
1428
+ return pixbuf_greyscale(src, src);
1429
+ end
1430
+ def bool:self.to_tiff(GdkPixbuf *src, char *filename)
1431
+ IGNORE(self);
1432
+ return pixbuf_save_tiff(src, filename);
1433
+ end
1434
+ def unref_pixbuf:self.greyscale(GdkPixbuf *src)
1435
+ IGNORE(self);
1436
+ return pixbuf_greyscale(src, gdk_pixbuf_copy(src));
1437
+ end
1438
+ def GdkPixbuf*:self.greyscale_go!(GdkPixbuf *src)
1439
+ IGNORE(self);
1440
+ return pixbuf_greyscale_go(src, src);
1441
+ end
1442
+ def unref_pixbuf:self.greyscale_go(GdkPixbuf *src)
1443
+ IGNORE(self);
1444
+ return pixbuf_greyscale_go(src, gdk_pixbuf_copy(src));
1445
+ end
1446
+ def unref_pixbuf:self.tint(GdkPixbuf *src, int r, int g, int b)
1447
+ IGNORE(self);
1448
+ return pixbuf_tint(src, gdk_pixbuf_copy(src), r, g, b);
1449
+ end
1450
+ def unref_pixbuf:self.perspect_v(GdkPixbuf *src, int top_x1, int top_x2, int bot_x1, int bot_x2)
1451
+ IGNORE(self);
1452
+ return pixbuf_perspect_v(src, top_x1, top_x2, bot_x1, bot_x2);
1453
+ end
1454
+ def unref_pixbuf:self.mask(GdkPixbuf *src, GdkPixbuf *mask)
1455
+ IGNORE(self);
1456
+ return pixbuf_mask(src, mask);
1457
+ end
1458
+ def unref_pixbuf:self.blend5050(GdkPixbuf *src1, GdkPixbuf *src2)
1459
+ IGNORE(self);
1460
+ return pixbuf_blend5050(src1, src2);
1461
+ end
1462
+ def self.mask_area(GdkPixbuf *mask, int cutoff = 127)
1463
+ IGNORE(self);
1464
+ return pixbuf_mask_area(mask, cutoff);
1465
+ end
1466
+ def unref_pixbuf:self.scale_max(GdkPixbuf *src, gulong max, GdkInterpType interp = GDK_INTERP_BILINEAR)
1467
+ gulong width, height, largest;
1468
+ gdouble scale;
1469
+
1470
+ IGNORE(self);
1471
+ width = gdk_pixbuf_get_width(src);
1472
+ height = gdk_pixbuf_get_height(src);
1473
+ largest = MAX(width, height);
1474
+ if (max > largest)
1475
+ {
1476
+ return gdk_pixbuf_copy(src);
1477
+ }
1478
+
1479
+ scale = (double)(max) / (double)(largest);
1480
+
1481
+ return gdk_pixbuf_scale_simple(src, (int)(scale * width), (int)(scale * height), interp);
1482
+ end
1483
+ def self.draw_scaled(GdkDrawable *drawable, GdkPixbuf *src, int x, int y,
1484
+ int width, int height, GdkInterpType interp = GDK_INTERP_BILINEAR)
1485
+
1486
+ GdkPixbuf *tmp;
1487
+
1488
+
1489
+ IGNORE(self);
1490
+ if((width == gdk_pixbuf_get_width(src)) && (height == gdk_pixbuf_get_height(src)))
1491
+ {
1492
+ tmp = src;
1493
+ }
1494
+ else if (((tmp = (GdkPixbuf*)g_object_get_data(G_OBJECT(src), "pixbuf_utils_scaled")) == NULL)
1495
+ || ((width != gdk_pixbuf_get_width(tmp)) || (height != gdk_pixbuf_get_height(tmp))))
1496
+ {
1497
+ if (tmp) fprintf(stderr, "Old pixbuf is %i,%i\n", gdk_pixbuf_get_width(tmp), gdk_pixbuf_get_height(tmp));
1498
+ fprintf(stderr, "Scaling pixbuf to %i,%i\n", width, height);
1499
+ tmp = gdk_pixbuf_scale_simple(src, width, height, interp);
1500
+ g_object_set_data_full(G_OBJECT(src), "pixbuf_utils_scaled", tmp, g_object_unref);
1501
+ }
1502
+ g_return_val_if_fail(tmp != NULL, Qfalse);
1503
+
1504
+ gdk_draw_pixbuf(/* GdkDrawable *drawable */ drawable,
1505
+ /* GdkGC *gc */ NULL,
1506
+ /* GdkPixbuf *pixbuf */ tmp,
1507
+ /* gint src_x */ 0,
1508
+ /* gint src_y */ 0,
1509
+ /* gint dest_x */ x,
1510
+ /* gint dest_y */ y,
1511
+ /* gint width */ width,
1512
+ /* gint height */ height,
1513
+ /* GdkRgbDither dither */ GDK_RGB_DITHER_NORMAL,
1514
+ /* gint x_dither */ 0,
1515
+ /* gint y_dither */ 0);
1516
+ return Qtrue;
1517
+
1518
+ end
1519
+ def self.draw_scaled_clip(GdkDrawable *drawable, GdkPixbuf *src, int x, int y,
1520
+ int width, int height, GdkRectangle *clip_area, GdkInterpType interp = GDK_INTERP_BILINEAR)
1521
+
1522
+ GdkPixbuf *tmp;
1523
+ GdkGC *gc;
1524
+
1525
+ IGNORE(self);
1526
+ if((width == gdk_pixbuf_get_width(src)) && (height == gdk_pixbuf_get_height(src)))
1527
+ {
1528
+ tmp = src;
1529
+ }
1530
+ else if (((tmp = (GdkPixbuf*)g_object_get_data(G_OBJECT(src), "pixbuf_utils_scaled")) == NULL)
1531
+ || ((width != gdk_pixbuf_get_width(tmp)) || (height != gdk_pixbuf_get_height(tmp))))
1532
+ {
1533
+ if (tmp) fprintf(stderr, "Old pixbuf is %i,%i\n", gdk_pixbuf_get_width(tmp), gdk_pixbuf_get_height(tmp));
1534
+ fprintf(stderr, "Scaling pixbuf to %i,%i\n", width, height);
1535
+ tmp = gdk_pixbuf_scale_simple(src, width, height, interp);
1536
+ g_object_set_data_full(G_OBJECT(src), "pixbuf_utils_scaled", tmp, g_object_unref);
1537
+ }
1538
+ g_return_val_if_fail(tmp != NULL, Qfalse);
1539
+
1540
+ gc = gdk_gc_new(drawable);
1541
+ gdk_gc_set_clip_rectangle(GDK_GC(gc), clip_area);
1542
+
1543
+ gdk_draw_pixbuf(/* GdkDrawable *drawable */ drawable,
1544
+ /* GdkGC *gc */ gc,
1545
+ /* GdkPixbuf *pixbuf */ tmp,
1546
+ /* gint src_x */ clip_area->x,
1547
+ /* gint src_y */ clip_area->y,
1548
+ /* gint dest_x */ x + clip_area->x,
1549
+ /* gint dest_y */ y + clip_area->y,
1550
+ /* gint width */ clip_area->width,
1551
+ /* gint height */ clip_area->height,
1552
+ /* GdkRgbDither dither */ GDK_RGB_DITHER_NORMAL,
1553
+ /* gint x_dither */ 0,
1554
+ /* gint y_dither */ 0);
1555
+ g_object_unref(gc);
1556
+
1557
+ return Qtrue;
1558
+
1559
+ end
1560
+ end
1561
+