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
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);
457 return type == SVt_PV || type == SVt_PVIV || type == SVt_PVNV
458 || type == SVt_PVMG || type == SVt_IV || type == SVt_NV
459 || type == SVt_PVLV || type == SVt_REGEXP;
463 do_io_new_buffer(pTHX_ SV *data_sv) {
470 if (SvROK(data_sv)) {
471 if (im_SvREFSCALAR(data_sv)) {
475 i_push_error(0, "data is not a scalar or a reference to scalar");
483 /* previously this would keep the SV around, but this is unsafe in
484 many ways, so always copy the bytes */
485 data = SvPVbyte(sv, length);
486 data_copy = mymalloc(length);
487 memcpy(data_copy, data, length);
488 return io_new_buffer(data_copy, length, free_buffer, data_copy);
492 describe_sv(SV *sv) {
495 svtype type = SvTYPE(SvRV(sv));
497 case SVt_PVCV: return "CV";
498 case SVt_PVGV: return "GV";
499 case SVt_PVLV: return "LV";
500 default: return "some reference";
504 return "non-reference scalar";
513 do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) {
516 cbd = mymalloc(sizeof(struct cbdata));
517 cbd->writecb = newSVsv(writecb);
518 cbd->readcb = newSVsv(readcb);
519 cbd->seekcb = newSVsv(seekcb);
520 cbd->closecb = newSVsv(closecb);
522 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)));
524 return io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
532 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
535 for (i = 0; i < count; ++i)
536 if (strEQ(names[i].name, name))
537 return names[i].value;
541 static struct value_name transp_names[] =
544 { "threshold", tr_threshold },
545 { "errdiff", tr_errdiff },
546 { "ordered", tr_ordered, },
549 static struct value_name make_color_names[] =
551 { "none", mc_none, },
552 { "webmap", mc_web_map, },
553 { "addi", mc_addi, },
554 { "mediancut", mc_median_cut, },
555 { "mono", mc_mono, },
556 { "monochrome", mc_mono, },
557 { "gray", mc_gray, },
558 { "gray4", mc_gray4, },
559 { "gray16", mc_gray16, },
562 static struct value_name translate_names[] =
564 { "giflib", pt_giflib, },
565 { "closest", pt_closest, },
566 { "perturb", pt_perturb, },
567 { "errdiff", pt_errdiff, },
570 static struct value_name errdiff_names[] =
572 { "floyd", ed_floyd, },
573 { "jarvis", ed_jarvis, },
574 { "stucki", ed_stucki, },
575 { "custom", ed_custom, },
578 static struct value_name orddith_names[] =
580 { "random", od_random, },
581 { "dot8", od_dot8, },
582 { "dot4", od_dot4, },
583 { "hline", od_hline, },
584 { "vline", od_vline, },
585 { "/line", od_slashline, },
586 { "slashline", od_slashline, },
587 { "\\line", od_backline, },
588 { "backline", od_backline, },
589 { "tiny", od_tiny, },
590 { "custom", od_custom, },
593 /* look through the hash for quantization options */
595 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
597 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
603 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
605 sv = hv_fetch(hv, "transp", 6, 0);
606 if (sv && *sv && (str = SvPV(*sv, len))) {
608 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
610 if (quant->transp != tr_none) {
611 quant->tr_threshold = 127;
612 sv = hv_fetch(hv, "tr_threshold", 12, 0);
614 quant->tr_threshold = SvIV(*sv);
616 if (quant->transp == tr_errdiff) {
617 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
618 if (sv && *sv && (str = SvPV(*sv, len)))
619 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
621 if (quant->transp == tr_ordered) {
622 quant->tr_orddith = od_tiny;
623 sv = hv_fetch(hv, "tr_orddith", 10, 0);
624 if (sv && *sv && (str = SvPV(*sv, len)))
625 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
627 if (quant->tr_orddith == od_custom) {
628 sv = hv_fetch(hv, "tr_map", 6, 0);
629 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
630 AV *av = (AV*)SvRV(*sv);
631 len = av_len(av) + 1;
632 if (len > sizeof(quant->tr_custom))
633 len = sizeof(quant->tr_custom);
634 for (i = 0; i < len; ++i) {
635 SV **sv2 = av_fetch(av, i, 0);
637 quant->tr_custom[i] = SvIV(*sv2);
640 while (i < sizeof(quant->tr_custom))
641 quant->tr_custom[i++] = 0;
646 quant->make_colors = mc_median_cut;
647 sv = hv_fetch(hv, "make_colors", 11, 0);
648 if (sv && *sv && (str = SvPV(*sv, len))) {
650 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
652 sv = hv_fetch(hv, "colors", 6, 0);
653 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
654 /* needs to be an array of Imager::Color
655 note that the caller allocates the mc_color array and sets mc_size
657 AV *av = (AV *)SvRV(*sv);
658 quant->mc_count = av_len(av)+1;
659 if (quant->mc_count > quant->mc_size)
660 quant->mc_count = quant->mc_size;
661 for (i = 0; i < quant->mc_count; ++i) {
662 SV **sv1 = av_fetch(av, i, 0);
663 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
664 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
665 quant->mc_colors[i] = *col;
669 sv = hv_fetch(hv, "max_colors", 10, 0);
672 if (i <= quant->mc_size && i >= quant->mc_count)
676 quant->translate = pt_closest;
677 sv = hv_fetch(hv, "translate", 9, 0);
678 if (sv && *sv && (str = SvPV(*sv, len))) {
679 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
681 sv = hv_fetch(hv, "errdiff", 7, 0);
682 if (sv && *sv && (str = SvPV(*sv, len))) {
683 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
685 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
686 /* get the error diffusion map */
687 sv = hv_fetch(hv, "errdiff_width", 13, 0);
689 quant->ed_width = SvIV(*sv);
690 sv = hv_fetch(hv, "errdiff_height", 14, 0);
692 quant->ed_height = SvIV(*sv);
693 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
695 quant->ed_orig = SvIV(*sv);
696 if (quant->ed_width > 0 && quant->ed_height > 0) {
698 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
699 sv = hv_fetch(hv, "errdiff_map", 11, 0);
700 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
701 AV *av = (AV*)SvRV(*sv);
702 len = av_len(av) + 1;
703 if (len > quant->ed_width * quant->ed_height)
704 len = quant->ed_width * quant->ed_height;
705 for (i = 0; i < len; ++i) {
706 SV **sv2 = av_fetch(av, i, 0);
708 quant->ed_map[i] = SvIV(*sv2);
709 sum += quant->ed_map[i];
715 myfree(quant->ed_map);
717 quant->errdiff = ed_floyd;
721 sv = hv_fetch(hv, "perturb", 7, 0);
723 quant->perturb = SvIV(*sv);
727 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
728 myfree(quant->mc_colors);
730 myfree(quant->ed_map);
733 /* copies the color map from the hv into the colors member of the HV */
735 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
741 sv = hv_fetch(hv, "colors", 6, 0);
742 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
747 av = (AV *)SvRV(*sv);
749 av_extend(av, quant->mc_count+1);
750 for (i = 0; i < quant->mc_count; ++i) {
751 i_color *in = quant->mc_colors+i;
752 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
753 work = sv_newmortal();
754 sv_setref_pv(work, "Imager::Color", (void *)c);
760 /* loads the segments of a fountain fill into an array */
761 static i_fountain_seg *
762 load_fount_segs(pTHX_ AV *asegs, int *count) {
763 /* Each element of segs must contain:
764 [ start, middle, end, c0, c1, segtype, colortrans ]
765 start, middle, end are doubles from 0 to 1
766 c0, c1 are Imager::Color::Float or Imager::Color objects
767 segtype, colortrans are ints
771 i_fountain_seg *segs;
775 *count = av_len(asegs)+1;
777 croak("i_fountain must have at least one segment");
778 segs = mymalloc(sizeof(i_fountain_seg) * *count);
779 for(i = 0; i < *count; i++) {
780 SV **sv1 = av_fetch(asegs, i, 0);
781 if (!sv1 || !*sv1 || !SvROK(*sv1)
782 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
784 croak("i_fountain: segs must be an arrayref of arrayrefs");
786 aseg = (AV *)SvRV(*sv1);
787 if (av_len(aseg) != 7-1) {
789 croak("i_fountain: a segment must have 7 members");
791 for (j = 0; j < 3; ++j) {
792 SV **sv2 = av_fetch(aseg, j, 0);
795 croak("i_fountain: XS error");
797 work[j] = SvNV(*sv2);
799 segs[i].start = work[0];
800 segs[i].middle = work[1];
801 segs[i].end = work[2];
802 for (j = 0; j < 2; ++j) {
803 SV **sv3 = av_fetch(aseg, 3+j, 0);
804 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
805 (!sv_derived_from(*sv3, "Imager::Color")
806 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
808 croak("i_fountain: segs must contain colors in elements 3 and 4");
810 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
811 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
814 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
816 for (ch = 0; ch < MAXCHANNELS; ++ch) {
817 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
821 for (j = 0; j < 2; ++j) {
822 SV **sv2 = av_fetch(aseg, j+5, 0);
825 croak("i_fountain: XS error");
827 worki[j] = SvIV(*sv2);
829 segs[i].type = worki[0];
830 segs[i].color = worki[1];
836 /* validates the indexes supplied to i_ppal
838 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
843 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
844 int color_count = i_colorcount(im);
847 if (color_count == -1)
848 croak("i_plin() called on direct color image");
850 for (i = 0; i < count; ++i) {
851 if (indexes[i] >= color_count) {
852 croak("i_plin() called with out of range color index %d (max %d)",
853 indexes[i], color_count-1);
858 /* I don't think ICLF_* names belong at the C interface
859 this makes the XS code think we have them, to let us avoid
860 putting function bodies in the XS code
862 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
863 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
866 #define i_log_enabled() 1
868 #define i_log_enabled() 0
871 #if i_int_hlines_testing()
873 typedef i_int_hlines *Imager__Internal__Hlines;
875 static i_int_hlines *
876 i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
877 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
878 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
883 static i_int_hlines *
884 i_int_hlines_new_img(i_img *im) {
885 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
886 i_int_init_hlines_img(result, im);
892 i_int_hlines_DESTROY(i_int_hlines *hlines) {
893 i_int_hlines_destroy(hlines);
897 #define i_int_hlines_CLONE_SKIP(cls) 1
899 static int seg_compare(const void *vleft, const void *vright) {
900 const i_int_hline_seg *left = vleft;
901 const i_int_hline_seg *right = vright;
903 return left->minx - right->minx;
907 i_int_hlines_dump(i_int_hlines *hlines) {
909 SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
910 i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
913 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
914 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
917 /* sort the segments, if any */
919 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
921 sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
922 for (i = 0; i < entry->count; ++i) {
923 sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx),
924 i_DFc(entry->segs[i].x_limit));
926 sv_catpv(dump, "\n");
936 i_sv_off_t(pTHX_ SV *sv) {
937 #if LSEEKSIZE > IVSIZE
938 return (off_t)SvNV(sv);
940 return (off_t)SvIV(sv);
945 i_new_sv_off_t(pTHX_ off_t off) {
946 #if LSEEKSIZE > IVSIZE
953 static im_pl_ext_funcs im_perl_funcs =
955 IMAGER_PL_API_VERSION,
957 ip_handle_quant_opts,
958 ip_cleanup_quant_opts,
962 #define PERL_PL_SET_GLOBAL_CALLBACKS \
963 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
965 #define IIM_new i_img_8_new
966 #define IIM_DESTROY i_img_destroy
970 #define i_exif_enabled() 1
972 #define i_exif_enabled() 0
975 /* trying to use more C style names, map them here */
976 #define i_io_DESTROY(ig) io_glue_destroy(ig)
978 #define i_img_get_width(im) ((im)->xsize)
979 #define i_img_get_height(im) ((im)->ysize)
981 #define i_img_epsilonf() (DBL_EPSILON * 4)
983 /* avoid some xsubpp strangeness */
986 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
989 ICL_new_internal(r,g,b,a)
1001 ICL_set_internal(cl,r,g,b,a)
1008 ICL_set_internal(cl, r, g, b, a);
1022 PUSHs(sv_2mortal(newSViv(cl->rgba.r)));
1023 PUSHs(sv_2mortal(newSViv(cl->rgba.g)));
1024 PUSHs(sv_2mortal(newSViv(cl->rgba.b)));
1025 PUSHs(sv_2mortal(newSViv(cl->rgba.a)));
1031 RETVAL = mymalloc(sizeof(i_color));
1033 i_hsv_to_rgb(RETVAL);
1041 RETVAL = mymalloc(sizeof(i_color));
1043 i_rgb_to_hsv(RETVAL);
1049 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
1051 Imager::Color::Float
1052 ICLF_new_internal(r, g, b, a)
1060 Imager::Color::Float cl
1064 Imager::Color::Float cl
1068 EXTEND(SP, MAXCHANNELS);
1069 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1070 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1071 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1075 ICLF_set_internal(cl,r,g,b,a)
1076 Imager::Color::Float cl
1089 Imager::Color::Float
1091 Imager::Color::Float c
1093 RETVAL = mymalloc(sizeof(i_fcolor));
1095 i_hsv_to_rgbf(RETVAL);
1099 Imager::Color::Float
1101 Imager::Color::Float c
1103 RETVAL = mymalloc(sizeof(i_fcolor));
1105 i_rgb_to_hsvf(RETVAL);
1109 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1123 MODULE = Imager PACKAGE = Imager
1137 io_new_buffer(data_sv)
1141 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1148 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1154 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1162 unsigned char* data;
1166 tlength = io_slurp(ig, &data);
1167 RETVAL = newSVpv((char *)data,tlength);
1174 i_set_image_file_limits(width, height, bytes)
1180 i_get_image_file_limits()
1182 i_img_dim width, height;
1185 if (i_get_image_file_limits(&width, &height, &bytes)) {
1187 PUSHs(sv_2mortal(newSViv(width)));
1188 PUSHs(sv_2mortal(newSViv(height)));
1189 PUSHs(sv_2mortal(newSVuv(bytes)));
1193 i_int_check_image_file_limits(width, height, channels, sample_size)
1200 MODULE = Imager PACKAGE = Imager::IO PREFIX = io_
1203 io_new_fd(class, fd)
1206 RETVAL = io_new_fd(fd);
1211 io_new_buffer(class, data_sv)
1215 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1222 io_new_cb(class, writecb, readcb, seekcb, closecb)
1228 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1233 io_new_bufchain(class)
1235 RETVAL = io_new_bufchain();
1240 io__new_perlio(class, io)
1243 RETVAL = im_io_new_perlio(aTHX_ io);
1251 unsigned char* data;
1255 tlength = io_slurp(ig, &data);
1256 RETVAL = newSVpv((char *)data,tlength);
1261 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1264 i_io_raw_write(ig, data_sv)
1271 data = SvPVbyte(data_sv, size);
1272 RETVAL = i_io_raw_write(ig, data, size);
1277 i_io_raw_read(ig, buffer_sv, size)
1286 croak("size negative in call to i_io_raw_read()");
1287 if (SvTHINKFIRST(buffer_sv))
1288 sv_force_normal_flags(buffer_sv, SV_COW_DROP_PV);
1289 SvUPGRADE(buffer_sv, SVt_PV);
1290 buffer = SvGROW(buffer_sv, size+1);
1291 result = i_io_raw_read(ig, buffer, size);
1293 SvCUR_set(buffer_sv, result);
1294 *SvEND(buffer_sv) = '\0';
1295 SvPOK_only(buffer_sv);
1297 PUSHs(sv_2mortal(newSViv(result)));
1303 i_io_raw_read2(ig, size)
1312 croak("size negative in call to i_io_read2()");
1313 buffer_sv = newSV(size);
1314 buffer = SvGROW(buffer_sv, size+1);
1315 result = i_io_raw_read(ig, buffer, size);
1317 SvCUR_set(buffer_sv, result);
1318 *SvEND(buffer_sv) = '\0';
1319 SvPOK_only(buffer_sv);
1321 PUSHs(sv_2mortal(buffer_sv));
1325 SvREFCNT_dec(buffer_sv);
1329 i_io_raw_seek(ig, position, whence)
1343 i_io_CLONE_SKIP(...)
1345 (void)items; /* avoid unused warning for XS variable */
1372 i_io_seek(ig, off, whence)
1378 i_io_peekn(ig, size)
1386 buffer_sv = newSV(size+1);
1387 buffer = SvGROW(buffer_sv, size+1);
1388 result = i_io_peekn(ig, buffer, size);
1390 SvCUR_set(buffer_sv, result);
1391 *SvEND(buffer_sv) = '\0';
1392 SvPOK_only(buffer_sv);
1394 PUSHs(sv_2mortal(buffer_sv));
1398 SvREFCNT_dec(buffer_sv);
1402 i_io_read(ig, buffer_sv, size)
1411 croak("size negative in call to i_io_read()");
1412 if (SvTHINKFIRST(buffer_sv))
1413 sv_force_normal_flags(buffer_sv, SV_COW_DROP_PV);
1414 SvUPGRADE(buffer_sv, SVt_PV);
1415 buffer = SvGROW(buffer_sv, size+1);
1416 result = i_io_read(ig, buffer, size);
1418 SvCUR_set(buffer_sv, result);
1419 *SvEND(buffer_sv) = '\0';
1420 SvPOK_only(buffer_sv);
1422 PUSHs(sv_2mortal(newSViv(result)));
1428 i_io_read2(ig, size)
1437 croak("size zero in call to read2()");
1438 buffer_sv = newSV(size);
1439 buffer = SvGROW(buffer_sv, size+1);
1440 result = i_io_read(ig, buffer, size);
1442 SvCUR_set(buffer_sv, result);
1443 *SvEND(buffer_sv) = '\0';
1444 SvPOK_only(buffer_sv);
1446 PUSHs(sv_2mortal(buffer_sv));
1450 SvREFCNT_dec(buffer_sv);
1454 i_io_gets(ig, size = 8192, eol = NEWLINE)
1464 croak("size too small in call to gets()");
1465 buffer_sv = sv_2mortal(newSV(size+1));
1466 buffer = SvPVX(buffer_sv);
1467 result = i_io_gets(ig, buffer, size+1, eol);
1469 SvCUR_set(buffer_sv, result);
1470 *SvEND(buffer_sv) = '\0';
1471 SvPOK_only(buffer_sv);
1477 i_io_write(ig, data_sv)
1484 data = SvPVbyte(data_sv, size);
1485 RETVAL = i_io_write(ig, data, size);
1490 i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
1495 i_io_set_buffered(ig, flag = 1)
1500 i_io_is_buffered(ig)
1511 MODULE = Imager PACKAGE = Imager
1522 while( (item=i_format_list[i++]) != NULL ) {
1524 PUSHs(sv_2mortal(newSVpv(item,0)));
1528 i_sametype(im, x, y)
1534 i_sametype_chans(im, x, y, channels)
1541 i_init_log(name_sv,level)
1545 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1547 RETVAL = i_init_log(name, level);
1552 i_log_entry(string,level)
1565 i_img_info(im,info);
1567 PUSHs(sv_2mortal(newSViv(info[0])));
1568 PUSHs(sv_2mortal(newSViv(info[1])));
1569 PUSHs(sv_2mortal(newSViv(info[2])));
1570 PUSHs(sv_2mortal(newSViv(info[3])));
1576 i_img_setmask(im,ch_mask)
1585 i_img_getchannels(im)
1594 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1602 i_img_get_height(im)
1607 i_img_is_monochrome(im)
1613 result = i_img_is_monochrome(im, &zero_is_white);
1615 if (GIMME_V == G_ARRAY) {
1618 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1627 i_line(im,x1,y1,x2,y2,val,endp)
1637 i_line_aa(im,x1,y1,x2,y2,val,endp)
1647 i_box(im,x1,y1,x2,y2,val)
1656 i_box_filled(im,x1,y1,x2,y2,val)
1665 i_box_filledf(im,x1,y1,x2,y2,val)
1671 Imager::Color::Float val
1674 i_box_cfill(im,x1,y1,x2,y2,fill)
1680 Imager::FillHandle fill
1683 i_arc(im,x,y,rad,d1,d2,val)
1693 i_arc_aa(im,x,y,rad,d1,d2,val)
1703 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1710 Imager::FillHandle fill
1713 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1720 Imager::FillHandle fill
1724 i_circle_aa(im,x,y,rad,val)
1732 i_circle_out(im,x,y,rad,val)
1740 i_circle_out_aa(im,x,y,rad,val)
1748 i_arc_out(im,x,y,rad,d1,d2,val)
1758 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1769 i_bezier_multi(im,x,y,val)
1778 if (size_x != size_y)
1779 croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1780 i_bezier_multi(im,size_x,x,y,val);
1783 i_poly_aa(im,x,y,val)
1792 if (size_x != size_y)
1793 croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1794 RETVAL = i_poly_aa(im, size_x, x, y, val);
1799 i_poly_aa_cfill(im, x, y, fill)
1803 Imager::FillHandle fill
1808 if (size_x != size_y)
1809 croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1810 RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
1815 i_flood_fill(im,seedx,seedy,dcol)
1822 i_flood_cfill(im,seedx,seedy,fill)
1826 Imager::FillHandle fill
1829 i_flood_fill_border(im,seedx,seedy,dcol, border)
1834 Imager::Color border
1837 i_flood_cfill_border(im,seedx,seedy,fill, border)
1841 Imager::FillHandle fill
1842 Imager::Color border
1846 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1858 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1875 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1886 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1899 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)
1915 i_combine(src_av, channels_av = NULL)
1919 i_img **imgs = NULL;
1921 int *channels = NULL;
1926 in_count = av_len(src_av) + 1;
1928 imgs = mymalloc(sizeof(i_img*) * in_count);
1929 channels = mymalloc(sizeof(int) * in_count);
1930 for (i = 0; i < in_count; ++i) {
1931 psv = av_fetch(src_av, i, 0);
1932 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1935 croak("imgs must contain only images");
1937 tmp = SvIV((SV*)SvRV(*psv));
1938 imgs[i] = INT2PTR(i_img*, tmp);
1940 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1942 channels[i] = SvIV(*psv);
1949 RETVAL = i_combine(imgs, channels, in_count);
1956 i_flipxy(im, direction)
1961 i_rotate90(im, degrees)
1966 i_rotate_exact(im, amount, ...)
1970 i_color *backp = NULL;
1971 i_fcolor *fbackp = NULL;
1975 /* extract the bg colors if any */
1976 /* yes, this is kind of strange */
1977 for (i = 2; i < items; ++i) {
1979 if (sv_derived_from(sv1, "Imager::Color")) {
1980 IV tmp = SvIV((SV*)SvRV(sv1));
1981 backp = INT2PTR(i_color *, tmp);
1983 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1984 IV tmp = SvIV((SV*)SvRV(sv1));
1985 fbackp = INT2PTR(i_fcolor *, tmp);
1988 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1993 i_matrix_transform(im, xsize, ysize, matrix_av, ...)
2003 i_color *backp = NULL;
2004 i_fcolor *fbackp = NULL;
2006 len=av_len(matrix_av)+1;
2009 for (i = 0; i < len; ++i) {
2010 sv1=(*(av_fetch(matrix_av,i,0)));
2011 matrix[i] = SvNV(sv1);
2015 /* extract the bg colors if any */
2016 /* yes, this is kind of strange */
2017 for (i = 4; i < items; ++i) {
2019 if (sv_derived_from(sv1, "Imager::Color")) {
2020 IV tmp = SvIV((SV*)SvRV(sv1));
2021 backp = INT2PTR(i_color *, tmp);
2023 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2024 IV tmp = SvIV((SV*)SvRV(sv1));
2025 fbackp = INT2PTR(i_fcolor *, tmp);
2028 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2033 i_gaussian(im,stdev)
2038 i_unsharp_mask(im,stdev,scale)
2053 len = av_len(coef) + 1;
2054 c_coef=mymalloc( len * sizeof(double) );
2055 for(i = 0; i < len; i++) {
2056 sv1 = (*(av_fetch(coef, i, 0)));
2057 c_coef[i] = (double)SvNV(sv1);
2059 RETVAL = i_conv(im, c_coef, len);
2065 i_convert(src, avmain)
2077 outchan = av_len(avmain)+1;
2078 /* find the biggest */
2080 for (j=0; j < outchan; ++j) {
2081 temp = av_fetch(avmain, j, 0);
2082 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2083 avsub = (AV*)SvRV(*temp);
2084 len = av_len(avsub)+1;
2089 i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2093 coeff = mymalloc(sizeof(double) * outchan * inchan);
2094 for (j = 0; j < outchan; ++j) {
2095 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2096 len = av_len(avsub)+1;
2097 for (i = 0; i < len; ++i) {
2098 temp = av_fetch(avsub, i, 0);
2100 coeff[i+j*inchan] = SvNV(*temp);
2102 coeff[i+j*inchan] = 0;
2105 coeff[i++ + j*inchan] = 0;
2107 RETVAL = i_convert(src, coeff, outchan, inchan);
2118 unsigned int mask = 0;
2123 unsigned char (*maps)[256];
2125 len = av_len(pmaps_av)+1;
2126 if (im->channels < len)
2128 maps = mymalloc( len * sizeof(unsigned char [256]) );
2129 for (j=0; j<len ; j++) {
2130 temp = av_fetch(pmaps_av, j, 0);
2131 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2132 avsub = (AV*)SvRV(*temp);
2133 if(av_len(avsub) != 255)
2136 for (i=0; i<256 ; i++) {
2138 temp = av_fetch(avsub, i, 0);
2139 val = temp ? SvIV(*temp) : 0;
2141 if (val>255) val = 255;
2146 i_map(im, maps, mask);
2158 i_img_diffd(im1,im2)
2163 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2173 _is_color_object(sv)
2177 RETVAL = SvOK(sv) && SvROK(sv) &&
2178 (sv_derived_from(sv, "Imager::Color")
2179 || sv_derived_from(sv, "Imager::Color::Float"));
2191 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2193 #define TT_DESTROY(handle) i_tt_destroy(handle)
2197 Imager::Font::TT handle
2202 (void)items; /* avoid unused warning */
2208 MODULE = Imager PACKAGE = Imager
2212 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
2213 Imager::Font::TT handle
2227 str = SvPV(str_sv, len);
2232 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2233 len, smooth, utf8, align);
2239 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
2240 Imager::Font::TT handle
2254 str = SvPV(str_sv, len);
2259 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2260 smooth, utf8, align);
2266 i_tt_bbox(handle,point,str_sv,utf8)
2267 Imager::Font::TT handle
2272 i_img_dim cords[BOUNDING_BOX_COUNT];
2278 str = SvPV(str_sv, len);
2283 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2285 for (i = 0; i < rc; ++i) {
2286 PUSHs(sv_2mortal(newSViv(cords[i])));
2291 i_tt_has_chars(handle, text_sv, utf8)
2292 Imager::Font::TT handle
2303 text = SvPV(text_sv, len);
2305 if (SvUTF8(text_sv))
2308 work = mymalloc(len);
2309 count = i_tt_has_chars(handle, text, len, utf8, work);
2310 if (GIMME_V == G_ARRAY) {
2312 for (i = 0; i < count; ++i) {
2313 PUSHs(boolSV(work[i]));
2318 PUSHs(sv_2mortal(newSVpv(work, count)));
2323 i_tt_dump_names(handle)
2324 Imager::Font::TT handle
2327 i_tt_face_name(handle)
2328 Imager::Font::TT handle
2333 len = i_tt_face_name(handle, name, sizeof(name));
2336 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2340 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2341 Imager::Font::TT handle
2353 text = SvPV(text_sv, work_len);
2355 if (SvUTF8(text_sv))
2362 ch = i_utf8_advance(&text, &len);
2364 i_push_error(0, "invalid UTF8 character");
2372 EXTEND(SP, count+1);
2373 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2374 ST(count) = sv_2mortal(newSVpv(name, 0));
2377 ST(count) = &PL_sv_undef;
2386 i_test_format_probe(ig, length)
2391 i_readpnm_wiol(ig, allow_incomplete)
2393 int allow_incomplete
2397 i_readpnm_multi_wiol(ig, allow_incomplete)
2399 int allow_incomplete
2405 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2408 for (i = 0; i < count; ++i) {
2409 SV *sv = sv_newmortal();
2410 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2417 i_writeppm_wiol(im, ig)
2426 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2435 i_writeraw_wiol(im,ig)
2440 i_writebmp_wiol(im,ig)
2445 i_readbmp_wiol(ig, allow_incomplete=0)
2447 int allow_incomplete
2451 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2460 idlen = SvCUR(ST(4));
2461 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2467 i_readtga_wiol(ig, length)
2475 i_scaleaxis(im,Value,Axis)
2481 i_scale_nn(im,scx,scy)
2487 i_scale_mixing(im, width, height)
2497 i_count_colors(im,maxc)
2502 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2507 unsigned int * col_usage = NULL;
2510 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2511 EXTEND(SP, col_cnt);
2512 for (i = 0; i < col_cnt; i++) {
2513 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2520 i_transform(im, opx, opy, parm)
2526 STRLEN size_opx, size_opy, size_parm;
2529 result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
2531 SV *result_sv = sv_newmortal();
2533 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2538 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2564 in_imgs_count = av_len(av_in_imgs)+1;
2565 for (i = 0; i < in_imgs_count; ++i) {
2566 sv1 = *av_fetch(av_in_imgs, i, 0);
2567 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2568 croak("sv_in_img must contain only images");
2571 if (in_imgs_count > 0) {
2572 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2573 for (i = 0; i < in_imgs_count; ++i) {
2574 sv1 = *av_fetch(av_in_imgs,i,0);
2575 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2576 croak("Parameter 5 must contain only images");
2578 tmp = SvIV((SV*)SvRV(sv1));
2579 in_imgs[i] = INT2PTR(i_img*, tmp);
2583 /* no input images */
2586 /* default the output size from the first input if possible */
2588 width = SvIV(sv_width);
2589 else if (in_imgs_count)
2590 width = in_imgs[0]->xsize;
2592 croak("No output image width supplied");
2594 if (SvOK(sv_height))
2595 height = SvIV(sv_height);
2596 else if (in_imgs_count)
2597 height = in_imgs[0]->ysize;
2599 croak("No output image height supplied");
2601 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2602 if (ops_len % sizeof(struct rm_op))
2603 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2604 ops_count = ops_len / sizeof(struct rm_op);
2606 n_regs_count = av_len(av_n_regs)+1;
2607 n_regs = mymalloc(n_regs_count * sizeof(double));
2608 for (i = 0; i < n_regs_count; ++i) {
2609 sv1 = *av_fetch(av_n_regs,i,0);
2611 n_regs[i] = SvNV(sv1);
2613 c_regs_count = av_len(av_c_regs)+1;
2614 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2615 /* I don't bother initializing the colou?r registers */
2617 result=i_transform2(width, height, channels, ops, ops_count,
2618 n_regs, n_regs_count,
2619 c_regs, c_regs_count, in_imgs, in_imgs_count);
2625 SV *result_sv = sv_newmortal();
2627 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2633 i_contrast(im,intensity)
2646 i_noise(im,amount,type)
2652 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2662 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2681 i_postlevels(im,levels)
2691 i_watermark(im,wmark,tx,ty,pixdiff)
2693 Imager::ImgRaw wmark
2700 i_autolevels(im,lsat,usat,skew)
2707 i_radnoise(im,xo,yo,rscale,ascale)
2715 i_turbnoise(im, xo, yo, scale)
2723 i_gradgen(im, xo, yo, ac, dmeasure)
2734 if (size_xo != size_yo || size_xo != size_ac)
2735 croak("i_gradgen: x, y and color arrays must be the same size");
2737 croak("Usage: i_gradgen array refs must have more than 1 entry each");
2738 i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
2741 i_diff_image(im, im2, mindist=0)
2747 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2757 double ssample_param
2761 i_fountain_seg *segs;
2763 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2764 croak("i_fountain: argument 11 must be an array ref");
2766 asegs = (AV *)SvRV(ST(10));
2767 segs = load_fount_segs(aTHX_ asegs, &count);
2768 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2769 super_sample, ssample_param, count, segs);
2775 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2784 double ssample_param
2788 i_fountain_seg *segs;
2790 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2791 croak("i_fountain: argument 11 must be an array ref");
2793 asegs = (AV *)SvRV(ST(9));
2794 segs = load_fount_segs(aTHX_ asegs, &count);
2795 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2796 super_sample, ssample_param, count, segs);
2802 i_new_fill_opacity(other_fill, alpha_mult)
2803 Imager::FillHandle other_fill
2814 errors = i_errors();
2816 while (errors[i].msg) {
2818 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2819 if (!av_store(av, 0, sv)) {
2822 sv = newSViv(errors[i].code);
2823 if (!av_store(av, 1, sv)) {
2826 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2834 i_push_error(code, msg)
2839 i_nearest_color(im, ...)
2854 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2855 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2856 croak("i_nearest_color: Second argument must be an array ref");
2857 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2858 croak("i_nearest_color: Third argument must be an array ref");
2859 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2860 croak("i_nearest_color: Fourth argument must be an array ref");
2861 axx = (AV *)SvRV(ST(1));
2862 ayy = (AV *)SvRV(ST(2));
2863 ac = (AV *)SvRV(ST(3));
2864 dmeasure = (int)SvIV(ST(4));
2866 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2867 num = num <= av_len(ac) ? num : av_len(ac);
2869 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2870 xo = mymalloc( sizeof(i_img_dim) * num );
2871 yo = mymalloc( sizeof(i_img_dim) * num );
2872 ival = mymalloc( sizeof(i_color) * num );
2873 for(i = 0; i<num; i++) {
2874 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2875 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2876 sv = *av_fetch(ac, i, 0);
2877 if ( !sv_derived_from(sv, "Imager::Color") ) {
2878 free(axx); free(ayy); free(ac);
2879 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2881 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2883 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2897 rc=DSO_open(filename,&evstr);
2901 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2902 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2905 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2911 DSO_close(dso_handle)
2915 DSO_funclist(dso_handle_v)
2919 DSO_handle *dso_handle;
2920 func_ptr *functions;
2922 dso_handle=(DSO_handle*)dso_handle_v;
2923 functions = DSO_funclist(dso_handle);
2925 while( functions[i].name != NULL) {
2927 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2929 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2933 DSO_call(handle,func_index,hv)
2938 DSO_call( (DSO_handle *)handle,func_index,hv);
2941 i_get_pixel(im, x, y)
2946 RETVAL = (i_color *)mymalloc(sizeof(i_color));
2947 if (i_gpix(im, x, y, RETVAL) != 0) {
2956 i_ppix(im, x, y, cl)
2963 i_img_pal_new(x, y, channels, maxpal)
2970 i_img_to_pal(src, quant)
2976 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2977 croak("i_img_to_pal: second argument must be a hash ref");
2978 hv = (HV *)SvRV(ST(1));
2979 memset(&quant, 0, sizeof(quant));
2981 quant.mc_size = 256;
2982 ip_handle_quant_opts(aTHX_ &quant, hv);
2983 RETVAL = i_img_to_pal(src, &quant);
2985 ip_copy_colors_back(aTHX_ hv, &quant);
2987 ip_cleanup_quant_opts(aTHX_ &quant);
2996 i_img_make_palette(HV *quant_hv, ...)
2998 size_t count = items - 1;
3000 i_img **imgs = NULL;
3004 croak("Please supply at least one image (%d)", (int)count);
3005 imgs = mymalloc(sizeof(i_img *) * count);
3006 for (i = 0; i < count; ++i) {
3007 SV *img_sv = ST(i + 1);
3008 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3009 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3013 croak("Image %d is not an image object", (int)i+1);
3016 memset(&quant, 0, sizeof(quant));
3018 quant.mc_size = 256;
3019 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3020 i_quant_makemap(&quant, imgs, count);
3021 EXTEND(SP, quant.mc_count);
3022 for (i = 0; i < quant.mc_count; ++i) {
3023 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3026 ip_cleanup_quant_opts(aTHX_ &quant);
3040 work = mymalloc((r-l) * sizeof(i_palidx));
3041 count = i_gpal(im, l, r, y, work);
3042 if (GIMME_V == G_ARRAY) {
3044 for (i = 0; i < count; ++i) {
3045 PUSHs(sv_2mortal(newSViv(work[i])));
3050 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3055 if (GIMME_V != G_ARRAY) {
3057 PUSHs(&PL_sv_undef);
3062 i_ppal(im, l, y, ...)
3071 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3072 for (i=0; i < items-3; ++i) {
3073 work[i] = SvIV(ST(i+3));
3075 validate_i_ppal(im, work, items - 3);
3076 RETVAL = i_ppal(im, l, l+items-3, y, work);
3085 i_ppal_p(im, l, y, data)
3091 i_palidx const *work;
3094 work = (i_palidx const *)SvPV(data, len);
3095 len /= sizeof(i_palidx);
3097 validate_i_ppal(im, work, len);
3098 RETVAL = i_ppal(im, l, l+len, y, work);
3107 i_addcolors(im, ...)
3114 croak("i_addcolors: no colors to add");
3115 colors = mymalloc((items-1) * sizeof(i_color));
3116 for (i=0; i < items-1; ++i) {
3117 if (sv_isobject(ST(i+1))
3118 && sv_derived_from(ST(i+1), "Imager::Color")) {
3119 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3120 colors[i] = *INT2PTR(i_color *, tmp);
3124 croak("i_addcolor: pixels must be Imager::Color objects");
3127 RETVAL = i_addcolors(im, colors, items-1);
3132 i_setcolors(im, index, ...)
3140 croak("i_setcolors: no colors to add");
3141 colors = mymalloc((items-2) * sizeof(i_color));
3142 for (i=0; i < items-2; ++i) {
3143 if (sv_isobject(ST(i+2))
3144 && sv_derived_from(ST(i+2), "Imager::Color")) {
3145 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3146 colors[i] = *INT2PTR(i_color *, tmp);
3150 croak("i_setcolors: pixels must be Imager::Color objects");
3153 RETVAL = i_setcolors(im, index, colors, items-2);
3159 i_getcolors(im, index, count=1)
3168 croak("i_getcolors: count must be positive");
3169 colors = malloc_temp(aTHX_ sizeof(i_color) * count);
3170 if (i_getcolors(im, index, colors, count)) {
3172 for (i = 0; i < count; ++i) {
3173 SV *sv = make_i_color_sv(aTHX_ colors+i);
3187 i_findcolor(im, color)
3191 if (!i_findcolor(im, color, &RETVAL)) {
3210 i_gsamp(im, l, r, y, channels)
3215 i_channel_list channels
3221 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count);
3222 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3223 if (GIMME_V == G_ARRAY) {
3225 for (i = 0; i < count; ++i)
3226 PUSHs(sv_2mortal(newSViv(data[i])));
3230 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3235 if (GIMME_V != G_ARRAY) {
3241 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3249 i_channel_list channels
3256 croak("No channel numbers supplied to g_samp()");
3258 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3259 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3260 for (i = 0; i < count; ++i) {
3261 av_store(target, i+offset, newSVuv(data[i]));
3273 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3278 i_channel_list channels
3280 i_img_dim data_offset
3281 i_img_dim pixel_count
3290 data_count = av_len(data_av) + 1;
3291 if (data_offset < 0) {
3292 croak("data_offset must be non-negative");
3294 if (data_offset > data_count) {
3295 croak("data_offset greater than number of samples supplied");
3297 if (pixel_count == -1 ||
3298 data_offset + pixel_count * channels.count > data_count) {
3299 pixel_count = (data_count - data_offset) / channels.count;
3302 data_used = pixel_count * channels.count;
3303 data = mymalloc(sizeof(unsigned) * data_count);
3304 for (i = 0; i < data_used; ++i)
3305 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3307 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3308 channels.count, bits);
3316 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3320 i_channel_list channels
3329 i_push_error(0, "offset must be non-negative");
3333 if (offset > data.count) {
3334 i_push_error(0, "offset greater than number of samples supplied");
3337 data.samples += offset;
3338 data.count -= offset;
3341 width * channels.count > data.count) {
3342 width = data.count / channels.count;
3345 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3350 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3354 i_channel_list channels
3363 i_push_error(0, "offset must be non-negative");
3367 if (offset > data.count) {
3368 i_push_error(0, "offset greater than number of samples supplied");
3371 data.samples += offset;
3372 data.count -= offset;
3375 width * channels.count > data.count) {
3376 width = data.count / channels.count;
3379 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3384 i_img_masked_new(targ, mask, x, y, w, h)
3394 if (!sv_isobject(ST(1))
3395 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3396 croak("i_img_masked_new: parameter 2 must undef or an image");
3398 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3402 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3407 i_plin(im, l, y, ...)
3418 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3419 /* supplied as a byte string */
3420 work = (i_color *)SvPV(ST(3), len);
3421 count = len / sizeof(i_color);
3422 if (count * sizeof(i_color) != len) {
3423 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3425 RETVAL = i_plin(im, l, l+count, y, work);
3428 work = mymalloc(sizeof(i_color) * (items-3));
3429 for (i=0; i < items-3; ++i) {
3430 if (sv_isobject(ST(i+3))
3431 && sv_derived_from(ST(i+3), "Imager::Color")) {
3432 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3433 work[i] = *INT2PTR(i_color *, tmp);
3437 croak("i_plin: pixels must be Imager::Color objects");
3440 RETVAL = i_plin(im, l, l+items-3, y, work);
3451 i_ppixf(im, x, y, cl)
3455 Imager::Color::Float cl
3458 i_gsampf(im, l, r, y, channels)
3463 i_channel_list channels
3469 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3470 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3471 if (GIMME_V == G_ARRAY) {
3473 for (i = 0; i < count; ++i)
3474 PUSHs(sv_2mortal(newSVnv(data[i])));
3478 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3483 if (GIMME_V != G_ARRAY) {
3489 i_plinf(im, l, y, ...)
3500 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3501 /* supplied as a byte string */
3502 work = (i_fcolor *)SvPV(ST(3), len);
3503 count = len / sizeof(i_fcolor);
3504 if (count * sizeof(i_fcolor) != len) {
3505 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3507 RETVAL = i_plinf(im, l, l+count, y, work);
3510 work = mymalloc(sizeof(i_fcolor) * (items-3));
3511 for (i=0; i < items-3; ++i) {
3512 if (sv_isobject(ST(i+3))
3513 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3514 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3515 work[i] = *INT2PTR(i_fcolor *, tmp);
3519 croak("i_plinf: pixels must be Imager::Color::Float objects");
3523 RETVAL = i_plinf(im, l, l+items-3, y, work);
3533 Imager::Color::Float
3539 RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3540 if (i_gpixf(im, x, y, RETVAL) != 0) {
3558 vals = mymalloc((r-l) * sizeof(i_color));
3559 memset(vals, 0, (r-l) * sizeof(i_color));
3560 count = i_glin(im, l, r, y, vals);
3561 if (GIMME_V == G_ARRAY) {
3563 for (i = 0; i < count; ++i) {
3564 SV *sv = make_i_color_sv(aTHX_ vals+i);
3570 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3576 i_glinf(im, l, r, y)
3586 for (i = 0; i < MAXCHANNELS; ++i)
3587 zero.channel[i] = 0;
3589 vals = mymalloc((r-l) * sizeof(i_fcolor));
3590 for (i = 0; i < r-l; ++i)
3592 count = i_glinf(im, l, r, y, vals);
3593 if (GIMME_V == G_ARRAY) {
3595 for (i = 0; i < count; ++i) {
3597 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3599 sv = sv_newmortal();
3600 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3606 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3612 i_img_8_new(x, y, ch)
3618 i_img_16_new(x, y, ch)
3628 i_img_double_new(x, y, ch)
3638 i_tags_addn(im, name_sv, code, idata)
3647 SvGETMAGIC(name_sv);
3649 name = SvPV_nomg(name_sv, len);
3652 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3657 i_tags_add(im, name_sv, code, data_sv, idata)
3668 SvGETMAGIC(name_sv);
3670 name = SvPV_nomg(name_sv, len);
3673 SvGETMAGIC(data_sv);
3675 data = SvPV(data_sv, len);
3680 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3685 i_tags_find(im, name, start)
3692 if (i_tags_find(&im->tags, name, start, &entry)) {
3701 i_tags_findn(im, code, start)
3708 if (i_tags_findn(&im->tags, code, start, &entry)) {
3718 i_tags_delete(im, entry)
3722 RETVAL = i_tags_delete(&im->tags, entry);
3727 i_tags_delbyname(im, name)
3731 RETVAL = i_tags_delbyname(&im->tags, name);
3736 i_tags_delbycode(im, code)
3740 RETVAL = i_tags_delbycode(&im->tags, code);
3745 i_tags_get(im, index)
3749 if (index >= 0 && index < im->tags.count) {
3750 i_img_tag *entry = im->tags.tags + index;
3754 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3757 PUSHs(sv_2mortal(newSViv(entry->code)));
3760 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3763 PUSHs(sv_2mortal(newSViv(entry->idata)));
3768 i_tags_get_string(im, what_sv)
3772 char const *name = NULL;
3776 if (SvIOK(what_sv)) {
3777 code = SvIV(what_sv);
3781 name = SvPV_nolen(what_sv);
3784 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3786 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3793 RETVAL = im->tags.count;
3799 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3803 Imager::FillHandle fill
3806 IFILL_CLONE_SKIP(...)
3808 (void)items; /* avoid unused warning for XS variable */
3813 MODULE = Imager PACKAGE = Imager
3816 i_new_fill_solid(cl, combine)
3821 i_new_fill_solidf(cl, combine)
3822 Imager::Color::Float cl
3826 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3835 unsigned char *cust_hatch;
3838 SvGETMAGIC(cust_hatch_sv);
3839 if (SvOK(cust_hatch_sv)) {
3840 cust_hatch = (unsigned char *)SvPV_nomg(cust_hatch_sv, len);
3844 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3849 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3850 Imager::Color::Float fg
3851 Imager::Color::Float bg
3858 unsigned char *cust_hatch;
3861 SvGETMAGIC(cust_hatch_sv);
3862 if (SvOK(cust_hatch_sv)) {
3863 cust_hatch = (unsigned char *)SvPV(cust_hatch_sv, len);
3867 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3872 i_new_fill_image(src, matrix_sv, xoff, yoff, combine)
3886 SvGETMAGIC(matrix_sv);
3887 if (!SvOK(matrix_sv)) {
3891 if (!SvROK(matrix_sv) || SvTYPE(SvRV(matrix_sv)) != SVt_PVAV)
3892 croak("i_new_fill_image: matrix parameter must be an arrayref or undef");
3893 av=(AV*)SvRV(matrix_sv);
3897 for (i = 0; i < len; ++i) {
3898 sv1=(*(av_fetch(av,i,0)));
3899 matrix[i] = SvNV(sv1);
3905 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3909 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3911 # this class is only exposed for testing
3914 i_int_hlines_testing()
3916 #if i_int_hlines_testing()
3918 Imager::Internal::Hlines
3919 i_int_hlines_new(start_y, count_y, start_x, count_x)
3925 Imager::Internal::Hlines
3926 i_int_hlines_new_img(im)
3930 i_int_hlines_add(hlines, y, minx, width)
3931 Imager::Internal::Hlines hlines
3937 i_int_hlines_DESTROY(hlines)
3938 Imager::Internal::Hlines hlines
3941 i_int_hlines_dump(hlines)
3942 Imager::Internal::Hlines hlines
3945 i_int_hlines_CLONE_SKIP(cls)
3949 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
3952 im_context_DESTROY(ctx)
3955 #ifdef PERL_IMPLICIT_CONTEXT
3958 im_context_CLONE(...)
3962 /* the following sv_setref_pv() will free this inc */
3963 im_context_refinc(MY_CXT.ctx, "CLONE");
3964 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
3965 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
3970 PERL_SET_GLOBAL_CALLBACKS;
3971 PERL_PL_SET_GLOBAL_CALLBACKS;
3972 #ifdef PERL_IMPLICIT_CONTEXT
3978 start_context(aTHX);
3979 im_get_context = perl_get_context;