12 #define i_int_hlines_testing() 1
20 #if i_int_hlines_testing()
26 /* These functions are all shared - then comes platform dependant code */
27 static int getstr(void *hv_t,char *key,char **store) {
31 mm_log((1,"getstr(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
33 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
35 svpp=hv_fetch(hv, key, strlen(key), 0);
36 *store=SvPV(*svpp, PL_na );
41 static int getint(void *hv_t,char *key,int *store) {
45 mm_log((1,"getint(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
47 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
49 svpp=hv_fetch(hv, key, strlen(key), 0);
50 *store=(int)SvIV(*svpp);
54 static int getdouble(void *hv_t,char* key,double *store) {
58 mm_log((1,"getdouble(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
60 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
61 svpp=hv_fetch(hv, key, strlen(key), 0);
62 *store=(float)SvNV(*svpp);
66 static int getvoid(void *hv_t,char* key,void **store) {
70 mm_log((1,"getvoid(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
72 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
74 svpp=hv_fetch(hv, key, strlen(key), 0);
75 *store = INT2PTR(void*, SvIV(*svpp));
80 static int getobj(void *hv_t,char *key,char *type,void **store) {
84 mm_log((1,"getobj(hv_t 0x%X, key %s,type %s, store 0x%X)\n",hv_t,key,type,store));
86 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
88 svpp=hv_fetch(hv, key, strlen(key), 0);
90 if (sv_derived_from(*svpp,type)) {
91 IV tmp = SvIV((SV*)SvRV(*svpp));
92 *store = INT2PTR(void*, tmp);
94 mm_log((1,"getobj: key exists in hash but is not of correct type"));
101 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
103 void my_SvREFCNT_dec(void *p) {
104 SvREFCNT_dec((SV*)p);
109 i_log_entry(char *string, int level) {
110 mm_log((level, string));
114 typedef struct i_reader_data_tag
116 /* presumably a CODE ref or name of a sub */
120 /* used by functions that want callbacks */
121 static int read_callback(char *userdata, char *buffer, int need, int want) {
122 i_reader_data *rd = (i_reader_data *)userdata;
126 dSP; dTARG = sv_newmortal();
127 /* thanks to Simon Cozens for help with the dTARG above */
137 count = perl_call_sv(rd->sv, G_SCALAR);
142 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
148 char *ptr = SvPV(data, len);
150 croak("Too much data returned in reader callback");
152 memcpy(buffer, ptr, len);
168 SV *sv; /* a coderef or sub name */
171 /* used by functions that want callbacks */
172 static int write_callback(char *userdata, char const *data, int size) {
173 i_writer_data *wd = (i_writer_data *)userdata;
183 XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
186 count = perl_call_sv(wd->sv, G_SCALAR);
191 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
194 success = SvTRUE(sv);
204 #define CBDATA_BUFSIZE 8192
207 /* the SVs we use to call back to Perl */
213 /* we need to remember whether the buffer contains write data or
219 /* how far we've read into the buffer (not used for writing) */
222 /* the amount of space used/data available in the buffer */
225 /* the maximum amount to fill the buffer before flushing
226 If any write is larger than this then the buffer is flushed and
227 the full write is performed. The write is _not_ split into
232 char buffer[CBDATA_BUFSIZE];
237 call_writer(cbd, buf, size)
239 Low-level function to call the perl writer callback.
243 static ssize_t call_writer(struct cbdata *cbd, void const *buf, size_t size) {
249 if (!SvOK(cbd->writecb))
256 PUSHs(sv_2mortal(newSVpv((char *)buf, size)));
259 count = perl_call_sv(cbd->writecb, G_SCALAR);
263 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
266 success = SvTRUE(sv);
273 return success ? size : 0;
276 static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
283 if (!SvOK(cbd->readcb))
290 PUSHs(sv_2mortal(newSViv(size)));
291 PUSHs(sv_2mortal(newSViv(maxread)));
294 count = perl_call_sv(cbd->readcb, G_SCALAR);
299 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
305 char *ptr = SvPV(data, len);
307 croak("Too much data returned in reader callback");
309 memcpy(buf, ptr, len);
323 static ssize_t write_flush(struct cbdata *cbd) {
326 result = call_writer(cbd, cbd->buffer, cbd->used);
331 static off_t io_seeker(void *p, off_t offset, int whence) {
332 struct cbdata *cbd = p;
337 if (!SvOK(cbd->seekcb))
341 if (cbd->used && write_flush(cbd) <= 0)
345 if (whence == SEEK_CUR && cbd->reading && cbd->where != cbd->used) {
346 offset -= cbd->where - cbd->used;
349 cbd->where = cbd->used = 0;
355 PUSHs(sv_2mortal(newSViv(offset)));
356 PUSHs(sv_2mortal(newSViv(whence)));
359 count = perl_call_sv(cbd->seekcb, G_SCALAR);
364 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
375 static ssize_t io_writer(void *p, void const *data, size_t size) {
376 struct cbdata *cbd = p;
378 /*printf("io_writer(%p, %p, %u)\n", p, data, size);*/
380 if (cbd->reading && cbd->where < cbd->used) {
381 /* we read past the place where the caller expected us to be
382 so adjust our position a bit */
384 if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
389 cbd->where = cbd->used = 0;
392 if (cbd->used && cbd->used + size > cbd->maxlength) {
393 if (write_flush(cbd) <= 0) {
398 if (cbd->used+size <= cbd->maxlength) {
399 memcpy(cbd->buffer + cbd->used, data, size);
403 /* it doesn't fit - just pass it up */
404 return call_writer(cbd, data, size);
407 static ssize_t io_reader(void *p, void *data, size_t size) {
408 struct cbdata *cbd = p;
410 char *out = data; /* so we can do pointer arithmetic */
413 if (write_flush(cbd) <= 0)
419 if (size <= cbd->used - cbd->where) {
421 memcpy(data, cbd->buffer+cbd->where, size);
426 memcpy(out, cbd->buffer + cbd->where, cbd->used - cbd->where);
427 total += cbd->used - cbd->where;
428 size -= cbd->used - cbd->where;
429 out += cbd->used - cbd->where;
430 if (size < sizeof(cbd->buffer)) {
434 && (did_read = call_reader(cbd, cbd->buffer, size,
435 sizeof(cbd->buffer))) > 0) {
437 cbd->used = did_read;
439 copy_size = i_min(size, cbd->used);
440 memcpy(out, cbd->buffer, copy_size);
441 cbd->where += copy_size;
448 /* just read the rest - too big for our buffer*/
450 while ((did_read = call_reader(cbd, out, size, size)) > 0) {
460 static void io_closer(void *p) {
461 struct cbdata *cbd = p;
463 if (cbd->writing && cbd->used > 0) {
468 if (SvOK(cbd->closecb)) {
476 perl_call_sv(cbd->closecb, G_VOID);
485 static void io_destroyer(void *p) {
486 struct cbdata *cbd = p;
488 SvREFCNT_dec(cbd->writecb);
489 SvREFCNT_dec(cbd->readcb);
490 SvREFCNT_dec(cbd->seekcb);
491 SvREFCNT_dec(cbd->closecb);
499 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
502 for (i = 0; i < count; ++i)
503 if (strEQ(names[i].name, name))
504 return names[i].value;
508 static struct value_name transp_names[] =
511 { "threshold", tr_threshold },
512 { "errdiff", tr_errdiff },
513 { "ordered", tr_ordered, },
516 static struct value_name make_color_names[] =
518 { "none", mc_none, },
519 { "webmap", mc_web_map, },
520 { "addi", mc_addi, },
521 { "mediancut", mc_median_cut, },
524 static struct value_name translate_names[] =
527 { "giflib", pt_giflib, },
529 { "closest", pt_closest, },
530 { "perturb", pt_perturb, },
531 { "errdiff", pt_errdiff, },
534 static struct value_name errdiff_names[] =
536 { "floyd", ed_floyd, },
537 { "jarvis", ed_jarvis, },
538 { "stucki", ed_stucki, },
539 { "custom", ed_custom, },
542 static struct value_name orddith_names[] =
544 { "random", od_random, },
545 { "dot8", od_dot8, },
546 { "dot4", od_dot4, },
547 { "hline", od_hline, },
548 { "vline", od_vline, },
549 { "/line", od_slashline, },
550 { "slashline", od_slashline, },
551 { "\\line", od_backline, },
552 { "backline", od_backline, },
553 { "tiny", od_tiny, },
554 { "custom", od_custom, },
557 /* look through the hash for quantization options */
558 static void handle_quant_opts(i_quantize *quant, HV *hv)
560 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
566 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
568 sv = hv_fetch(hv, "transp", 6, 0);
569 if (sv && *sv && (str = SvPV(*sv, len))) {
571 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
573 if (quant->transp != tr_none) {
574 quant->tr_threshold = 127;
575 sv = hv_fetch(hv, "tr_threshold", 12, 0);
577 quant->tr_threshold = SvIV(*sv);
579 if (quant->transp == tr_errdiff) {
580 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
581 if (sv && *sv && (str = SvPV(*sv, len)))
582 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
584 if (quant->transp == tr_ordered) {
585 quant->tr_orddith = od_tiny;
586 sv = hv_fetch(hv, "tr_orddith", 10, 0);
587 if (sv && *sv && (str = SvPV(*sv, len)))
588 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
590 if (quant->tr_orddith == od_custom) {
591 sv = hv_fetch(hv, "tr_map", 6, 0);
592 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
593 AV *av = (AV*)SvRV(*sv);
594 len = av_len(av) + 1;
595 if (len > sizeof(quant->tr_custom))
596 len = sizeof(quant->tr_custom);
597 for (i = 0; i < len; ++i) {
598 SV **sv2 = av_fetch(av, i, 0);
600 quant->tr_custom[i] = SvIV(*sv2);
603 while (i < sizeof(quant->tr_custom))
604 quant->tr_custom[i++] = 0;
609 quant->make_colors = mc_addi;
610 sv = hv_fetch(hv, "make_colors", 11, 0);
611 if (sv && *sv && (str = SvPV(*sv, len))) {
613 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_addi);
615 sv = hv_fetch(hv, "colors", 6, 0);
616 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
617 /* needs to be an array of Imager::Color
618 note that the caller allocates the mc_color array and sets mc_size
620 AV *av = (AV *)SvRV(*sv);
621 quant->mc_count = av_len(av)+1;
622 if (quant->mc_count > quant->mc_size)
623 quant->mc_count = quant->mc_size;
624 for (i = 0; i < quant->mc_count; ++i) {
625 SV **sv1 = av_fetch(av, i, 0);
626 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
627 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
628 quant->mc_colors[i] = *col;
632 sv = hv_fetch(hv, "max_colors", 10, 0);
635 if (i <= quant->mc_size && i >= quant->mc_count)
639 quant->translate = pt_closest;
640 sv = hv_fetch(hv, "translate", 9, 0);
641 if (sv && *sv && (str = SvPV(*sv, len))) {
642 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
644 sv = hv_fetch(hv, "errdiff", 7, 0);
645 if (sv && *sv && (str = SvPV(*sv, len))) {
646 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
648 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
649 /* get the error diffusion map */
650 sv = hv_fetch(hv, "errdiff_width", 13, 0);
652 quant->ed_width = SvIV(*sv);
653 sv = hv_fetch(hv, "errdiff_height", 14, 0);
655 quant->ed_height = SvIV(*sv);
656 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
658 quant->ed_orig = SvIV(*sv);
659 if (quant->ed_width > 0 && quant->ed_height > 0) {
661 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
662 sv = hv_fetch(hv, "errdiff_map", 11, 0);
663 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
664 AV *av = (AV*)SvRV(*sv);
665 len = av_len(av) + 1;
666 if (len > quant->ed_width * quant->ed_height)
667 len = quant->ed_width * quant->ed_height;
668 for (i = 0; i < len; ++i) {
669 SV **sv2 = av_fetch(av, i, 0);
671 quant->ed_map[i] = SvIV(*sv2);
672 sum += quant->ed_map[i];
678 myfree(quant->ed_map);
680 quant->errdiff = ed_floyd;
684 sv = hv_fetch(hv, "perturb", 7, 0);
686 quant->perturb = SvIV(*sv);
689 static void cleanup_quant_opts(i_quantize *quant) {
690 myfree(quant->mc_colors);
692 myfree(quant->ed_map);
695 /* copies the color map from the hv into the colors member of the HV */
696 static void copy_colors_back(HV *hv, i_quantize *quant) {
702 sv = hv_fetch(hv, "colors", 6, 0);
703 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
706 ref = newRV_inc((SV*) av);
707 sv = hv_store(hv, "colors", 6, ref, 0);
710 av = (AV *)SvRV(*sv);
712 av_extend(av, quant->mc_count+1);
713 for (i = 0; i < quant->mc_count; ++i) {
714 i_color *in = quant->mc_colors+i;
715 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
716 work = sv_newmortal();
717 sv_setref_pv(work, "Imager::Color", (void *)c);
719 if (!av_store(av, i, work)) {
725 /* loads the segments of a fountain fill into an array */
726 static i_fountain_seg *
727 load_fount_segs(AV *asegs, int *count) {
728 /* Each element of segs must contain:
729 [ start, middle, end, c0, c1, segtype, colortrans ]
730 start, middle, end are doubles from 0 to 1
731 c0, c1 are Imager::Color::Float or Imager::Color objects
732 segtype, colortrans are ints
736 i_fountain_seg *segs;
740 *count = av_len(asegs)+1;
742 croak("i_fountain must have at least one segment");
743 segs = mymalloc(sizeof(i_fountain_seg) * *count);
744 for(i = 0; i < *count; i++) {
745 SV **sv1 = av_fetch(asegs, i, 0);
746 if (!sv1 || !*sv1 || !SvROK(*sv1)
747 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
749 croak("i_fountain: segs must be an arrayref of arrayrefs");
751 aseg = (AV *)SvRV(*sv1);
752 if (av_len(aseg) != 7-1) {
754 croak("i_fountain: a segment must have 7 members");
756 for (j = 0; j < 3; ++j) {
757 SV **sv2 = av_fetch(aseg, j, 0);
760 croak("i_fountain: XS error");
762 work[j] = SvNV(*sv2);
764 segs[i].start = work[0];
765 segs[i].middle = work[1];
766 segs[i].end = work[2];
767 for (j = 0; j < 2; ++j) {
768 SV **sv3 = av_fetch(aseg, 3+j, 0);
769 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
770 (!sv_derived_from(*sv3, "Imager::Color")
771 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
773 croak("i_fountain: segs must contain colors in elements 3 and 4");
775 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
776 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
779 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
781 for (ch = 0; ch < MAXCHANNELS; ++ch) {
782 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
786 for (j = 0; j < 2; ++j) {
787 SV **sv2 = av_fetch(aseg, j+5, 0);
790 croak("i_fountain: XS error");
792 worki[j] = SvIV(*sv2);
794 segs[i].type = worki[0];
795 segs[i].color = worki[1];
801 /* I don't think ICLF_* names belong at the C interface
802 this makes the XS code think we have them, to let us avoid
803 putting function bodies in the XS code
805 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
806 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
809 /* the m_init_log() function was called init_log(), renamed to reduce
810 potential naming conflicts */
811 #define init_log m_init_log
813 #if i_int_hlines_testing()
815 typedef i_int_hlines *Imager__Internal__Hlines;
817 static i_int_hlines *
818 i_int_hlines_new(int start_y, int count_y, int start_x, int count_x) {
819 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
820 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
825 static i_int_hlines *
826 i_int_hlines_new_img(i_img *im) {
827 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
828 i_int_init_hlines_img(result, im);
834 i_int_hlines_DESTROY(i_int_hlines *hlines) {
835 i_int_hlines_destroy(hlines);
839 static int seg_compare(const void *vleft, const void *vright) {
840 const i_int_hline_seg *left = vleft;
841 const i_int_hline_seg *right = vright;
843 return left->minx - right->minx;
847 i_int_hlines_dump(i_int_hlines *hlines) {
848 SV *dump = newSVpvf("start_y: %d limit_y: %d start_x: %d limit_x: %d\n",
849 hlines->start_y, hlines->limit_y, hlines->start_x, hlines->limit_x);
852 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
853 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
856 /* sort the segments, if any */
858 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
860 sv_catpvf(dump, " %d (%d):", y, entry->count);
861 for (i = 0; i < entry->count; ++i) {
862 sv_catpvf(dump, " [%d, %d)", entry->segs[i].minx,
863 entry->segs[i].x_limit);
865 sv_catpv(dump, "\n");
875 #define i_exif_enabled() 1
877 #define i_exif_enabled() 0
880 /* trying to use more C style names, map them here */
881 #define i_io_DESTROY(ig) io_glue_destroy(ig)
883 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
886 ICL_new_internal(r,g,b,a)
898 ICL_set_internal(cl,r,g,b,a)
905 ICL_set_internal(cl, r, g, b, a);
919 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
920 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
921 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
922 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
928 RETVAL = mymalloc(sizeof(i_color));
930 i_hsv_to_rgb(RETVAL);
938 RETVAL = mymalloc(sizeof(i_color));
940 i_rgb_to_hsv(RETVAL);
946 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
949 ICLF_new_internal(r, g, b, a)
957 Imager::Color::Float cl
961 Imager::Color::Float cl
965 EXTEND(SP, MAXCHANNELS);
966 for (ch = 0; ch < MAXCHANNELS; ++ch) {
967 /* printf("%d: %g\n", ch, cl->channel[ch]); */
968 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
972 ICLF_set_internal(cl,r,g,b,a)
973 Imager::Color::Float cl
988 Imager::Color::Float c
990 RETVAL = mymalloc(sizeof(i_fcolor));
992 i_hsv_to_rgbf(RETVAL);
998 Imager::Color::Float c
1000 RETVAL = mymalloc(sizeof(i_fcolor));
1002 i_rgb_to_hsvf(RETVAL);
1006 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1020 MODULE = Imager PACKAGE = Imager
1039 SvPV(ST(0), length);
1040 SvREFCNT_inc(ST(0));
1041 RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0));
1046 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1055 cbd = mymalloc(sizeof(struct cbdata));
1056 SvREFCNT_inc(writecb);
1057 cbd->writecb = writecb;
1058 SvREFCNT_inc(readcb);
1059 cbd->readcb = readcb;
1060 SvREFCNT_inc(seekcb);
1061 cbd->seekcb = seekcb;
1062 SvREFCNT_inc(closecb);
1063 cbd->closecb = closecb;
1064 cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
1065 if (maxwrite > CBDATA_BUFSIZE)
1066 maxwrite = CBDATA_BUFSIZE;
1067 cbd->maxlength = maxwrite;
1068 RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
1077 unsigned char* data;
1081 tlength = io_slurp(ig, &data);
1083 PUSHs(sv_2mortal(newSVpv((char *)data,tlength)));
1088 i_set_image_file_limits(width, height, bytes)
1094 i_get_image_file_limits()
1096 int width, height, bytes;
1098 if (i_get_image_file_limits(&width, &height, &bytes)) {
1100 PUSHs(sv_2mortal(newSViv(width)));
1101 PUSHs(sv_2mortal(newSViv(height)));
1102 PUSHs(sv_2mortal(newSViv(bytes)));
1105 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1108 i_io_write(ig, data_sv)
1116 if (SvUTF8(data_sv)) {
1117 data_sv = sv_2mortal(newSVsv(data_sv));
1118 sv_utf8_downgrade(data_sv, FALSE);
1121 data = SvPV(data_sv, size);
1122 RETVAL = i_io_write(ig, data, size);
1127 i_io_read(ig, buffer_sv, size)
1136 croak("size negative in call to i_io_read()");
1137 /* prevent an undefined value warning if they supplied an
1139 Orginally conditional on !SvOK(), but this will prevent the
1140 downgrade from croaking */
1141 sv_setpvn(buffer_sv, "", 0);
1143 if (SvUTF8(buffer_sv))
1144 sv_utf8_downgrade(buffer_sv, FALSE);
1146 buffer = SvGROW(buffer_sv, size+1);
1147 result = i_io_read(ig, buffer, size);
1149 RETVAL = &PL_sv_undef;
1152 SvCUR_set(buffer_sv, result);
1153 *SvEND(buffer_sv) = '\0';
1154 SvPOK_only(buffer_sv);
1155 RETVAL = newSViv(result); /* XS will mortal this */
1162 i_io_seek(ig, position, whence)
1176 MODULE = Imager PACKAGE = Imager
1187 while( (item=i_format_list[i++]) != NULL ) {
1189 PUSHs(sv_2mortal(newSVpv(item,0)));
1206 i_img_empty_ch(im,x,y,ch)
1213 i_sametype(im, x, y)
1219 i_sametype_chans(im, x, y, channels)
1226 i_init_log(name,level)
1231 i_log_entry(string,level)
1250 i_img_info(im,info);
1252 PUSHs(sv_2mortal(newSViv(info[0])));
1253 PUSHs(sv_2mortal(newSViv(info[1])));
1254 PUSHs(sv_2mortal(newSViv(info[2])));
1255 PUSHs(sv_2mortal(newSViv(info[3])));
1261 i_img_setmask(im,ch_mask)
1270 i_img_getchannels(im)
1279 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1284 i_line(im,x1,y1,x2,y2,val,endp)
1294 i_line_aa(im,x1,y1,x2,y2,val,endp)
1304 i_box(im,x1,y1,x2,y2,val)
1313 i_box_filled(im,x1,y1,x2,y2,val)
1322 i_box_cfill(im,x1,y1,x2,y2,fill)
1328 Imager::FillHandle fill
1331 i_arc(im,x,y,rad,d1,d2,val)
1341 i_arc_aa(im,x,y,rad,d1,d2,val)
1351 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1358 Imager::FillHandle fill
1361 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1368 Imager::FillHandle fill
1372 i_circle_aa(im,x,y,rad,val)
1382 i_bezier_multi(im,xc,yc,val)
1395 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1396 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1397 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1398 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1399 av1=(AV*)SvRV(ST(1));
1400 av2=(AV*)SvRV(ST(2));
1401 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1403 x=mymalloc( len*sizeof(double) );
1404 y=mymalloc( len*sizeof(double) );
1405 for(i=0;i<len;i++) {
1406 sv1=(*(av_fetch(av1,i,0)));
1407 sv2=(*(av_fetch(av2,i,0)));
1408 x[i]=(double)SvNV(sv1);
1409 y[i]=(double)SvNV(sv2);
1411 i_bezier_multi(im,len,x,y,val);
1417 i_poly_aa(im,xc,yc,val)
1430 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1431 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1432 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1433 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1434 av1=(AV*)SvRV(ST(1));
1435 av2=(AV*)SvRV(ST(2));
1436 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1438 x=mymalloc( len*sizeof(double) );
1439 y=mymalloc( len*sizeof(double) );
1440 for(i=0;i<len;i++) {
1441 sv1=(*(av_fetch(av1,i,0)));
1442 sv2=(*(av_fetch(av2,i,0)));
1443 x[i]=(double)SvNV(sv1);
1444 y[i]=(double)SvNV(sv2);
1446 i_poly_aa(im,len,x,y,val);
1451 i_poly_aa_cfill(im,xc,yc,fill)
1453 Imager::FillHandle fill
1463 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1464 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1465 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1466 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1467 av1=(AV*)SvRV(ST(1));
1468 av2=(AV*)SvRV(ST(2));
1469 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1471 x=mymalloc( len*sizeof(double) );
1472 y=mymalloc( len*sizeof(double) );
1473 for(i=0;i<len;i++) {
1474 sv1=(*(av_fetch(av1,i,0)));
1475 sv2=(*(av_fetch(av2,i,0)));
1476 x[i]=(double)SvNV(sv1);
1477 y[i]=(double)SvNV(sv2);
1479 i_poly_aa_cfill(im,len,x,y,fill);
1486 i_flood_fill(im,seedx,seedy,dcol)
1493 i_flood_cfill(im,seedx,seedy,fill)
1497 Imager::FillHandle fill
1501 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1513 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1530 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1542 i_flipxy(im, direction)
1547 i_rotate90(im, degrees)
1552 i_rotate_exact(im, amount, ...)
1556 i_color *backp = NULL;
1557 i_fcolor *fbackp = NULL;
1561 /* extract the bg colors if any */
1562 /* yes, this is kind of strange */
1563 for (i = 2; i < items; ++i) {
1565 if (sv_derived_from(sv1, "Imager::Color")) {
1566 IV tmp = SvIV((SV*)SvRV(sv1));
1567 backp = INT2PTR(i_color *, tmp);
1569 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1570 IV tmp = SvIV((SV*)SvRV(sv1));
1571 fbackp = INT2PTR(i_fcolor *, tmp);
1574 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1579 i_matrix_transform(im, xsize, ysize, matrix, ...)
1589 i_color *backp = NULL;
1590 i_fcolor *fbackp = NULL;
1592 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1593 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1594 av=(AV*)SvRV(ST(3));
1598 for (i = 0; i < len; ++i) {
1599 sv1=(*(av_fetch(av,i,0)));
1600 matrix[i] = SvNV(sv1);
1604 /* extract the bg colors if any */
1605 /* yes, this is kind of strange */
1606 for (i = 4; i < items; ++i) {
1608 if (sv_derived_from(sv1, "Imager::Color")) {
1609 IV tmp = SvIV((SV*)SvRV(sv1));
1610 backp = INT2PTR(i_color *, tmp);
1612 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1613 IV tmp = SvIV((SV*)SvRV(sv1));
1614 fbackp = INT2PTR(i_fcolor *, tmp);
1617 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
1622 i_gaussian(im,stdev)
1627 i_unsharp_mask(im,stdev,scale)
1642 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1643 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1644 av=(AV*)SvRV(ST(1));
1646 coeff=mymalloc( len*sizeof(float) );
1647 for(i=0;i<len;i++) {
1648 sv1=(*(av_fetch(av,i,0)));
1649 coeff[i]=(float)SvNV(sv1);
1651 i_conv(im,coeff,len);
1655 i_convert(im, src, coeff)
1668 if (!SvROK(ST(2)) || SvTYPE(SvRV(ST(2))) != SVt_PVAV)
1669 croak("i_convert: parameter 3 must be an arrayref\n");
1670 avmain = (AV*)SvRV(ST(2));
1671 outchan = av_len(avmain)+1;
1672 /* find the biggest */
1674 for (j=0; j < outchan; ++j) {
1675 temp = av_fetch(avmain, j, 0);
1676 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1677 avsub = (AV*)SvRV(*temp);
1678 len = av_len(avsub)+1;
1683 coeff = mymalloc(sizeof(float) * outchan * inchan);
1684 for (j = 0; j < outchan; ++j) {
1685 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1686 len = av_len(avsub)+1;
1687 for (i = 0; i < len; ++i) {
1688 temp = av_fetch(avsub, i, 0);
1690 coeff[i+j*inchan] = SvNV(*temp);
1692 coeff[i+j*inchan] = 0;
1695 coeff[i++ + j*inchan] = 0;
1697 RETVAL = i_convert(im, src, coeff, outchan, inchan);
1707 unsigned int mask = 0;
1713 unsigned char (*maps)[256];
1715 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1716 croak("i_map: parameter 2 must be an arrayref\n");
1717 avmain = (AV*)SvRV(ST(1));
1718 len = av_len(avmain)+1;
1719 if (im->channels < len) len = im->channels;
1721 maps = mymalloc( len * sizeof(unsigned char [256]) );
1723 for (j=0; j<len ; j++) {
1724 temp = av_fetch(avmain, j, 0);
1725 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1726 avsub = (AV*)SvRV(*temp);
1727 if(av_len(avsub) != 255) continue;
1729 for (i=0; i<256 ; i++) {
1731 temp = av_fetch(avsub, i, 0);
1732 val = temp ? SvIV(*temp) : 0;
1734 if (val>255) val = 255;
1739 i_map(im, maps, mask);
1752 i_init_fonts(t1log=0)
1767 i_t1_destroy(font_id)
1772 i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
1791 str = SvPV(str_sv, len);
1792 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
1799 i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
1808 int cords[BOUNDING_BOX_COUNT];
1816 str = SvPV(str_sv, len);
1817 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
1820 for (i = 0; i < rc; ++i)
1821 PUSHs(sv_2mortal(newSViv(cords[i])));
1827 i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
1846 str = SvPV(str_sv, len);
1847 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
1853 i_t1_has_chars(handle, text_sv, utf8 = 0)
1865 if (SvUTF8(text_sv))
1868 text = SvPV(text_sv, len);
1869 work = mymalloc(len);
1870 count = i_t1_has_chars(handle, text, len, utf8, work);
1871 if (GIMME_V == G_ARRAY) {
1873 for (i = 0; i < count; ++i) {
1874 PUSHs(sv_2mortal(newSViv(work[i])));
1879 PUSHs(sv_2mortal(newSVpv(work, count)));
1884 i_t1_face_name(handle)
1890 len = i_t1_face_name(handle, name, sizeof(name));
1893 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
1897 i_t1_glyph_name(handle, text_sv, utf8 = 0)
1908 if (SvUTF8(text_sv))
1911 text = SvPV(text_sv, work_len);
1916 ch = i_utf8_advance(&text, &len);
1918 i_push_error(0, "invalid UTF8 character");
1927 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
1928 PUSHs(sv_2mortal(newSVpv(name, 0)));
1931 PUSHs(&PL_sv_undef);
1945 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
1947 #define TT_DESTROY(handle) i_tt_destroy(handle)
1951 Imager::Font::TT handle
1954 MODULE = Imager PACKAGE = Imager
1958 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
1959 Imager::Font::TT handle
1977 str = SvPV(str_sv, len);
1978 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
1979 len, smooth, utf8, align);
1985 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
1986 Imager::Font::TT handle
2004 str = SvPV(str_sv, len);
2005 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2006 smooth, utf8, align);
2012 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
2013 Imager::Font::TT handle
2018 int cords[BOUNDING_BOX_COUNT],rc;
2027 str = SvPV(str_sv, len);
2028 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2030 for (i = 0; i < rc; ++i) {
2031 PUSHs(sv_2mortal(newSViv(cords[i])));
2036 i_tt_has_chars(handle, text_sv, utf8)
2037 Imager::Font::TT handle
2048 if (SvUTF8(text_sv))
2051 text = SvPV(text_sv, len);
2052 work = mymalloc(len);
2053 count = i_tt_has_chars(handle, text, len, utf8, work);
2054 if (GIMME_V == G_ARRAY) {
2056 for (i = 0; i < count; ++i) {
2057 PUSHs(sv_2mortal(newSViv(work[i])));
2062 PUSHs(sv_2mortal(newSVpv(work, count)));
2067 i_tt_dump_names(handle)
2068 Imager::Font::TT handle
2071 i_tt_face_name(handle)
2072 Imager::Font::TT handle
2077 len = i_tt_face_name(handle, name, sizeof(name));
2080 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2084 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2085 Imager::Font::TT handle
2096 if (SvUTF8(text_sv))
2099 text = SvPV(text_sv, work_len);
2104 ch = i_utf8_advance(&text, &len);
2106 i_push_error(0, "invalid UTF8 character");
2115 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2116 PUSHs(sv_2mortal(newSVpv(name, 0)));
2119 PUSHs(&PL_sv_undef);
2128 i_writejpeg_wiol(im, ig, qfactor)
2144 rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
2145 if (iptc_itext == NULL) {
2148 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2153 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2155 PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
2166 i_test_format_probe(ig, length)
2175 i_readtiff_wiol(ig, length, page=0)
2181 i_readtiff_multi_wiol(ig, length)
2189 imgs = i_readtiff_multi_wiol(ig, length, &count);
2192 for (i = 0; i < count; ++i) {
2193 SV *sv = sv_newmortal();
2194 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2202 i_writetiff_wiol(im, ig)
2207 i_writetiff_multi_wiol(ig, ...)
2215 croak("Usage: i_writetiff_multi_wiol(ig, images...)");
2216 img_count = items - 1;
2218 if (img_count < 1) {
2221 i_push_error(0, "You need to specify images to save");
2224 imgs = mymalloc(sizeof(i_img *) * img_count);
2225 for (i = 0; i < img_count; ++i) {
2228 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2229 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2233 i_push_error(0, "Only images can be saved");
2240 RETVAL = i_writetiff_multi_wiol(ig, imgs, img_count);
2248 i_writetiff_wiol_faxable(im, ig, fine)
2254 i_writetiff_multi_wiol_faxable(ig, fine, ...)
2263 croak("Usage: i_writetiff_multi_wiol_faxable(ig, fine, images...)");
2264 img_count = items - 2;
2266 if (img_count < 1) {
2269 i_push_error(0, "You need to specify images to save");
2272 imgs = mymalloc(sizeof(i_img *) * img_count);
2273 for (i = 0; i < img_count; ++i) {
2276 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2277 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2281 i_push_error(0, "Only images can be saved");
2288 RETVAL = i_writetiff_multi_wiol_faxable(ig, imgs, img_count, fine);
2296 #endif /* HAVE_LIBTIFF */
2302 i_readpng_wiol(ig, length)
2308 i_writepng_wiol(im, ig)
2321 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
2324 i_writegif(im,fd,colors,pixdev,fixed)
2331 Imager__Color fixed;
2338 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
2339 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2340 av=(AV*)SvRV(ST(4));
2341 fixedlen=av_len(av)+1;
2342 fixed=mymalloc( fixedlen*sizeof(i_color) );
2343 for(i=0;i<fixedlen;i++) {
2344 sv1=(*(av_fetch(av,i,0)));
2345 if (sv_derived_from(sv1, "Imager::Color")) {
2346 Itmp = SvIV((SV*)SvRV(sv1));
2347 tmp = INT2PTR(i_color*, Itmp);
2348 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
2351 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
2353 ST(0) = sv_newmortal();
2354 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2355 else sv_setiv(ST(0), (IV)RETVAL);
2361 i_writegifmc(im,fd,colors)
2368 i_writegif_gen(fd, ...)
2373 i_img **imgs = NULL;
2379 croak("Usage: i_writegif_gen(fd,hashref, images...)");
2380 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2381 croak("i_writegif_gen: Second argument must be a hash ref");
2382 hv = (HV *)SvRV(ST(1));
2383 memset(&quant, 0, sizeof(quant));
2384 quant.mc_size = 256;
2385 handle_quant_opts(&quant, hv);
2386 img_count = items - 2;
2388 if (img_count < 1) {
2391 i_push_error(0, "You need to specify images to save");
2394 imgs = mymalloc(sizeof(i_img *) * img_count);
2395 for (i = 0; i < img_count; ++i) {
2398 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2399 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2403 i_push_error(0, "Only images can be saved");
2409 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
2413 copy_colors_back(hv, &quant);
2416 ST(0) = sv_newmortal();
2417 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2418 else sv_setiv(ST(0), (IV)RETVAL);
2419 cleanup_quant_opts(&quant);
2423 i_writegif_callback(cb, maxbuffer,...)
2427 i_img **imgs = NULL;
2434 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2435 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2436 croak("i_writegif_callback: Second argument must be a hash ref");
2437 hv = (HV *)SvRV(ST(2));
2438 memset(&quant, 0, sizeof(quant));
2439 quant.mc_size = 256;
2440 handle_quant_opts(&quant, hv);
2441 img_count = items - 3;
2443 if (img_count < 1) {
2447 imgs = mymalloc(sizeof(i_img *) * img_count);
2448 for (i = 0; i < img_count; ++i) {
2451 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2452 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2461 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count);
2465 copy_colors_back(hv, &quant);
2468 ST(0) = sv_newmortal();
2469 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2470 else sv_setiv(ST(0), (IV)RETVAL);
2471 cleanup_quant_opts(&quant);
2474 i_writegif_wiol(ig, opts,...)
2478 i_img **imgs = NULL;
2484 croak("Usage: i_writegif_wiol(IO,hashref, images...)");
2485 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2486 croak("i_writegif_callback: Second argument must be a hash ref");
2487 hv = (HV *)SvRV(ST(1));
2488 memset(&quant, 0, sizeof(quant));
2489 quant.mc_size = 256;
2490 handle_quant_opts(&quant, hv);
2491 img_count = items - 2;
2493 if (img_count < 1) {
2497 imgs = mymalloc(sizeof(i_img *) * img_count);
2498 for (i = 0; i < img_count; ++i) {
2501 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2502 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2510 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
2514 copy_colors_back(hv, &quant);
2517 ST(0) = sv_newmortal();
2518 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2519 else sv_setiv(ST(0), (IV)RETVAL);
2520 cleanup_quant_opts(&quant);
2533 colour_table = NULL;
2536 if(GIMME_V == G_ARRAY) {
2537 rimg = i_readgif(fd,&colour_table,&colours);
2539 /* don't waste time with colours if they aren't wanted */
2540 rimg = i_readgif(fd,NULL,NULL);
2543 if (colour_table == NULL) {
2546 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2549 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2550 /* I don't know if I have the reference counts right or not :( */
2551 /* Neither do I :-) */
2552 /* No Idea here either */
2555 av_extend(ct, colours);
2556 for(q=0; q<colours; q++) {
2558 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2559 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2561 myfree(colour_table);
2565 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2567 PUSHs(newRV_noinc((SV*)ct));
2581 colour_table = NULL;
2584 if(GIMME_V == G_ARRAY) {
2585 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2587 /* don't waste time with colours if they aren't wanted */
2588 rimg = i_readgif_wiol(ig,NULL,NULL);
2591 if (colour_table == NULL) {
2594 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2597 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2598 /* I don't know if I have the reference counts right or not :( */
2599 /* Neither do I :-) */
2600 /* No Idea here either */
2603 av_extend(ct, colours);
2604 for(q=0; q<colours; q++) {
2606 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2607 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2609 myfree(colour_table);
2613 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2615 PUSHs(newRV_noinc((SV*)ct));
2619 i_readgif_single_wiol(ig, page=0)
2624 i_readgif_scalar(...)
2636 data = (char *)SvPV(ST(0), length);
2640 if(GIMME_V == G_ARRAY) {
2641 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2643 /* don't waste time with colours if they aren't wanted */
2644 rimg=i_readgif_scalar(data,length,NULL,NULL);
2647 if (colour_table == NULL) {
2650 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2653 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2654 /* I don't know if I have the reference counts right or not :( */
2655 /* Neither do I :-) */
2657 av_extend(ct, colours);
2658 for(q=0; q<colours; q++) {
2660 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2661 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2663 myfree(colour_table);
2667 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2669 PUSHs(newRV_noinc((SV*)ct));
2673 i_readgif_callback(...)
2688 if(GIMME_V == G_ARRAY) {
2689 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2691 /* don't waste time with colours if they aren't wanted */
2692 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2695 if (colour_table == NULL) {
2698 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2701 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2702 /* I don't know if I have the reference counts right or not :( */
2703 /* Neither do I :-) */
2704 /* Neither do I - maybe I'll move this somewhere */
2706 av_extend(ct, colours);
2707 for(q=0; q<colours; q++) {
2709 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2710 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2712 myfree(colour_table);
2716 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2718 PUSHs(newRV_noinc((SV*)ct));
2729 imgs = i_readgif_multi(fd, &count);
2732 for (i = 0; i < count; ++i) {
2733 SV *sv = sv_newmortal();
2734 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2741 i_readgif_multi_scalar(data)
2749 data = (char *)SvPV(ST(0), length);
2750 imgs = i_readgif_multi_scalar(data, length, &count);
2753 for (i = 0; i < count; ++i) {
2754 SV *sv = sv_newmortal();
2755 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2762 i_readgif_multi_callback(cb)
2770 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2773 for (i = 0; i < count; ++i) {
2774 SV *sv = sv_newmortal();
2775 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2782 i_readgif_multi_wiol(ig)
2789 imgs = i_readgif_multi_wiol(ig, &count);
2792 for (i = 0; i < count; ++i) {
2793 SV *sv = sv_newmortal();
2794 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2806 i_readpnm_wiol(ig, length)
2812 i_writeppm_wiol(im, ig)
2818 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2827 i_writeraw_wiol(im,ig)
2832 i_writebmp_wiol(im,ig)
2842 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2851 idlen = SvCUR(ST(4));
2852 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2858 i_readtga_wiol(ig, length)
2864 i_writergb_wiol(im,ig, wierdpack, compress, idstring)
2873 idlen = SvCUR(ST(4));
2874 RETVAL = i_writergb_wiol(im, ig, wierdpack, compress, idstring, idlen);
2880 i_readrgb_wiol(ig, length)
2887 i_scaleaxis(im,Value,Axis)
2893 i_scale_nn(im,scx,scy)
2903 i_count_colors(im,maxc)
2909 i_transform(im,opx,opy,parm)
2922 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2923 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2924 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2925 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2926 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2927 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2928 av=(AV*)SvRV(ST(1));
2930 opx=mymalloc( opxl*sizeof(int) );
2931 for(i=0;i<opxl;i++) {
2932 sv1=(*(av_fetch(av,i,0)));
2933 opx[i]=(int)SvIV(sv1);
2935 av=(AV*)SvRV(ST(2));
2937 opy=mymalloc( opyl*sizeof(int) );
2938 for(i=0;i<opyl;i++) {
2939 sv1=(*(av_fetch(av,i,0)));
2940 opy[i]=(int)SvIV(sv1);
2942 av=(AV*)SvRV(ST(3));
2943 parmlen=av_len(av)+1;
2944 parm=mymalloc( parmlen*sizeof(double) );
2945 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2946 sv1=(*(av_fetch(av,i,0)));
2947 parm[i]=(double)SvNV(sv1);
2949 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2953 ST(0) = sv_newmortal();
2954 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2955 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2958 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2983 in_imgs_count = av_len(av_in_imgs)+1;
2984 for (i = 0; i < in_imgs_count; ++i) {
2985 sv1 = *av_fetch(av_in_imgs, i, 0);
2986 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2987 croak("sv_in_img must contain only images");
2990 if (in_imgs_count > 0) {
2991 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2992 for (i = 0; i < in_imgs_count; ++i) {
2993 sv1 = *av_fetch(av_in_imgs,i,0);
2994 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2995 croak("Parameter 5 must contain only images");
2997 tmp = SvIV((SV*)SvRV(sv1));
2998 in_imgs[i] = INT2PTR(i_img*, tmp);
3002 /* no input images */
3005 /* default the output size from the first input if possible */
3007 width = SvIV(sv_width);
3008 else if (in_imgs_count)
3009 width = in_imgs[0]->xsize;
3011 croak("No output image width supplied");
3013 if (SvOK(sv_height))
3014 height = SvIV(sv_height);
3015 else if (in_imgs_count)
3016 height = in_imgs[0]->ysize;
3018 croak("No output image height supplied");
3020 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
3021 if (ops_len % sizeof(struct rm_op))
3022 croak("Imager: Parameter 3 must be a bitmap of regops\n");
3023 ops_count = ops_len / sizeof(struct rm_op);
3025 n_regs_count = av_len(av_n_regs)+1;
3026 n_regs = mymalloc(n_regs_count * sizeof(double));
3027 for (i = 0; i < n_regs_count; ++i) {
3028 sv1 = *av_fetch(av_n_regs,i,0);
3030 n_regs[i] = SvNV(sv1);
3032 c_regs_count = av_len(av_c_regs)+1;
3033 c_regs = mymalloc(c_regs_count * sizeof(i_color));
3034 /* I don't bother initializing the colou?r registers */
3036 RETVAL=i_transform2(width, height, channels, ops, ops_count,
3037 n_regs, n_regs_count,
3038 c_regs, c_regs_count, in_imgs, in_imgs_count);
3043 ST(0) = sv_newmortal();
3044 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3045 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3049 i_contrast(im,intensity)
3058 i_noise(im,amount,type)
3064 i_bumpmap(im,bump,channel,light_x,light_y,strength)
3074 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
3093 i_postlevels(im,levels)
3103 i_watermark(im,wmark,tx,ty,pixdiff)
3105 Imager::ImgRaw wmark
3112 i_autolevels(im,lsat,usat,skew)
3119 i_radnoise(im,xo,yo,rscale,ascale)
3127 i_turbnoise(im, xo, yo, scale)
3150 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
3151 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3152 croak("i_gradgen: Second argument must be an array ref");
3153 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3154 croak("i_gradgen: Third argument must be an array ref");
3155 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3156 croak("i_gradgen: Fourth argument must be an array ref");
3157 axx = (AV *)SvRV(ST(1));
3158 ayy = (AV *)SvRV(ST(2));
3159 ac = (AV *)SvRV(ST(3));
3160 dmeasure = (int)SvIV(ST(4));
3162 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3163 num = num <= av_len(ac) ? num : av_len(ac);
3165 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
3166 xo = mymalloc( sizeof(int) * num );
3167 yo = mymalloc( sizeof(int) * num );
3168 ival = mymalloc( sizeof(i_color) * num );
3169 for(i = 0; i<num; i++) {
3170 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3171 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3172 sv = *av_fetch(ac, i, 0);
3173 if ( !sv_derived_from(sv, "Imager::Color") ) {
3174 free(axx); free(ayy); free(ac);
3175 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
3177 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
3179 i_gradgen(im, num, xo, yo, ival, dmeasure);
3185 i_diff_image(im, im2, mindist=0)
3191 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3201 double ssample_param
3205 i_fountain_seg *segs;
3207 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
3208 croak("i_fountain: argument 11 must be an array ref");
3210 asegs = (AV *)SvRV(ST(10));
3211 segs = load_fount_segs(asegs, &count);
3212 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
3213 super_sample, ssample_param, count, segs);
3219 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3228 double ssample_param
3232 i_fountain_seg *segs;
3234 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
3235 croak("i_fountain: argument 11 must be an array ref");
3237 asegs = (AV *)SvRV(ST(9));
3238 segs = load_fount_segs(asegs, &count);
3239 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
3240 super_sample, ssample_param, count, segs);
3253 errors = i_errors();
3255 while (errors[i].msg) {
3257 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
3258 if (!av_store(av, 0, sv)) {
3261 sv = newSViv(errors[i].code);
3262 if (!av_store(av, 1, sv)) {
3265 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
3270 i_nearest_color(im, ...)
3285 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
3286 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3287 croak("i_nearest_color: Second argument must be an array ref");
3288 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3289 croak("i_nearest_color: Third argument must be an array ref");
3290 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3291 croak("i_nearest_color: Fourth argument must be an array ref");
3292 axx = (AV *)SvRV(ST(1));
3293 ayy = (AV *)SvRV(ST(2));
3294 ac = (AV *)SvRV(ST(3));
3295 dmeasure = (int)SvIV(ST(4));
3297 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3298 num = num <= av_len(ac) ? num : av_len(ac);
3300 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
3301 xo = mymalloc( sizeof(int) * num );
3302 yo = mymalloc( sizeof(int) * num );
3303 ival = mymalloc( sizeof(i_color) * num );
3304 for(i = 0; i<num; i++) {
3305 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3306 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3307 sv = *av_fetch(ac, i, 0);
3308 if ( !sv_derived_from(sv, "Imager::Color") ) {
3309 free(axx); free(ayy); free(ac);
3310 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
3312 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
3314 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
3328 rc=DSO_open(filename,&evstr);
3332 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
3333 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
3336 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
3342 DSO_close(dso_handle)
3346 DSO_funclist(dso_handle_v)
3350 DSO_handle *dso_handle;
3352 dso_handle=(DSO_handle*)dso_handle_v;
3354 while( dso_handle->function_list[i].name != NULL) {
3356 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
3358 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
3363 DSO_call(handle,func_index,hv)
3369 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3370 hv=(HV*)SvRV(ST(2));
3371 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3372 DSO_call( (DSO_handle *)handle,func_index,hv);
3377 i_get_pixel(im, x, y)
3384 color = (i_color *)mymalloc(sizeof(i_color));
3385 if (i_gpix(im, x, y, color) == 0) {
3386 RETVAL = NEWSV(0, 0);
3387 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
3391 RETVAL = &PL_sv_undef;
3398 i_ppix(im, x, y, cl)
3405 i_img_pal_new(x, y, channels, maxpal)
3412 i_img_to_pal(src, quant)
3418 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3419 croak("i_img_to_pal: second argument must be a hash ref");
3420 hv = (HV *)SvRV(ST(1));
3421 memset(&quant, 0, sizeof(quant));
3422 quant.mc_size = 256;
3423 handle_quant_opts(&quant, hv);
3424 RETVAL = i_img_to_pal(src, &quant);
3426 copy_colors_back(hv, &quant);
3428 cleanup_quant_opts(&quant);
3447 work = mymalloc((r-l) * sizeof(i_palidx));
3448 count = i_gpal(im, l, r, y, work);
3449 if (GIMME_V == G_ARRAY) {
3451 for (i = 0; i < count; ++i) {
3452 PUSHs(sv_2mortal(newSViv(work[i])));
3457 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3462 if (GIMME_V != G_ARRAY) {
3464 PUSHs(&PL_sv_undef);
3469 i_ppal(im, l, y, ...)
3478 work = mymalloc(sizeof(i_palidx) * (items-3));
3479 for (i=0; i < items-3; ++i) {
3480 work[i] = SvIV(ST(i+3));
3482 RETVAL = i_ppal(im, l, l+items-3, y, work);
3492 i_addcolors(im, ...)
3500 croak("i_addcolors: no colors to add");
3501 colors = mymalloc((items-1) * sizeof(i_color));
3502 for (i=0; i < items-1; ++i) {
3503 if (sv_isobject(ST(i+1))
3504 && sv_derived_from(ST(i+1), "Imager::Color")) {
3505 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3506 colors[i] = *INT2PTR(i_color *, tmp);
3510 croak("i_addcolor: pixels must be Imager::Color objects");
3513 index = i_addcolors(im, colors, items-1);
3516 RETVAL = newSVpv("0 but true", 0);
3518 else if (index == -1) {
3519 RETVAL = &PL_sv_undef;
3522 RETVAL = newSViv(index);
3528 i_setcolors(im, index, ...)
3536 croak("i_setcolors: no colors to add");
3537 colors = mymalloc((items-2) * sizeof(i_color));
3538 for (i=0; i < items-2; ++i) {
3539 if (sv_isobject(ST(i+2))
3540 && sv_derived_from(ST(i+2), "Imager::Color")) {
3541 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3542 colors[i] = *INT2PTR(i_color *, tmp);
3546 croak("i_setcolors: pixels must be Imager::Color objects");
3549 RETVAL = i_setcolors(im, index, colors, items-2);
3555 i_getcolors(im, index, ...)
3564 croak("i_getcolors: too many arguments");
3566 count = SvIV(ST(2));
3568 croak("i_getcolors: count must be positive");
3569 colors = mymalloc(sizeof(i_color) * count);
3570 if (i_getcolors(im, index, colors, count)) {
3571 for (i = 0; i < count; ++i) {
3573 SV *sv = sv_newmortal();
3574 pv = mymalloc(sizeof(i_color));
3576 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3592 i_findcolor(im, color)
3598 if (i_findcolor(im, color, &index)) {
3599 RETVAL = newSViv(index);
3602 RETVAL = &PL_sv_undef;
3620 i_gsamp(im, l, r, y, ...)
3632 croak("No channel numbers supplied to g_samp()");
3634 chan_count = items - 4;
3635 chans = mymalloc(sizeof(int) * chan_count);
3636 for (i = 0; i < chan_count; ++i)
3637 chans[i] = SvIV(ST(i+4));
3638 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
3639 count = i_gsamp(im, l, r, y, data, chans, chan_count);
3641 if (GIMME_V == G_ARRAY) {
3643 for (i = 0; i < count; ++i)
3644 PUSHs(sv_2mortal(newSViv(data[i])));
3648 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3653 if (GIMME_V != G_ARRAY) {
3655 PUSHs(&PL_sv_undef);
3661 i_img_masked_new(targ, mask, x, y, w, h)
3671 if (!sv_isobject(ST(1))
3672 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3673 croak("i_img_masked_new: parameter 2 must undef or an image");
3675 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3679 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3684 i_plin(im, l, y, ...)
3695 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3696 /* supplied as a byte string */
3697 work = (i_color *)SvPV(ST(3), len);
3698 count = len / sizeof(i_color);
3699 if (count * sizeof(i_color) != len) {
3700 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3702 RETVAL = i_plin(im, l, l+count, y, work);
3705 work = mymalloc(sizeof(i_color) * (items-3));
3706 for (i=0; i < items-3; ++i) {
3707 if (sv_isobject(ST(i+3))
3708 && sv_derived_from(ST(i+3), "Imager::Color")) {
3709 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3710 work[i] = *INT2PTR(i_color *, tmp);
3714 croak("i_plin: pixels must be Imager::Color objects");
3717 RETVAL = i_plin(im, l, l+items-3, y, work);
3728 i_ppixf(im, x, y, cl)
3732 Imager::Color::Float cl
3735 i_gsampf(im, l, r, y, ...)
3747 croak("No channel numbers supplied to g_sampf()");
3749 chan_count = items - 4;
3750 chans = mymalloc(sizeof(int) * chan_count);
3751 for (i = 0; i < chan_count; ++i)
3752 chans[i] = SvIV(ST(i+4));
3753 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3754 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3756 if (GIMME_V == G_ARRAY) {
3758 for (i = 0; i < count; ++i)
3759 PUSHs(sv_2mortal(newSVnv(data[i])));
3763 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3768 if (GIMME_V != G_ARRAY) {
3770 PUSHs(&PL_sv_undef);
3775 i_plinf(im, l, y, ...)
3786 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3787 /* supplied as a byte string */
3788 work = (i_fcolor *)SvPV(ST(3), len);
3789 count = len / sizeof(i_fcolor);
3790 if (count * sizeof(i_fcolor) != len) {
3791 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3793 RETVAL = i_plinf(im, l, l+count, y, work);
3796 work = mymalloc(sizeof(i_fcolor) * (items-3));
3797 for (i=0; i < items-3; ++i) {
3798 if (sv_isobject(ST(i+3))
3799 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3800 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3801 work[i] = *INT2PTR(i_fcolor *, tmp);
3805 croak("i_plinf: pixels must be Imager::Color::Float objects");
3809 RETVAL = i_plinf(im, l, l+items-3, y, work);
3827 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3828 if (i_gpixf(im, x, y, color) == 0) {
3829 RETVAL = NEWSV(0,0);
3830 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
3834 RETVAL = &PL_sv_undef;
3850 vals = mymalloc((r-l) * sizeof(i_color));
3851 count = i_glin(im, l, r, y, vals);
3852 if (GIMME_V == G_ARRAY) {
3854 for (i = 0; i < count; ++i) {
3856 i_color *col = mymalloc(sizeof(i_color));
3858 sv = sv_newmortal();
3859 sv_setref_pv(sv, "Imager::Color", (void *)col);
3865 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3871 i_glinf(im, l, r, y)
3881 vals = mymalloc((r-l) * sizeof(i_fcolor));
3882 count = i_glinf(im, l, r, y, vals);
3883 if (GIMME_V == G_ARRAY) {
3885 for (i = 0; i < count; ++i) {
3887 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3889 sv = sv_newmortal();
3890 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3896 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3902 i_img_16_new(x, y, ch)
3908 i_img_double_new(x, y, ch)
3914 i_tags_addn(im, name, code, idata)
3923 name = SvPV(ST(1), len);
3926 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3931 i_tags_add(im, name, code, data, idata)
3941 name = SvPV(ST(1), len);
3945 data = SvPV(ST(3), len);
3950 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3955 i_tags_find(im, name, start)
3962 if (i_tags_find(&im->tags, name, start, &entry)) {
3964 RETVAL = newSVpv("0 but true", 0);
3966 RETVAL = newSViv(entry);
3968 RETVAL = &PL_sv_undef;
3974 i_tags_findn(im, code, start)
3981 if (i_tags_findn(&im->tags, code, start, &entry)) {
3983 RETVAL = newSVpv("0 but true", 0);
3985 RETVAL = newSViv(entry);
3988 RETVAL = &PL_sv_undef;
3994 i_tags_delete(im, entry)
3998 RETVAL = i_tags_delete(&im->tags, entry);
4003 i_tags_delbyname(im, name)
4007 RETVAL = i_tags_delbyname(&im->tags, name);
4012 i_tags_delbycode(im, code)
4016 RETVAL = i_tags_delbycode(&im->tags, code);
4021 i_tags_get(im, index)
4025 if (index >= 0 && index < im->tags.count) {
4026 i_img_tag *entry = im->tags.tags + index;
4030 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
4033 PUSHs(sv_2mortal(newSViv(entry->code)));
4036 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
4039 PUSHs(sv_2mortal(newSViv(entry->idata)));
4044 i_tags_get_string(im, what_sv)
4048 char const *name = NULL;
4052 if (SvIOK(what_sv)) {
4053 code = SvIV(what_sv);
4057 name = SvPV_nolen(what_sv);
4060 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
4062 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
4069 RETVAL = im->tags.count;
4076 i_wf_bbox(face, size, text)
4081 int cords[BOUNDING_BOX_COUNT];
4084 if (rc = i_wf_bbox(face, size, text, strlen(text), cords)) {
4086 for (i = 0; i < rc; ++i)
4087 PUSHs(sv_2mortal(newSViv(cords[i])));
4091 i_wf_text(face, im, tx, ty, cl, size, text, align, aa)
4102 RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text),
4108 i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
4119 RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text),
4132 MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_
4134 #define FT2_DESTROY(font) i_ft2_destroy(font)
4138 Imager::Font::FT2 font
4140 MODULE = Imager PACKAGE = Imager::Font::FreeType2
4143 i_ft2_new(name, index)
4148 i_ft2_setdpi(font, xdpi, ydpi)
4149 Imager::Font::FT2 font
4155 Imager::Font::FT2 font
4159 if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
4161 PUSHs(sv_2mortal(newSViv(xdpi)));
4162 PUSHs(sv_2mortal(newSViv(ydpi)));
4166 i_ft2_sethinting(font, hinting)
4167 Imager::Font::FT2 font
4171 i_ft2_settransform(font, matrix)
4172 Imager::Font::FT2 font
4180 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4181 croak("i_ft2_settransform: parameter 2 must be an array ref\n");
4182 av=(AV*)SvRV(ST(1));
4186 for (i = 0; i < len; ++i) {
4187 sv1=(*(av_fetch(av,i,0)));
4188 matrix[i] = SvNV(sv1);
4192 RETVAL = i_ft2_settransform(font, matrix);
4197 i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
4198 Imager::Font::FT2 font
4204 int bbox[BOUNDING_BOX_COUNT];
4210 text = SvPV(text_sv, text_len);
4212 if (SvUTF8(text_sv))
4215 rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8);
4218 for (i = 0; i < rc; ++i)
4219 PUSHs(sv_2mortal(newSViv(bbox[i])));
4223 i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
4224 Imager::Font::FT2 font
4238 if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
4241 for (i = 0; i < 8; ++i)
4242 PUSHs(sv_2mortal(newSViv(bbox[i])));
4246 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
4247 Imager::Font::FT2 font
4263 if (SvUTF8(ST(7))) {
4267 text = SvPV(ST(7), len);
4268 RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
4269 len, align, aa, vlayout, utf8);
4274 i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, utf8)
4275 Imager::Font::FT2 font
4292 RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
4293 strlen(text), align, aa, vlayout, 1);
4298 ft2_transform_box(font, x0, x1, x2, x3)
4299 Imager::Font::FT2 font
4307 box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
4308 ft2_transform_box(font, box);
4310 PUSHs(sv_2mortal(newSViv(box[0])));
4311 PUSHs(sv_2mortal(newSViv(box[1])));
4312 PUSHs(sv_2mortal(newSViv(box[2])));
4313 PUSHs(sv_2mortal(newSViv(box[3])));
4316 i_ft2_has_chars(handle, text_sv, utf8)
4317 Imager::Font::FT2 handle
4328 if (SvUTF8(text_sv))
4331 text = SvPV(text_sv, len);
4332 work = mymalloc(len);
4333 count = i_ft2_has_chars(handle, text, len, utf8, work);
4334 if (GIMME_V == G_ARRAY) {
4336 for (i = 0; i < count; ++i) {
4337 PUSHs(sv_2mortal(newSViv(work[i])));
4342 PUSHs(sv_2mortal(newSVpv(work, count)));
4347 i_ft2_face_name(handle)
4348 Imager::Font::FT2 handle
4353 len = i_ft2_face_name(handle, name, sizeof(name));
4356 PUSHs(sv_2mortal(newSVpv(name, 0)));
4360 i_ft2_can_face_name()
4363 i_ft2_glyph_name(handle, text_sv, utf8 = 0, reliable_only = 1)
4364 Imager::Font::FT2 handle
4375 if (SvUTF8(text_sv))
4378 text = SvPV(text_sv, work_len);
4383 ch = i_utf8_advance(&text, &len);
4385 i_push_error(0, "invalid UTF8 character");
4394 if (i_ft2_glyph_name(handle, ch, name, sizeof(name),
4396 PUSHs(sv_2mortal(newSVpv(name, 0)));
4399 PUSHs(&PL_sv_undef);
4404 i_ft2_can_do_glyph_names()
4407 i_ft2_face_has_glyph_names(handle)
4408 Imager::Font::FT2 handle
4411 i_ft2_is_multiple_master(handle)
4412 Imager::Font::FT2 handle
4415 i_ft2_get_multiple_masters(handle)
4416 Imager::Font::FT2 handle
4421 if (i_ft2_get_multiple_masters(handle, &mm)) {
4422 EXTEND(SP, 2+mm.num_axis);
4423 PUSHs(sv_2mortal(newSViv(mm.num_axis)));
4424 PUSHs(sv_2mortal(newSViv(mm.num_designs)));
4425 for (i = 0; i < mm.num_axis; ++i) {
4429 sv = newSVpv(mm.axis[i].name, strlen(mm.axis[i].name));
4431 av_store(av, 0, sv);
4432 sv = newSViv(mm.axis[i].minimum);
4434 av_store(av, 1, sv);
4435 sv = newSViv(mm.axis[i].maximum);
4437 av_store(av, 2, sv);
4438 PUSHs(newRV_noinc((SV *)av));
4443 i_ft2_set_mm_coords(handle, ...)
4444 Imager::Font::FT2 handle
4450 /* T_ARRAY handling by xsubpp seems to be busted in 5.6.1, so
4451 transfer the array manually */
4452 ix_coords = items-1;
4453 coords = mymalloc(sizeof(long) * ix_coords);
4454 for (i = 0; i < ix_coords; ++i) {
4455 coords[i] = (long)SvIV(ST(1+i));
4457 RETVAL = i_ft2_set_mm_coords(handle, ix_coords, coords);
4464 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
4468 Imager::FillHandle fill
4470 MODULE = Imager PACKAGE = Imager
4473 i_new_fill_solid(cl, combine)
4478 i_new_fill_solidf(cl, combine)
4479 Imager::Color::Float cl
4483 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
4491 unsigned char *cust_hatch;
4495 cust_hatch = (unsigned char *)SvPV(ST(4), len);
4499 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
4504 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
4505 Imager::Color::Float fg
4506 Imager::Color::Float bg
4512 unsigned char *cust_hatch;
4516 cust_hatch = (unsigned char *)SvPV(ST(4), len);
4520 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
4525 i_new_fill_image(src, matrix, xoff, yoff, combine)
4542 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4543 croak("i_new_fill_image: parameter must be an arrayref");
4544 av=(AV*)SvRV(ST(1));
4548 for (i = 0; i < len; ++i) {
4549 sv1=(*(av_fetch(av,i,0)));
4550 matrix[i] = SvNV(sv1);
4556 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
4560 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
4562 # this class is only exposed for testing
4565 i_int_hlines_testing()
4567 #if i_int_hlines_testing()
4569 Imager::Internal::Hlines
4570 i_int_hlines_new(start_y, count_y, start_x, count_x)
4576 Imager::Internal::Hlines
4577 i_int_hlines_new_img(im)
4581 i_int_hlines_add(hlines, y, minx, width)
4582 Imager::Internal::Hlines hlines
4588 i_int_hlines_DESTROY(hlines)
4589 Imager::Internal::Hlines hlines
4592 i_int_hlines_dump(hlines)
4593 Imager::Internal::Hlines hlines
4598 PERL_SET_GLOBAL_CALLBACKS;