1 #define PERL_NO_GET_CONTEXT
8 #define NEED_newRV_noinc
9 #define NEED_sv_2pv_nolen
10 #define NEED_sv_2pvbyte
16 #define i_int_hlines_testing() 1
23 #include "imextpltypes.h"
27 #if i_int_hlines_testing()
33 #ifndef SV_COW_DROP_PV
34 #define SV_COW_DROP_PV 0
39 Context object management
43 typedef im_context_t Imager__Context;
45 #define im_context_DESTROY(ctx) im_context_refdec((ctx), "DESTROY")
47 #ifdef PERL_IMPLICIT_CONTEXT
49 #define MY_CXT_KEY "Imager::_context" XS_VERSION
57 im_context_t fallback_context;
62 MY_CXT.ctx = im_context_new();
63 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
65 /* Ideally we'd free this reference, but the error message memory
66 was never released on exit, so the associated memory here is reasonable
68 With logging enabled we always need at least one context, since
69 objects may be released fairly late and attempt to get the log file.
71 im_context_refinc(MY_CXT.ctx, "start_context");
72 fallback_context = MY_CXT.ctx;
76 perl_get_context(void) {
80 return MY_CXT.ctx ? MY_CXT.ctx : fallback_context;
85 static im_context_t perl_context;
89 perl_context = im_context_new();
90 im_context_refinc(perl_context, "start_context");
94 perl_get_context(void) {
100 /* used to represent channel lists parameters */
101 typedef struct i_channel_list_tag {
108 const i_sample_t *samples;
113 const i_fsample_t *samples;
118 Allocate memory that will be discarded when mortals are discarded.
123 malloc_temp(pTHX_ size_t size) {
124 SV *sv = sv_2mortal(newSV(size));
130 calloc_temp(pTHX_ size_t size) {
131 void *result = malloc_temp(aTHX_ size);
132 memset(result, 0, size);
137 /* for use with the T_AVARRAY typemap */
138 #define doublePtr(size) ((double *)calloc_temp(aTHX_ sizeof(double) * (size)))
139 #define SvDouble(sv, pname) (SvNV(sv))
141 #define intPtr(size) ((int *)calloc_temp(aTHX_ sizeof(int) * (size)))
142 #define SvInt(sv, pname) (SvIV(sv))
144 #define i_img_dimPtr(size) ((i_img_dim *)calloc_temp(aTHX_ sizeof(i_img_dim) * (size)))
145 #define SvI_img_dim(sv, pname) (SvIV(sv))
147 #define i_colorPtr(size) ((i_color *)calloc_temp(aTHX_ sizeof(i_color *) * (size)))
149 #define SvI_color(sv, pname) S_sv_to_i_color(aTHX_ sv, pname)
152 S_sv_to_i_color(pTHX_ SV *sv, const char *pname) {
153 if (!sv_derived_from(sv, "Imager::Color")) {
154 croak("%s: not a color object", pname);
156 return *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
159 /* These functions are all shared - then comes platform dependant code */
160 static int getstr(void *hv_t,char *key,char **store) {
165 mm_log((1,"getstr(hv_t %p, key %s, store %p)\n",hv_t,key,store));
167 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
169 svpp=hv_fetch(hv, key, strlen(key), 0);
170 *store=SvPV(*svpp, PL_na );
175 static int getint(void *hv_t,char *key,int *store) {
180 mm_log((1,"getint(hv_t %p, key %s, store %p)\n",hv_t,key,store));
182 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
184 svpp=hv_fetch(hv, key, strlen(key), 0);
185 *store=(int)SvIV(*svpp);
189 static int getdouble(void *hv_t,char* key,double *store) {
194 mm_log((1,"getdouble(hv_t %p, key %s, store %p)\n",hv_t,key,store));
196 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
197 svpp=hv_fetch(hv, key, strlen(key), 0);
198 *store=(double)SvNV(*svpp);
202 static int getvoid(void *hv_t,char* key,void **store) {
207 mm_log((1,"getvoid(hv_t %p, key %s, store %p)\n",hv_t,key,store));
209 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
211 svpp=hv_fetch(hv, key, strlen(key), 0);
212 *store = INT2PTR(void*, SvIV(*svpp));
217 static int getobj(void *hv_t,char *key,char *type,void **store) {
222 mm_log((1,"getobj(hv_t %p, key %s,type %s, store %p)\n",hv_t,key,type,store));
224 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
226 svpp=hv_fetch(hv, key, strlen(key), 0);
228 if (sv_derived_from(*svpp,type)) {
229 IV tmp = SvIV((SV*)SvRV(*svpp));
230 *store = INT2PTR(void*, tmp);
232 mm_log((1,"getobj: key exists in hash but is not of correct type"));
239 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
242 free_buffer(void *p) {
248 i_log_entry(char *string, int level) {
249 mm_log((level, "%s", string));
253 make_i_color_sv(pTHX_ const i_color *c) {
255 i_color *col = mymalloc(sizeof(i_color));
258 sv_setref_pv(sv, "Imager::Color", (void *)col);
263 #define CBDATA_BUFSIZE 8192
266 /* the SVs we use to call back to Perl */
274 call_reader(struct cbdata *cbd, void *buf, size_t size,
282 if (!SvOK(cbd->readcb)) {
283 mm_log((1, "read callback called but no readcb supplied\n"));
284 i_push_error(0, "read callback called but no readcb supplied");
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 = SvPVbyte(data, len);
309 croak("Too much data returned in reader callback (wanted %d, got %d, expected %d)",
310 (int)size, (int)len, (int)maxread);
312 memcpy(buf, ptr, len);
327 io_seeker(void *p, off_t offset, int whence) {
329 struct cbdata *cbd = p;
334 if (!SvOK(cbd->seekcb)) {
335 mm_log((1, "seek callback called but no seekcb supplied\n"));
336 i_push_error(0, "seek callback called but no seekcb supplied");
344 PUSHs(sv_2mortal(newSViv(offset)));
345 PUSHs(sv_2mortal(newSViv(whence)));
348 count = perl_call_sv(cbd->seekcb, G_SCALAR);
353 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
365 io_writer(void *p, void const *data, size_t size) {
367 struct cbdata *cbd = p;
373 if (!SvOK(cbd->writecb)) {
374 mm_log((1, "write callback called but no writecb supplied\n"));
375 i_push_error(0, "write callback called but no writecb supplied");
383 PUSHs(sv_2mortal(newSVpv((char *)data, size)));
386 count = perl_call_sv(cbd->writecb, G_SCALAR);
390 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
393 success = SvTRUE(sv);
400 return success ? size : -1;
404 io_reader(void *p, void *data, size_t size) {
405 struct cbdata *cbd = p;
407 return call_reader(cbd, data, size, size);
410 static int io_closer(void *p) {
412 struct cbdata *cbd = p;
415 if (SvOK(cbd->closecb)) {
424 count = perl_call_sv(cbd->closecb, G_SCALAR);
430 success = SvTRUE(sv);
440 return success ? 0 : -1;
443 static void io_destroyer(void *p) {
445 struct cbdata *cbd = p;
447 SvREFCNT_dec(cbd->writecb);
448 SvREFCNT_dec(cbd->readcb);
449 SvREFCNT_dec(cbd->seekcb);
450 SvREFCNT_dec(cbd->closecb);
455 im_SvREFSCALAR(SV *sv) {
456 svtype type = SvTYPE(sv);
466 #if PERL_VERSION > 10
477 describe_sv(SV *sv) {
480 svtype type = SvTYPE(SvRV(sv));
482 case SVt_PVCV: return "CV";
483 case SVt_PVGV: return "GV";
484 case SVt_PVLV: return "LV";
485 default: return "some reference";
489 return "non-reference scalar";
498 do_io_new_buffer(pTHX_ SV *data_sv) {
505 if (SvROK(data_sv)) {
506 if (im_SvREFSCALAR(SvRV(data_sv))) {
510 i_push_errorf(0, "data is not a scalar or a reference to scalar");
518 /* previously this would keep the SV around, but this is unsafe in
519 many ways, so always copy the bytes */
520 data = SvPVbyte(sv, length);
521 data_copy = mymalloc(length);
522 memcpy(data_copy, data, length);
523 return io_new_buffer(data_copy, length, free_buffer, data_copy);
527 do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) {
530 cbd = mymalloc(sizeof(struct cbdata));
531 cbd->writecb = newSVsv(writecb);
532 cbd->readcb = newSVsv(readcb);
533 cbd->seekcb = newSVsv(seekcb);
534 cbd->closecb = newSVsv(closecb);
536 mm_log((1, "do_io_new_cb(writecb %p (%s), readcb %p (%s), seekcb %p (%s), closecb %p (%s))\n", writecb, describe_sv(writecb), readcb, describe_sv(readcb), seekcb, describe_sv(seekcb), closecb, describe_sv(closecb)));
538 return io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
546 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
549 for (i = 0; i < count; ++i)
550 if (strEQ(names[i].name, name))
551 return names[i].value;
555 static struct value_name transp_names[] =
558 { "threshold", tr_threshold },
559 { "errdiff", tr_errdiff },
560 { "ordered", tr_ordered, },
563 static struct value_name make_color_names[] =
565 { "none", mc_none, },
566 { "webmap", mc_web_map, },
567 { "addi", mc_addi, },
568 { "mediancut", mc_median_cut, },
569 { "mono", mc_mono, },
570 { "monochrome", mc_mono, },
571 { "gray", mc_gray, },
572 { "gray4", mc_gray4, },
573 { "gray16", mc_gray16, },
576 static struct value_name translate_names[] =
578 { "giflib", pt_giflib, },
579 { "closest", pt_closest, },
580 { "perturb", pt_perturb, },
581 { "errdiff", pt_errdiff, },
584 static struct value_name errdiff_names[] =
586 { "floyd", ed_floyd, },
587 { "jarvis", ed_jarvis, },
588 { "stucki", ed_stucki, },
589 { "custom", ed_custom, },
592 static struct value_name orddith_names[] =
594 { "random", od_random, },
595 { "dot8", od_dot8, },
596 { "dot4", od_dot4, },
597 { "hline", od_hline, },
598 { "vline", od_vline, },
599 { "/line", od_slashline, },
600 { "slashline", od_slashline, },
601 { "\\line", od_backline, },
602 { "backline", od_backline, },
603 { "tiny", od_tiny, },
604 { "custom", od_custom, },
607 /* look through the hash for quantization options */
609 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
611 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
617 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
619 sv = hv_fetch(hv, "transp", 6, 0);
620 if (sv && *sv && (str = SvPV(*sv, len))) {
622 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
624 if (quant->transp != tr_none) {
625 quant->tr_threshold = 127;
626 sv = hv_fetch(hv, "tr_threshold", 12, 0);
628 quant->tr_threshold = SvIV(*sv);
630 if (quant->transp == tr_errdiff) {
631 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
632 if (sv && *sv && (str = SvPV(*sv, len)))
633 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
635 if (quant->transp == tr_ordered) {
636 quant->tr_orddith = od_tiny;
637 sv = hv_fetch(hv, "tr_orddith", 10, 0);
638 if (sv && *sv && (str = SvPV(*sv, len)))
639 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
641 if (quant->tr_orddith == od_custom) {
642 sv = hv_fetch(hv, "tr_map", 6, 0);
643 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
644 AV *av = (AV*)SvRV(*sv);
645 len = av_len(av) + 1;
646 if (len > sizeof(quant->tr_custom))
647 len = sizeof(quant->tr_custom);
648 for (i = 0; i < len; ++i) {
649 SV **sv2 = av_fetch(av, i, 0);
651 quant->tr_custom[i] = SvIV(*sv2);
654 while (i < sizeof(quant->tr_custom))
655 quant->tr_custom[i++] = 0;
660 quant->make_colors = mc_median_cut;
661 sv = hv_fetch(hv, "make_colors", 11, 0);
662 if (sv && *sv && (str = SvPV(*sv, len))) {
664 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
666 sv = hv_fetch(hv, "colors", 6, 0);
667 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
668 /* needs to be an array of Imager::Color
669 note that the caller allocates the mc_color array and sets mc_size
671 AV *av = (AV *)SvRV(*sv);
672 quant->mc_count = av_len(av)+1;
673 if (quant->mc_count > quant->mc_size)
674 quant->mc_count = quant->mc_size;
675 for (i = 0; i < quant->mc_count; ++i) {
676 SV **sv1 = av_fetch(av, i, 0);
677 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
678 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
679 quant->mc_colors[i] = *col;
683 sv = hv_fetch(hv, "max_colors", 10, 0);
686 if (i <= quant->mc_size && i >= quant->mc_count)
690 quant->translate = pt_closest;
691 sv = hv_fetch(hv, "translate", 9, 0);
692 if (sv && *sv && (str = SvPV(*sv, len))) {
693 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
695 sv = hv_fetch(hv, "errdiff", 7, 0);
696 if (sv && *sv && (str = SvPV(*sv, len))) {
697 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
699 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
700 /* get the error diffusion map */
701 sv = hv_fetch(hv, "errdiff_width", 13, 0);
703 quant->ed_width = SvIV(*sv);
704 sv = hv_fetch(hv, "errdiff_height", 14, 0);
706 quant->ed_height = SvIV(*sv);
707 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
709 quant->ed_orig = SvIV(*sv);
710 if (quant->ed_width > 0 && quant->ed_height > 0) {
712 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
713 sv = hv_fetch(hv, "errdiff_map", 11, 0);
714 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
715 AV *av = (AV*)SvRV(*sv);
716 len = av_len(av) + 1;
717 if (len > quant->ed_width * quant->ed_height)
718 len = quant->ed_width * quant->ed_height;
719 for (i = 0; i < len; ++i) {
720 SV **sv2 = av_fetch(av, i, 0);
722 quant->ed_map[i] = SvIV(*sv2);
723 sum += quant->ed_map[i];
729 myfree(quant->ed_map);
731 quant->errdiff = ed_floyd;
735 sv = hv_fetch(hv, "perturb", 7, 0);
737 quant->perturb = SvIV(*sv);
741 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
742 myfree(quant->mc_colors);
744 myfree(quant->ed_map);
747 /* copies the color map from the hv into the colors member of the HV */
749 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
755 sv = hv_fetch(hv, "colors", 6, 0);
756 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
761 av = (AV *)SvRV(*sv);
763 av_extend(av, quant->mc_count+1);
764 for (i = 0; i < quant->mc_count; ++i) {
765 i_color *in = quant->mc_colors+i;
766 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
767 work = sv_newmortal();
768 sv_setref_pv(work, "Imager::Color", (void *)c);
774 /* loads the segments of a fountain fill into an array */
775 static i_fountain_seg *
776 load_fount_segs(pTHX_ AV *asegs, int *count) {
777 /* Each element of segs must contain:
778 [ start, middle, end, c0, c1, segtype, colortrans ]
779 start, middle, end are doubles from 0 to 1
780 c0, c1 are Imager::Color::Float or Imager::Color objects
781 segtype, colortrans are ints
785 i_fountain_seg *segs;
789 *count = av_len(asegs)+1;
791 croak("i_fountain must have at least one segment");
792 segs = mymalloc(sizeof(i_fountain_seg) * *count);
793 for(i = 0; i < *count; i++) {
794 SV **sv1 = av_fetch(asegs, i, 0);
795 if (!sv1 || !*sv1 || !SvROK(*sv1)
796 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
798 croak("i_fountain: segs must be an arrayref of arrayrefs");
800 aseg = (AV *)SvRV(*sv1);
801 if (av_len(aseg) != 7-1) {
803 croak("i_fountain: a segment must have 7 members");
805 for (j = 0; j < 3; ++j) {
806 SV **sv2 = av_fetch(aseg, j, 0);
809 croak("i_fountain: XS error");
811 work[j] = SvNV(*sv2);
813 segs[i].start = work[0];
814 segs[i].middle = work[1];
815 segs[i].end = work[2];
816 for (j = 0; j < 2; ++j) {
817 SV **sv3 = av_fetch(aseg, 3+j, 0);
818 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
819 (!sv_derived_from(*sv3, "Imager::Color")
820 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
822 croak("i_fountain: segs must contain colors in elements 3 and 4");
824 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
825 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
828 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
830 for (ch = 0; ch < MAXCHANNELS; ++ch) {
831 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
835 for (j = 0; j < 2; ++j) {
836 SV **sv2 = av_fetch(aseg, j+5, 0);
839 croak("i_fountain: XS error");
841 worki[j] = SvIV(*sv2);
843 segs[i].type = worki[0];
844 segs[i].color = worki[1];
850 /* validates the indexes supplied to i_ppal
852 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
857 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
858 int color_count = i_colorcount(im);
861 if (color_count == -1)
862 croak("i_plin() called on direct color image");
864 for (i = 0; i < count; ++i) {
865 if (indexes[i] >= color_count) {
866 croak("i_plin() called with out of range color index %d (max %d)",
867 indexes[i], color_count-1);
872 /* I don't think ICLF_* names belong at the C interface
873 this makes the XS code think we have them, to let us avoid
874 putting function bodies in the XS code
876 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
877 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
880 #define i_log_enabled() 1
882 #define i_log_enabled() 0
885 #if i_int_hlines_testing()
887 typedef i_int_hlines *Imager__Internal__Hlines;
889 static i_int_hlines *
890 i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
891 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
892 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
897 static i_int_hlines *
898 i_int_hlines_new_img(i_img *im) {
899 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
900 i_int_init_hlines_img(result, im);
906 i_int_hlines_DESTROY(i_int_hlines *hlines) {
907 i_int_hlines_destroy(hlines);
911 #define i_int_hlines_CLONE_SKIP(cls) 1
913 static int seg_compare(const void *vleft, const void *vright) {
914 const i_int_hline_seg *left = vleft;
915 const i_int_hline_seg *right = vright;
917 return left->minx - right->minx;
921 i_int_hlines_dump(i_int_hlines *hlines) {
923 SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
924 i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
927 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
928 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
931 /* sort the segments, if any */
933 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
935 sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
936 for (i = 0; i < entry->count; ++i) {
937 sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx),
938 i_DFc(entry->segs[i].x_limit));
940 sv_catpv(dump, "\n");
950 i_sv_off_t(pTHX_ SV *sv) {
951 #if LSEEKSIZE > IVSIZE
952 return (off_t)SvNV(sv);
954 return (off_t)SvIV(sv);
959 i_new_sv_off_t(pTHX_ off_t off) {
960 #if LSEEKSIZE > IVSIZE
967 static im_pl_ext_funcs im_perl_funcs =
969 IMAGER_PL_API_VERSION,
971 ip_handle_quant_opts,
972 ip_cleanup_quant_opts,
976 #define PERL_PL_SET_GLOBAL_CALLBACKS \
977 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
979 #define IIM_new i_img_8_new
980 #define IIM_DESTROY i_img_destroy
984 #define i_exif_enabled() 1
986 #define i_exif_enabled() 0
989 /* trying to use more C style names, map them here */
990 #define i_io_DESTROY(ig) io_glue_destroy(ig)
992 #define i_img_get_width(im) ((im)->xsize)
993 #define i_img_get_height(im) ((im)->ysize)
995 #define i_img_epsilonf() (DBL_EPSILON * 4)
997 /* avoid some xsubpp strangeness */
1000 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
1003 ICL_new_internal(r,g,b,a)
1015 ICL_set_internal(cl,r,g,b,a)
1022 ICL_set_internal(cl, r, g, b, a);
1036 PUSHs(sv_2mortal(newSViv(cl->rgba.r)));
1037 PUSHs(sv_2mortal(newSViv(cl->rgba.g)));
1038 PUSHs(sv_2mortal(newSViv(cl->rgba.b)));
1039 PUSHs(sv_2mortal(newSViv(cl->rgba.a)));
1045 RETVAL = mymalloc(sizeof(i_color));
1047 i_hsv_to_rgb(RETVAL);
1055 RETVAL = mymalloc(sizeof(i_color));
1057 i_rgb_to_hsv(RETVAL);
1063 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
1065 Imager::Color::Float
1066 ICLF_new_internal(r, g, b, a)
1074 Imager::Color::Float cl
1078 Imager::Color::Float cl
1082 EXTEND(SP, MAXCHANNELS);
1083 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1084 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1085 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1089 ICLF_set_internal(cl,r,g,b,a)
1090 Imager::Color::Float cl
1103 Imager::Color::Float
1105 Imager::Color::Float c
1107 RETVAL = mymalloc(sizeof(i_fcolor));
1109 i_hsv_to_rgbf(RETVAL);
1113 Imager::Color::Float
1115 Imager::Color::Float c
1117 RETVAL = mymalloc(sizeof(i_fcolor));
1119 i_rgb_to_hsvf(RETVAL);
1123 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1137 MODULE = Imager PACKAGE = Imager
1151 io_new_buffer(data_sv)
1155 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1162 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1168 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1176 unsigned char* data;
1180 tlength = io_slurp(ig, &data);
1181 RETVAL = newSVpv((char *)data,tlength);
1188 i_set_image_file_limits(width, height, bytes)
1194 i_get_image_file_limits()
1196 i_img_dim width, height;
1199 if (i_get_image_file_limits(&width, &height, &bytes)) {
1201 PUSHs(sv_2mortal(newSViv(width)));
1202 PUSHs(sv_2mortal(newSViv(height)));
1203 PUSHs(sv_2mortal(newSVuv(bytes)));
1207 i_int_check_image_file_limits(width, height, channels, sample_size)
1214 MODULE = Imager PACKAGE = Imager::IO PREFIX = io_
1217 io_new_fd(class, fd)
1220 RETVAL = io_new_fd(fd);
1225 io_new_buffer(class, data_sv)
1229 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1236 io_new_cb(class, writecb, readcb, seekcb, closecb)
1242 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1247 io_new_bufchain(class)
1249 RETVAL = io_new_bufchain();
1254 io__new_perlio(class, io)
1257 RETVAL = im_io_new_perlio(aTHX_ io);
1265 unsigned char* data;
1269 tlength = io_slurp(ig, &data);
1270 RETVAL = newSVpv((char *)data,tlength);
1275 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1278 i_io_raw_write(ig, data_sv)
1285 data = SvPVbyte(data_sv, size);
1286 RETVAL = i_io_raw_write(ig, data, size);
1291 i_io_raw_read(ig, buffer_sv, size)
1300 croak("size negative in call to i_io_raw_read()");
1301 if (SvTHINKFIRST(buffer_sv))
1302 sv_force_normal_flags(buffer_sv, SV_COW_DROP_PV);
1303 SvUPGRADE(buffer_sv, SVt_PV);
1304 buffer = SvGROW(buffer_sv, size+1);
1305 result = i_io_raw_read(ig, buffer, size);
1307 SvCUR_set(buffer_sv, result);
1308 *SvEND(buffer_sv) = '\0';
1309 SvPOK_only(buffer_sv);
1311 PUSHs(sv_2mortal(newSViv(result)));
1317 i_io_raw_read2(ig, size)
1326 croak("size negative in call to i_io_read2()");
1327 buffer_sv = newSV(size);
1328 buffer = SvGROW(buffer_sv, size+1);
1329 result = i_io_raw_read(ig, buffer, size);
1331 SvCUR_set(buffer_sv, result);
1332 *SvEND(buffer_sv) = '\0';
1333 SvPOK_only(buffer_sv);
1335 PUSHs(sv_2mortal(buffer_sv));
1339 SvREFCNT_dec(buffer_sv);
1343 i_io_raw_seek(ig, position, whence)
1357 i_io_CLONE_SKIP(...)
1359 (void)items; /* avoid unused warning for XS variable */
1386 i_io_seek(ig, off, whence)
1392 i_io_peekn(ig, size)
1400 buffer_sv = newSV(size+1);
1401 buffer = SvGROW(buffer_sv, size+1);
1402 result = i_io_peekn(ig, buffer, size);
1404 SvCUR_set(buffer_sv, result);
1405 *SvEND(buffer_sv) = '\0';
1406 SvPOK_only(buffer_sv);
1408 PUSHs(sv_2mortal(buffer_sv));
1412 SvREFCNT_dec(buffer_sv);
1416 i_io_read(ig, buffer_sv, size)
1425 croak("size negative in call to i_io_read()");
1426 if (SvTHINKFIRST(buffer_sv))
1427 sv_force_normal_flags(buffer_sv, SV_COW_DROP_PV);
1428 SvUPGRADE(buffer_sv, SVt_PV);
1429 buffer = SvGROW(buffer_sv, size+1);
1430 result = i_io_read(ig, buffer, size);
1432 SvCUR_set(buffer_sv, result);
1433 *SvEND(buffer_sv) = '\0';
1434 SvPOK_only(buffer_sv);
1436 PUSHs(sv_2mortal(newSViv(result)));
1442 i_io_read2(ig, size)
1451 croak("size zero in call to read2()");
1452 buffer_sv = newSV(size);
1453 buffer = SvGROW(buffer_sv, size+1);
1454 result = i_io_read(ig, buffer, size);
1456 SvCUR_set(buffer_sv, result);
1457 *SvEND(buffer_sv) = '\0';
1458 SvPOK_only(buffer_sv);
1460 PUSHs(sv_2mortal(buffer_sv));
1464 SvREFCNT_dec(buffer_sv);
1468 i_io_gets(ig, size = 8192, eol = NEWLINE)
1478 croak("size too small in call to gets()");
1479 buffer_sv = sv_2mortal(newSV(size+1));
1480 buffer = SvPVX(buffer_sv);
1481 result = i_io_gets(ig, buffer, size+1, eol);
1483 SvCUR_set(buffer_sv, result);
1484 *SvEND(buffer_sv) = '\0';
1485 SvPOK_only(buffer_sv);
1491 i_io_write(ig, data_sv)
1498 data = SvPVbyte(data_sv, size);
1499 RETVAL = i_io_write(ig, data, size);
1504 i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
1509 i_io_set_buffered(ig, flag = 1)
1514 i_io_is_buffered(ig)
1525 MODULE = Imager PACKAGE = Imager
1536 while( (item=i_format_list[i++]) != NULL ) {
1538 PUSHs(sv_2mortal(newSVpv(item,0)));
1542 i_sametype(im, x, y)
1548 i_sametype_chans(im, x, y, channels)
1555 i_init_log(name_sv,level)
1559 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1561 RETVAL = i_init_log(name, level);
1566 i_log_entry(string,level)
1579 i_img_info(im,info);
1581 PUSHs(sv_2mortal(newSViv(info[0])));
1582 PUSHs(sv_2mortal(newSViv(info[1])));
1583 PUSHs(sv_2mortal(newSViv(info[2])));
1584 PUSHs(sv_2mortal(newSViv(info[3])));
1590 i_img_setmask(im,ch_mask)
1599 i_img_getchannels(im)
1608 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1616 i_img_get_height(im)
1621 i_img_is_monochrome(im)
1627 result = i_img_is_monochrome(im, &zero_is_white);
1629 if (GIMME_V == G_ARRAY) {
1632 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1641 i_line(im,x1,y1,x2,y2,val,endp)
1651 i_line_aa(im,x1,y1,x2,y2,val,endp)
1661 i_box(im,x1,y1,x2,y2,val)
1670 i_box_filled(im,x1,y1,x2,y2,val)
1679 i_box_filledf(im,x1,y1,x2,y2,val)
1685 Imager::Color::Float val
1688 i_box_cfill(im,x1,y1,x2,y2,fill)
1694 Imager::FillHandle fill
1697 i_arc(im,x,y,rad,d1,d2,val)
1707 i_arc_aa(im,x,y,rad,d1,d2,val)
1717 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1724 Imager::FillHandle fill
1727 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1734 Imager::FillHandle fill
1738 i_circle_aa(im,x,y,rad,val)
1746 i_circle_out(im,x,y,rad,val)
1754 i_circle_out_aa(im,x,y,rad,val)
1762 i_arc_out(im,x,y,rad,d1,d2,val)
1772 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1783 i_bezier_multi(im,x,y,val)
1792 if (size_x != size_y)
1793 croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1794 i_bezier_multi(im,size_x,x,y,val);
1797 i_poly_aa(im,x,y,val)
1806 if (size_x != size_y)
1807 croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1808 RETVAL = i_poly_aa(im, size_x, x, y, val);
1813 i_poly_aa_cfill(im, x, y, fill)
1817 Imager::FillHandle fill
1822 if (size_x != size_y)
1823 croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1824 RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
1829 i_flood_fill(im,seedx,seedy,dcol)
1836 i_flood_cfill(im,seedx,seedy,fill)
1840 Imager::FillHandle fill
1843 i_flood_fill_border(im,seedx,seedy,dcol, border)
1848 Imager::Color border
1851 i_flood_cfill_border(im,seedx,seedy,fill, border)
1855 Imager::FillHandle fill
1856 Imager::Color border
1860 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1872 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1889 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1900 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1913 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)
1929 i_combine(src_av, channels_av = NULL)
1933 i_img **imgs = NULL;
1935 int *channels = NULL;
1940 in_count = av_len(src_av) + 1;
1942 imgs = mymalloc(sizeof(i_img*) * in_count);
1943 channels = mymalloc(sizeof(int) * in_count);
1944 for (i = 0; i < in_count; ++i) {
1945 psv = av_fetch(src_av, i, 0);
1946 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1949 croak("imgs must contain only images");
1951 tmp = SvIV((SV*)SvRV(*psv));
1952 imgs[i] = INT2PTR(i_img*, tmp);
1954 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1956 channels[i] = SvIV(*psv);
1963 RETVAL = i_combine(imgs, channels, in_count);
1970 i_flipxy(im, direction)
1975 i_rotate90(im, degrees)
1980 i_rotate_exact(im, amount, ...)
1984 i_color *backp = NULL;
1985 i_fcolor *fbackp = NULL;
1989 /* extract the bg colors if any */
1990 /* yes, this is kind of strange */
1991 for (i = 2; i < items; ++i) {
1993 if (sv_derived_from(sv1, "Imager::Color")) {
1994 IV tmp = SvIV((SV*)SvRV(sv1));
1995 backp = INT2PTR(i_color *, tmp);
1997 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1998 IV tmp = SvIV((SV*)SvRV(sv1));
1999 fbackp = INT2PTR(i_fcolor *, tmp);
2002 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
2007 i_matrix_transform(im, xsize, ysize, matrix_av, ...)
2017 i_color *backp = NULL;
2018 i_fcolor *fbackp = NULL;
2020 len=av_len(matrix_av)+1;
2023 for (i = 0; i < len; ++i) {
2024 sv1=(*(av_fetch(matrix_av,i,0)));
2025 matrix[i] = SvNV(sv1);
2029 /* extract the bg colors if any */
2030 /* yes, this is kind of strange */
2031 for (i = 4; i < items; ++i) {
2033 if (sv_derived_from(sv1, "Imager::Color")) {
2034 IV tmp = SvIV((SV*)SvRV(sv1));
2035 backp = INT2PTR(i_color *, tmp);
2037 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2038 IV tmp = SvIV((SV*)SvRV(sv1));
2039 fbackp = INT2PTR(i_fcolor *, tmp);
2042 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2047 i_gaussian(im,stdev)
2052 i_unsharp_mask(im,stdev,scale)
2067 len = av_len(coef) + 1;
2068 c_coef=mymalloc( len * sizeof(double) );
2069 for(i = 0; i < len; i++) {
2070 sv1 = (*(av_fetch(coef, i, 0)));
2071 c_coef[i] = (double)SvNV(sv1);
2073 RETVAL = i_conv(im, c_coef, len);
2079 i_convert(src, avmain)
2091 outchan = av_len(avmain)+1;
2092 /* find the biggest */
2094 for (j=0; j < outchan; ++j) {
2095 temp = av_fetch(avmain, j, 0);
2096 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2097 avsub = (AV*)SvRV(*temp);
2098 len = av_len(avsub)+1;
2103 i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2107 coeff = mymalloc(sizeof(double) * outchan * inchan);
2108 for (j = 0; j < outchan; ++j) {
2109 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2110 len = av_len(avsub)+1;
2111 for (i = 0; i < len; ++i) {
2112 temp = av_fetch(avsub, i, 0);
2114 coeff[i+j*inchan] = SvNV(*temp);
2116 coeff[i+j*inchan] = 0;
2119 coeff[i++ + j*inchan] = 0;
2121 RETVAL = i_convert(src, coeff, outchan, inchan);
2132 unsigned int mask = 0;
2137 unsigned char (*maps)[256];
2139 len = av_len(pmaps_av)+1;
2140 if (im->channels < len)
2142 maps = mymalloc( len * sizeof(unsigned char [256]) );
2143 for (j=0; j<len ; j++) {
2144 temp = av_fetch(pmaps_av, j, 0);
2145 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2146 avsub = (AV*)SvRV(*temp);
2147 if(av_len(avsub) != 255)
2150 for (i=0; i<256 ; i++) {
2152 temp = av_fetch(avsub, i, 0);
2153 val = temp ? SvIV(*temp) : 0;
2155 if (val>255) val = 255;
2160 i_map(im, maps, mask);
2172 i_img_diffd(im1,im2)
2177 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2187 _is_color_object(sv)
2191 RETVAL = SvOK(sv) && SvROK(sv) &&
2192 (sv_derived_from(sv, "Imager::Color")
2193 || sv_derived_from(sv, "Imager::Color::Float"));
2205 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2207 #define TT_DESTROY(handle) i_tt_destroy(handle)
2211 Imager::Font::TT handle
2216 (void)items; /* avoid unused warning */
2222 MODULE = Imager PACKAGE = Imager
2226 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
2227 Imager::Font::TT handle
2241 str = SvPV(str_sv, len);
2246 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2247 len, smooth, utf8, align);
2253 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
2254 Imager::Font::TT handle
2268 str = SvPV(str_sv, len);
2273 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2274 smooth, utf8, align);
2280 i_tt_bbox(handle,point,str_sv,utf8)
2281 Imager::Font::TT handle
2286 i_img_dim cords[BOUNDING_BOX_COUNT];
2292 str = SvPV(str_sv, len);
2297 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2299 for (i = 0; i < rc; ++i) {
2300 PUSHs(sv_2mortal(newSViv(cords[i])));
2305 i_tt_has_chars(handle, text_sv, utf8)
2306 Imager::Font::TT handle
2317 text = SvPV(text_sv, len);
2319 if (SvUTF8(text_sv))
2322 work = mymalloc(len);
2323 count = i_tt_has_chars(handle, text, len, utf8, work);
2324 if (GIMME_V == G_ARRAY) {
2326 for (i = 0; i < count; ++i) {
2327 PUSHs(boolSV(work[i]));
2332 PUSHs(sv_2mortal(newSVpv(work, count)));
2337 i_tt_dump_names(handle)
2338 Imager::Font::TT handle
2341 i_tt_face_name(handle)
2342 Imager::Font::TT handle
2347 len = i_tt_face_name(handle, name, sizeof(name));
2350 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2354 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2355 Imager::Font::TT handle
2367 text = SvPV(text_sv, work_len);
2369 if (SvUTF8(text_sv))
2376 ch = i_utf8_advance(&text, &len);
2378 i_push_error(0, "invalid UTF8 character");
2386 EXTEND(SP, count+1);
2387 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2388 ST(count) = sv_2mortal(newSVpv(name, 0));
2391 ST(count) = &PL_sv_undef;
2400 i_test_format_probe(ig, length)
2405 i_readpnm_wiol(ig, allow_incomplete)
2407 int allow_incomplete
2411 i_readpnm_multi_wiol(ig, allow_incomplete)
2413 int allow_incomplete
2419 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2422 for (i = 0; i < count; ++i) {
2423 SV *sv = sv_newmortal();
2424 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2431 i_writeppm_wiol(im, ig)
2440 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2449 i_writeraw_wiol(im,ig)
2454 i_writebmp_wiol(im,ig)
2459 i_readbmp_wiol(ig, allow_incomplete=0)
2461 int allow_incomplete
2465 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2474 idlen = SvCUR(ST(4));
2475 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2481 i_readtga_wiol(ig, length)
2489 i_scaleaxis(im,Value,Axis)
2495 i_scale_nn(im,scx,scy)
2501 i_scale_mixing(im, width, height)
2511 i_count_colors(im,maxc)
2516 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2521 unsigned int * col_usage = NULL;
2524 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2525 EXTEND(SP, col_cnt);
2526 for (i = 0; i < col_cnt; i++) {
2527 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2534 i_transform(im, opx, opy, parm)
2540 STRLEN size_opx, size_opy, size_parm;
2543 result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
2545 SV *result_sv = sv_newmortal();
2547 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2552 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2578 in_imgs_count = av_len(av_in_imgs)+1;
2579 for (i = 0; i < in_imgs_count; ++i) {
2580 sv1 = *av_fetch(av_in_imgs, i, 0);
2581 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2582 croak("sv_in_img must contain only images");
2585 if (in_imgs_count > 0) {
2586 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2587 for (i = 0; i < in_imgs_count; ++i) {
2588 sv1 = *av_fetch(av_in_imgs,i,0);
2589 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2590 croak("Parameter 5 must contain only images");
2592 tmp = SvIV((SV*)SvRV(sv1));
2593 in_imgs[i] = INT2PTR(i_img*, tmp);
2597 /* no input images */
2600 /* default the output size from the first input if possible */
2602 width = SvIV(sv_width);
2603 else if (in_imgs_count)
2604 width = in_imgs[0]->xsize;
2606 croak("No output image width supplied");
2608 if (SvOK(sv_height))
2609 height = SvIV(sv_height);
2610 else if (in_imgs_count)
2611 height = in_imgs[0]->ysize;
2613 croak("No output image height supplied");
2615 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2616 if (ops_len % sizeof(struct rm_op))
2617 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2618 ops_count = ops_len / sizeof(struct rm_op);
2620 n_regs_count = av_len(av_n_regs)+1;
2621 n_regs = mymalloc(n_regs_count * sizeof(double));
2622 for (i = 0; i < n_regs_count; ++i) {
2623 sv1 = *av_fetch(av_n_regs,i,0);
2625 n_regs[i] = SvNV(sv1);
2627 c_regs_count = av_len(av_c_regs)+1;
2628 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2629 /* I don't bother initializing the colou?r registers */
2631 result=i_transform2(width, height, channels, ops, ops_count,
2632 n_regs, n_regs_count,
2633 c_regs, c_regs_count, in_imgs, in_imgs_count);
2639 SV *result_sv = sv_newmortal();
2641 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2647 i_contrast(im,intensity)
2660 i_noise(im,amount,type)
2666 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2676 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2695 i_postlevels(im,levels)
2705 i_watermark(im,wmark,tx,ty,pixdiff)
2707 Imager::ImgRaw wmark
2714 i_autolevels(im,lsat,usat,skew)
2721 i_autolevels_mono(im,lsat,usat)
2727 i_radnoise(im,xo,yo,rscale,ascale)
2735 i_turbnoise(im, xo, yo, scale)
2743 i_gradgen(im, xo, yo, ac, dmeasure)
2754 if (size_xo != size_yo || size_xo != size_ac)
2755 croak("i_gradgen: x, y and color arrays must be the same size");
2757 croak("Usage: i_gradgen array refs must have more than 1 entry each");
2758 i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
2761 i_diff_image(im, im2, mindist=0)
2767 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2777 double ssample_param
2781 i_fountain_seg *segs;
2783 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2784 croak("i_fountain: argument 11 must be an array ref");
2786 asegs = (AV *)SvRV(ST(10));
2787 segs = load_fount_segs(aTHX_ asegs, &count);
2788 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2789 super_sample, ssample_param, count, segs);
2795 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2804 double ssample_param
2808 i_fountain_seg *segs;
2810 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2811 croak("i_fountain: argument 11 must be an array ref");
2813 asegs = (AV *)SvRV(ST(9));
2814 segs = load_fount_segs(aTHX_ asegs, &count);
2815 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2816 super_sample, ssample_param, count, segs);
2822 i_new_fill_opacity(other_fill, alpha_mult)
2823 Imager::FillHandle other_fill
2834 errors = i_errors();
2836 while (errors[i].msg) {
2838 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2839 if (!av_store(av, 0, sv)) {
2842 sv = newSViv(errors[i].code);
2843 if (!av_store(av, 1, sv)) {
2846 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2854 i_push_error(code, msg)
2859 i_nearest_color(im, ...)
2874 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2875 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2876 croak("i_nearest_color: Second argument must be an array ref");
2877 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2878 croak("i_nearest_color: Third argument must be an array ref");
2879 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2880 croak("i_nearest_color: Fourth argument must be an array ref");
2881 axx = (AV *)SvRV(ST(1));
2882 ayy = (AV *)SvRV(ST(2));
2883 ac = (AV *)SvRV(ST(3));
2884 dmeasure = (int)SvIV(ST(4));
2886 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2887 num = num <= av_len(ac) ? num : av_len(ac);
2889 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2890 xo = mymalloc( sizeof(i_img_dim) * num );
2891 yo = mymalloc( sizeof(i_img_dim) * num );
2892 ival = mymalloc( sizeof(i_color) * num );
2893 for(i = 0; i<num; i++) {
2894 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2895 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2896 sv = *av_fetch(ac, i, 0);
2897 if ( !sv_derived_from(sv, "Imager::Color") ) {
2898 free(axx); free(ayy); free(ac);
2899 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2901 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2903 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2917 rc=DSO_open(filename,&evstr);
2921 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2922 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2925 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2931 DSO_close(dso_handle)
2935 DSO_funclist(dso_handle_v)
2939 DSO_handle *dso_handle;
2940 func_ptr *functions;
2942 dso_handle=(DSO_handle*)dso_handle_v;
2943 functions = DSO_funclist(dso_handle);
2945 while( functions[i].name != NULL) {
2947 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2949 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2953 DSO_call(handle,func_index,hv)
2958 DSO_call( (DSO_handle *)handle,func_index,hv);
2961 i_get_pixel(im, x, y)
2966 RETVAL = (i_color *)mymalloc(sizeof(i_color));
2967 if (i_gpix(im, x, y, RETVAL) != 0) {
2976 i_ppix(im, x, y, cl)
2983 i_img_pal_new(x, y, channels, maxpal)
2990 i_img_to_pal(src, quant)
2996 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2997 croak("i_img_to_pal: second argument must be a hash ref");
2998 hv = (HV *)SvRV(ST(1));
2999 memset(&quant, 0, sizeof(quant));
3001 quant.mc_size = 256;
3002 ip_handle_quant_opts(aTHX_ &quant, hv);
3003 RETVAL = i_img_to_pal(src, &quant);
3005 ip_copy_colors_back(aTHX_ hv, &quant);
3007 ip_cleanup_quant_opts(aTHX_ &quant);
3016 i_img_make_palette(HV *quant_hv, ...)
3018 size_t count = items - 1;
3020 i_img **imgs = NULL;
3024 croak("Please supply at least one image (%d)", (int)count);
3025 imgs = mymalloc(sizeof(i_img *) * count);
3026 for (i = 0; i < count; ++i) {
3027 SV *img_sv = ST(i + 1);
3028 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3029 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3033 croak("Image %d is not an image object", (int)i+1);
3036 memset(&quant, 0, sizeof(quant));
3038 quant.mc_size = 256;
3039 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3040 i_quant_makemap(&quant, imgs, count);
3041 EXTEND(SP, quant.mc_count);
3042 for (i = 0; i < quant.mc_count; ++i) {
3043 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3046 ip_cleanup_quant_opts(aTHX_ &quant);
3060 work = mymalloc((r-l) * sizeof(i_palidx));
3061 count = i_gpal(im, l, r, y, work);
3062 if (GIMME_V == G_ARRAY) {
3064 for (i = 0; i < count; ++i) {
3065 PUSHs(sv_2mortal(newSViv(work[i])));
3070 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3075 if (GIMME_V != G_ARRAY) {
3077 PUSHs(&PL_sv_undef);
3082 i_ppal(im, l, y, ...)
3091 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3092 for (i=0; i < items-3; ++i) {
3093 work[i] = SvIV(ST(i+3));
3095 validate_i_ppal(im, work, items - 3);
3096 RETVAL = i_ppal(im, l, l+items-3, y, work);
3105 i_ppal_p(im, l, y, data)
3111 i_palidx const *work;
3114 work = (i_palidx const *)SvPV(data, len);
3115 len /= sizeof(i_palidx);
3117 validate_i_ppal(im, work, len);
3118 RETVAL = i_ppal(im, l, l+len, y, work);
3127 i_addcolors(im, ...)
3134 croak("i_addcolors: no colors to add");
3135 colors = mymalloc((items-1) * sizeof(i_color));
3136 for (i=0; i < items-1; ++i) {
3137 if (sv_isobject(ST(i+1))
3138 && sv_derived_from(ST(i+1), "Imager::Color")) {
3139 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3140 colors[i] = *INT2PTR(i_color *, tmp);
3144 croak("i_addcolor: pixels must be Imager::Color objects");
3147 RETVAL = i_addcolors(im, colors, items-1);
3152 i_setcolors(im, index, ...)
3160 croak("i_setcolors: no colors to add");
3161 colors = mymalloc((items-2) * sizeof(i_color));
3162 for (i=0; i < items-2; ++i) {
3163 if (sv_isobject(ST(i+2))
3164 && sv_derived_from(ST(i+2), "Imager::Color")) {
3165 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3166 colors[i] = *INT2PTR(i_color *, tmp);
3170 croak("i_setcolors: pixels must be Imager::Color objects");
3173 RETVAL = i_setcolors(im, index, colors, items-2);
3179 i_getcolors(im, index, count=1)
3188 croak("i_getcolors: count must be positive");
3189 colors = malloc_temp(aTHX_ sizeof(i_color) * count);
3190 if (i_getcolors(im, index, colors, count)) {
3192 for (i = 0; i < count; ++i) {
3193 SV *sv = make_i_color_sv(aTHX_ colors+i);
3207 i_findcolor(im, color)
3211 if (!i_findcolor(im, color, &RETVAL)) {
3230 i_gsamp(im, l, r, y, channels)
3235 i_channel_list channels
3241 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count);
3242 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3243 if (GIMME_V == G_ARRAY) {
3245 for (i = 0; i < count; ++i)
3246 PUSHs(sv_2mortal(newSViv(data[i])));
3250 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3255 if (GIMME_V != G_ARRAY) {
3261 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3269 i_channel_list channels
3276 croak("No channel numbers supplied to g_samp()");
3278 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3279 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3280 for (i = 0; i < count; ++i) {
3281 av_store(target, i+offset, newSVuv(data[i]));
3293 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3298 i_channel_list channels
3300 i_img_dim data_offset
3301 i_img_dim pixel_count
3310 data_count = av_len(data_av) + 1;
3311 if (data_offset < 0) {
3312 croak("data_offset must be non-negative");
3314 if (data_offset > data_count) {
3315 croak("data_offset greater than number of samples supplied");
3317 if (pixel_count == -1 ||
3318 data_offset + pixel_count * channels.count > data_count) {
3319 pixel_count = (data_count - data_offset) / channels.count;
3322 data_used = pixel_count * channels.count;
3323 data = mymalloc(sizeof(unsigned) * data_count);
3324 for (i = 0; i < data_used; ++i)
3325 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3327 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3328 channels.count, bits);
3336 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3340 i_channel_list channels
3349 i_push_error(0, "offset must be non-negative");
3353 if (offset > data.count) {
3354 i_push_error(0, "offset greater than number of samples supplied");
3357 data.samples += offset;
3358 data.count -= offset;
3361 width * channels.count > data.count) {
3362 width = data.count / channels.count;
3365 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3370 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3374 i_channel_list channels
3383 i_push_error(0, "offset must be non-negative");
3387 if (offset > data.count) {
3388 i_push_error(0, "offset greater than number of samples supplied");
3391 data.samples += offset;
3392 data.count -= offset;
3395 width * channels.count > data.count) {
3396 width = data.count / channels.count;
3399 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3404 i_img_masked_new(targ, mask, x, y, w, h)
3414 if (!sv_isobject(ST(1))
3415 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3416 croak("i_img_masked_new: parameter 2 must undef or an image");
3418 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3422 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3427 i_plin(im, l, y, ...)
3438 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3439 /* supplied as a byte string */
3440 work = (i_color *)SvPV(ST(3), len);
3441 count = len / sizeof(i_color);
3442 if (count * sizeof(i_color) != len) {
3443 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3445 RETVAL = i_plin(im, l, l+count, y, work);
3448 work = mymalloc(sizeof(i_color) * (items-3));
3449 for (i=0; i < items-3; ++i) {
3450 if (sv_isobject(ST(i+3))
3451 && sv_derived_from(ST(i+3), "Imager::Color")) {
3452 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3453 work[i] = *INT2PTR(i_color *, tmp);
3457 croak("i_plin: pixels must be Imager::Color objects");
3460 RETVAL = i_plin(im, l, l+items-3, y, work);
3471 i_ppixf(im, x, y, cl)
3475 Imager::Color::Float cl
3478 i_gsampf(im, l, r, y, channels)
3483 i_channel_list channels
3489 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3490 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3491 if (GIMME_V == G_ARRAY) {
3493 for (i = 0; i < count; ++i)
3494 PUSHs(sv_2mortal(newSVnv(data[i])));
3498 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3503 if (GIMME_V != G_ARRAY) {
3509 i_plinf(im, l, y, ...)
3520 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3521 /* supplied as a byte string */
3522 work = (i_fcolor *)SvPV(ST(3), len);
3523 count = len / sizeof(i_fcolor);
3524 if (count * sizeof(i_fcolor) != len) {
3525 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3527 RETVAL = i_plinf(im, l, l+count, y, work);
3530 work = mymalloc(sizeof(i_fcolor) * (items-3));
3531 for (i=0; i < items-3; ++i) {
3532 if (sv_isobject(ST(i+3))
3533 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3534 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3535 work[i] = *INT2PTR(i_fcolor *, tmp);
3539 croak("i_plinf: pixels must be Imager::Color::Float objects");
3543 RETVAL = i_plinf(im, l, l+items-3, y, work);
3553 Imager::Color::Float
3559 RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3560 if (i_gpixf(im, x, y, RETVAL) != 0) {
3578 vals = mymalloc((r-l) * sizeof(i_color));
3579 memset(vals, 0, (r-l) * sizeof(i_color));
3580 count = i_glin(im, l, r, y, vals);
3581 if (GIMME_V == G_ARRAY) {
3583 for (i = 0; i < count; ++i) {
3584 SV *sv = make_i_color_sv(aTHX_ vals+i);
3590 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3596 i_glinf(im, l, r, y)
3606 for (i = 0; i < MAXCHANNELS; ++i)
3607 zero.channel[i] = 0;
3609 vals = mymalloc((r-l) * sizeof(i_fcolor));
3610 for (i = 0; i < r-l; ++i)
3612 count = i_glinf(im, l, r, y, vals);
3613 if (GIMME_V == G_ARRAY) {
3615 for (i = 0; i < count; ++i) {
3617 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3619 sv = sv_newmortal();
3620 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3626 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3632 i_img_8_new(x, y, ch)
3638 i_img_16_new(x, y, ch)
3648 i_img_double_new(x, y, ch)
3658 i_tags_addn(im, name_sv, code, idata)
3667 SvGETMAGIC(name_sv);
3669 name = SvPV_nomg(name_sv, len);
3672 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3677 i_tags_add(im, name_sv, code, data_sv, idata)
3688 SvGETMAGIC(name_sv);
3690 name = SvPV_nomg(name_sv, len);
3693 SvGETMAGIC(data_sv);
3695 data = SvPV(data_sv, len);
3700 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3705 i_tags_find(im, name, start)
3712 if (i_tags_find(&im->tags, name, start, &entry)) {
3721 i_tags_findn(im, code, start)
3728 if (i_tags_findn(&im->tags, code, start, &entry)) {
3738 i_tags_delete(im, entry)
3742 RETVAL = i_tags_delete(&im->tags, entry);
3747 i_tags_delbyname(im, name)
3751 RETVAL = i_tags_delbyname(&im->tags, name);
3756 i_tags_delbycode(im, code)
3760 RETVAL = i_tags_delbycode(&im->tags, code);
3765 i_tags_get(im, index)
3769 if (index >= 0 && index < im->tags.count) {
3770 i_img_tag *entry = im->tags.tags + index;
3774 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3777 PUSHs(sv_2mortal(newSViv(entry->code)));
3780 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3783 PUSHs(sv_2mortal(newSViv(entry->idata)));
3788 i_tags_get_string(im, what_sv)
3792 char const *name = NULL;
3796 if (SvIOK(what_sv)) {
3797 code = SvIV(what_sv);
3801 name = SvPV_nolen(what_sv);
3804 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3806 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3813 RETVAL = im->tags.count;
3819 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3823 Imager::FillHandle fill
3826 IFILL_CLONE_SKIP(...)
3828 (void)items; /* avoid unused warning for XS variable */
3833 MODULE = Imager PACKAGE = Imager
3836 i_new_fill_solid(cl, combine)
3841 i_new_fill_solidf(cl, combine)
3842 Imager::Color::Float cl
3846 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3855 unsigned char *cust_hatch;
3858 SvGETMAGIC(cust_hatch_sv);
3859 if (SvOK(cust_hatch_sv)) {
3860 cust_hatch = (unsigned char *)SvPV_nomg(cust_hatch_sv, len);
3864 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3869 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3870 Imager::Color::Float fg
3871 Imager::Color::Float bg
3878 unsigned char *cust_hatch;
3881 SvGETMAGIC(cust_hatch_sv);
3882 if (SvOK(cust_hatch_sv)) {
3883 cust_hatch = (unsigned char *)SvPV(cust_hatch_sv, len);
3887 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3892 i_new_fill_image(src, matrix_sv, xoff, yoff, combine)
3906 SvGETMAGIC(matrix_sv);
3907 if (!SvOK(matrix_sv)) {
3911 if (!SvROK(matrix_sv) || SvTYPE(SvRV(matrix_sv)) != SVt_PVAV)
3912 croak("i_new_fill_image: matrix parameter must be an arrayref or undef");
3913 av=(AV*)SvRV(matrix_sv);
3917 for (i = 0; i < len; ++i) {
3918 sv1=(*(av_fetch(av,i,0)));
3919 matrix[i] = SvNV(sv1);
3925 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3929 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3931 # this class is only exposed for testing
3934 i_int_hlines_testing()
3936 #if i_int_hlines_testing()
3938 Imager::Internal::Hlines
3939 i_int_hlines_new(start_y, count_y, start_x, count_x)
3945 Imager::Internal::Hlines
3946 i_int_hlines_new_img(im)
3950 i_int_hlines_add(hlines, y, minx, width)
3951 Imager::Internal::Hlines hlines
3957 i_int_hlines_DESTROY(hlines)
3958 Imager::Internal::Hlines hlines
3961 i_int_hlines_dump(hlines)
3962 Imager::Internal::Hlines hlines
3965 i_int_hlines_CLONE_SKIP(cls)
3969 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
3972 im_context_DESTROY(ctx)
3975 #ifdef PERL_IMPLICIT_CONTEXT
3978 im_context_CLONE(...)
3982 /* the following sv_setref_pv() will free this inc */
3983 im_context_refinc(MY_CXT.ctx, "CLONE");
3984 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
3985 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
3990 PERL_SET_GLOBAL_CALLBACKS;
3991 PERL_PL_SET_GLOBAL_CALLBACKS;
3992 #ifdef PERL_IMPLICIT_CONTEXT
3998 start_context(aTHX);
3999 im_get_context = perl_get_context;