1 #define PERL_NO_GET_CONTEXT
8 #define NEED_newRV_noinc
9 #define NEED_sv_2pv_nolen
15 #define i_int_hlines_testing() 1
22 #include "imextpltypes.h"
24 #if i_int_hlines_testing()
30 /* These functions are all shared - then comes platform dependant code */
31 static int getstr(void *hv_t,char *key,char **store) {
36 mm_log((1,"getstr(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
38 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
40 svpp=hv_fetch(hv, key, strlen(key), 0);
41 *store=SvPV(*svpp, PL_na );
46 static int getint(void *hv_t,char *key,int *store) {
51 mm_log((1,"getint(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
53 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
55 svpp=hv_fetch(hv, key, strlen(key), 0);
56 *store=(int)SvIV(*svpp);
60 static int getdouble(void *hv_t,char* key,double *store) {
65 mm_log((1,"getdouble(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
67 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
68 svpp=hv_fetch(hv, key, strlen(key), 0);
69 *store=(float)SvNV(*svpp);
73 static int getvoid(void *hv_t,char* key,void **store) {
78 mm_log((1,"getvoid(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
80 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
82 svpp=hv_fetch(hv, key, strlen(key), 0);
83 *store = INT2PTR(void*, SvIV(*svpp));
88 static int getobj(void *hv_t,char *key,char *type,void **store) {
93 mm_log((1,"getobj(hv_t 0x%X, key %s,type %s, store 0x%X)\n",hv_t,key,type,store));
95 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
97 svpp=hv_fetch(hv, key, strlen(key), 0);
99 if (sv_derived_from(*svpp,type)) {
100 IV tmp = SvIV((SV*)SvRV(*svpp));
101 *store = INT2PTR(void*, tmp);
103 mm_log((1,"getobj: key exists in hash but is not of correct type"));
110 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
112 void my_SvREFCNT_dec(void *p) {
114 SvREFCNT_dec((SV*)p);
119 i_log_entry(char *string, int level) {
120 mm_log((level, string));
124 typedef struct i_reader_data_tag
126 /* presumably a CODE ref or name of a sub */
130 /* used by functions that want callbacks */
131 static int read_callback(char *userdata, char *buffer, int need, int want) {
133 i_reader_data *rd = (i_reader_data *)userdata;
137 dSP; dTARG = sv_newmortal();
138 /* thanks to Simon Cozens for help with the dTARG above */
148 count = perl_call_sv(rd->sv, G_SCALAR);
153 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
159 char *ptr = SvPV(data, len);
161 croak("Too much data returned in reader callback");
163 memcpy(buffer, ptr, len);
179 SV *sv; /* a coderef or sub name */
182 /* used by functions that want callbacks */
183 static int write_callback(char *userdata, char const *data, int size) {
185 i_writer_data *wd = (i_writer_data *)userdata;
195 XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
198 count = perl_call_sv(wd->sv, G_SCALAR);
203 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
206 success = SvTRUE(sv);
216 #define CBDATA_BUFSIZE 8192
219 /* the SVs we use to call back to Perl */
225 /* we need to remember whether the buffer contains write data or
231 /* how far we've read into the buffer (not used for writing) */
234 /* the amount of space used/data available in the buffer */
237 /* the maximum amount to fill the buffer before flushing
238 If any write is larger than this then the buffer is flushed and
239 the full write is performed. The write is _not_ split into
244 char buffer[CBDATA_BUFSIZE];
249 call_writer(cbd, buf, size)
251 Low-level function to call the perl writer callback.
255 static ssize_t call_writer(struct cbdata *cbd, void const *buf, size_t size) {
262 if (!SvOK(cbd->writecb))
269 PUSHs(sv_2mortal(newSVpv((char *)buf, size)));
272 count = perl_call_sv(cbd->writecb, G_SCALAR);
276 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
279 success = SvTRUE(sv);
286 return success ? size : -1;
289 static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
297 if (!SvOK(cbd->readcb))
304 PUSHs(sv_2mortal(newSViv(size)));
305 PUSHs(sv_2mortal(newSViv(maxread)));
308 count = perl_call_sv(cbd->readcb, G_SCALAR);
313 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
319 char *ptr = SvPV(data, len);
321 croak("Too much data returned in reader callback");
323 memcpy(buf, ptr, len);
337 static ssize_t write_flush(struct cbdata *cbd) {
342 result = call_writer(cbd, cbd->buffer, cbd->used);
347 return 1; /* success of some sort */
351 static off_t io_seeker(void *p, off_t offset, int whence) {
353 struct cbdata *cbd = p;
358 if (!SvOK(cbd->seekcb))
362 if (cbd->used && write_flush(cbd) <= 0)
366 if (whence == SEEK_CUR && cbd->reading && cbd->where != cbd->used) {
367 offset -= cbd->where - cbd->used;
370 cbd->where = cbd->used = 0;
376 PUSHs(sv_2mortal(newSViv(offset)));
377 PUSHs(sv_2mortal(newSViv(whence)));
380 count = perl_call_sv(cbd->seekcb, G_SCALAR);
385 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
396 static ssize_t io_writer(void *p, void const *data, size_t size) {
398 struct cbdata *cbd = p;
400 /* printf("io_writer(%p, %p, %u)\n", p, data, size); */
402 if (cbd->reading && cbd->where < cbd->used) {
403 /* we read past the place where the caller expected us to be
404 so adjust our position a bit */
405 if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
410 cbd->where = cbd->used = 0;
413 if (cbd->used && cbd->used + size > cbd->maxlength) {
414 int write_res = write_flush(cbd);
415 if (write_res <= 0) {
420 if (cbd->used+size <= cbd->maxlength) {
421 memcpy(cbd->buffer + cbd->used, data, size);
425 /* it doesn't fit - just pass it up */
426 return call_writer(cbd, data, size);
430 io_reader(void *p, void *data, size_t size) {
432 struct cbdata *cbd = p;
434 char *out = data; /* so we can do pointer arithmetic */
436 /* printf("io_reader(%p, %p, %d)\n", p, data, size); */
438 if (write_flush(cbd) <= 0)
444 if (size <= cbd->used - cbd->where) {
446 memcpy(data, cbd->buffer+cbd->where, size);
451 memcpy(out, cbd->buffer + cbd->where, cbd->used - cbd->where);
452 total += cbd->used - cbd->where;
453 size -= cbd->used - cbd->where;
454 out += cbd->used - cbd->where;
455 if (size < sizeof(cbd->buffer)) {
459 && (did_read = call_reader(cbd, cbd->buffer, size,
460 sizeof(cbd->buffer))) > 0) {
462 cbd->used = did_read;
464 copy_size = i_min(size, cbd->used);
465 memcpy(out, cbd->buffer, copy_size);
466 cbd->where += copy_size;
475 /* just read the rest - too big for our buffer*/
477 while ((did_read = call_reader(cbd, out, size, size)) > 0) {
489 static int io_closer(void *p) {
491 struct cbdata *cbd = p;
493 if (cbd->writing && cbd->used > 0) {
494 if (write_flush(cbd) < 0)
499 if (SvOK(cbd->closecb)) {
507 perl_call_sv(cbd->closecb, G_VOID);
518 static void io_destroyer(void *p) {
520 struct cbdata *cbd = p;
522 SvREFCNT_dec(cbd->writecb);
523 SvREFCNT_dec(cbd->readcb);
524 SvREFCNT_dec(cbd->seekcb);
525 SvREFCNT_dec(cbd->closecb);
533 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
536 for (i = 0; i < count; ++i)
537 if (strEQ(names[i].name, name))
538 return names[i].value;
542 static struct value_name transp_names[] =
545 { "threshold", tr_threshold },
546 { "errdiff", tr_errdiff },
547 { "ordered", tr_ordered, },
550 static struct value_name make_color_names[] =
552 { "none", mc_none, },
553 { "webmap", mc_web_map, },
554 { "addi", mc_addi, },
555 { "mediancut", mc_median_cut, },
556 { "mono", mc_mono, },
557 { "monochrome", mc_mono, },
560 static struct value_name translate_names[] =
562 { "giflib", pt_giflib, },
563 { "closest", pt_closest, },
564 { "perturb", pt_perturb, },
565 { "errdiff", pt_errdiff, },
568 static struct value_name errdiff_names[] =
570 { "floyd", ed_floyd, },
571 { "jarvis", ed_jarvis, },
572 { "stucki", ed_stucki, },
573 { "custom", ed_custom, },
576 static struct value_name orddith_names[] =
578 { "random", od_random, },
579 { "dot8", od_dot8, },
580 { "dot4", od_dot4, },
581 { "hline", od_hline, },
582 { "vline", od_vline, },
583 { "/line", od_slashline, },
584 { "slashline", od_slashline, },
585 { "\\line", od_backline, },
586 { "backline", od_backline, },
587 { "tiny", od_tiny, },
588 { "custom", od_custom, },
591 /* look through the hash for quantization options */
593 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
595 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
601 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
603 sv = hv_fetch(hv, "transp", 6, 0);
604 if (sv && *sv && (str = SvPV(*sv, len))) {
606 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
608 if (quant->transp != tr_none) {
609 quant->tr_threshold = 127;
610 sv = hv_fetch(hv, "tr_threshold", 12, 0);
612 quant->tr_threshold = SvIV(*sv);
614 if (quant->transp == tr_errdiff) {
615 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
616 if (sv && *sv && (str = SvPV(*sv, len)))
617 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
619 if (quant->transp == tr_ordered) {
620 quant->tr_orddith = od_tiny;
621 sv = hv_fetch(hv, "tr_orddith", 10, 0);
622 if (sv && *sv && (str = SvPV(*sv, len)))
623 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
625 if (quant->tr_orddith == od_custom) {
626 sv = hv_fetch(hv, "tr_map", 6, 0);
627 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
628 AV *av = (AV*)SvRV(*sv);
629 len = av_len(av) + 1;
630 if (len > sizeof(quant->tr_custom))
631 len = sizeof(quant->tr_custom);
632 for (i = 0; i < len; ++i) {
633 SV **sv2 = av_fetch(av, i, 0);
635 quant->tr_custom[i] = SvIV(*sv2);
638 while (i < sizeof(quant->tr_custom))
639 quant->tr_custom[i++] = 0;
644 quant->make_colors = mc_median_cut;
645 sv = hv_fetch(hv, "make_colors", 11, 0);
646 if (sv && *sv && (str = SvPV(*sv, len))) {
648 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_addi);
650 sv = hv_fetch(hv, "colors", 6, 0);
651 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
652 /* needs to be an array of Imager::Color
653 note that the caller allocates the mc_color array and sets mc_size
655 AV *av = (AV *)SvRV(*sv);
656 quant->mc_count = av_len(av)+1;
657 if (quant->mc_count > quant->mc_size)
658 quant->mc_count = quant->mc_size;
659 for (i = 0; i < quant->mc_count; ++i) {
660 SV **sv1 = av_fetch(av, i, 0);
661 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
662 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
663 quant->mc_colors[i] = *col;
667 sv = hv_fetch(hv, "max_colors", 10, 0);
670 if (i <= quant->mc_size && i >= quant->mc_count)
674 quant->translate = pt_closest;
675 sv = hv_fetch(hv, "translate", 9, 0);
676 if (sv && *sv && (str = SvPV(*sv, len))) {
677 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
679 sv = hv_fetch(hv, "errdiff", 7, 0);
680 if (sv && *sv && (str = SvPV(*sv, len))) {
681 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
683 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
684 /* get the error diffusion map */
685 sv = hv_fetch(hv, "errdiff_width", 13, 0);
687 quant->ed_width = SvIV(*sv);
688 sv = hv_fetch(hv, "errdiff_height", 14, 0);
690 quant->ed_height = SvIV(*sv);
691 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
693 quant->ed_orig = SvIV(*sv);
694 if (quant->ed_width > 0 && quant->ed_height > 0) {
696 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
697 sv = hv_fetch(hv, "errdiff_map", 11, 0);
698 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
699 AV *av = (AV*)SvRV(*sv);
700 len = av_len(av) + 1;
701 if (len > quant->ed_width * quant->ed_height)
702 len = quant->ed_width * quant->ed_height;
703 for (i = 0; i < len; ++i) {
704 SV **sv2 = av_fetch(av, i, 0);
706 quant->ed_map[i] = SvIV(*sv2);
707 sum += quant->ed_map[i];
713 myfree(quant->ed_map);
715 quant->errdiff = ed_floyd;
719 sv = hv_fetch(hv, "perturb", 7, 0);
721 quant->perturb = SvIV(*sv);
725 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
726 myfree(quant->mc_colors);
728 myfree(quant->ed_map);
731 /* copies the color map from the hv into the colors member of the HV */
733 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
739 sv = hv_fetch(hv, "colors", 6, 0);
740 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
745 av = (AV *)SvRV(*sv);
747 av_extend(av, quant->mc_count+1);
748 for (i = 0; i < quant->mc_count; ++i) {
749 i_color *in = quant->mc_colors+i;
750 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
751 work = sv_newmortal();
752 sv_setref_pv(work, "Imager::Color", (void *)c);
758 /* loads the segments of a fountain fill into an array */
759 static i_fountain_seg *
760 load_fount_segs(pTHX_ AV *asegs, int *count) {
761 /* Each element of segs must contain:
762 [ start, middle, end, c0, c1, segtype, colortrans ]
763 start, middle, end are doubles from 0 to 1
764 c0, c1 are Imager::Color::Float or Imager::Color objects
765 segtype, colortrans are ints
769 i_fountain_seg *segs;
773 *count = av_len(asegs)+1;
775 croak("i_fountain must have at least one segment");
776 segs = mymalloc(sizeof(i_fountain_seg) * *count);
777 for(i = 0; i < *count; i++) {
778 SV **sv1 = av_fetch(asegs, i, 0);
779 if (!sv1 || !*sv1 || !SvROK(*sv1)
780 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
782 croak("i_fountain: segs must be an arrayref of arrayrefs");
784 aseg = (AV *)SvRV(*sv1);
785 if (av_len(aseg) != 7-1) {
787 croak("i_fountain: a segment must have 7 members");
789 for (j = 0; j < 3; ++j) {
790 SV **sv2 = av_fetch(aseg, j, 0);
793 croak("i_fountain: XS error");
795 work[j] = SvNV(*sv2);
797 segs[i].start = work[0];
798 segs[i].middle = work[1];
799 segs[i].end = work[2];
800 for (j = 0; j < 2; ++j) {
801 SV **sv3 = av_fetch(aseg, 3+j, 0);
802 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
803 (!sv_derived_from(*sv3, "Imager::Color")
804 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
806 croak("i_fountain: segs must contain colors in elements 3 and 4");
808 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
809 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
812 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
814 for (ch = 0; ch < MAXCHANNELS; ++ch) {
815 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
819 for (j = 0; j < 2; ++j) {
820 SV **sv2 = av_fetch(aseg, j+5, 0);
823 croak("i_fountain: XS error");
825 worki[j] = SvIV(*sv2);
827 segs[i].type = worki[0];
828 segs[i].color = worki[1];
834 /* validates the indexes supplied to i_ppal
836 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
841 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
842 int color_count = i_colorcount(im);
845 if (color_count == -1)
846 croak("i_plin() called on direct color image");
848 for (i = 0; i < count; ++i) {
849 if (indexes[i] >= color_count) {
850 croak("i_plin() called with out of range color index %d (max %d)",
851 indexes[i], color_count-1);
857 /* I don't think ICLF_* names belong at the C interface
858 this makes the XS code think we have them, to let us avoid
859 putting function bodies in the XS code
861 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
862 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
865 /* the m_init_log() function was called init_log(), renamed to reduce
866 potential naming conflicts */
867 #define init_log m_init_log
869 #if i_int_hlines_testing()
871 typedef i_int_hlines *Imager__Internal__Hlines;
873 static i_int_hlines *
874 i_int_hlines_new(int start_y, int count_y, int start_x, int count_x) {
875 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
876 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
881 static i_int_hlines *
882 i_int_hlines_new_img(i_img *im) {
883 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
884 i_int_init_hlines_img(result, im);
890 i_int_hlines_DESTROY(i_int_hlines *hlines) {
891 i_int_hlines_destroy(hlines);
895 #define i_int_hlines_CLONE_SKIP(cls) 1
897 static int seg_compare(const void *vleft, const void *vright) {
898 const i_int_hline_seg *left = vleft;
899 const i_int_hline_seg *right = vright;
901 return left->minx - right->minx;
905 i_int_hlines_dump(i_int_hlines *hlines) {
907 SV *dump = newSVpvf("start_y: %d limit_y: %d start_x: %d limit_x: %d\n",
908 hlines->start_y, hlines->limit_y, hlines->start_x, hlines->limit_x);
911 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
912 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
915 /* sort the segments, if any */
917 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
919 sv_catpvf(dump, " %d (%d):", y, entry->count);
920 for (i = 0; i < entry->count; ++i) {
921 sv_catpvf(dump, " [%d, %d)", entry->segs[i].minx,
922 entry->segs[i].x_limit);
924 sv_catpv(dump, "\n");
933 static im_pl_ext_funcs im_perl_funcs =
935 IMAGER_PL_API_VERSION,
937 ip_handle_quant_opts,
938 ip_cleanup_quant_opts,
942 #define PERL_PL_SET_GLOBAL_CALLBACKS \
943 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
946 #define i_exif_enabled() 1
948 #define i_exif_enabled() 0
951 /* trying to use more C style names, map them here */
952 #define i_io_DESTROY(ig) io_glue_destroy(ig)
954 #define i_img_get_width(im) ((im)->xsize)
955 #define i_img_get_height(im) ((im)->ysize)
957 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
960 ICL_new_internal(r,g,b,a)
972 ICL_set_internal(cl,r,g,b,a)
979 ICL_set_internal(cl, r, g, b, a);
993 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
994 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
995 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
996 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
1002 RETVAL = mymalloc(sizeof(i_color));
1004 i_hsv_to_rgb(RETVAL);
1012 RETVAL = mymalloc(sizeof(i_color));
1014 i_rgb_to_hsv(RETVAL);
1020 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
1022 Imager::Color::Float
1023 ICLF_new_internal(r, g, b, a)
1031 Imager::Color::Float cl
1035 Imager::Color::Float cl
1039 EXTEND(SP, MAXCHANNELS);
1040 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1041 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1042 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1046 ICLF_set_internal(cl,r,g,b,a)
1047 Imager::Color::Float cl
1060 Imager::Color::Float
1062 Imager::Color::Float c
1064 RETVAL = mymalloc(sizeof(i_fcolor));
1066 i_hsv_to_rgbf(RETVAL);
1070 Imager::Color::Float
1072 Imager::Color::Float c
1074 RETVAL = mymalloc(sizeof(i_fcolor));
1076 i_rgb_to_hsvf(RETVAL);
1080 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1094 MODULE = Imager PACKAGE = Imager
1113 SvPV(ST(0), length);
1114 SvREFCNT_inc(ST(0));
1115 RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0));
1120 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1129 cbd = mymalloc(sizeof(struct cbdata));
1130 SvREFCNT_inc(writecb);
1131 cbd->writecb = writecb;
1132 SvREFCNT_inc(readcb);
1133 cbd->readcb = readcb;
1134 SvREFCNT_inc(seekcb);
1135 cbd->seekcb = seekcb;
1136 SvREFCNT_inc(closecb);
1137 cbd->closecb = closecb;
1138 cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
1139 if (maxwrite > CBDATA_BUFSIZE)
1140 maxwrite = CBDATA_BUFSIZE;
1141 cbd->maxlength = maxwrite;
1142 RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
1151 unsigned char* data;
1155 tlength = io_slurp(ig, &data);
1157 PUSHs(sv_2mortal(newSVpv((char *)data,tlength)));
1162 i_set_image_file_limits(width, height, bytes)
1168 i_get_image_file_limits()
1170 int width, height, bytes;
1172 if (i_get_image_file_limits(&width, &height, &bytes)) {
1174 PUSHs(sv_2mortal(newSViv(width)));
1175 PUSHs(sv_2mortal(newSViv(height)));
1176 PUSHs(sv_2mortal(newSViv(bytes)));
1179 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1182 i_io_write(ig, data_sv)
1190 if (SvUTF8(data_sv)) {
1191 data_sv = sv_2mortal(newSVsv(data_sv));
1192 /* yes, we want this to croak() if the SV can't be downgraded */
1193 sv_utf8_downgrade(data_sv, FALSE);
1196 data = SvPV(data_sv, size);
1197 RETVAL = i_io_write(ig, data, size);
1202 i_io_read(ig, buffer_sv, size)
1211 croak("size negative in call to i_io_read()");
1212 /* prevent an undefined value warning if they supplied an
1214 Orginally conditional on !SvOK(), but this will prevent the
1215 downgrade from croaking */
1216 sv_setpvn(buffer_sv, "", 0);
1218 if (SvUTF8(buffer_sv))
1219 sv_utf8_downgrade(buffer_sv, FALSE);
1221 buffer = SvGROW(buffer_sv, size+1);
1222 result = i_io_read(ig, buffer, size);
1224 SvCUR_set(buffer_sv, result);
1225 *SvEND(buffer_sv) = '\0';
1226 SvPOK_only(buffer_sv);
1228 PUSHs(sv_2mortal(newSViv(result)));
1234 i_io_read2(ig, size)
1243 croak("size negative in call to i_io_read2()");
1244 buffer_sv = newSV(size);
1245 buffer = SvGROW(buffer_sv, size+1);
1246 result = i_io_read(ig, buffer, size);
1248 SvCUR_set(buffer_sv, result);
1249 *SvEND(buffer_sv) = '\0';
1250 SvPOK_only(buffer_sv);
1252 PUSHs(sv_2mortal(buffer_sv));
1256 SvREFCNT_dec(buffer_sv);
1260 i_io_seek(ig, position, whence)
1274 i_io_CLONE_SKIP(...)
1280 MODULE = Imager PACKAGE = Imager
1291 while( (item=i_format_list[i++]) != NULL ) {
1293 PUSHs(sv_2mortal(newSVpv(item,0)));
1306 i_img_empty_ch(im,x,y,ch)
1313 i_sametype(im, x, y)
1319 i_sametype_chans(im, x, y, channels)
1326 i_init_log(name_sv,level)
1330 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1332 i_init_log(name, level);
1335 i_log_entry(string,level)
1354 i_img_info(im,info);
1356 PUSHs(sv_2mortal(newSViv(info[0])));
1357 PUSHs(sv_2mortal(newSViv(info[1])));
1358 PUSHs(sv_2mortal(newSViv(info[2])));
1359 PUSHs(sv_2mortal(newSViv(info[3])));
1365 i_img_setmask(im,ch_mask)
1374 i_img_getchannels(im)
1383 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1391 i_img_get_height(im)
1396 i_img_is_monochrome(im)
1402 result = i_img_is_monochrome(im, &zero_is_white);
1404 if (GIMME_V == G_ARRAY) {
1407 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1416 i_line(im,x1,y1,x2,y2,val,endp)
1426 i_line_aa(im,x1,y1,x2,y2,val,endp)
1436 i_box(im,x1,y1,x2,y2,val)
1445 i_box_filled(im,x1,y1,x2,y2,val)
1454 i_box_cfill(im,x1,y1,x2,y2,fill)
1460 Imager::FillHandle fill
1463 i_arc(im,x,y,rad,d1,d2,val)
1473 i_arc_aa(im,x,y,rad,d1,d2,val)
1483 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1490 Imager::FillHandle fill
1493 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1500 Imager::FillHandle fill
1504 i_circle_aa(im,x,y,rad,val)
1512 i_circle_out(im,x,y,rad,val)
1520 i_circle_out_aa(im,x,y,rad,val)
1528 i_arc_out(im,x,y,rad,d1,d2,val)
1538 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1549 i_bezier_multi(im,xc,yc,val)
1562 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1563 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1564 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1565 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1566 av1=(AV*)SvRV(ST(1));
1567 av2=(AV*)SvRV(ST(2));
1568 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1570 x=mymalloc( len*sizeof(double) );
1571 y=mymalloc( len*sizeof(double) );
1572 for(i=0;i<len;i++) {
1573 sv1=(*(av_fetch(av1,i,0)));
1574 sv2=(*(av_fetch(av2,i,0)));
1575 x[i]=(double)SvNV(sv1);
1576 y[i]=(double)SvNV(sv2);
1578 i_bezier_multi(im,len,x,y,val);
1584 i_poly_aa(im,xc,yc,val)
1597 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1598 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1599 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1600 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1601 av1=(AV*)SvRV(ST(1));
1602 av2=(AV*)SvRV(ST(2));
1603 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1605 x=mymalloc( len*sizeof(double) );
1606 y=mymalloc( len*sizeof(double) );
1607 for(i=0;i<len;i++) {
1608 sv1=(*(av_fetch(av1,i,0)));
1609 sv2=(*(av_fetch(av2,i,0)));
1610 x[i]=(double)SvNV(sv1);
1611 y[i]=(double)SvNV(sv2);
1613 RETVAL = i_poly_aa(im,len,x,y,val);
1620 i_poly_aa_cfill(im,xc,yc,fill)
1622 Imager::FillHandle fill
1632 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1633 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1634 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1635 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1636 av1=(AV*)SvRV(ST(1));
1637 av2=(AV*)SvRV(ST(2));
1638 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1640 x=mymalloc( len*sizeof(double) );
1641 y=mymalloc( len*sizeof(double) );
1642 for(i=0;i<len;i++) {
1643 sv1=(*(av_fetch(av1,i,0)));
1644 sv2=(*(av_fetch(av2,i,0)));
1645 x[i]=(double)SvNV(sv1);
1646 y[i]=(double)SvNV(sv2);
1648 RETVAL = i_poly_aa_cfill(im,len,x,y,fill);
1657 i_flood_fill(im,seedx,seedy,dcol)
1664 i_flood_cfill(im,seedx,seedy,fill)
1668 Imager::FillHandle fill
1671 i_flood_fill_border(im,seedx,seedy,dcol, border)
1676 Imager::Color border
1679 i_flood_cfill_border(im,seedx,seedy,fill, border)
1683 Imager::FillHandle fill
1684 Imager::Color border
1688 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1700 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1717 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1728 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1741 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)
1757 i_combine(src_av, channels_av = NULL)
1761 i_img **imgs = NULL;
1763 int *channels = NULL;
1768 in_count = av_len(src_av) + 1;
1770 imgs = mymalloc(sizeof(i_img*) * in_count);
1771 channels = mymalloc(sizeof(int) * in_count);
1772 for (i = 0; i < in_count; ++i) {
1773 psv = av_fetch(src_av, i, 0);
1774 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1777 croak("imgs must contain only images");
1779 tmp = SvIV((SV*)SvRV(*psv));
1780 imgs[i] = INT2PTR(i_img*, tmp);
1782 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1784 channels[i] = SvIV(*psv);
1791 RETVAL = i_combine(imgs, channels, in_count);
1798 i_flipxy(im, direction)
1803 i_rotate90(im, degrees)
1808 i_rotate_exact(im, amount, ...)
1812 i_color *backp = NULL;
1813 i_fcolor *fbackp = NULL;
1817 /* extract the bg colors if any */
1818 /* yes, this is kind of strange */
1819 for (i = 2; i < items; ++i) {
1821 if (sv_derived_from(sv1, "Imager::Color")) {
1822 IV tmp = SvIV((SV*)SvRV(sv1));
1823 backp = INT2PTR(i_color *, tmp);
1825 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1826 IV tmp = SvIV((SV*)SvRV(sv1));
1827 fbackp = INT2PTR(i_fcolor *, tmp);
1830 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1835 i_matrix_transform(im, xsize, ysize, matrix, ...)
1845 i_color *backp = NULL;
1846 i_fcolor *fbackp = NULL;
1848 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1849 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1850 av=(AV*)SvRV(ST(3));
1854 for (i = 0; i < len; ++i) {
1855 sv1=(*(av_fetch(av,i,0)));
1856 matrix[i] = SvNV(sv1);
1860 /* extract the bg colors if any */
1861 /* yes, this is kind of strange */
1862 for (i = 4; i < items; ++i) {
1864 if (sv_derived_from(sv1, "Imager::Color")) {
1865 IV tmp = SvIV((SV*)SvRV(sv1));
1866 backp = INT2PTR(i_color *, tmp);
1868 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1869 IV tmp = SvIV((SV*)SvRV(sv1));
1870 fbackp = INT2PTR(i_fcolor *, tmp);
1873 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
1878 i_gaussian(im,stdev)
1883 i_unsharp_mask(im,stdev,scale)
1898 len = av_len(coef) + 1;
1899 c_coef=mymalloc( len * sizeof(double) );
1900 for(i = 0; i < len; i++) {
1901 sv1 = (*(av_fetch(coef, i, 0)));
1902 c_coef[i] = (double)SvNV(sv1);
1904 RETVAL = i_conv(im, c_coef, len);
1910 i_convert(src, avmain)
1922 outchan = av_len(avmain)+1;
1923 /* find the biggest */
1925 for (j=0; j < outchan; ++j) {
1926 temp = av_fetch(avmain, j, 0);
1927 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1928 avsub = (AV*)SvRV(*temp);
1929 len = av_len(avsub)+1;
1934 coeff = mymalloc(sizeof(double) * outchan * inchan);
1935 for (j = 0; j < outchan; ++j) {
1936 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1937 len = av_len(avsub)+1;
1938 for (i = 0; i < len; ++i) {
1939 temp = av_fetch(avsub, i, 0);
1941 coeff[i+j*inchan] = SvNV(*temp);
1943 coeff[i+j*inchan] = 0;
1946 coeff[i++ + j*inchan] = 0;
1948 RETVAL = i_convert(src, coeff, outchan, inchan);
1958 unsigned int mask = 0;
1964 unsigned char (*maps)[256];
1966 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1967 croak("i_map: parameter 2 must be an arrayref\n");
1968 avmain = (AV*)SvRV(ST(1));
1969 len = av_len(avmain)+1;
1970 if (im->channels < len) len = im->channels;
1972 maps = mymalloc( len * sizeof(unsigned char [256]) );
1974 for (j=0; j<len ; j++) {
1975 temp = av_fetch(avmain, j, 0);
1976 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1977 avsub = (AV*)SvRV(*temp);
1978 if(av_len(avsub) != 255) continue;
1980 for (i=0; i<256 ; i++) {
1982 temp = av_fetch(avsub, i, 0);
1983 val = temp ? SvIV(*temp) : 0;
1985 if (val>255) val = 255;
1990 i_map(im, maps, mask);
2001 i_img_diffd(im1,im2)
2006 _is_color_object(sv)
2010 RETVAL = SvOK(sv) && SvROK(sv) &&
2011 (sv_derived_from(sv, "Imager::Color")
2012 || sv_derived_from(sv, "Imager::Color::Float"));
2027 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2029 #define TT_DESTROY(handle) i_tt_destroy(handle)
2033 Imager::Font::TT handle
2043 MODULE = Imager PACKAGE = Imager
2047 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
2048 Imager::Font::TT handle
2066 str = SvPV(str_sv, len);
2067 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2068 len, smooth, utf8, align);
2074 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
2075 Imager::Font::TT handle
2093 str = SvPV(str_sv, len);
2094 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2095 smooth, utf8, align);
2101 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
2102 Imager::Font::TT handle
2107 int cords[BOUNDING_BOX_COUNT],rc;
2116 str = SvPV(str_sv, len);
2117 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2119 for (i = 0; i < rc; ++i) {
2120 PUSHs(sv_2mortal(newSViv(cords[i])));
2125 i_tt_has_chars(handle, text_sv, utf8)
2126 Imager::Font::TT handle
2137 if (SvUTF8(text_sv))
2140 text = SvPV(text_sv, len);
2141 work = mymalloc(len);
2142 count = i_tt_has_chars(handle, text, len, utf8, work);
2143 if (GIMME_V == G_ARRAY) {
2145 for (i = 0; i < count; ++i) {
2146 PUSHs(sv_2mortal(newSViv(work[i])));
2151 PUSHs(sv_2mortal(newSVpv(work, count)));
2156 i_tt_dump_names(handle)
2157 Imager::Font::TT handle
2160 i_tt_face_name(handle)
2161 Imager::Font::TT handle
2166 len = i_tt_face_name(handle, name, sizeof(name));
2169 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2173 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2174 Imager::Font::TT handle
2185 if (SvUTF8(text_sv))
2188 text = SvPV(text_sv, work_len);
2193 ch = i_utf8_advance(&text, &len);
2195 i_push_error(0, "invalid UTF8 character");
2204 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2205 PUSHs(sv_2mortal(newSVpv(name, 0)));
2208 PUSHs(&PL_sv_undef);
2215 i_test_format_probe(ig, length)
2220 i_readpnm_wiol(ig, allow_incomplete)
2222 int allow_incomplete
2226 i_readpnm_multi_wiol(ig, allow_incomplete)
2228 int allow_incomplete
2234 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2237 for (i = 0; i < count; ++i) {
2238 SV *sv = sv_newmortal();
2239 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2246 i_writeppm_wiol(im, ig)
2255 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2264 i_writeraw_wiol(im,ig)
2269 i_writebmp_wiol(im,ig)
2274 i_readbmp_wiol(ig, allow_incomplete=0)
2276 int allow_incomplete
2280 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2289 idlen = SvCUR(ST(4));
2290 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2296 i_readtga_wiol(ig, length)
2304 i_scaleaxis(im,Value,Axis)
2310 i_scale_nn(im,scx,scy)
2316 i_scale_mixing(im, width, height)
2326 i_count_colors(im,maxc)
2331 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2336 unsigned int * col_usage = NULL;
2339 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2340 EXTEND(SP, col_cnt);
2341 for (i = 0; i < col_cnt; i++) {
2342 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2349 i_transform(im,opx,opy,parm)
2362 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2363 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2364 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2365 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2366 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2367 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2368 av=(AV*)SvRV(ST(1));
2370 opx=mymalloc( opxl*sizeof(int) );
2371 for(i=0;i<opxl;i++) {
2372 sv1=(*(av_fetch(av,i,0)));
2373 opx[i]=(int)SvIV(sv1);
2375 av=(AV*)SvRV(ST(2));
2377 opy=mymalloc( opyl*sizeof(int) );
2378 for(i=0;i<opyl;i++) {
2379 sv1=(*(av_fetch(av,i,0)));
2380 opy[i]=(int)SvIV(sv1);
2382 av=(AV*)SvRV(ST(3));
2383 parmlen=av_len(av)+1;
2384 parm=mymalloc( parmlen*sizeof(double) );
2385 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2386 sv1=(*(av_fetch(av,i,0)));
2387 parm[i]=(double)SvNV(sv1);
2389 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2393 ST(0) = sv_newmortal();
2394 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2395 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2398 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2423 in_imgs_count = av_len(av_in_imgs)+1;
2424 for (i = 0; i < in_imgs_count; ++i) {
2425 sv1 = *av_fetch(av_in_imgs, i, 0);
2426 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2427 croak("sv_in_img must contain only images");
2430 if (in_imgs_count > 0) {
2431 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2432 for (i = 0; i < in_imgs_count; ++i) {
2433 sv1 = *av_fetch(av_in_imgs,i,0);
2434 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2435 croak("Parameter 5 must contain only images");
2437 tmp = SvIV((SV*)SvRV(sv1));
2438 in_imgs[i] = INT2PTR(i_img*, tmp);
2442 /* no input images */
2445 /* default the output size from the first input if possible */
2447 width = SvIV(sv_width);
2448 else if (in_imgs_count)
2449 width = in_imgs[0]->xsize;
2451 croak("No output image width supplied");
2453 if (SvOK(sv_height))
2454 height = SvIV(sv_height);
2455 else if (in_imgs_count)
2456 height = in_imgs[0]->ysize;
2458 croak("No output image height supplied");
2460 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2461 if (ops_len % sizeof(struct rm_op))
2462 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2463 ops_count = ops_len / sizeof(struct rm_op);
2465 n_regs_count = av_len(av_n_regs)+1;
2466 n_regs = mymalloc(n_regs_count * sizeof(double));
2467 for (i = 0; i < n_regs_count; ++i) {
2468 sv1 = *av_fetch(av_n_regs,i,0);
2470 n_regs[i] = SvNV(sv1);
2472 c_regs_count = av_len(av_c_regs)+1;
2473 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2474 /* I don't bother initializing the colou?r registers */
2476 RETVAL=i_transform2(width, height, channels, ops, ops_count,
2477 n_regs, n_regs_count,
2478 c_regs, c_regs_count, in_imgs, in_imgs_count);
2483 ST(0) = sv_newmortal();
2484 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2485 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2489 i_contrast(im,intensity)
2502 i_noise(im,amount,type)
2508 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2518 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2537 i_postlevels(im,levels)
2547 i_watermark(im,wmark,tx,ty,pixdiff)
2549 Imager::ImgRaw wmark
2556 i_autolevels(im,lsat,usat,skew)
2563 i_radnoise(im,xo,yo,rscale,ascale)
2571 i_turbnoise(im, xo, yo, scale)
2594 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2595 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2596 croak("i_gradgen: Second argument must be an array ref");
2597 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2598 croak("i_gradgen: Third argument must be an array ref");
2599 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2600 croak("i_gradgen: Fourth argument must be an array ref");
2601 axx = (AV *)SvRV(ST(1));
2602 ayy = (AV *)SvRV(ST(2));
2603 ac = (AV *)SvRV(ST(3));
2604 dmeasure = (int)SvIV(ST(4));
2606 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2607 num = num <= av_len(ac) ? num : av_len(ac);
2609 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2610 xo = mymalloc( sizeof(int) * num );
2611 yo = mymalloc( sizeof(int) * num );
2612 ival = mymalloc( sizeof(i_color) * num );
2613 for(i = 0; i<num; i++) {
2614 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2615 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2616 sv = *av_fetch(ac, i, 0);
2617 if ( !sv_derived_from(sv, "Imager::Color") ) {
2618 free(axx); free(ayy); free(ac);
2619 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2621 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2623 i_gradgen(im, num, xo, yo, ival, dmeasure);
2629 i_diff_image(im, im2, mindist=0)
2635 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2645 double ssample_param
2649 i_fountain_seg *segs;
2651 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2652 croak("i_fountain: argument 11 must be an array ref");
2654 asegs = (AV *)SvRV(ST(10));
2655 segs = load_fount_segs(aTHX_ asegs, &count);
2656 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2657 super_sample, ssample_param, count, segs);
2663 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2672 double ssample_param
2676 i_fountain_seg *segs;
2678 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2679 croak("i_fountain: argument 11 must be an array ref");
2681 asegs = (AV *)SvRV(ST(9));
2682 segs = load_fount_segs(aTHX_ asegs, &count);
2683 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2684 super_sample, ssample_param, count, segs);
2690 i_new_fill_opacity(other_fill, alpha_mult)
2691 Imager::FillHandle other_fill
2702 errors = i_errors();
2704 while (errors[i].msg) {
2706 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2707 if (!av_store(av, 0, sv)) {
2710 sv = newSViv(errors[i].code);
2711 if (!av_store(av, 1, sv)) {
2714 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2722 i_push_error(code, msg)
2727 i_nearest_color(im, ...)
2742 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2743 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2744 croak("i_nearest_color: Second argument must be an array ref");
2745 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2746 croak("i_nearest_color: Third argument must be an array ref");
2747 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2748 croak("i_nearest_color: Fourth argument must be an array ref");
2749 axx = (AV *)SvRV(ST(1));
2750 ayy = (AV *)SvRV(ST(2));
2751 ac = (AV *)SvRV(ST(3));
2752 dmeasure = (int)SvIV(ST(4));
2754 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2755 num = num <= av_len(ac) ? num : av_len(ac);
2757 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2758 xo = mymalloc( sizeof(int) * num );
2759 yo = mymalloc( sizeof(int) * num );
2760 ival = mymalloc( sizeof(i_color) * num );
2761 for(i = 0; i<num; i++) {
2762 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2763 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2764 sv = *av_fetch(ac, i, 0);
2765 if ( !sv_derived_from(sv, "Imager::Color") ) {
2766 free(axx); free(ayy); free(ac);
2767 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2769 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2771 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2785 rc=DSO_open(filename,&evstr);
2789 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2790 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2793 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2799 DSO_close(dso_handle)
2803 DSO_funclist(dso_handle_v)
2807 DSO_handle *dso_handle;
2808 func_ptr *functions;
2810 dso_handle=(DSO_handle*)dso_handle_v;
2811 functions = DSO_funclist(dso_handle);
2813 while( functions[i].name != NULL) {
2815 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2817 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2821 DSO_call(handle,func_index,hv)
2827 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
2828 hv=(HV*)SvRV(ST(2));
2829 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2830 DSO_call( (DSO_handle *)handle,func_index,hv);
2833 i_get_pixel(im, x, y)
2840 color = (i_color *)mymalloc(sizeof(i_color));
2841 if (i_gpix(im, x, y, color) == 0) {
2842 RETVAL = NEWSV(0, 0);
2843 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
2847 RETVAL = &PL_sv_undef;
2854 i_ppix(im, x, y, cl)
2861 i_img_pal_new(x, y, channels, maxpal)
2868 i_img_to_pal(src, quant)
2874 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2875 croak("i_img_to_pal: second argument must be a hash ref");
2876 hv = (HV *)SvRV(ST(1));
2877 memset(&quant, 0, sizeof(quant));
2879 quant.mc_size = 256;
2880 ip_handle_quant_opts(aTHX_ &quant, hv);
2881 RETVAL = i_img_to_pal(src, &quant);
2883 ip_copy_colors_back(aTHX_ hv, &quant);
2885 ip_cleanup_quant_opts(aTHX_ &quant);
2904 work = mymalloc((r-l) * sizeof(i_palidx));
2905 count = i_gpal(im, l, r, y, work);
2906 if (GIMME_V == G_ARRAY) {
2908 for (i = 0; i < count; ++i) {
2909 PUSHs(sv_2mortal(newSViv(work[i])));
2914 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
2919 if (GIMME_V != G_ARRAY) {
2921 PUSHs(&PL_sv_undef);
2926 i_ppal(im, l, y, ...)
2935 work = mymalloc(sizeof(i_palidx) * (items-3));
2936 for (i=0; i < items-3; ++i) {
2937 work[i] = SvIV(ST(i+3));
2939 validate_i_ppal(im, work, items - 3);
2940 RETVAL = i_ppal(im, l, l+items-3, y, work);
2950 i_ppal_p(im, l, y, data)
2956 i_palidx const *work;
2959 work = (i_palidx const *)SvPV(data, len);
2960 len /= sizeof(i_palidx);
2962 validate_i_ppal(im, work, len);
2963 RETVAL = i_ppal(im, l, l+len, y, work);
2972 i_addcolors(im, ...)
2980 croak("i_addcolors: no colors to add");
2981 colors = mymalloc((items-1) * sizeof(i_color));
2982 for (i=0; i < items-1; ++i) {
2983 if (sv_isobject(ST(i+1))
2984 && sv_derived_from(ST(i+1), "Imager::Color")) {
2985 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
2986 colors[i] = *INT2PTR(i_color *, tmp);
2990 croak("i_addcolor: pixels must be Imager::Color objects");
2993 index = i_addcolors(im, colors, items-1);
2996 RETVAL = newSVpv("0 but true", 0);
2998 else if (index == -1) {
2999 RETVAL = &PL_sv_undef;
3002 RETVAL = newSViv(index);
3008 i_setcolors(im, index, ...)
3016 croak("i_setcolors: no colors to add");
3017 colors = mymalloc((items-2) * sizeof(i_color));
3018 for (i=0; i < items-2; ++i) {
3019 if (sv_isobject(ST(i+2))
3020 && sv_derived_from(ST(i+2), "Imager::Color")) {
3021 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3022 colors[i] = *INT2PTR(i_color *, tmp);
3026 croak("i_setcolors: pixels must be Imager::Color objects");
3029 RETVAL = i_setcolors(im, index, colors, items-2);
3035 i_getcolors(im, index, ...)
3044 croak("i_getcolors: too many arguments");
3046 count = SvIV(ST(2));
3048 croak("i_getcolors: count must be positive");
3049 colors = mymalloc(sizeof(i_color) * count);
3050 if (i_getcolors(im, index, colors, count)) {
3051 for (i = 0; i < count; ++i) {
3053 SV *sv = sv_newmortal();
3054 pv = mymalloc(sizeof(i_color));
3056 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3072 i_findcolor(im, color)
3078 if (i_findcolor(im, color, &index)) {
3079 RETVAL = newSViv(index);
3082 RETVAL = &PL_sv_undef;
3100 i_gsamp(im, l, r, y, ...)
3112 croak("No channel numbers supplied to g_samp()");
3114 chan_count = items - 4;
3115 chans = mymalloc(sizeof(int) * chan_count);
3116 for (i = 0; i < chan_count; ++i)
3117 chans[i] = SvIV(ST(i+4));
3118 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
3119 count = i_gsamp(im, l, r, y, data, chans, chan_count);
3121 if (GIMME_V == G_ARRAY) {
3123 for (i = 0; i < count; ++i)
3124 PUSHs(sv_2mortal(newSViv(data[i])));
3128 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3133 if (GIMME_V != G_ARRAY) {
3135 PUSHs(&PL_sv_undef);
3140 i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3156 croak("No channel numbers supplied to g_samp()");
3158 chan_count = items - 7;
3159 chans = mymalloc(sizeof(int) * chan_count);
3160 for (i = 0; i < chan_count; ++i)
3161 chans[i] = SvIV(ST(i+7));
3162 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3163 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3165 for (i = 0; i < count; ++i) {
3166 av_store(target, i+offset, newSVuv(data[i]));
3178 i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3196 if (SvOK(channels_sv)) {
3198 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3199 croak("channels is not an array ref");
3201 channels_av = (AV *)SvRV(channels_sv);
3202 chan_count = av_len(channels_av) + 1;
3203 if (chan_count < 1) {
3204 croak("i_psamp_bits: no channels provided");
3206 channels = mymalloc(sizeof(int) * chan_count);
3207 for (i = 0; i < chan_count; ++i)
3208 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3211 chan_count = im->channels;
3215 data_count = av_len(data_av) + 1;
3216 if (data_offset < 0) {
3217 croak("data_offset must by non-negative");
3219 if (data_offset > data_count) {
3220 croak("data_offset greater than number of samples supplied");
3222 if (pixel_count == -1 ||
3223 data_offset + pixel_count * chan_count > data_count) {
3224 pixel_count = (data_count - data_offset) / chan_count;
3227 data_used = pixel_count * chan_count;
3228 data = mymalloc(sizeof(unsigned) * data_count);
3229 for (i = 0; i < data_used; ++i)
3230 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3232 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3243 i_img_masked_new(targ, mask, x, y, w, h)
3253 if (!sv_isobject(ST(1))
3254 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3255 croak("i_img_masked_new: parameter 2 must undef or an image");
3257 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3261 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3266 i_plin(im, l, y, ...)
3277 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3278 /* supplied as a byte string */
3279 work = (i_color *)SvPV(ST(3), len);
3280 count = len / sizeof(i_color);
3281 if (count * sizeof(i_color) != len) {
3282 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3284 RETVAL = i_plin(im, l, l+count, y, work);
3287 work = mymalloc(sizeof(i_color) * (items-3));
3288 for (i=0; i < items-3; ++i) {
3289 if (sv_isobject(ST(i+3))
3290 && sv_derived_from(ST(i+3), "Imager::Color")) {
3291 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3292 work[i] = *INT2PTR(i_color *, tmp);
3296 croak("i_plin: pixels must be Imager::Color objects");
3299 RETVAL = i_plin(im, l, l+items-3, y, work);
3310 i_ppixf(im, x, y, cl)
3314 Imager::Color::Float cl
3317 i_gsampf(im, l, r, y, ...)
3329 croak("No channel numbers supplied to g_sampf()");
3331 chan_count = items - 4;
3332 chans = mymalloc(sizeof(int) * chan_count);
3333 for (i = 0; i < chan_count; ++i)
3334 chans[i] = SvIV(ST(i+4));
3335 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3336 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3338 if (GIMME_V == G_ARRAY) {
3340 for (i = 0; i < count; ++i)
3341 PUSHs(sv_2mortal(newSVnv(data[i])));
3345 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3350 if (GIMME_V != G_ARRAY) {
3352 PUSHs(&PL_sv_undef);
3357 i_plinf(im, l, y, ...)
3368 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3369 /* supplied as a byte string */
3370 work = (i_fcolor *)SvPV(ST(3), len);
3371 count = len / sizeof(i_fcolor);
3372 if (count * sizeof(i_fcolor) != len) {
3373 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3375 RETVAL = i_plinf(im, l, l+count, y, work);
3378 work = mymalloc(sizeof(i_fcolor) * (items-3));
3379 for (i=0; i < items-3; ++i) {
3380 if (sv_isobject(ST(i+3))
3381 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3382 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3383 work[i] = *INT2PTR(i_fcolor *, tmp);
3387 croak("i_plinf: pixels must be Imager::Color::Float objects");
3391 RETVAL = i_plinf(im, l, l+items-3, y, work);
3409 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3410 if (i_gpixf(im, x, y, color) == 0) {
3411 RETVAL = NEWSV(0,0);
3412 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
3416 RETVAL = &PL_sv_undef;
3432 vals = mymalloc((r-l) * sizeof(i_color));
3433 memset(vals, 0, (r-l) * sizeof(i_color));
3434 count = i_glin(im, l, r, y, vals);
3435 if (GIMME_V == G_ARRAY) {
3437 for (i = 0; i < count; ++i) {
3439 i_color *col = mymalloc(sizeof(i_color));
3441 sv = sv_newmortal();
3442 sv_setref_pv(sv, "Imager::Color", (void *)col);
3448 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3454 i_glinf(im, l, r, y)
3464 for (i = 0; i < MAXCHANNELS; ++i)
3465 zero.channel[i] = 0;
3467 vals = mymalloc((r-l) * sizeof(i_fcolor));
3468 for (i = 0; i < r-l; ++i)
3470 count = i_glinf(im, l, r, y, vals);
3471 if (GIMME_V == G_ARRAY) {
3473 for (i = 0; i < count; ++i) {
3475 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3477 sv = sv_newmortal();
3478 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3484 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3490 i_img_16_new(x, y, ch)
3500 i_img_double_new(x, y, ch)
3506 i_tags_addn(im, name, code, idata)
3515 name = SvPV(ST(1), len);
3518 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3523 i_tags_add(im, name, code, data, idata)
3533 name = SvPV(ST(1), len);
3537 data = SvPV(ST(3), len);
3542 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3547 i_tags_find(im, name, start)
3554 if (i_tags_find(&im->tags, name, start, &entry)) {
3556 RETVAL = newSVpv("0 but true", 0);
3558 RETVAL = newSViv(entry);
3560 RETVAL = &PL_sv_undef;
3566 i_tags_findn(im, code, start)
3573 if (i_tags_findn(&im->tags, code, start, &entry)) {
3575 RETVAL = newSVpv("0 but true", 0);
3577 RETVAL = newSViv(entry);
3580 RETVAL = &PL_sv_undef;
3586 i_tags_delete(im, entry)
3590 RETVAL = i_tags_delete(&im->tags, entry);
3595 i_tags_delbyname(im, name)
3599 RETVAL = i_tags_delbyname(&im->tags, name);
3604 i_tags_delbycode(im, code)
3608 RETVAL = i_tags_delbycode(&im->tags, code);
3613 i_tags_get(im, index)
3617 if (index >= 0 && index < im->tags.count) {
3618 i_img_tag *entry = im->tags.tags + index;
3622 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3625 PUSHs(sv_2mortal(newSViv(entry->code)));
3628 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3631 PUSHs(sv_2mortal(newSViv(entry->idata)));
3636 i_tags_get_string(im, what_sv)
3640 char const *name = NULL;
3644 if (SvIOK(what_sv)) {
3645 code = SvIV(what_sv);
3649 name = SvPV_nolen(what_sv);
3652 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3654 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3661 RETVAL = im->tags.count;
3667 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3671 Imager::FillHandle fill
3674 IFILL_CLONE_SKIP(...)
3680 MODULE = Imager PACKAGE = Imager
3683 i_new_fill_solid(cl, combine)
3688 i_new_fill_solidf(cl, combine)
3689 Imager::Color::Float cl
3693 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3701 unsigned char *cust_hatch;
3705 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3709 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3714 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3715 Imager::Color::Float fg
3716 Imager::Color::Float bg
3722 unsigned char *cust_hatch;
3726 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3730 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3735 i_new_fill_image(src, matrix, xoff, yoff, combine)
3752 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3753 croak("i_new_fill_image: parameter must be an arrayref");
3754 av=(AV*)SvRV(ST(1));
3758 for (i = 0; i < len; ++i) {
3759 sv1=(*(av_fetch(av,i,0)));
3760 matrix[i] = SvNV(sv1);
3766 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3770 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3772 # this class is only exposed for testing
3775 i_int_hlines_testing()
3777 #if i_int_hlines_testing()
3779 Imager::Internal::Hlines
3780 i_int_hlines_new(start_y, count_y, start_x, count_x)
3786 Imager::Internal::Hlines
3787 i_int_hlines_new_img(im)
3791 i_int_hlines_add(hlines, y, minx, width)
3792 Imager::Internal::Hlines hlines
3798 i_int_hlines_DESTROY(hlines)
3799 Imager::Internal::Hlines hlines
3802 i_int_hlines_dump(hlines)
3803 Imager::Internal::Hlines hlines
3806 i_int_hlines_CLONE_SKIP(cls)
3812 PERL_SET_GLOBAL_CALLBACKS;
3813 PERL_PL_SET_GLOBAL_CALLBACKS;