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,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
+