ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CV/CV.xs
(Generate patch)

Comparing CV/CV.xs (file contents):
Revision 1.4 by root, Sat Nov 8 18:22:21 2003 UTC vs.
Revision 1.46 by root, Sat Jul 4 05:31:17 2015 UTC

1#include "EXTERN.h" 1#include "EXTERN.h"
2#include "perl.h" 2#include "perl.h"
3#include "XSUB.h" 3#include "XSUB.h"
4 4
5#include <string.h>
6#include <setjmp.h>
7#include <math.h>
8
9#include <magic.h>
10
11#include <jpeglib.h>
12#include <glib.h>
13#include <gtk/gtk.h>
5#include <gdk-pixbuf/gdk-pixbuf.h> 14#include <gdk-pixbuf/gdk-pixbuf.h>
6 15
7#include <gperl.h> 16#include <gperl.h>
8#include <gtk2perl.h> 17#include <gtk2perl.h>
9 18
19#include <assert.h>
20
21#include "perlmulticore.h"
22
23#define IW 80 /* MUST match Schnauzer.pm! */
24#define IH 60 /* MUST match Schnauzer.pm! */
25
26#define RAND (seed = (seed + 7141) * 54773 % 134456)
27
28#define LINELENGTH 240
29
30#define ELLIPSIS "\xe2\x80\xa6"
31
32typedef char *octet_string;
33
34struct jpg_err_mgr
35{
36 struct jpeg_error_mgr err;
37 jmp_buf setjmp_buffer;
38};
39
40static void
41cv_error_exit (j_common_ptr cinfo)
42{
43 longjmp (((struct jpg_err_mgr *)cinfo->err)->setjmp_buffer, 99);
44}
45
46static void
47cv_error_output (j_common_ptr cinfo)
48{
49 return;
50}
51
52static void
53rgb_to_hsv (unsigned int r, unsigned int g, unsigned int b,
54 unsigned int *h, unsigned int *s, unsigned int *v)
55{
56 unsigned int mx = r; if (g > mx) mx = g; if (b > mx) mx = b;
57 unsigned int mn = r; if (g < mn) mn = g; if (b < mn) mn = b;
58 unsigned int delta = mx - mn;
59
60 *v = mx;
61
62 *s = mx ? delta * 255 / mx : 0;
63
64 if (delta == 0)
65 *h = 0;
66 else
67 {
68 if (r == mx)
69 *h = ((int)g - (int)b) * 255 / (int)(delta * 3);
70 else if (g == mx)
71 *h = ((int)b - (int)r) * 255 / (int)(delta * 3) + 52;
72 else if (b == mx)
73 *h = ((int)r - (int)g) * 255 / (int)(delta * 3) + 103;
74
75 *h &= 255;
76 }
77}
78
79struct feature {
80 float v1, v2, v3; // mean, square, cube
81 int n;
82};
83
84static void
85feature_init (struct feature *f)
86{
87 f->v1 = 0.;
88 f->v2 = 0.;
89 f->v3 = 0.;
90 f->n = 0;
91}
92
93// didn't find an algorithm to neatly do mean, variance and skew in one pass.
94// elmex ist schuld.
95static void
96feature_update_pass_1 (struct feature *f, unsigned int v)
97{
98 f->v1 += v;
99 f->n += 1;
100}
101
102static void
103feature_finish_pass_1 (struct feature *f)
104{
105 if (f->n < 1)
106 return;
107
108 f->v1 /= f->n;
109}
110
111static void
112feature_update_pass_2 (struct feature *f, unsigned int v)
113{
114 float d = v - f->v1;
115
116 f->v2 += d * d;
117 f->v3 += d * d * d;
118}
119
120static void
121feature_finish_pass_2 (struct feature *f)
122{
123 if (f->n < 1)
124 return;
125
126 f->v2 /= f->n;
127 f->v3 /= f->n;
128
129 f->v1 /= 255.;
130 f->v2 /= 255. * 255.; f->v2 = sqrtf (f->v2);
131 f->v3 /= 255. * 255. * 255.; f->v3 = powf (fabsf (f->v3), 1./3.);
132}
133
10static guint32 a85_val; 134static guint32 a85_val;
11static guint a85_cnt; 135static guint a85_cnt;
12static guchar a85_buf[80], *a85_ptr; 136static guchar a85_buf[LINELENGTH], *a85_ptr;
13 137
14static void 138static void
15a85_init (void) 139a85_init (void)
16{ 140{
17 a85_cnt = 4; 141 a85_cnt = 4;
47 } 171 }
48 } 172 }
49 173
50} 174}
51 175
176static void
52a85_finish (PerlIO *fp) 177a85_finish (PerlIO *fp)
53{ 178{
54 while (a85_cnt != 4) 179 while (a85_cnt != 4)
55 a85_push (fp, 0); 180 a85_push (fp, 0);
56 181
59 *a85_ptr++ = '\n'; 184 *a85_ptr++ = '\n';
60 185
61 PerlIO_write (fp, a85_buf, a85_ptr - a85_buf); 186 PerlIO_write (fp, a85_buf, a85_ptr - a85_buf);
62} 187}
63 188
189/////////////////////////////////////////////////////////////////////////////
190
64MODULE = Gtk2::CV PACKAGE = Gtk2::CV::ImageWindow 191MODULE = Gtk2::CV PACKAGE = Gtk2::CV
65 192
66PROTOTYPES: ENABLE 193PROTOTYPES: ENABLE
67 194
195# missing function in perl. really :)
196int
197common_prefix_length (a, b)
198 unsigned char *a = (unsigned char *)SvPVutf8_nolen ($arg);
199 unsigned char *b = (unsigned char *)SvPVutf8_nolen ($arg);
200 CODE:
201 RETVAL = 0;
202
203 while (*a == *b && *a)
204 {
205 RETVAL += (*a & 0xc0) != 0x80;
206 a++, b++;
207 }
208
209 OUTPUT:
210 RETVAL
211
212const char *
213magic (octet_string path)
214 CODE:
215{
216 static magic_t cookie;
217
218 if (!cookie)
219 {
220 cookie = magic_open (MAGIC_SYMLINK);
221
222 if (cookie)
223 magic_load (cookie, 0);
224 else
225 XSRETURN_UNDEF;
226 }
227
228 RETVAL = magic_file (cookie, path);
229}
230 OUTPUT:
231 RETVAL
232
233const char *
234magic_mime (octet_string path)
235 CODE:
236{
237 static magic_t cookie;
238
239 if (!cookie)
240 {
241 cookie = magic_open (MAGIC_MIME | MAGIC_SYMLINK);
242
243 if (cookie)
244 magic_load (cookie, 0);
245 else
246 XSRETURN_UNDEF;
247 }
248
249 perlinterp_release ();
250 RETVAL = magic_file (cookie, path);
251 perlinterp_acquire ();
252}
253 OUTPUT:
254 RETVAL
255
256# missing/broken in Gtk2 perl module
257
258void
259gdk_window_clear_hints (GdkWindow *window)
260 CODE:
261 gdk_window_set_geometry_hints (window, 0, 0);
262
263gboolean
264gdk_net_wm_supports (GdkAtom property)
265 CODE:
266#if defined(GDK_WINDOWING_X11) && !defined(GDK_MULTIHEAD_SAFE)
267 RETVAL = gdk_net_wm_supports (property);
268#else
269 RETVAL = 0;
270#endif
271 OUTPUT:
272 RETVAL
273
68GdkPixbuf_noinc * 274GdkPixbuf_noinc *
69transpose (GdkPixbuf *pb) 275dealpha_expose (GdkPixbuf *pb)
70 CODE: 276 CODE:
277 perlinterp_release ();
71{ 278{
72 int w = gdk_pixbuf_get_width (pb); 279 int w = gdk_pixbuf_get_width (pb);
73 int h = gdk_pixbuf_get_height (pb); 280 int h = gdk_pixbuf_get_height (pb);
74 int bpp = gdk_pixbuf_get_has_alpha (pb) ? 4 : 3; 281 int bpp = gdk_pixbuf_get_n_channels (pb);
75 int x, y, i; 282 int x, y, i;
76 guchar *src = gdk_pixbuf_get_pixels (pb), *dst; 283 guchar *src = gdk_pixbuf_get_pixels (pb), *dst;
77 int sstr = gdk_pixbuf_get_rowstride (pb), dstr; 284 int sstr = gdk_pixbuf_get_rowstride (pb), dstr;
78 285
79 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, bpp == 4, 8, h, w); 286 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 0, 8, w, h);
80 287
81 dst = gdk_pixbuf_get_pixels (RETVAL); 288 dst = gdk_pixbuf_get_pixels (RETVAL);
82 dstr = gdk_pixbuf_get_rowstride (RETVAL); 289 dstr = gdk_pixbuf_get_rowstride (RETVAL);
83 290
84 for (y = 0; y < h; y++)
85 for (x = 0; x < w; x++) 291 for (x = 0; x < w; x++)
292 for (y = 0; y < h; y++)
86 for (i = 0; i < bpp; i++) 293 for (i = 0; i < 3; i++)
87 dst[y * bpp + x * dstr + i] = src[x * bpp + y * sstr + i]; 294 dst[x * 3 + y * dstr + i] = src[x * bpp + y * sstr + i];
88} 295}
296 perlinterp_acquire ();
89 OUTPUT: 297 OUTPUT:
90 RETVAL 298 RETVAL
91 299
92GdkPixbuf_noinc * 300GdkPixbuf_noinc *
93flop (GdkPixbuf *pb) 301rotate (GdkPixbuf *pb, int angle)
94 CODE: 302 CODE:
95{ 303 perlinterp_release ();
96 int w = gdk_pixbuf_get_width (pb); 304 if (angle < 0)
97 int h = gdk_pixbuf_get_height (pb); 305 angle += 360;
98 int bpp = gdk_pixbuf_get_has_alpha (pb) ? 4 : 3; 306 RETVAL = gdk_pixbuf_rotate_simple (pb, angle == 0 ? GDK_PIXBUF_ROTATE_NONE
99 int x, y, i; 307 : angle == 90 ? GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE
100 guchar *src = gdk_pixbuf_get_pixels (pb), *dst; 308 : angle == 180 ? GDK_PIXBUF_ROTATE_UPSIDEDOWN
101 int sstr = gdk_pixbuf_get_rowstride (pb), dstr; 309 : angle == 270 ? GDK_PIXBUF_ROTATE_CLOCKWISE
310 : angle);
311 perlinterp_acquire ();
312 OUTPUT:
313 RETVAL
102 314
103 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, bpp == 4, 8, w, h); 315GdkPixbuf_noinc *
316load_jpeg (SV *path, int thumbnail=0)
317 CODE:
318{
319 struct jpeg_decompress_struct cinfo;
320 struct jpg_err_mgr jerr;
321 guchar *data;
322 int rs;
323 FILE *fp;
324 volatile GdkPixbuf *pb = 0;
104 325
326 RETVAL = 0;
327
328 fp = fopen (SvPVbyte_nolen (path), "rb");
329
330 if (!fp)
331 XSRETURN_UNDEF;
332
333 perlinterp_release ();
334
335 cinfo.err = jpeg_std_error (&jerr.err);
336
337 jerr.err.error_exit = cv_error_exit;
338 jerr.err.output_message = cv_error_output;
339
340 if ((rs = setjmp (jerr.setjmp_buffer)))
341 {
342 fclose (fp);
343 jpeg_destroy_decompress (&cinfo);
344
345 if (pb)
346 g_object_unref ((gpointer)pb);
347
348 perlinterp_acquire ();
349 XSRETURN_UNDEF;
350 }
351
352 jpeg_create_decompress (&cinfo);
353
354 jpeg_stdio_src (&cinfo, fp);
355 jpeg_read_header (&cinfo, TRUE);
356
357 cinfo.dct_method = JDCT_DEFAULT;
358 cinfo.do_fancy_upsampling = FALSE; /* worse quality, but nobody compained so far, and gdk-pixbuf does the same */
359 cinfo.do_block_smoothing = FALSE;
360 cinfo.out_color_space = JCS_RGB;
361 cinfo.quantize_colors = FALSE;
362
363 cinfo.scale_num = 1;
364 cinfo.scale_denom = 1;
365
366 jpeg_calc_output_dimensions (&cinfo);
367
368 if (thumbnail)
369 {
370 cinfo.dct_method = JDCT_FASTEST;
371 cinfo.do_fancy_upsampling = FALSE;
372
373 while (cinfo.scale_denom < 8
374 && cinfo.output_width >= IW*4
375 && cinfo.output_height >= IH*4)
376 {
377 cinfo.scale_denom <<= 1;
378 jpeg_calc_output_dimensions (&cinfo);
379 }
380 }
381
382 pb = RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 0, 8, cinfo.output_width, cinfo.output_height);
383 if (!RETVAL)
384 longjmp (jerr.setjmp_buffer, 2);
385
105 dst = gdk_pixbuf_get_pixels (RETVAL); 386 data = gdk_pixbuf_get_pixels (RETVAL);
106 dstr = gdk_pixbuf_get_rowstride (RETVAL); 387 rs = gdk_pixbuf_get_rowstride (RETVAL);
107 388
389 if (cinfo.output_components != 3)
390 longjmp (jerr.setjmp_buffer, 3);
391
392 jpeg_start_decompress (&cinfo);
393
394 while (cinfo.output_scanline < cinfo.output_height)
395 {
396 int remaining = cinfo.output_height - cinfo.output_scanline;
397 JSAMPROW rp[4];
398
399 rp [0] = data + cinfo.output_scanline * rs;
400 rp [1] = (guchar *)rp [0] + rs;
401 rp [2] = (guchar *)rp [1] + rs;
402 rp [3] = (guchar *)rp [2] + rs;
403
404 jpeg_read_scanlines (&cinfo, rp, remaining < 4 ? remaining : 4);
405 }
406
407 jpeg_finish_decompress (&cinfo);
408 fclose (fp);
409 jpeg_destroy_decompress (&cinfo);
410 perlinterp_acquire ();
411}
412 OUTPUT:
413 RETVAL
414
415void
416compare (GdkPixbuf *a, GdkPixbuf *b)
417 PPCODE:
418 perlinterp_release ();
419{
420 int w = gdk_pixbuf_get_width (a);
421 int h = gdk_pixbuf_get_height (a);
422
423 int sa = gdk_pixbuf_get_rowstride (a);
424 int sb = gdk_pixbuf_get_rowstride (b);
425
426 guchar *pa = gdk_pixbuf_get_pixels (a);
427 guchar *pb = gdk_pixbuf_get_pixels (b);
428
429 int x, y;
430
431 assert (w == gdk_pixbuf_get_width (b));
432 assert (h == gdk_pixbuf_get_height (b));
433
434 assert (gdk_pixbuf_get_n_channels (a) == 3);
435 assert (gdk_pixbuf_get_n_channels (b) == 3);
436
437 double diff = 0.;
438 int peak = 0;
439
440 if (w && h)
108 for (y = 0; y < h; y++) 441 for (y = 0; y < h; y++)
442 {
443 guchar *pa_ = pa + y * sa;
444 guchar *pb_ = pb + y * sb;
445
109 for (x = 0; x < w; x++) 446 for (x = 0; x < w; x++)
110 for (i = 0; i < bpp; i++) 447 {
111 dst[(w - 1 - x) * bpp + y * dstr + i] = src[x * bpp + y * sstr + i]; 448 int d;
449
450 d = ((int)*pa_++) - ((int)*pb_++); diff += d*d; peak = MAX (peak, abs (d));
451 d = ((int)*pa_++) - ((int)*pb_++); diff += d*d; peak = MAX (peak, abs (d));
452 d = ((int)*pa_++) - ((int)*pb_++); diff += d*d; peak = MAX (peak, abs (d));
453 }
454 }
455
456 perlinterp_acquire ();
457
458 EXTEND (SP, 2);
459 PUSHs (sv_2mortal (newSVnv (sqrt (diff / (w * h * 3. * 255. * 255.)))));
460 PUSHs (sv_2mortal (newSVnv (peak / 255.)));
112} 461}
113 OUTPUT: 462
114 RETVAL 463#############################################################################
115 464
116MODULE = Gtk2::CV PACKAGE = Gtk2::CV::Schnauzer 465MODULE = Gtk2::CV PACKAGE = Gtk2::CV::Schnauzer
117 466
467# currently only works for filenames (octet strings)
468
469SV *
470foldcase (SV *pathsv)
471 PROTOTYPE: $
472 CODE:
473{
474 STRLEN plen;
475 U8 *path = (U8 *)SvPV (pathsv, plen);
476 U8 *pend = path + plen;
477 U8 dst [plen * 6 * 3], *dstp = dst;
478
479 while (path < pend)
480 {
481 U8 ch = *path;
482
483 if (ch >= 'a' && ch <= 'z')
484 *dstp++ = *path++;
485 else if (ch >= 'A' && ch <= 'Z')
486 *dstp++ = *path++ + ('a' - 'A');
487 else if (ch >= '0' && ch <= '9')
488 {
489 STRLEN el, nl = 0;
490 while (*path >= '0' && *path <= '9' && path < pend)
491 path++, nl++;
492
493 for (el = nl; el < 6; el++)
494 *dstp++ = '0';
495
496 memcpy (dstp, path - nl, nl);
497 dstp += nl;
498 }
499 else
500 *dstp++ = *path++;
501#if 0
502 else
503 {
504 STRLEN cl;
505 to_utf8_fold (path, dstp, &cl);
506 dstp += cl;
507 path += is_utf8_char (path);
508 }
509#endif
510 }
511
512 RETVAL = newSVpvn ((const char *)dst, dstp - dst);
513}
514 OUTPUT:
515 RETVAL
516
118GdkPixbuf_noinc * 517GdkPixbuf_noinc *
119p7_to_pb (int w, int h, guchar *src) 518p7_to_pb (int w, int h, SV *src_sv)
519 PROTOTYPE: @
120 CODE: 520 CODE:
121{ 521{
122 int x, y; 522 int x, y;
123 guchar *dst, *d; 523 guchar *dst, *d;
124 int dstr; 524 int dstr;
525 guchar *src = (guchar *)SvPVbyte_nolen (src_sv);
125 526
126 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 0, 8, w, h); 527 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 0, 8, w, h);
127 dst = gdk_pixbuf_get_pixels (RETVAL); 528 dst = gdk_pixbuf_get_pixels (RETVAL);
128 dstr = gdk_pixbuf_get_rowstride (RETVAL); 529 dstr = gdk_pixbuf_get_rowstride (RETVAL);
129 530
138 } 539 }
139} 540}
140 OUTPUT: 541 OUTPUT:
141 RETVAL 542 RETVAL
142 543
544#############################################################################
545
546MODULE = Gtk2::CV PACKAGE = Gtk2::CV::PostScript
547
548void
549dump_ascii85 (PerlIO *fp, GdkPixbuf *pb)
550 CODE:
551{
552 int w = gdk_pixbuf_get_width (pb);
553 int h = gdk_pixbuf_get_height (pb);
554 int x, y, i;
555 guchar *dst;
556 int bpp = gdk_pixbuf_get_n_channels (pb);
557 guchar *src = gdk_pixbuf_get_pixels (pb);
558 int sstr = gdk_pixbuf_get_rowstride (pb);
559
560 a85_init ();
561
562 for (y = 0; y < h; y++)
563 for (x = 0; x < w; x++)
564 for (i = 0; i < (bpp < 3 ? 1 : 3); i++)
565 a85_push (fp, src [x * bpp + y * sstr + i]);
566
567 a85_finish (fp);
568}
569
570void
571dump_binary (PerlIO *fp, GdkPixbuf *pb)
572 CODE:
573{
574 int w = gdk_pixbuf_get_width (pb);
575 int h = gdk_pixbuf_get_height (pb);
576 int x, y, i;
577 guchar *dst;
578 int bpp = gdk_pixbuf_get_n_channels (pb);
579 guchar *src = gdk_pixbuf_get_pixels (pb);
580 int sstr = gdk_pixbuf_get_rowstride (pb);
581
582 for (y = 0; y < h; y++)
583 for (x = 0; x < w; x++)
584 for (i = 0; i < (bpp < 3 ? 1 : 3); i++)
585 PerlIO_putc (fp, src [x * bpp + y * sstr + i]);
586}
587
588#############################################################################
589
590MODULE = Gtk2::CV PACKAGE = Gtk2::CV
591
143SV * 592SV *
144pb_to_p7 (GdkPixbuf *pb) 593pb_to_hv84 (GdkPixbuf *pb)
145 CODE: 594 CODE:
146{ 595{
147 int w = gdk_pixbuf_get_width (pb); 596 int w = gdk_pixbuf_get_width (pb);
148 int h = gdk_pixbuf_get_height (pb); 597 int h = gdk_pixbuf_get_height (pb);
149 int x, y; 598 int x, y;
150 guchar *dst; 599 guchar *dst;
151 int bpp = gdk_pixbuf_get_has_alpha (pb) ? 4 : 3; 600 int bpp = gdk_pixbuf_get_n_channels (pb);
152 guchar *src = gdk_pixbuf_get_pixels (pb); 601 guchar *src = gdk_pixbuf_get_pixels (pb);
153 int sstr = gdk_pixbuf_get_rowstride (pb); 602 int sstr = gdk_pixbuf_get_rowstride (pb);
154 603
155 RETVAL = newSV (w * h); 604 RETVAL = newSV (6 * 8 * 12 / 8);
156 SvPOK_only (RETVAL); 605 SvPOK_only (RETVAL);
157 SvCUR_set (RETVAL, w * h); 606 SvCUR_set (RETVAL, 6 * 8 * 12 / 8);
158 607
159 dst = SvPVX (RETVAL); 608 dst = (guchar *)SvPVX (RETVAL);
609
610 /* some primitive error distribution + random dithering */
160 611
161 for (y = 0; y < h; y++) 612 for (y = 0; y < h; y++)
162 { 613 {
163 /* use a very primitive form of error distribution. */ 614 guchar *p = src + y * sstr;
164 int er = 0, eg = 0, eb = 0;
165 615
166 for (x = 0; x < w; x++) 616 for (x = 0; x < w; x += 2)
167 { 617 {
168 int r, g, b; 618 unsigned int r, g, b, h, s, v, H, V1, V2;
169 guchar *p = src + x * bpp + y * sstr;
170 619
171 r = ((p[0] + er) * 7 + 128) / 255; 620 if (bpp == 3)
172 g = ((p[1] + eg) * 7 + 128) / 255; 621 r = *p++, g = *p++, b = *p++;
173 b = ((p[2] + eb) * 3 + 128) / 255; 622 else if (bpp == 1)
623 r = g = b = *p++;
624 else
625 abort ();
174 626
175 r = r > 7 ? 7 : r < 0 ? 0 : r; 627 rgb_to_hsv (r, g, b, &h, &s, &v);
176 g = g > 7 ? 7 : g < 0 ? 0 : g;
177 b = b > 3 ? 3 : b < 0 ? 0 : b;
178 628
179 er += p[0] - (r * 255 + 4) / 7; 629 H = (h * 15 / 255) << 4;
180 eg += p[1] - (g * 255 + 4) / 7; 630 V1 = v;
181 eb += p[2] - (b * 255 + 2) / 3;
182 631
183 *dst++ = r << 5 | g << 2 | b; 632 if (bpp == 3)
633 r = *p++, g = *p++, b = *p++;
634 else if (bpp == 1)
635 r = g = b = *p++;
636 else
637 abort ();
638
639 rgb_to_hsv (r, g, b, &h, &s, &v);
640
641 H |= h * 15 / 255;
642 V2 = v;
643
644 *dst++ = H;
645 *dst++ = V1;
646 *dst++ = V2;
184 } 647 }
185 } 648 }
186} 649}
187 OUTPUT: 650 OUTPUT:
188 RETVAL 651 RETVAL
189 652
653SV *
654hv84_to_av (unsigned char *hv84)
655 CODE:
656{
657 int i = 72 / 3;
658 AV *av = newAV ();
659
660 RETVAL = (SV *)newRV_noinc ((SV *)av);
661 while (i--)
662 {
663 int h = *hv84++;
664 int v1 = *hv84++;
665 int v2 = *hv84++;
666
667 av_push (av, newSViv (v1));
668 av_push (av, newSViv ((h >> 4) * 255 / 15));
669 av_push (av, newSViv (v2));
670 av_push (av, newSViv ((h & 15) * 255 / 15));
671 }
672}
673 OUTPUT:
674 RETVAL
675
676#############################################################################
677
190MODULE = Gtk2::CV PACKAGE = Gtk2::CV::PostScript 678MODULE = Gtk2::CV PACKAGE = Gtk2::CV::Plugin::RCluster
191 679
192void 680SV *
193dump_pb (PerlIO *fp, GdkPixbuf *pb) 681extract_features (SV *ar)
194 CODE: 682 CODE:
195{ 683{
196 int w = gdk_pixbuf_get_width (pb); 684 int i;
197 int h = gdk_pixbuf_get_height (pb); 685 AV *av, *result;
198 int x, y, i;
199 guchar *dst;
200 int bpp = gdk_pixbuf_get_has_alpha (pb) ? 4 : 3;
201 guchar *src = gdk_pixbuf_get_pixels (pb);
202 int sstr = gdk_pixbuf_get_rowstride (pb);
203 686
204 a85_init (); 687 if (!SvROK (ar) || SvTYPE (SvRV (ar)) != SVt_PVAV)
688 croak ("Not an array ref as first argument to extract_features");
205 689
206 for (y = 0; y < h; y++) 690 av = (AV *) SvRV (ar);
207 for (x = 0; x < w; x++) 691 result = newAV ();
208 for (i = 0; i < 3; i++)
209 a85_push (fp, src [x * bpp + y * sstr + i]);
210 692
211 a85_finish (fp); 693 for (i = 0; i <= av_len (av); ++i)
212} 694 {
695 SV *sv = *av_fetch (av, i, 1);
696 SV *histsv = newSV (9 * sizeof (float) + 1);
213 697
698 SvPOK_on (histsv);
699 SvCUR_set (histsv, 9 * sizeof (float));
700 float *hist = (float *)SvPVX (histsv);
214 701
702 struct feature f_h, f_s, f_v;
703 feature_init (&f_h);
704 feature_init (&f_s);
705 feature_init (&f_v);
215 706
707 {
708 STRLEN len;
709 unsigned char *buf = (unsigned char *)SvPVbyte (sv, len);
710 while (len >= 3)
711 {
712 unsigned int r, g, b, h, s, v;
713 r = *buf++; g = *buf++; b = *buf++;
714 rgb_to_hsv (r, g, b, &h, &s, &v);
216 715
716 feature_update_pass_1 (&f_h, h);
717 feature_update_pass_1 (&f_s, s);
718 feature_update_pass_1 (&f_v, v);
719
720 len -= 3;
721 }
722
723 feature_finish_pass_1 (&f_h);
724 feature_finish_pass_1 (&f_s);
725 feature_finish_pass_1 (&f_v);
726 }
727
728 {
729 STRLEN len;
730 unsigned char *buf = (unsigned char *)SvPVbyte (sv, len);
731 while (len >= 3)
732 {
733 unsigned int r, g, b, h, s, v;
734 r = *buf++; g = *buf++; b = *buf++;
735 rgb_to_hsv (r, g, b, &h, &s, &v);
736
737 feature_update_pass_2 (&f_h, h);
738 feature_update_pass_2 (&f_s, s);
739 feature_update_pass_2 (&f_v, v);
740
741 len -= 3;
742 }
743
744 feature_finish_pass_2 (&f_h);
745 feature_finish_pass_2 (&f_s);
746 feature_finish_pass_2 (&f_v);
747 }
748
749 hist [0] = f_h.v1 * 2.; hist [1] = f_h.v2 * 2.; hist [2] = f_h.v3 * 2.;
750 hist [3] = f_s.v1 ; hist [4] = f_s.v2 ; hist [5] = f_s.v3 ;
751 hist [6] = f_v.v1 * .5; hist [7] = f_v.v2 * .5; hist [8] = f_v.v3 * .5;
752
753 av_push (result, histsv);
754 }
755
756 RETVAL = newRV_noinc ((SV *)result);
757}
758 OUTPUT:
759 RETVAL
760

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines