7 #define NEED_newRV_noinc
8 #define NEED_sv_2pv_nolen
14 #define i_int_hlines_testing() 1
22 #if i_int_hlines_testing()
28 /* These functions are all shared - then comes platform dependant code */
29 static int getstr(void *hv_t,char *key,char **store) {
33 mm_log((1,"getstr(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
35 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
37 svpp=hv_fetch(hv, key, strlen(key), 0);
38 *store=SvPV(*svpp, PL_na );
43 static int getint(void *hv_t,char *key,int *store) {
47 mm_log((1,"getint(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
49 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
51 svpp=hv_fetch(hv, key, strlen(key), 0);
52 *store=(int)SvIV(*svpp);
56 static int getdouble(void *hv_t,char* key,double *store) {
60 mm_log((1,"getdouble(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
62 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
63 svpp=hv_fetch(hv, key, strlen(key), 0);
64 *store=(float)SvNV(*svpp);
68 static int getvoid(void *hv_t,char* key,void **store) {
72 mm_log((1,"getvoid(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
74 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
76 svpp=hv_fetch(hv, key, strlen(key), 0);
77 *store = INT2PTR(void*, SvIV(*svpp));
82 static int getobj(void *hv_t,char *key,char *type,void **store) {
86 mm_log((1,"getobj(hv_t 0x%X, key %s,type %s, store 0x%X)\n",hv_t,key,type,store));
88 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
90 svpp=hv_fetch(hv, key, strlen(key), 0);
92 if (sv_derived_from(*svpp,type)) {
93 IV tmp = SvIV((SV*)SvRV(*svpp));
94 *store = INT2PTR(void*, tmp);
96 mm_log((1,"getobj: key exists in hash but is not of correct type"));
103 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
105 void my_SvREFCNT_dec(void *p) {
106 SvREFCNT_dec((SV*)p);
111 i_log_entry(char *string, int level) {
112 mm_log((level, string));
116 typedef struct i_reader_data_tag
118 /* presumably a CODE ref or name of a sub */
122 /* used by functions that want callbacks */
123 static int read_callback(char *userdata, char *buffer, int need, int want) {
124 i_reader_data *rd = (i_reader_data *)userdata;
128 dSP; dTARG = sv_newmortal();
129 /* thanks to Simon Cozens for help with the dTARG above */
139 count = perl_call_sv(rd->sv, G_SCALAR);
144 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
150 char *ptr = SvPV(data, len);
152 croak("Too much data returned in reader callback");
154 memcpy(buffer, ptr, len);
170 SV *sv; /* a coderef or sub name */
173 /* used by functions that want callbacks */
174 static int write_callback(char *userdata, char const *data, int size) {
175 i_writer_data *wd = (i_writer_data *)userdata;
185 XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
188 count = perl_call_sv(wd->sv, G_SCALAR);
193 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
196 success = SvTRUE(sv);
206 #define CBDATA_BUFSIZE 8192
209 /* the SVs we use to call back to Perl */
215 /* we need to remember whether the buffer contains write data or
221 /* how far we've read into the buffer (not used for writing) */
224 /* the amount of space used/data available in the buffer */
227 /* the maximum amount to fill the buffer before flushing
228 If any write is larger than this then the buffer is flushed and
229 the full write is performed. The write is _not_ split into
234 char buffer[CBDATA_BUFSIZE];
239 call_writer(cbd, buf, size)
241 Low-level function to call the perl writer callback.
245 static ssize_t call_writer(struct cbdata *cbd, void const *buf, size_t size) {
251 if (!SvOK(cbd->writecb))
258 PUSHs(sv_2mortal(newSVpv((char *)buf, size)));
261 count = perl_call_sv(cbd->writecb, G_SCALAR);
265 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
268 success = SvTRUE(sv);
275 return success ? size : -1;
278 static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
285 if (!SvOK(cbd->readcb))
292 PUSHs(sv_2mortal(newSViv(size)));
293 PUSHs(sv_2mortal(newSViv(maxread)));
296 count = perl_call_sv(cbd->readcb, G_SCALAR);
301 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
307 char *ptr = SvPV(data, len);
309 croak("Too much data returned in reader callback");
311 memcpy(buf, ptr, len);
325 static ssize_t write_flush(struct cbdata *cbd) {
329 result = call_writer(cbd, cbd->buffer, cbd->used);
334 return 1; /* success of some sort */
338 static off_t io_seeker(void *p, off_t offset, int whence) {
339 struct cbdata *cbd = p;
344 if (!SvOK(cbd->seekcb))
348 if (cbd->used && write_flush(cbd) <= 0)
352 if (whence == SEEK_CUR && cbd->reading && cbd->where != cbd->used) {
353 offset -= cbd->where - cbd->used;
356 cbd->where = cbd->used = 0;
362 PUSHs(sv_2mortal(newSViv(offset)));
363 PUSHs(sv_2mortal(newSViv(whence)));
366 count = perl_call_sv(cbd->seekcb, G_SCALAR);
371 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
382 static ssize_t io_writer(void *p, void const *data, size_t size) {
383 struct cbdata *cbd = p;
385 /* printf("io_writer(%p, %p, %u)\n", p, data, size); */
387 if (cbd->reading && cbd->where < cbd->used) {
388 /* we read past the place where the caller expected us to be
389 so adjust our position a bit */
390 if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
395 cbd->where = cbd->used = 0;
398 if (cbd->used && cbd->used + size > cbd->maxlength) {
399 int write_res = write_flush(cbd);
400 if (write_res <= 0) {
405 if (cbd->used+size <= cbd->maxlength) {
406 memcpy(cbd->buffer + cbd->used, data, size);
410 /* it doesn't fit - just pass it up */
411 return call_writer(cbd, data, size);
415 io_reader(void *p, void *data, size_t size) {
416 struct cbdata *cbd = p;
418 char *out = data; /* so we can do pointer arithmetic */
420 /* printf("io_reader(%p, %p, %d)\n", p, data, size); */
422 if (write_flush(cbd) <= 0)
428 if (size <= cbd->used - cbd->where) {
430 memcpy(data, cbd->buffer+cbd->where, size);
435 memcpy(out, cbd->buffer + cbd->where, cbd->used - cbd->where);
436 total += cbd->used - cbd->where;
437 size -= cbd->used - cbd->where;
438 out += cbd->used - cbd->where;
439 if (size < sizeof(cbd->buffer)) {
443 && (did_read = call_reader(cbd, cbd->buffer, size,
444 sizeof(cbd->buffer))) > 0) {
446 cbd->used = did_read;
448 copy_size = i_min(size, cbd->used);
449 memcpy(out, cbd->buffer, copy_size);
450 cbd->where += copy_size;
459 /* just read the rest - too big for our buffer*/
461 while ((did_read = call_reader(cbd, out, size, size)) > 0) {
473 static int io_closer(void *p) {
474 struct cbdata *cbd = p;
476 if (cbd->writing && cbd->used > 0) {
477 if (write_flush(cbd) < 0)
482 if (SvOK(cbd->closecb)) {
490 perl_call_sv(cbd->closecb, G_VOID);
501 static void io_destroyer(void *p) {
502 struct cbdata *cbd = p;
504 SvREFCNT_dec(cbd->writecb);
505 SvREFCNT_dec(cbd->readcb);
506 SvREFCNT_dec(cbd->seekcb);
507 SvREFCNT_dec(cbd->closecb);
515 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
518 for (i = 0; i < count; ++i)
519 if (strEQ(names[i].name, name))
520 return names[i].value;
524 static struct value_name transp_names[] =
527 { "threshold", tr_threshold },
528 { "errdiff", tr_errdiff },
529 { "ordered", tr_ordered, },
532 static struct value_name make_color_names[] =
534 { "none", mc_none, },
535 { "webmap", mc_web_map, },
536 { "addi", mc_addi, },
537 { "mediancut", mc_median_cut, },
538 { "mono", mc_mono, },
539 { "monochrome", mc_mono, },
542 static struct value_name translate_names[] =
545 { "giflib", pt_giflib, },
547 { "closest", pt_closest, },
548 { "perturb", pt_perturb, },
549 { "errdiff", pt_errdiff, },
552 static struct value_name errdiff_names[] =
554 { "floyd", ed_floyd, },
555 { "jarvis", ed_jarvis, },
556 { "stucki", ed_stucki, },
557 { "custom", ed_custom, },
560 static struct value_name orddith_names[] =
562 { "random", od_random, },
563 { "dot8", od_dot8, },
564 { "dot4", od_dot4, },
565 { "hline", od_hline, },
566 { "vline", od_vline, },
567 { "/line", od_slashline, },
568 { "slashline", od_slashline, },
569 { "\\line", od_backline, },
570 { "backline", od_backline, },
571 { "tiny", od_tiny, },
572 { "custom", od_custom, },
575 /* look through the hash for quantization options */
576 static void handle_quant_opts(i_quantize *quant, HV *hv)
578 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
584 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
586 sv = hv_fetch(hv, "transp", 6, 0);
587 if (sv && *sv && (str = SvPV(*sv, len))) {
589 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
591 if (quant->transp != tr_none) {
592 quant->tr_threshold = 127;
593 sv = hv_fetch(hv, "tr_threshold", 12, 0);
595 quant->tr_threshold = SvIV(*sv);
597 if (quant->transp == tr_errdiff) {
598 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
599 if (sv && *sv && (str = SvPV(*sv, len)))
600 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
602 if (quant->transp == tr_ordered) {
603 quant->tr_orddith = od_tiny;
604 sv = hv_fetch(hv, "tr_orddith", 10, 0);
605 if (sv && *sv && (str = SvPV(*sv, len)))
606 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
608 if (quant->tr_orddith == od_custom) {
609 sv = hv_fetch(hv, "tr_map", 6, 0);
610 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
611 AV *av = (AV*)SvRV(*sv);
612 len = av_len(av) + 1;
613 if (len > sizeof(quant->tr_custom))
614 len = sizeof(quant->tr_custom);
615 for (i = 0; i < len; ++i) {
616 SV **sv2 = av_fetch(av, i, 0);
618 quant->tr_custom[i] = SvIV(*sv2);
621 while (i < sizeof(quant->tr_custom))
622 quant->tr_custom[i++] = 0;
627 quant->make_colors = mc_addi;
628 sv = hv_fetch(hv, "make_colors", 11, 0);
629 if (sv && *sv && (str = SvPV(*sv, len))) {
631 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_addi);
633 sv = hv_fetch(hv, "colors", 6, 0);
634 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
635 /* needs to be an array of Imager::Color
636 note that the caller allocates the mc_color array and sets mc_size
638 AV *av = (AV *)SvRV(*sv);
639 quant->mc_count = av_len(av)+1;
640 if (quant->mc_count > quant->mc_size)
641 quant->mc_count = quant->mc_size;
642 for (i = 0; i < quant->mc_count; ++i) {
643 SV **sv1 = av_fetch(av, i, 0);
644 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
645 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
646 quant->mc_colors[i] = *col;
650 sv = hv_fetch(hv, "max_colors", 10, 0);
653 if (i <= quant->mc_size && i >= quant->mc_count)
657 quant->translate = pt_closest;
658 sv = hv_fetch(hv, "translate", 9, 0);
659 if (sv && *sv && (str = SvPV(*sv, len))) {
660 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
662 sv = hv_fetch(hv, "errdiff", 7, 0);
663 if (sv && *sv && (str = SvPV(*sv, len))) {
664 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
666 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
667 /* get the error diffusion map */
668 sv = hv_fetch(hv, "errdiff_width", 13, 0);
670 quant->ed_width = SvIV(*sv);
671 sv = hv_fetch(hv, "errdiff_height", 14, 0);
673 quant->ed_height = SvIV(*sv);
674 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
676 quant->ed_orig = SvIV(*sv);
677 if (quant->ed_width > 0 && quant->ed_height > 0) {
679 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
680 sv = hv_fetch(hv, "errdiff_map", 11, 0);
681 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
682 AV *av = (AV*)SvRV(*sv);
683 len = av_len(av) + 1;
684 if (len > quant->ed_width * quant->ed_height)
685 len = quant->ed_width * quant->ed_height;
686 for (i = 0; i < len; ++i) {
687 SV **sv2 = av_fetch(av, i, 0);
689 quant->ed_map[i] = SvIV(*sv2);
690 sum += quant->ed_map[i];
696 myfree(quant->ed_map);
698 quant->errdiff = ed_floyd;
702 sv = hv_fetch(hv, "perturb", 7, 0);
704 quant->perturb = SvIV(*sv);
707 static void cleanup_quant_opts(i_quantize *quant) {
708 myfree(quant->mc_colors);
710 myfree(quant->ed_map);
713 /* copies the color map from the hv into the colors member of the HV */
714 static void copy_colors_back(HV *hv, i_quantize *quant) {
720 sv = hv_fetch(hv, "colors", 6, 0);
721 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
726 av = (AV *)SvRV(*sv);
728 av_extend(av, quant->mc_count+1);
729 for (i = 0; i < quant->mc_count; ++i) {
730 i_color *in = quant->mc_colors+i;
731 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
732 work = sv_newmortal();
733 sv_setref_pv(work, "Imager::Color", (void *)c);
739 /* loads the segments of a fountain fill into an array */
740 static i_fountain_seg *
741 load_fount_segs(AV *asegs, int *count) {
742 /* Each element of segs must contain:
743 [ start, middle, end, c0, c1, segtype, colortrans ]
744 start, middle, end are doubles from 0 to 1
745 c0, c1 are Imager::Color::Float or Imager::Color objects
746 segtype, colortrans are ints
750 i_fountain_seg *segs;
754 *count = av_len(asegs)+1;
756 croak("i_fountain must have at least one segment");
757 segs = mymalloc(sizeof(i_fountain_seg) * *count);
758 for(i = 0; i < *count; i++) {
759 SV **sv1 = av_fetch(asegs, i, 0);
760 if (!sv1 || !*sv1 || !SvROK(*sv1)
761 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
763 croak("i_fountain: segs must be an arrayref of arrayrefs");
765 aseg = (AV *)SvRV(*sv1);
766 if (av_len(aseg) != 7-1) {
768 croak("i_fountain: a segment must have 7 members");
770 for (j = 0; j < 3; ++j) {
771 SV **sv2 = av_fetch(aseg, j, 0);
774 croak("i_fountain: XS error");
776 work[j] = SvNV(*sv2);
778 segs[i].start = work[0];
779 segs[i].middle = work[1];
780 segs[i].end = work[2];
781 for (j = 0; j < 2; ++j) {
782 SV **sv3 = av_fetch(aseg, 3+j, 0);
783 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
784 (!sv_derived_from(*sv3, "Imager::Color")
785 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
787 croak("i_fountain: segs must contain colors in elements 3 and 4");
789 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
790 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
793 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
795 for (ch = 0; ch < MAXCHANNELS; ++ch) {
796 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
800 for (j = 0; j < 2; ++j) {
801 SV **sv2 = av_fetch(aseg, j+5, 0);
804 croak("i_fountain: XS error");
806 worki[j] = SvIV(*sv2);
808 segs[i].type = worki[0];
809 segs[i].color = worki[1];
815 /* validates the indexes supplied to i_ppal
817 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
822 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
823 int color_count = i_colorcount(im);
826 if (color_count == -1)
827 croak("i_plin() called on direct color image");
829 for (i = 0; i < count; ++i) {
830 if (indexes[i] >= color_count) {
831 croak("i_plin() called with out of range color index %d (max %d)",
832 indexes[i], color_count-1);
838 /* I don't think ICLF_* names belong at the C interface
839 this makes the XS code think we have them, to let us avoid
840 putting function bodies in the XS code
842 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
843 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
846 /* the m_init_log() function was called init_log(), renamed to reduce
847 potential naming conflicts */
848 #define init_log m_init_log
850 #if i_int_hlines_testing()
852 typedef i_int_hlines *Imager__Internal__Hlines;
854 static i_int_hlines *
855 i_int_hlines_new(int start_y, int count_y, int start_x, int count_x) {
856 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
857 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
862 static i_int_hlines *
863 i_int_hlines_new_img(i_img *im) {
864 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
865 i_int_init_hlines_img(result, im);
871 i_int_hlines_DESTROY(i_int_hlines *hlines) {
872 i_int_hlines_destroy(hlines);
876 static int seg_compare(const void *vleft, const void *vright) {
877 const i_int_hline_seg *left = vleft;
878 const i_int_hline_seg *right = vright;
880 return left->minx - right->minx;
884 i_int_hlines_dump(i_int_hlines *hlines) {
885 SV *dump = newSVpvf("start_y: %d limit_y: %d start_x: %d limit_x: %d\n",
886 hlines->start_y, hlines->limit_y, hlines->start_x, hlines->limit_x);
889 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
890 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
893 /* sort the segments, if any */
895 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
897 sv_catpvf(dump, " %d (%d):", y, entry->count);
898 for (i = 0; i < entry->count; ++i) {
899 sv_catpvf(dump, " [%d, %d)", entry->segs[i].minx,
900 entry->segs[i].x_limit);
902 sv_catpv(dump, "\n");
912 #define i_exif_enabled() 1
914 #define i_exif_enabled() 0
917 /* trying to use more C style names, map them here */
918 #define i_io_DESTROY(ig) io_glue_destroy(ig)
920 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
923 ICL_new_internal(r,g,b,a)
935 ICL_set_internal(cl,r,g,b,a)
942 ICL_set_internal(cl, r, g, b, a);
956 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
957 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
958 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
959 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
965 RETVAL = mymalloc(sizeof(i_color));
967 i_hsv_to_rgb(RETVAL);
975 RETVAL = mymalloc(sizeof(i_color));
977 i_rgb_to_hsv(RETVAL);
983 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
986 ICLF_new_internal(r, g, b, a)
994 Imager::Color::Float cl
998 Imager::Color::Float cl
1002 EXTEND(SP, MAXCHANNELS);
1003 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1004 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1005 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1009 ICLF_set_internal(cl,r,g,b,a)
1010 Imager::Color::Float cl
1023 Imager::Color::Float
1025 Imager::Color::Float c
1027 RETVAL = mymalloc(sizeof(i_fcolor));
1029 i_hsv_to_rgbf(RETVAL);
1033 Imager::Color::Float
1035 Imager::Color::Float c
1037 RETVAL = mymalloc(sizeof(i_fcolor));
1039 i_rgb_to_hsvf(RETVAL);
1043 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1057 MODULE = Imager PACKAGE = Imager
1076 SvPV(ST(0), length);
1077 SvREFCNT_inc(ST(0));
1078 RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0));
1083 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1092 cbd = mymalloc(sizeof(struct cbdata));
1093 SvREFCNT_inc(writecb);
1094 cbd->writecb = writecb;
1095 SvREFCNT_inc(readcb);
1096 cbd->readcb = readcb;
1097 SvREFCNT_inc(seekcb);
1098 cbd->seekcb = seekcb;
1099 SvREFCNT_inc(closecb);
1100 cbd->closecb = closecb;
1101 cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
1102 if (maxwrite > CBDATA_BUFSIZE)
1103 maxwrite = CBDATA_BUFSIZE;
1104 cbd->maxlength = maxwrite;
1105 RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
1114 unsigned char* data;
1118 tlength = io_slurp(ig, &data);
1120 PUSHs(sv_2mortal(newSVpv((char *)data,tlength)));
1125 i_set_image_file_limits(width, height, bytes)
1131 i_get_image_file_limits()
1133 int width, height, bytes;
1135 if (i_get_image_file_limits(&width, &height, &bytes)) {
1137 PUSHs(sv_2mortal(newSViv(width)));
1138 PUSHs(sv_2mortal(newSViv(height)));
1139 PUSHs(sv_2mortal(newSViv(bytes)));
1142 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1145 i_io_write(ig, data_sv)
1153 if (SvUTF8(data_sv)) {
1154 data_sv = sv_2mortal(newSVsv(data_sv));
1155 /* yes, we want this to croak() if the SV can't be downgraded */
1156 sv_utf8_downgrade(data_sv, FALSE);
1159 data = SvPV(data_sv, size);
1160 RETVAL = i_io_write(ig, data, size);
1165 i_io_read(ig, buffer_sv, size)
1174 croak("size negative in call to i_io_read()");
1175 /* prevent an undefined value warning if they supplied an
1177 Orginally conditional on !SvOK(), but this will prevent the
1178 downgrade from croaking */
1179 sv_setpvn(buffer_sv, "", 0);
1181 if (SvUTF8(buffer_sv))
1182 sv_utf8_downgrade(buffer_sv, FALSE);
1184 buffer = SvGROW(buffer_sv, size+1);
1185 result = i_io_read(ig, buffer, size);
1187 SvCUR_set(buffer_sv, result);
1188 *SvEND(buffer_sv) = '\0';
1189 SvPOK_only(buffer_sv);
1191 PUSHs(sv_2mortal(newSViv(result)));
1197 i_io_read2(ig, size)
1206 croak("size negative in call to i_io_read2()");
1207 buffer_sv = newSV(size);
1208 buffer = SvGROW(buffer_sv, size+1);
1209 result = i_io_read(ig, buffer, size);
1211 SvCUR_set(buffer_sv, result);
1212 *SvEND(buffer_sv) = '\0';
1213 SvPOK_only(buffer_sv);
1215 PUSHs(sv_2mortal(buffer_sv));
1219 SvREFCNT_dec(buffer_sv);
1223 i_io_seek(ig, position, whence)
1236 MODULE = Imager PACKAGE = Imager
1247 while( (item=i_format_list[i++]) != NULL ) {
1249 PUSHs(sv_2mortal(newSVpv(item,0)));
1266 i_img_empty_ch(im,x,y,ch)
1273 i_sametype(im, x, y)
1279 i_sametype_chans(im, x, y, channels)
1286 i_init_log(name_sv,level)
1290 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1292 i_init_log(name, level);
1295 i_log_entry(string,level)
1314 i_img_info(im,info);
1316 PUSHs(sv_2mortal(newSViv(info[0])));
1317 PUSHs(sv_2mortal(newSViv(info[1])));
1318 PUSHs(sv_2mortal(newSViv(info[2])));
1319 PUSHs(sv_2mortal(newSViv(info[3])));
1325 i_img_setmask(im,ch_mask)
1334 i_img_getchannels(im)
1343 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1347 i_img_is_monochrome(im)
1353 result = i_img_is_monochrome(im, &zero_is_white);
1355 if (GIMME_V == G_ARRAY) {
1358 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1367 i_line(im,x1,y1,x2,y2,val,endp)
1377 i_line_aa(im,x1,y1,x2,y2,val,endp)
1387 i_box(im,x1,y1,x2,y2,val)
1396 i_box_filled(im,x1,y1,x2,y2,val)
1405 i_box_cfill(im,x1,y1,x2,y2,fill)
1411 Imager::FillHandle fill
1414 i_arc(im,x,y,rad,d1,d2,val)
1424 i_arc_aa(im,x,y,rad,d1,d2,val)
1434 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1441 Imager::FillHandle fill
1444 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1451 Imager::FillHandle fill
1455 i_circle_aa(im,x,y,rad,val)
1465 i_bezier_multi(im,xc,yc,val)
1478 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1479 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1480 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1481 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1482 av1=(AV*)SvRV(ST(1));
1483 av2=(AV*)SvRV(ST(2));
1484 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1486 x=mymalloc( len*sizeof(double) );
1487 y=mymalloc( len*sizeof(double) );
1488 for(i=0;i<len;i++) {
1489 sv1=(*(av_fetch(av1,i,0)));
1490 sv2=(*(av_fetch(av2,i,0)));
1491 x[i]=(double)SvNV(sv1);
1492 y[i]=(double)SvNV(sv2);
1494 i_bezier_multi(im,len,x,y,val);
1500 i_poly_aa(im,xc,yc,val)
1513 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1514 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1515 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1516 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1517 av1=(AV*)SvRV(ST(1));
1518 av2=(AV*)SvRV(ST(2));
1519 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1521 x=mymalloc( len*sizeof(double) );
1522 y=mymalloc( len*sizeof(double) );
1523 for(i=0;i<len;i++) {
1524 sv1=(*(av_fetch(av1,i,0)));
1525 sv2=(*(av_fetch(av2,i,0)));
1526 x[i]=(double)SvNV(sv1);
1527 y[i]=(double)SvNV(sv2);
1529 i_poly_aa(im,len,x,y,val);
1534 i_poly_aa_cfill(im,xc,yc,fill)
1536 Imager::FillHandle fill
1546 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1547 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1548 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1549 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1550 av1=(AV*)SvRV(ST(1));
1551 av2=(AV*)SvRV(ST(2));
1552 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1554 x=mymalloc( len*sizeof(double) );
1555 y=mymalloc( len*sizeof(double) );
1556 for(i=0;i<len;i++) {
1557 sv1=(*(av_fetch(av1,i,0)));
1558 sv2=(*(av_fetch(av2,i,0)));
1559 x[i]=(double)SvNV(sv1);
1560 y[i]=(double)SvNV(sv2);
1562 i_poly_aa_cfill(im,len,x,y,fill);
1569 i_flood_fill(im,seedx,seedy,dcol)
1576 i_flood_cfill(im,seedx,seedy,fill)
1580 Imager::FillHandle fill
1583 i_flood_fill_border(im,seedx,seedy,dcol, border)
1588 Imager::Color border
1591 i_flood_cfill_border(im,seedx,seedy,fill, border)
1595 Imager::FillHandle fill
1596 Imager::Color border
1600 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1612 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1629 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1640 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1653 i_compose_mask(out, src, mask, out_left, out_top, src_left, src_top, mask_left, mask_top, width, height, combine = ic_normal, opacity = 0.0)
1669 i_flipxy(im, direction)
1674 i_rotate90(im, degrees)
1679 i_rotate_exact(im, amount, ...)
1683 i_color *backp = NULL;
1684 i_fcolor *fbackp = NULL;
1688 /* extract the bg colors if any */
1689 /* yes, this is kind of strange */
1690 for (i = 2; i < items; ++i) {
1692 if (sv_derived_from(sv1, "Imager::Color")) {
1693 IV tmp = SvIV((SV*)SvRV(sv1));
1694 backp = INT2PTR(i_color *, tmp);
1696 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1697 IV tmp = SvIV((SV*)SvRV(sv1));
1698 fbackp = INT2PTR(i_fcolor *, tmp);
1701 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1706 i_matrix_transform(im, xsize, ysize, matrix, ...)
1716 i_color *backp = NULL;
1717 i_fcolor *fbackp = NULL;
1719 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1720 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1721 av=(AV*)SvRV(ST(3));
1725 for (i = 0; i < len; ++i) {
1726 sv1=(*(av_fetch(av,i,0)));
1727 matrix[i] = SvNV(sv1);
1731 /* extract the bg colors if any */
1732 /* yes, this is kind of strange */
1733 for (i = 4; i < items; ++i) {
1735 if (sv_derived_from(sv1, "Imager::Color")) {
1736 IV tmp = SvIV((SV*)SvRV(sv1));
1737 backp = INT2PTR(i_color *, tmp);
1739 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1740 IV tmp = SvIV((SV*)SvRV(sv1));
1741 fbackp = INT2PTR(i_fcolor *, tmp);
1744 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
1749 i_gaussian(im,stdev)
1754 i_unsharp_mask(im,stdev,scale)
1769 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1770 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1771 av=(AV*)SvRV(ST(1));
1773 coeff=mymalloc( len*sizeof(float) );
1774 for(i=0;i<len;i++) {
1775 sv1=(*(av_fetch(av,i,0)));
1776 coeff[i]=(float)SvNV(sv1);
1778 i_conv(im,coeff,len);
1782 i_convert(src, avmain)
1794 outchan = av_len(avmain)+1;
1795 /* find the biggest */
1797 for (j=0; j < outchan; ++j) {
1798 temp = av_fetch(avmain, j, 0);
1799 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1800 avsub = (AV*)SvRV(*temp);
1801 len = av_len(avsub)+1;
1806 coeff = mymalloc(sizeof(float) * outchan * inchan);
1807 for (j = 0; j < outchan; ++j) {
1808 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1809 len = av_len(avsub)+1;
1810 for (i = 0; i < len; ++i) {
1811 temp = av_fetch(avsub, i, 0);
1813 coeff[i+j*inchan] = SvNV(*temp);
1815 coeff[i+j*inchan] = 0;
1818 coeff[i++ + j*inchan] = 0;
1820 RETVAL = i_convert(src, coeff, outchan, inchan);
1830 unsigned int mask = 0;
1836 unsigned char (*maps)[256];
1838 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1839 croak("i_map: parameter 2 must be an arrayref\n");
1840 avmain = (AV*)SvRV(ST(1));
1841 len = av_len(avmain)+1;
1842 if (im->channels < len) len = im->channels;
1844 maps = mymalloc( len * sizeof(unsigned char [256]) );
1846 for (j=0; j<len ; j++) {
1847 temp = av_fetch(avmain, j, 0);
1848 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1849 avsub = (AV*)SvRV(*temp);
1850 if(av_len(avsub) != 255) continue;
1852 for (i=0; i<256 ; i++) {
1854 temp = av_fetch(avsub, i, 0);
1855 val = temp ? SvIV(*temp) : 0;
1857 if (val>255) val = 255;
1862 i_map(im, maps, mask);
1875 i_init_fonts(t1log=0)
1890 i_t1_destroy(font_id)
1895 i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
1914 str = SvPV(str_sv, len);
1915 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
1922 i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
1931 int cords[BOUNDING_BOX_COUNT];
1939 str = SvPV(str_sv, len);
1940 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
1943 for (i = 0; i < rc; ++i)
1944 PUSHs(sv_2mortal(newSViv(cords[i])));
1950 i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
1969 str = SvPV(str_sv, len);
1970 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
1976 i_t1_has_chars(handle, text_sv, utf8 = 0)
1988 if (SvUTF8(text_sv))
1991 text = SvPV(text_sv, len);
1992 work = mymalloc(len);
1993 count = i_t1_has_chars(handle, text, len, utf8, work);
1994 if (GIMME_V == G_ARRAY) {
1996 for (i = 0; i < count; ++i) {
1997 PUSHs(sv_2mortal(newSViv(work[i])));
2002 PUSHs(sv_2mortal(newSVpv(work, count)));
2007 i_t1_face_name(handle)
2013 len = i_t1_face_name(handle, name, sizeof(name));
2016 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2020 i_t1_glyph_name(handle, text_sv, utf8 = 0)
2031 if (SvUTF8(text_sv))
2034 text = SvPV(text_sv, work_len);
2039 ch = i_utf8_advance(&text, &len);
2041 i_push_error(0, "invalid UTF8 character");
2050 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
2051 PUSHs(sv_2mortal(newSVpv(name, 0)));
2054 PUSHs(&PL_sv_undef);
2068 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2070 #define TT_DESTROY(handle) i_tt_destroy(handle)
2074 Imager::Font::TT handle
2077 MODULE = Imager PACKAGE = Imager
2081 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
2082 Imager::Font::TT handle
2100 str = SvPV(str_sv, len);
2101 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2102 len, smooth, utf8, align);
2108 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
2109 Imager::Font::TT handle
2127 str = SvPV(str_sv, len);
2128 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2129 smooth, utf8, align);
2135 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
2136 Imager::Font::TT handle
2141 int cords[BOUNDING_BOX_COUNT],rc;
2150 str = SvPV(str_sv, len);
2151 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2153 for (i = 0; i < rc; ++i) {
2154 PUSHs(sv_2mortal(newSViv(cords[i])));
2159 i_tt_has_chars(handle, text_sv, utf8)
2160 Imager::Font::TT handle
2171 if (SvUTF8(text_sv))
2174 text = SvPV(text_sv, len);
2175 work = mymalloc(len);
2176 count = i_tt_has_chars(handle, text, len, utf8, work);
2177 if (GIMME_V == G_ARRAY) {
2179 for (i = 0; i < count; ++i) {
2180 PUSHs(sv_2mortal(newSViv(work[i])));
2185 PUSHs(sv_2mortal(newSVpv(work, count)));
2190 i_tt_dump_names(handle)
2191 Imager::Font::TT handle
2194 i_tt_face_name(handle)
2195 Imager::Font::TT handle
2200 len = i_tt_face_name(handle, name, sizeof(name));
2203 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2207 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2208 Imager::Font::TT handle
2219 if (SvUTF8(text_sv))
2222 text = SvPV(text_sv, work_len);
2227 ch = i_utf8_advance(&text, &len);
2229 i_push_error(0, "invalid UTF8 character");
2238 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2239 PUSHs(sv_2mortal(newSVpv(name, 0)));
2242 PUSHs(&PL_sv_undef);
2251 i_writejpeg_wiol(im, ig, qfactor)
2267 rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
2268 if (iptc_itext == NULL) {
2271 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2276 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2278 PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
2289 i_test_format_probe(ig, length)
2298 i_readtiff_wiol(ig, allow_incomplete, page=0)
2300 int allow_incomplete
2304 i_readtiff_multi_wiol(ig, length)
2312 imgs = i_readtiff_multi_wiol(ig, length, &count);
2315 for (i = 0; i < count; ++i) {
2316 SV *sv = sv_newmortal();
2317 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2325 i_writetiff_wiol(im, ig)
2330 i_writetiff_multi_wiol(ig, ...)
2338 croak("Usage: i_writetiff_multi_wiol(ig, images...)");
2339 img_count = items - 1;
2341 if (img_count < 1) {
2344 i_push_error(0, "You need to specify images to save");
2347 imgs = mymalloc(sizeof(i_img *) * img_count);
2348 for (i = 0; i < img_count; ++i) {
2351 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2352 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2356 i_push_error(0, "Only images can be saved");
2363 RETVAL = i_writetiff_multi_wiol(ig, imgs, img_count);
2371 i_writetiff_wiol_faxable(im, ig, fine)
2377 i_writetiff_multi_wiol_faxable(ig, fine, ...)
2386 croak("Usage: i_writetiff_multi_wiol_faxable(ig, fine, images...)");
2387 img_count = items - 2;
2389 if (img_count < 1) {
2392 i_push_error(0, "You need to specify images to save");
2395 imgs = mymalloc(sizeof(i_img *) * img_count);
2396 for (i = 0; i < img_count; ++i) {
2399 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2400 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2404 i_push_error(0, "Only images can be saved");
2411 RETVAL = i_writetiff_multi_wiol_faxable(ig, imgs, img_count, fine);
2422 i_tiff_has_compression(name)
2425 #endif /* HAVE_LIBTIFF */
2431 i_readpng_wiol(ig, length)
2437 i_writepng_wiol(im, ig)
2450 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
2453 i_writegif(im,fd,colors,pixdev,fixed)
2460 Imager__Color fixed;
2467 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
2468 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2469 av=(AV*)SvRV(ST(4));
2470 fixedlen=av_len(av)+1;
2471 fixed=mymalloc( fixedlen*sizeof(i_color) );
2472 for(i=0;i<fixedlen;i++) {
2473 sv1=(*(av_fetch(av,i,0)));
2474 if (sv_derived_from(sv1, "Imager::Color")) {
2475 Itmp = SvIV((SV*)SvRV(sv1));
2476 tmp = INT2PTR(i_color*, Itmp);
2477 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
2480 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
2482 ST(0) = sv_newmortal();
2483 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2484 else sv_setiv(ST(0), (IV)RETVAL);
2490 i_writegifmc(im,fd,colors)
2497 i_writegif_gen(fd, ...)
2502 i_img **imgs = NULL;
2508 croak("Usage: i_writegif_gen(fd,hashref, images...)");
2509 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2510 croak("i_writegif_gen: Second argument must be a hash ref");
2511 hv = (HV *)SvRV(ST(1));
2512 memset(&quant, 0, sizeof(quant));
2513 quant.mc_size = 256;
2514 quant.transp = tr_threshold;
2515 quant.tr_threshold = 127;
2516 handle_quant_opts(&quant, hv);
2517 img_count = items - 2;
2519 if (img_count < 1) {
2522 i_push_error(0, "You need to specify images to save");
2525 imgs = mymalloc(sizeof(i_img *) * img_count);
2526 for (i = 0; i < img_count; ++i) {
2529 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2530 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2534 i_push_error(0, "Only images can be saved");
2540 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
2544 copy_colors_back(hv, &quant);
2547 ST(0) = sv_newmortal();
2548 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2549 else sv_setiv(ST(0), (IV)RETVAL);
2550 cleanup_quant_opts(&quant);
2554 i_writegif_callback(cb, maxbuffer,...)
2558 i_img **imgs = NULL;
2565 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2566 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2567 croak("i_writegif_callback: Second argument must be a hash ref");
2568 hv = (HV *)SvRV(ST(2));
2569 memset(&quant, 0, sizeof(quant));
2570 quant.mc_size = 256;
2571 quant.transp = tr_threshold;
2572 quant.tr_threshold = 127;
2573 handle_quant_opts(&quant, hv);
2574 img_count = items - 3;
2576 if (img_count < 1) {
2580 imgs = mymalloc(sizeof(i_img *) * img_count);
2581 for (i = 0; i < img_count; ++i) {
2584 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2585 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2594 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count);
2598 copy_colors_back(hv, &quant);
2601 ST(0) = sv_newmortal();
2602 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2603 else sv_setiv(ST(0), (IV)RETVAL);
2604 cleanup_quant_opts(&quant);
2607 i_writegif_wiol(ig, opts,...)
2611 i_img **imgs = NULL;
2617 croak("Usage: i_writegif_wiol(IO,hashref, images...)");
2618 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2619 croak("i_writegif_callback: Second argument must be a hash ref");
2620 hv = (HV *)SvRV(ST(1));
2621 memset(&quant, 0, sizeof(quant));
2622 quant.mc_size = 256;
2623 quant.transp = tr_threshold;
2624 quant.tr_threshold = 127;
2625 handle_quant_opts(&quant, hv);
2626 img_count = items - 2;
2628 if (img_count < 1) {
2632 imgs = mymalloc(sizeof(i_img *) * img_count);
2633 for (i = 0; i < img_count; ++i) {
2636 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2637 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2645 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
2649 copy_colors_back(hv, &quant);
2652 ST(0) = sv_newmortal();
2653 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2654 else sv_setiv(ST(0), (IV)RETVAL);
2655 cleanup_quant_opts(&quant);
2668 colour_table = NULL;
2671 if(GIMME_V == G_ARRAY) {
2672 rimg = i_readgif(fd,&colour_table,&colours);
2674 /* don't waste time with colours if they aren't wanted */
2675 rimg = i_readgif(fd,NULL,NULL);
2678 if (colour_table == NULL) {
2681 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2684 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2685 /* I don't know if I have the reference counts right or not :( */
2686 /* Neither do I :-) */
2687 /* No Idea here either */
2690 av_extend(ct, colours);
2691 for(q=0; q<colours; q++) {
2693 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2694 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2696 myfree(colour_table);
2700 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2702 PUSHs(newRV_noinc((SV*)ct));
2716 colour_table = NULL;
2719 if(GIMME_V == G_ARRAY) {
2720 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2722 /* don't waste time with colours if they aren't wanted */
2723 rimg = i_readgif_wiol(ig,NULL,NULL);
2726 if (colour_table == NULL) {
2729 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2732 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2733 /* I don't know if I have the reference counts right or not :( */
2734 /* Neither do I :-) */
2735 /* No Idea here either */
2738 av_extend(ct, colours);
2739 for(q=0; q<colours; q++) {
2741 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2742 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2744 myfree(colour_table);
2748 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2750 PUSHs(newRV_noinc((SV*)ct));
2754 i_readgif_single_wiol(ig, page=0)
2759 i_readgif_scalar(...)
2771 data = (char *)SvPV(ST(0), length);
2775 if(GIMME_V == G_ARRAY) {
2776 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2778 /* don't waste time with colours if they aren't wanted */
2779 rimg=i_readgif_scalar(data,length,NULL,NULL);
2782 if (colour_table == NULL) {
2785 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2788 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2789 /* I don't know if I have the reference counts right or not :( */
2790 /* Neither do I :-) */
2792 av_extend(ct, colours);
2793 for(q=0; q<colours; q++) {
2795 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2796 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2798 myfree(colour_table);
2802 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2804 PUSHs(newRV_noinc((SV*)ct));
2808 i_readgif_callback(...)
2823 if(GIMME_V == G_ARRAY) {
2824 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2826 /* don't waste time with colours if they aren't wanted */
2827 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2830 if (colour_table == NULL) {
2833 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2836 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2837 /* I don't know if I have the reference counts right or not :( */
2838 /* Neither do I :-) */
2839 /* Neither do I - maybe I'll move this somewhere */
2841 av_extend(ct, colours);
2842 for(q=0; q<colours; q++) {
2844 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2845 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2847 myfree(colour_table);
2851 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2853 PUSHs(newRV_noinc((SV*)ct));
2864 imgs = i_readgif_multi(fd, &count);
2867 for (i = 0; i < count; ++i) {
2868 SV *sv = sv_newmortal();
2869 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2876 i_readgif_multi_scalar(data)
2884 data = (char *)SvPV(ST(0), length);
2885 imgs = i_readgif_multi_scalar(data, length, &count);
2888 for (i = 0; i < count; ++i) {
2889 SV *sv = sv_newmortal();
2890 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2897 i_readgif_multi_callback(cb)
2905 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2908 for (i = 0; i < count; ++i) {
2909 SV *sv = sv_newmortal();
2910 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2917 i_readgif_multi_wiol(ig)
2924 imgs = i_readgif_multi_wiol(ig, &count);
2927 for (i = 0; i < count; ++i) {
2928 SV *sv = sv_newmortal();
2929 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2941 i_readpnm_wiol(ig, allow_incomplete)
2943 int allow_incomplete
2947 i_writeppm_wiol(im, ig)
2953 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2962 i_writeraw_wiol(im,ig)
2967 i_writebmp_wiol(im,ig)
2972 i_readbmp_wiol(ig, allow_incomplete=0)
2974 int allow_incomplete
2978 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2987 idlen = SvCUR(ST(4));
2988 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2994 i_readtga_wiol(ig, length)
3002 i_scaleaxis(im,Value,Axis)
3008 i_scale_nn(im,scx,scy)
3014 i_scale_mixing(im, width, height)
3024 i_count_colors(im,maxc)
3029 i_get_anonymous_color_histo(im, maxc = 0x40000000)
3034 unsigned int * col_usage = NULL;
3037 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
3038 EXTEND(SP, col_cnt);
3039 for (i = 0; i < col_cnt; i++) {
3040 PUSHs(sv_2mortal(newSViv( col_usage[i])));
3047 i_transform(im,opx,opy,parm)
3060 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
3061 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
3062 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
3063 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
3064 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
3065 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
3066 av=(AV*)SvRV(ST(1));
3068 opx=mymalloc( opxl*sizeof(int) );
3069 for(i=0;i<opxl;i++) {
3070 sv1=(*(av_fetch(av,i,0)));
3071 opx[i]=(int)SvIV(sv1);
3073 av=(AV*)SvRV(ST(2));
3075 opy=mymalloc( opyl*sizeof(int) );
3076 for(i=0;i<opyl;i++) {
3077 sv1=(*(av_fetch(av,i,0)));
3078 opy[i]=(int)SvIV(sv1);
3080 av=(AV*)SvRV(ST(3));
3081 parmlen=av_len(av)+1;
3082 parm=mymalloc( parmlen*sizeof(double) );
3083 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
3084 sv1=(*(av_fetch(av,i,0)));
3085 parm[i]=(double)SvNV(sv1);
3087 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
3091 ST(0) = sv_newmortal();
3092 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3093 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3096 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
3121 in_imgs_count = av_len(av_in_imgs)+1;
3122 for (i = 0; i < in_imgs_count; ++i) {
3123 sv1 = *av_fetch(av_in_imgs, i, 0);
3124 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3125 croak("sv_in_img must contain only images");
3128 if (in_imgs_count > 0) {
3129 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
3130 for (i = 0; i < in_imgs_count; ++i) {
3131 sv1 = *av_fetch(av_in_imgs,i,0);
3132 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3133 croak("Parameter 5 must contain only images");
3135 tmp = SvIV((SV*)SvRV(sv1));
3136 in_imgs[i] = INT2PTR(i_img*, tmp);
3140 /* no input images */
3143 /* default the output size from the first input if possible */
3145 width = SvIV(sv_width);
3146 else if (in_imgs_count)
3147 width = in_imgs[0]->xsize;
3149 croak("No output image width supplied");
3151 if (SvOK(sv_height))
3152 height = SvIV(sv_height);
3153 else if (in_imgs_count)
3154 height = in_imgs[0]->ysize;
3156 croak("No output image height supplied");
3158 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
3159 if (ops_len % sizeof(struct rm_op))
3160 croak("Imager: Parameter 3 must be a bitmap of regops\n");
3161 ops_count = ops_len / sizeof(struct rm_op);
3163 n_regs_count = av_len(av_n_regs)+1;
3164 n_regs = mymalloc(n_regs_count * sizeof(double));
3165 for (i = 0; i < n_regs_count; ++i) {
3166 sv1 = *av_fetch(av_n_regs,i,0);
3168 n_regs[i] = SvNV(sv1);
3170 c_regs_count = av_len(av_c_regs)+1;
3171 c_regs = mymalloc(c_regs_count * sizeof(i_color));
3172 /* I don't bother initializing the colou?r registers */
3174 RETVAL=i_transform2(width, height, channels, ops, ops_count,
3175 n_regs, n_regs_count,
3176 c_regs, c_regs_count, in_imgs, in_imgs_count);
3181 ST(0) = sv_newmortal();
3182 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3183 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3187 i_contrast(im,intensity)
3196 i_noise(im,amount,type)
3202 i_bumpmap(im,bump,channel,light_x,light_y,strength)
3212 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
3231 i_postlevels(im,levels)
3241 i_watermark(im,wmark,tx,ty,pixdiff)
3243 Imager::ImgRaw wmark
3250 i_autolevels(im,lsat,usat,skew)
3257 i_radnoise(im,xo,yo,rscale,ascale)
3265 i_turbnoise(im, xo, yo, scale)
3288 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
3289 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3290 croak("i_gradgen: Second argument must be an array ref");
3291 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3292 croak("i_gradgen: Third argument must be an array ref");
3293 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3294 croak("i_gradgen: Fourth argument must be an array ref");
3295 axx = (AV *)SvRV(ST(1));
3296 ayy = (AV *)SvRV(ST(2));
3297 ac = (AV *)SvRV(ST(3));
3298 dmeasure = (int)SvIV(ST(4));
3300 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3301 num = num <= av_len(ac) ? num : av_len(ac);
3303 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
3304 xo = mymalloc( sizeof(int) * num );
3305 yo = mymalloc( sizeof(int) * num );
3306 ival = mymalloc( sizeof(i_color) * num );
3307 for(i = 0; i<num; i++) {
3308 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3309 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3310 sv = *av_fetch(ac, i, 0);
3311 if ( !sv_derived_from(sv, "Imager::Color") ) {
3312 free(axx); free(ayy); free(ac);
3313 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
3315 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
3317 i_gradgen(im, num, xo, yo, ival, dmeasure);
3323 i_diff_image(im, im2, mindist=0)
3329 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3339 double ssample_param
3343 i_fountain_seg *segs;
3345 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
3346 croak("i_fountain: argument 11 must be an array ref");
3348 asegs = (AV *)SvRV(ST(10));
3349 segs = load_fount_segs(asegs, &count);
3350 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
3351 super_sample, ssample_param, count, segs);
3357 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3366 double ssample_param
3370 i_fountain_seg *segs;
3372 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
3373 croak("i_fountain: argument 11 must be an array ref");
3375 asegs = (AV *)SvRV(ST(9));
3376 segs = load_fount_segs(asegs, &count);
3377 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
3378 super_sample, ssample_param, count, segs);
3391 errors = i_errors();
3393 while (errors[i].msg) {
3395 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
3396 if (!av_store(av, 0, sv)) {
3399 sv = newSViv(errors[i].code);
3400 if (!av_store(av, 1, sv)) {
3403 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
3411 i_push_error(code, msg)
3416 i_nearest_color(im, ...)
3431 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
3432 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3433 croak("i_nearest_color: Second argument must be an array ref");
3434 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3435 croak("i_nearest_color: Third argument must be an array ref");
3436 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3437 croak("i_nearest_color: Fourth argument must be an array ref");
3438 axx = (AV *)SvRV(ST(1));
3439 ayy = (AV *)SvRV(ST(2));
3440 ac = (AV *)SvRV(ST(3));
3441 dmeasure = (int)SvIV(ST(4));
3443 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3444 num = num <= av_len(ac) ? num : av_len(ac);
3446 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
3447 xo = mymalloc( sizeof(int) * num );
3448 yo = mymalloc( sizeof(int) * num );
3449 ival = mymalloc( sizeof(i_color) * num );
3450 for(i = 0; i<num; i++) {
3451 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3452 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3453 sv = *av_fetch(ac, i, 0);
3454 if ( !sv_derived_from(sv, "Imager::Color") ) {
3455 free(axx); free(ayy); free(ac);
3456 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
3458 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
3460 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
3474 rc=DSO_open(filename,&evstr);
3478 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
3479 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
3482 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
3488 DSO_close(dso_handle)
3492 DSO_funclist(dso_handle_v)
3496 DSO_handle *dso_handle;
3497 func_ptr *functions;
3499 dso_handle=(DSO_handle*)dso_handle_v;
3500 functions = DSO_funclist(dso_handle);
3502 while( functions[i].name != NULL) {
3504 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
3506 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
3510 DSO_call(handle,func_index,hv)
3516 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3517 hv=(HV*)SvRV(ST(2));
3518 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3519 DSO_call( (DSO_handle *)handle,func_index,hv);
3522 i_get_pixel(im, x, y)
3529 color = (i_color *)mymalloc(sizeof(i_color));
3530 if (i_gpix(im, x, y, color) == 0) {
3531 RETVAL = NEWSV(0, 0);
3532 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
3536 RETVAL = &PL_sv_undef;
3543 i_ppix(im, x, y, cl)
3550 i_img_pal_new(x, y, channels, maxpal)
3557 i_img_to_pal(src, quant)
3563 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3564 croak("i_img_to_pal: second argument must be a hash ref");
3565 hv = (HV *)SvRV(ST(1));
3566 memset(&quant, 0, sizeof(quant));
3567 quant.mc_size = 256;
3568 handle_quant_opts(&quant, hv);
3569 RETVAL = i_img_to_pal(src, &quant);
3571 copy_colors_back(hv, &quant);
3573 cleanup_quant_opts(&quant);
3592 work = mymalloc((r-l) * sizeof(i_palidx));
3593 count = i_gpal(im, l, r, y, work);
3594 if (GIMME_V == G_ARRAY) {
3596 for (i = 0; i < count; ++i) {
3597 PUSHs(sv_2mortal(newSViv(work[i])));
3602 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3607 if (GIMME_V != G_ARRAY) {
3609 PUSHs(&PL_sv_undef);
3614 i_ppal(im, l, y, ...)
3623 work = mymalloc(sizeof(i_palidx) * (items-3));
3624 for (i=0; i < items-3; ++i) {
3625 work[i] = SvIV(ST(i+3));
3627 validate_i_ppal(im, work, items - 3);
3628 RETVAL = i_ppal(im, l, l+items-3, y, work);
3638 i_ppal_p(im, l, y, data)
3644 i_palidx const *work;
3647 work = (i_palidx const *)SvPV(data, len);
3648 len /= sizeof(i_palidx);
3650 validate_i_ppal(im, work, len);
3651 RETVAL = i_ppal(im, l, l+len, y, work);
3660 i_addcolors(im, ...)
3668 croak("i_addcolors: no colors to add");
3669 colors = mymalloc((items-1) * sizeof(i_color));
3670 for (i=0; i < items-1; ++i) {
3671 if (sv_isobject(ST(i+1))
3672 && sv_derived_from(ST(i+1), "Imager::Color")) {
3673 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3674 colors[i] = *INT2PTR(i_color *, tmp);
3678 croak("i_addcolor: pixels must be Imager::Color objects");
3681 index = i_addcolors(im, colors, items-1);
3684 RETVAL = newSVpv("0 but true", 0);
3686 else if (index == -1) {
3687 RETVAL = &PL_sv_undef;
3690 RETVAL = newSViv(index);
3696 i_setcolors(im, index, ...)
3704 croak("i_setcolors: no colors to add");
3705 colors = mymalloc((items-2) * sizeof(i_color));
3706 for (i=0; i < items-2; ++i) {
3707 if (sv_isobject(ST(i+2))
3708 && sv_derived_from(ST(i+2), "Imager::Color")) {
3709 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3710 colors[i] = *INT2PTR(i_color *, tmp);
3714 croak("i_setcolors: pixels must be Imager::Color objects");
3717 RETVAL = i_setcolors(im, index, colors, items-2);
3723 i_getcolors(im, index, ...)
3732 croak("i_getcolors: too many arguments");
3734 count = SvIV(ST(2));
3736 croak("i_getcolors: count must be positive");
3737 colors = mymalloc(sizeof(i_color) * count);
3738 if (i_getcolors(im, index, colors, count)) {
3739 for (i = 0; i < count; ++i) {
3741 SV *sv = sv_newmortal();
3742 pv = mymalloc(sizeof(i_color));
3744 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3760 i_findcolor(im, color)
3766 if (i_findcolor(im, color, &index)) {
3767 RETVAL = newSViv(index);
3770 RETVAL = &PL_sv_undef;
3788 i_gsamp(im, l, r, y, ...)
3800 croak("No channel numbers supplied to g_samp()");
3802 chan_count = items - 4;
3803 chans = mymalloc(sizeof(int) * chan_count);
3804 for (i = 0; i < chan_count; ++i)
3805 chans[i] = SvIV(ST(i+4));
3806 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
3807 count = i_gsamp(im, l, r, y, data, chans, chan_count);
3809 if (GIMME_V == G_ARRAY) {
3811 for (i = 0; i < count; ++i)
3812 PUSHs(sv_2mortal(newSViv(data[i])));
3816 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3821 if (GIMME_V != G_ARRAY) {
3823 PUSHs(&PL_sv_undef);
3828 i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3844 croak("No channel numbers supplied to g_samp()");
3846 chan_count = items - 7;
3847 chans = mymalloc(sizeof(int) * chan_count);
3848 for (i = 0; i < chan_count; ++i)
3849 chans[i] = SvIV(ST(i+7));
3850 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3851 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3853 for (i = 0; i < count; ++i) {
3854 av_store(target, i+offset, newSVuv(data[i]));
3866 i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3884 if (SvOK(channels_sv)) {
3886 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3887 croak("channels is not an array ref");
3889 channels_av = (AV *)SvRV(channels_sv);
3890 chan_count = av_len(channels_av) + 1;
3891 if (chan_count < 1) {
3892 croak("i_psamp_bits: no channels provided");
3894 channels = mymalloc(sizeof(int) * chan_count);
3895 for (i = 0; i < chan_count; ++i)
3896 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3899 chan_count = im->channels;
3903 data_count = av_len(data_av) + 1;
3904 if (data_offset < 0) {
3905 croak("data_offset must by non-negative");
3907 if (data_offset > data_count) {
3908 croak("data_offset greater than number of samples supplied");
3910 if (pixel_count == -1 ||
3911 data_offset + pixel_count * chan_count > data_count) {
3912 pixel_count = (data_count - data_offset) / chan_count;
3915 data_used = pixel_count * chan_count;
3916 data = mymalloc(sizeof(unsigned) * data_count);
3917 for (i = 0; i < data_used; ++i)
3918 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3920 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3931 i_img_masked_new(targ, mask, x, y, w, h)
3941 if (!sv_isobject(ST(1))
3942 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3943 croak("i_img_masked_new: parameter 2 must undef or an image");
3945 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3949 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3954 i_plin(im, l, y, ...)
3965 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3966 /* supplied as a byte string */
3967 work = (i_color *)SvPV(ST(3), len);
3968 count = len / sizeof(i_color);
3969 if (count * sizeof(i_color) != len) {
3970 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3972 RETVAL = i_plin(im, l, l+count, y, work);
3975 work = mymalloc(sizeof(i_color) * (items-3));
3976 for (i=0; i < items-3; ++i) {
3977 if (sv_isobject(ST(i+3))
3978 && sv_derived_from(ST(i+3), "Imager::Color")) {
3979 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3980 work[i] = *INT2PTR(i_color *, tmp);
3984 croak("i_plin: pixels must be Imager::Color objects");
3987 RETVAL = i_plin(im, l, l+items-3, y, work);
3998 i_ppixf(im, x, y, cl)
4002 Imager::Color::Float cl
4005 i_gsampf(im, l, r, y, ...)
4017 croak("No channel numbers supplied to g_sampf()");
4019 chan_count = items - 4;
4020 chans = mymalloc(sizeof(int) * chan_count);
4021 for (i = 0; i < chan_count; ++i)
4022 chans[i] = SvIV(ST(i+4));
4023 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
4024 count = i_gsampf(im, l, r, y, data, chans, chan_count);
4026 if (GIMME_V == G_ARRAY) {
4028 for (i = 0; i < count; ++i)
4029 PUSHs(sv_2mortal(newSVnv(data[i])));
4033 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
4038 if (GIMME_V != G_ARRAY) {
4040 PUSHs(&PL_sv_undef);
4045 i_plinf(im, l, y, ...)
4056 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
4057 /* supplied as a byte string */
4058 work = (i_fcolor *)SvPV(ST(3), len);
4059 count = len / sizeof(i_fcolor);
4060 if (count * sizeof(i_fcolor) != len) {
4061 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
4063 RETVAL = i_plinf(im, l, l+count, y, work);
4066 work = mymalloc(sizeof(i_fcolor) * (items-3));
4067 for (i=0; i < items-3; ++i) {
4068 if (sv_isobject(ST(i+3))
4069 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
4070 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
4071 work[i] = *INT2PTR(i_fcolor *, tmp);
4075 croak("i_plinf: pixels must be Imager::Color::Float objects");
4079 RETVAL = i_plinf(im, l, l+items-3, y, work);
4097 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
4098 if (i_gpixf(im, x, y, color) == 0) {
4099 RETVAL = NEWSV(0,0);
4100 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
4104 RETVAL = &PL_sv_undef;
4120 vals = mymalloc((r-l) * sizeof(i_color));
4121 memset(vals, 0, (r-l) * sizeof(i_color));
4122 count = i_glin(im, l, r, y, vals);
4123 if (GIMME_V == G_ARRAY) {
4125 for (i = 0; i < count; ++i) {
4127 i_color *col = mymalloc(sizeof(i_color));
4129 sv = sv_newmortal();
4130 sv_setref_pv(sv, "Imager::Color", (void *)col);
4136 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
4142 i_glinf(im, l, r, y)
4152 for (i = 0; i < MAXCHANNELS; ++i)
4153 zero.channel[i] = 0;
4155 vals = mymalloc((r-l) * sizeof(i_fcolor));
4156 for (i = 0; i < r-l; ++i)
4158 count = i_glinf(im, l, r, y, vals);
4159 if (GIMME_V == G_ARRAY) {
4161 for (i = 0; i < count; ++i) {
4163 i_fcolor *col = mymalloc(sizeof(i_fcolor));
4165 sv = sv_newmortal();
4166 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
4172 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
4178 i_img_16_new(x, y, ch)
4188 i_img_double_new(x, y, ch)
4194 i_tags_addn(im, name, code, idata)
4203 name = SvPV(ST(1), len);
4206 RETVAL = i_tags_addn(&im->tags, name, code, idata);
4211 i_tags_add(im, name, code, data, idata)
4221 name = SvPV(ST(1), len);
4225 data = SvPV(ST(3), len);
4230 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
4235 i_tags_find(im, name, start)
4242 if (i_tags_find(&im->tags, name, start, &entry)) {
4244 RETVAL = newSVpv("0 but true", 0);
4246 RETVAL = newSViv(entry);
4248 RETVAL = &PL_sv_undef;
4254 i_tags_findn(im, code, start)
4261 if (i_tags_findn(&im->tags, code, start, &entry)) {
4263 RETVAL = newSVpv("0 but true", 0);
4265 RETVAL = newSViv(entry);
4268 RETVAL = &PL_sv_undef;
4274 i_tags_delete(im, entry)
4278 RETVAL = i_tags_delete(&im->tags, entry);
4283 i_tags_delbyname(im, name)
4287 RETVAL = i_tags_delbyname(&im->tags, name);
4292 i_tags_delbycode(im, code)
4296 RETVAL = i_tags_delbycode(&im->tags, code);
4301 i_tags_get(im, index)
4305 if (index >= 0 && index < im->tags.count) {
4306 i_img_tag *entry = im->tags.tags + index;
4310 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
4313 PUSHs(sv_2mortal(newSViv(entry->code)));
4316 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
4319 PUSHs(sv_2mortal(newSViv(entry->idata)));
4324 i_tags_get_string(im, what_sv)
4328 char const *name = NULL;
4332 if (SvIOK(what_sv)) {
4333 code = SvIV(what_sv);
4337 name = SvPV_nolen(what_sv);
4340 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
4342 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
4349 RETVAL = im->tags.count;
4356 i_wf_bbox(face, size, text_sv, utf8=0)
4362 int cords[BOUNDING_BOX_COUNT];
4367 text = SvPV(text_sv, text_len);
4369 if (SvUTF8(text_sv))
4372 if (rc = i_wf_bbox(face, size, text, text_len, cords, utf8)) {
4374 for (i = 0; i < rc; ++i)
4375 PUSHs(sv_2mortal(newSViv(cords[i])));
4379 i_wf_text(face, im, tx, ty, cl, size, text_sv, align, aa, utf8 = 0)
4394 text = SvPV(text_sv, text_len);
4396 if (SvUTF8(text_sv))
4399 RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, text_len,
4405 i_wf_cp(face, im, tx, ty, channel, size, text_sv, align, aa, utf8 = 0)
4420 text = SvPV(text_sv, text_len);
4422 if (SvUTF8(text_sv))
4425 RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, text_len,
4442 MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_
4444 #define FT2_DESTROY(font) i_ft2_destroy(font)
4448 Imager::Font::FT2 font
4450 MODULE = Imager PACKAGE = Imager::Font::FreeType2
4453 i_ft2_new(name, index)
4458 i_ft2_setdpi(font, xdpi, ydpi)
4459 Imager::Font::FT2 font
4465 Imager::Font::FT2 font
4469 if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
4471 PUSHs(sv_2mortal(newSViv(xdpi)));
4472 PUSHs(sv_2mortal(newSViv(ydpi)));
4476 i_ft2_sethinting(font, hinting)
4477 Imager::Font::FT2 font
4481 i_ft2_settransform(font, matrix)
4482 Imager::Font::FT2 font
4490 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4491 croak("i_ft2_settransform: parameter 2 must be an array ref\n");
4492 av=(AV*)SvRV(ST(1));
4496 for (i = 0; i < len; ++i) {
4497 sv1=(*(av_fetch(av,i,0)));
4498 matrix[i] = SvNV(sv1);
4502 RETVAL = i_ft2_settransform(font, matrix);
4507 i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
4508 Imager::Font::FT2 font
4514 int bbox[BOUNDING_BOX_COUNT];
4520 text = SvPV(text_sv, text_len);
4522 if (SvUTF8(text_sv))
4525 rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8);
4528 for (i = 0; i < rc; ++i)
4529 PUSHs(sv_2mortal(newSViv(bbox[i])));
4533 i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
4534 Imager::Font::FT2 font
4548 if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
4551 for (i = 0; i < 8; ++i)
4552 PUSHs(sv_2mortal(newSViv(bbox[i])));
4556 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
4557 Imager::Font::FT2 font
4573 if (SvUTF8(ST(7))) {
4577 text = SvPV(ST(7), len);
4578 RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
4579 len, align, aa, vlayout, utf8);
4584 i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text_sv, align, aa, vlayout, utf8)
4585 Imager::Font::FT2 font
4605 text = SvPV(text_sv, len);
4606 RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
4607 len, align, aa, vlayout, 1);
4612 ft2_transform_box(font, x0, x1, x2, x3)
4613 Imager::Font::FT2 font
4621 box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
4622 ft2_transform_box(font, box);
4624 PUSHs(sv_2mortal(newSViv(box[0])));
4625 PUSHs(sv_2mortal(newSViv(box[1])));
4626 PUSHs(sv_2mortal(newSViv(box[2])));
4627 PUSHs(sv_2mortal(newSViv(box[3])));
4630 i_ft2_has_chars(handle, text_sv, utf8)
4631 Imager::Font::FT2 handle
4642 if (SvUTF8(text_sv))
4645 text = SvPV(text_sv, len);
4646 work = mymalloc(len);
4647 count = i_ft2_has_chars(handle, text, len, utf8, work);
4648 if (GIMME_V == G_ARRAY) {
4650 for (i = 0; i < count; ++i) {
4651 PUSHs(sv_2mortal(newSViv(work[i])));
4656 PUSHs(sv_2mortal(newSVpv(work, count)));
4661 i_ft2_face_name(handle)
4662 Imager::Font::FT2 handle
4667 len = i_ft2_face_name(handle, name, sizeof(name));
4670 PUSHs(sv_2mortal(newSVpv(name, 0)));
4674 i_ft2_can_face_name()
4677 i_ft2_glyph_name(handle, text_sv, utf8 = 0, reliable_only = 1)
4678 Imager::Font::FT2 handle
4689 if (SvUTF8(text_sv))
4692 text = SvPV(text_sv, work_len);
4697 ch = i_utf8_advance(&text, &len);
4699 i_push_error(0, "invalid UTF8 character");
4708 if (i_ft2_glyph_name(handle, ch, name, sizeof(name),
4710 PUSHs(sv_2mortal(newSVpv(name, 0)));
4713 PUSHs(&PL_sv_undef);
4718 i_ft2_can_do_glyph_names()
4721 i_ft2_face_has_glyph_names(handle)
4722 Imager::Font::FT2 handle
4725 i_ft2_is_multiple_master(handle)
4726 Imager::Font::FT2 handle
4729 i_ft2_get_multiple_masters(handle)
4730 Imager::Font::FT2 handle
4735 if (i_ft2_get_multiple_masters(handle, &mm)) {
4736 EXTEND(SP, 2+mm.num_axis);
4737 PUSHs(sv_2mortal(newSViv(mm.num_axis)));
4738 PUSHs(sv_2mortal(newSViv(mm.num_designs)));
4739 for (i = 0; i < mm.num_axis; ++i) {
4743 sv = newSVpv(mm.axis[i].name, strlen(mm.axis[i].name));
4745 av_store(av, 0, sv);
4746 sv = newSViv(mm.axis[i].minimum);
4748 av_store(av, 1, sv);
4749 sv = newSViv(mm.axis[i].maximum);
4751 av_store(av, 2, sv);
4752 PUSHs(newRV_noinc((SV *)av));
4757 i_ft2_set_mm_coords(handle, ...)
4758 Imager::Font::FT2 handle
4764 /* T_ARRAY handling by xsubpp seems to be busted in 5.6.1, so
4765 transfer the array manually */
4766 ix_coords = items-1;
4767 coords = mymalloc(sizeof(long) * ix_coords);
4768 for (i = 0; i < ix_coords; ++i) {
4769 coords[i] = (long)SvIV(ST(1+i));
4771 RETVAL = i_ft2_set_mm_coords(handle, ix_coords, coords);
4778 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
4782 Imager::FillHandle fill
4784 MODULE = Imager PACKAGE = Imager
4787 i_new_fill_solid(cl, combine)
4792 i_new_fill_solidf(cl, combine)
4793 Imager::Color::Float cl
4797 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
4805 unsigned char *cust_hatch;
4809 cust_hatch = (unsigned char *)SvPV(ST(4), len);
4813 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
4818 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
4819 Imager::Color::Float fg
4820 Imager::Color::Float bg
4826 unsigned char *cust_hatch;
4830 cust_hatch = (unsigned char *)SvPV(ST(4), len);
4834 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
4839 i_new_fill_image(src, matrix, xoff, yoff, combine)
4856 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4857 croak("i_new_fill_image: parameter must be an arrayref");
4858 av=(AV*)SvRV(ST(1));
4862 for (i = 0; i < len; ++i) {
4863 sv1=(*(av_fetch(av,i,0)));
4864 matrix[i] = SvNV(sv1);
4870 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
4874 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
4876 # this class is only exposed for testing
4879 i_int_hlines_testing()
4881 #if i_int_hlines_testing()
4883 Imager::Internal::Hlines
4884 i_int_hlines_new(start_y, count_y, start_x, count_x)
4890 Imager::Internal::Hlines
4891 i_int_hlines_new_img(im)
4895 i_int_hlines_add(hlines, y, minx, width)
4896 Imager::Internal::Hlines hlines
4902 i_int_hlines_DESTROY(hlines)
4903 Imager::Internal::Hlines hlines
4906 i_int_hlines_dump(hlines)
4907 Imager::Internal::Hlines hlines
4912 PERL_SET_GLOBAL_CALLBACKS;