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()
35 Context object management
39 typedef im_context_t Imager__Context;
41 #define im_context_DESTROY(ctx) im_context_refdec((ctx), "DESTROY")
43 #ifdef PERL_IMPLICIT_CONTEXT
45 #define MY_CXT_KEY "Imager::_context" XS_VERSION
53 im_context_t fallback_context;
58 MY_CXT.ctx = im_context_new();
59 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
61 /* Ideally we'd free this reference, but the error message memory
62 was never released on exit, so the associated memory here is reasonable
64 With logging enabled we always need at least one context, since
65 objects may be released fairly late and attempt to get the log file.
67 im_context_refinc(MY_CXT.ctx, "start_context");
68 fallback_context = MY_CXT.ctx;
72 perl_get_context(void) {
76 return MY_CXT.ctx ? MY_CXT.ctx : fallback_context;
81 static im_context_t perl_context;
85 perl_context = im_context_new();
86 im_context_refinc(perl_context, "start_context");
90 perl_get_context(void) {
96 /* used to represent channel lists parameters */
97 typedef struct i_channel_list_tag {
104 const i_sample_t *samples;
109 const i_fsample_t *samples;
114 Allocate memory that will be discarded when mortals are discarded.
119 malloc_temp(pTHX_ size_t size) {
120 SV *sv = sv_2mortal(newSV(size));
126 calloc_temp(pTHX_ size_t size) {
127 void *result = malloc_temp(aTHX_ size);
128 memset(result, 0, size);
133 /* for use with the T_AVARRAY typemap */
134 #define doublePtr(size) ((double *)calloc_temp(aTHX_ sizeof(double) * (size)))
135 #define SvDouble(sv, pname) (SvNV(sv))
137 #define intPtr(size) ((int *)calloc_temp(aTHX_ sizeof(int) * (size)))
138 #define SvInt(sv, pname) (SvIV(sv))
140 #define i_img_dimPtr(size) ((i_img_dim *)calloc_temp(aTHX_ sizeof(i_img_dim) * (size)))
141 #define SvI_img_dim(sv, pname) (SvIV(sv))
143 #define i_colorPtr(size) ((i_color *)calloc_temp(aTHX_ sizeof(i_color *) * (size)))
145 #define SvI_color(sv, pname) S_sv_to_i_color(aTHX_ sv, pname)
148 S_sv_to_i_color(pTHX_ SV *sv, const char *pname) {
149 if (!sv_derived_from(sv, "Imager::Color")) {
150 croak("%s: not a color object", pname);
152 return *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
155 /* These functions are all shared - then comes platform dependant code */
156 static int getstr(void *hv_t,char *key,char **store) {
161 mm_log((1,"getstr(hv_t %p, key %s, store %p)\n",hv_t,key,store));
163 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
165 svpp=hv_fetch(hv, key, strlen(key), 0);
166 *store=SvPV(*svpp, PL_na );
171 static int getint(void *hv_t,char *key,int *store) {
176 mm_log((1,"getint(hv_t %p, key %s, store %p)\n",hv_t,key,store));
178 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
180 svpp=hv_fetch(hv, key, strlen(key), 0);
181 *store=(int)SvIV(*svpp);
185 static int getdouble(void *hv_t,char* key,double *store) {
190 mm_log((1,"getdouble(hv_t %p, key %s, store %p)\n",hv_t,key,store));
192 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
193 svpp=hv_fetch(hv, key, strlen(key), 0);
194 *store=(double)SvNV(*svpp);
198 static int getvoid(void *hv_t,char* key,void **store) {
203 mm_log((1,"getvoid(hv_t %p, key %s, store %p)\n",hv_t,key,store));
205 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
207 svpp=hv_fetch(hv, key, strlen(key), 0);
208 *store = INT2PTR(void*, SvIV(*svpp));
213 static int getobj(void *hv_t,char *key,char *type,void **store) {
218 mm_log((1,"getobj(hv_t %p, key %s,type %s, store %p)\n",hv_t,key,type,store));
220 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
222 svpp=hv_fetch(hv, key, strlen(key), 0);
224 if (sv_derived_from(*svpp,type)) {
225 IV tmp = SvIV((SV*)SvRV(*svpp));
226 *store = INT2PTR(void*, tmp);
228 mm_log((1,"getobj: key exists in hash but is not of correct type"));
235 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
238 free_buffer(void *p) {
244 i_log_entry(char *string, int level) {
245 mm_log((level, "%s", string));
249 make_i_color_sv(pTHX_ const i_color *c) {
251 i_color *col = mymalloc(sizeof(i_color));
254 sv_setref_pv(sv, "Imager::Color", (void *)col);
259 #define CBDATA_BUFSIZE 8192
262 /* the SVs we use to call back to Perl */
270 call_reader(struct cbdata *cbd, void *buf, size_t size,
278 if (!SvOK(cbd->readcb)) {
279 mm_log((1, "read callback called but no readcb supplied\n"));
280 i_push_error(0, "read callback called but no readcb supplied");
288 PUSHs(sv_2mortal(newSViv(size)));
289 PUSHs(sv_2mortal(newSViv(maxread)));
292 count = perl_call_sv(cbd->readcb, G_SCALAR);
297 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
303 char *ptr = SvPVbyte(data, len);
305 croak("Too much data returned in reader callback (wanted %d, got %d, expected %d)",
306 (int)size, (int)len, (int)maxread);
308 memcpy(buf, ptr, len);
323 io_seeker(void *p, off_t offset, int whence) {
325 struct cbdata *cbd = p;
330 if (!SvOK(cbd->seekcb)) {
331 mm_log((1, "seek callback called but no seekcb supplied\n"));
332 i_push_error(0, "seek callback called but no seekcb supplied");
340 PUSHs(sv_2mortal(newSViv(offset)));
341 PUSHs(sv_2mortal(newSViv(whence)));
344 count = perl_call_sv(cbd->seekcb, G_SCALAR);
349 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
361 io_writer(void *p, void const *data, size_t size) {
363 struct cbdata *cbd = p;
369 if (!SvOK(cbd->writecb)) {
370 mm_log((1, "write callback called but no writecb supplied\n"));
371 i_push_error(0, "write callback called but no writecb supplied");
379 PUSHs(sv_2mortal(newSVpv((char *)data, size)));
382 count = perl_call_sv(cbd->writecb, G_SCALAR);
386 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
389 success = SvTRUE(sv);
396 return success ? size : -1;
400 io_reader(void *p, void *data, size_t size) {
401 struct cbdata *cbd = p;
403 return call_reader(cbd, data, size, size);
406 static int io_closer(void *p) {
408 struct cbdata *cbd = p;
411 if (SvOK(cbd->closecb)) {
420 count = perl_call_sv(cbd->closecb, G_SCALAR);
426 success = SvTRUE(sv);
436 return success ? 0 : -1;
439 static void io_destroyer(void *p) {
441 struct cbdata *cbd = p;
443 SvREFCNT_dec(cbd->writecb);
444 SvREFCNT_dec(cbd->readcb);
445 SvREFCNT_dec(cbd->seekcb);
446 SvREFCNT_dec(cbd->closecb);
451 im_SvREFSCALAR(SV *sv) {
452 svtype type = SvTYPE(sv);
462 #if PERL_VERSION > 10
473 describe_sv(SV *sv) {
476 svtype type = SvTYPE(SvRV(sv));
478 case SVt_PVCV: return "CV";
479 case SVt_PVGV: return "GV";
480 case SVt_PVLV: return "LV";
481 default: return "some reference";
485 return "non-reference scalar";
494 do_io_new_buffer(pTHX_ SV *data_sv) {
501 if (SvROK(data_sv)) {
502 if (im_SvREFSCALAR(SvRV(data_sv))) {
506 i_push_errorf(0, "data is not a scalar or a reference to scalar");
514 /* previously this would keep the SV around, but this is unsafe in
515 many ways, so always copy the bytes */
516 data = SvPVbyte(sv, length);
517 data_copy = mymalloc(length);
518 memcpy(data_copy, data, length);
519 return io_new_buffer(data_copy, length, free_buffer, data_copy);
523 do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) {
526 cbd = mymalloc(sizeof(struct cbdata));
527 cbd->writecb = newSVsv(writecb);
528 cbd->readcb = newSVsv(readcb);
529 cbd->seekcb = newSVsv(seekcb);
530 cbd->closecb = newSVsv(closecb);
532 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)));
534 return io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
542 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
545 for (i = 0; i < count; ++i)
546 if (strEQ(names[i].name, name))
547 return names[i].value;
551 static struct value_name transp_names[] =
554 { "threshold", tr_threshold },
555 { "errdiff", tr_errdiff },
556 { "ordered", tr_ordered, },
559 static struct value_name make_color_names[] =
561 { "none", mc_none, },
562 { "webmap", mc_web_map, },
563 { "addi", mc_addi, },
564 { "mediancut", mc_median_cut, },
565 { "mono", mc_mono, },
566 { "monochrome", mc_mono, },
567 { "gray", mc_gray, },
568 { "gray4", mc_gray4, },
569 { "gray16", mc_gray16, },
572 static struct value_name translate_names[] =
574 { "giflib", pt_giflib, },
575 { "closest", pt_closest, },
576 { "perturb", pt_perturb, },
577 { "errdiff", pt_errdiff, },
580 static struct value_name errdiff_names[] =
582 { "floyd", ed_floyd, },
583 { "jarvis", ed_jarvis, },
584 { "stucki", ed_stucki, },
585 { "custom", ed_custom, },
588 static struct value_name orddith_names[] =
590 { "random", od_random, },
591 { "dot8", od_dot8, },
592 { "dot4", od_dot4, },
593 { "hline", od_hline, },
594 { "vline", od_vline, },
595 { "/line", od_slashline, },
596 { "slashline", od_slashline, },
597 { "\\line", od_backline, },
598 { "backline", od_backline, },
599 { "tiny", od_tiny, },
600 { "custom", od_custom, },
603 /* look through the hash for quantization options */
605 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
607 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
613 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
615 sv = hv_fetch(hv, "transp", 6, 0);
616 if (sv && *sv && (str = SvPV(*sv, len))) {
618 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
620 if (quant->transp != tr_none) {
621 quant->tr_threshold = 127;
622 sv = hv_fetch(hv, "tr_threshold", 12, 0);
624 quant->tr_threshold = SvIV(*sv);
626 if (quant->transp == tr_errdiff) {
627 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
628 if (sv && *sv && (str = SvPV(*sv, len)))
629 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
631 if (quant->transp == tr_ordered) {
632 quant->tr_orddith = od_tiny;
633 sv = hv_fetch(hv, "tr_orddith", 10, 0);
634 if (sv && *sv && (str = SvPV(*sv, len)))
635 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
637 if (quant->tr_orddith == od_custom) {
638 sv = hv_fetch(hv, "tr_map", 6, 0);
639 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
640 AV *av = (AV*)SvRV(*sv);
641 len = av_len(av) + 1;
642 if (len > sizeof(quant->tr_custom))
643 len = sizeof(quant->tr_custom);
644 for (i = 0; i < len; ++i) {
645 SV **sv2 = av_fetch(av, i, 0);
647 quant->tr_custom[i] = SvIV(*sv2);
650 while (i < sizeof(quant->tr_custom))
651 quant->tr_custom[i++] = 0;
656 quant->make_colors = mc_median_cut;
657 sv = hv_fetch(hv, "make_colors", 11, 0);
658 if (sv && *sv && (str = SvPV(*sv, len))) {
660 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
662 sv = hv_fetch(hv, "colors", 6, 0);
663 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
664 /* needs to be an array of Imager::Color
665 note that the caller allocates the mc_color array and sets mc_size
667 AV *av = (AV *)SvRV(*sv);
668 quant->mc_count = av_len(av)+1;
669 if (quant->mc_count > quant->mc_size)
670 quant->mc_count = quant->mc_size;
671 for (i = 0; i < quant->mc_count; ++i) {
672 SV **sv1 = av_fetch(av, i, 0);
673 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
674 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
675 quant->mc_colors[i] = *col;
679 sv = hv_fetch(hv, "max_colors", 10, 0);
682 if (i <= quant->mc_size && i >= quant->mc_count)
686 quant->translate = pt_closest;
687 sv = hv_fetch(hv, "translate", 9, 0);
688 if (sv && *sv && (str = SvPV(*sv, len))) {
689 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
691 sv = hv_fetch(hv, "errdiff", 7, 0);
692 if (sv && *sv && (str = SvPV(*sv, len))) {
693 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
695 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
696 /* get the error diffusion map */
697 sv = hv_fetch(hv, "errdiff_width", 13, 0);
699 quant->ed_width = SvIV(*sv);
700 sv = hv_fetch(hv, "errdiff_height", 14, 0);
702 quant->ed_height = SvIV(*sv);
703 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
705 quant->ed_orig = SvIV(*sv);
706 if (quant->ed_width > 0 && quant->ed_height > 0) {
708 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
709 sv = hv_fetch(hv, "errdiff_map", 11, 0);
710 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
711 AV *av = (AV*)SvRV(*sv);
712 len = av_len(av) + 1;
713 if (len > quant->ed_width * quant->ed_height)
714 len = quant->ed_width * quant->ed_height;
715 for (i = 0; i < len; ++i) {
716 SV **sv2 = av_fetch(av, i, 0);
718 quant->ed_map[i] = SvIV(*sv2);
719 sum += quant->ed_map[i];
725 myfree(quant->ed_map);
727 quant->errdiff = ed_floyd;
731 sv = hv_fetch(hv, "perturb", 7, 0);
733 quant->perturb = SvIV(*sv);
737 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
738 myfree(quant->mc_colors);
740 myfree(quant->ed_map);
743 /* copies the color map from the hv into the colors member of the HV */
745 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
751 sv = hv_fetch(hv, "colors", 6, 0);
752 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
757 av = (AV *)SvRV(*sv);
759 av_extend(av, quant->mc_count+1);
760 for (i = 0; i < quant->mc_count; ++i) {
761 i_color *in = quant->mc_colors+i;
762 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
763 work = sv_newmortal();
764 sv_setref_pv(work, "Imager::Color", (void *)c);
770 /* loads the segments of a fountain fill into an array */
771 static i_fountain_seg *
772 load_fount_segs(pTHX_ AV *asegs, int *count) {
773 /* Each element of segs must contain:
774 [ start, middle, end, c0, c1, segtype, colortrans ]
775 start, middle, end are doubles from 0 to 1
776 c0, c1 are Imager::Color::Float or Imager::Color objects
777 segtype, colortrans are ints
781 i_fountain_seg *segs;
785 *count = av_len(asegs)+1;
787 croak("i_fountain must have at least one segment");
788 segs = mymalloc(sizeof(i_fountain_seg) * *count);
789 for(i = 0; i < *count; i++) {
790 SV **sv1 = av_fetch(asegs, i, 0);
791 if (!sv1 || !*sv1 || !SvROK(*sv1)
792 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
794 croak("i_fountain: segs must be an arrayref of arrayrefs");
796 aseg = (AV *)SvRV(*sv1);
797 if (av_len(aseg) != 7-1) {
799 croak("i_fountain: a segment must have 7 members");
801 for (j = 0; j < 3; ++j) {
802 SV **sv2 = av_fetch(aseg, j, 0);
805 croak("i_fountain: XS error");
807 work[j] = SvNV(*sv2);
809 segs[i].start = work[0];
810 segs[i].middle = work[1];
811 segs[i].end = work[2];
812 for (j = 0; j < 2; ++j) {
813 SV **sv3 = av_fetch(aseg, 3+j, 0);
814 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
815 (!sv_derived_from(*sv3, "Imager::Color")
816 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
818 croak("i_fountain: segs must contain colors in elements 3 and 4");
820 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
821 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
824 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
826 for (ch = 0; ch < MAXCHANNELS; ++ch) {
827 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
831 for (j = 0; j < 2; ++j) {
832 SV **sv2 = av_fetch(aseg, j+5, 0);
835 croak("i_fountain: XS error");
837 worki[j] = SvIV(*sv2);
839 segs[i].type = worki[0];
840 segs[i].color = worki[1];
846 /* validates the indexes supplied to i_ppal
848 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
853 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
854 int color_count = i_colorcount(im);
857 if (color_count == -1)
858 croak("i_plin() called on direct color image");
860 for (i = 0; i < count; ++i) {
861 if (indexes[i] >= color_count) {
862 croak("i_plin() called with out of range color index %d (max %d)",
863 indexes[i], color_count-1);
868 /* I don't think ICLF_* names belong at the C interface
869 this makes the XS code think we have them, to let us avoid
870 putting function bodies in the XS code
872 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
873 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
876 #define i_log_enabled() 1
878 #define i_log_enabled() 0
881 #if i_int_hlines_testing()
883 typedef i_int_hlines *Imager__Internal__Hlines;
885 static i_int_hlines *
886 i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
887 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
888 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
893 static i_int_hlines *
894 i_int_hlines_new_img(i_img *im) {
895 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
896 i_int_init_hlines_img(result, im);
902 i_int_hlines_DESTROY(i_int_hlines *hlines) {
903 i_int_hlines_destroy(hlines);
907 #define i_int_hlines_CLONE_SKIP(cls) 1
909 static int seg_compare(const void *vleft, const void *vright) {
910 const i_int_hline_seg *left = vleft;
911 const i_int_hline_seg *right = vright;
913 return left->minx - right->minx;
917 i_int_hlines_dump(i_int_hlines *hlines) {
919 SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
920 i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
923 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
924 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
927 /* sort the segments, if any */
929 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
931 sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
932 for (i = 0; i < entry->count; ++i) {
933 sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx),
934 i_DFc(entry->segs[i].x_limit));
936 sv_catpv(dump, "\n");
946 i_sv_off_t(pTHX_ SV *sv) {
947 #if LSEEKSIZE > IVSIZE
948 return (off_t)SvNV(sv);
950 return (off_t)SvIV(sv);
955 i_new_sv_off_t(pTHX_ off_t off) {
956 #if LSEEKSIZE > IVSIZE
963 static im_pl_ext_funcs im_perl_funcs =
965 IMAGER_PL_API_VERSION,
967 ip_handle_quant_opts,
968 ip_cleanup_quant_opts,
972 #define PERL_PL_SET_GLOBAL_CALLBACKS \
973 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
975 #define IIM_new i_img_8_new
976 #define IIM_DESTROY i_img_destroy
980 #define i_exif_enabled() 1
982 #define i_exif_enabled() 0
985 /* trying to use more C style names, map them here */
986 #define i_io_DESTROY(ig) io_glue_destroy(ig)
988 #define i_img_get_width(im) ((im)->xsize)
989 #define i_img_get_height(im) ((im)->ysize)
991 #define i_img_epsilonf() (DBL_EPSILON * 4)
993 /* avoid some xsubpp strangeness */
996 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
999 ICL_new_internal(r,g,b,a)
1011 ICL_set_internal(cl,r,g,b,a)
1018 ICL_set_internal(cl, r, g, b, a);
1032 PUSHs(sv_2mortal(newSViv(cl->rgba.r)));
1033 PUSHs(sv_2mortal(newSViv(cl->rgba.g)));
1034 PUSHs(sv_2mortal(newSViv(cl->rgba.b)));
1035 PUSHs(sv_2mortal(newSViv(cl->rgba.a)));
1041 RETVAL = mymalloc(sizeof(i_color));
1043 i_hsv_to_rgb(RETVAL);
1051 RETVAL = mymalloc(sizeof(i_color));
1053 i_rgb_to_hsv(RETVAL);
1059 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
1061 Imager::Color::Float
1062 ICLF_new_internal(r, g, b, a)
1070 Imager::Color::Float cl
1074 Imager::Color::Float cl
1078 EXTEND(SP, MAXCHANNELS);
1079 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1080 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1081 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1085 ICLF_set_internal(cl,r,g,b,a)
1086 Imager::Color::Float cl
1099 Imager::Color::Float
1101 Imager::Color::Float c
1103 RETVAL = mymalloc(sizeof(i_fcolor));
1105 i_hsv_to_rgbf(RETVAL);
1109 Imager::Color::Float
1111 Imager::Color::Float c
1113 RETVAL = mymalloc(sizeof(i_fcolor));
1115 i_rgb_to_hsvf(RETVAL);
1119 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1133 MODULE = Imager PACKAGE = Imager
1147 io_new_buffer(data_sv)
1151 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1158 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1164 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1172 unsigned char* data;
1176 tlength = io_slurp(ig, &data);
1177 RETVAL = newSVpv((char *)data,tlength);
1184 i_set_image_file_limits(width, height, bytes)
1190 i_get_image_file_limits()
1192 i_img_dim width, height;
1195 if (i_get_image_file_limits(&width, &height, &bytes)) {
1197 PUSHs(sv_2mortal(newSViv(width)));
1198 PUSHs(sv_2mortal(newSViv(height)));
1199 PUSHs(sv_2mortal(newSVuv(bytes)));
1203 i_int_check_image_file_limits(width, height, channels, sample_size)
1210 MODULE = Imager PACKAGE = Imager::IO PREFIX = io_
1213 io_new_fd(class, fd)
1216 RETVAL = io_new_fd(fd);
1221 io_new_buffer(class, data_sv)
1225 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1232 io_new_cb(class, writecb, readcb, seekcb, closecb)
1238 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1243 io_new_bufchain(class)
1245 RETVAL = io_new_bufchain();
1250 io__new_perlio(class, io)
1253 RETVAL = im_io_new_perlio(aTHX_ io);
1261 unsigned char* data;
1265 tlength = io_slurp(ig, &data);
1266 RETVAL = newSVpv((char *)data,tlength);
1271 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1274 i_io_raw_write(ig, data_sv)
1281 data = SvPVbyte(data_sv, size);
1282 RETVAL = i_io_raw_write(ig, data, size);
1287 i_io_raw_read(ig, buffer_sv, size)
1296 croak("size negative in call to i_io_raw_read()");
1297 /* prevent an undefined value warning if they supplied an
1299 Orginally conditional on !SvOK(), but this will prevent the
1300 downgrade from croaking */
1301 sv_setpvn(buffer_sv, "", 0);
1303 if (SvUTF8(buffer_sv))
1304 sv_utf8_downgrade(buffer_sv, FALSE);
1306 buffer = SvGROW(buffer_sv, size+1);
1307 result = i_io_raw_read(ig, buffer, size);
1309 SvCUR_set(buffer_sv, result);
1310 *SvEND(buffer_sv) = '\0';
1311 SvPOK_only(buffer_sv);
1313 PUSHs(sv_2mortal(newSViv(result)));
1319 i_io_raw_read2(ig, size)
1328 croak("size negative in call to i_io_read2()");
1329 buffer_sv = newSV(size);
1330 buffer = SvGROW(buffer_sv, size+1);
1331 result = i_io_raw_read(ig, buffer, size);
1333 SvCUR_set(buffer_sv, result);
1334 *SvEND(buffer_sv) = '\0';
1335 SvPOK_only(buffer_sv);
1337 PUSHs(sv_2mortal(buffer_sv));
1341 SvREFCNT_dec(buffer_sv);
1345 i_io_raw_seek(ig, position, whence)
1359 i_io_CLONE_SKIP(...)
1361 (void)items; /* avoid unused warning for XS variable */
1388 i_io_seek(ig, off, whence)
1394 i_io_peekn(ig, size)
1402 buffer_sv = newSV(size+1);
1403 buffer = SvGROW(buffer_sv, size+1);
1404 result = i_io_peekn(ig, buffer, size);
1406 SvCUR_set(buffer_sv, result);
1407 *SvEND(buffer_sv) = '\0';
1408 SvPOK_only(buffer_sv);
1410 PUSHs(sv_2mortal(buffer_sv));
1414 SvREFCNT_dec(buffer_sv);
1418 i_io_read(ig, buffer_sv, size)
1427 croak("size negative in call to i_io_read()");
1428 /* prevent an undefined value warning if they supplied an
1430 Orginally conditional on !SvOK(), but this will prevent the
1431 downgrade from croaking */
1432 sv_setpvn(buffer_sv, "", 0);
1434 if (SvUTF8(buffer_sv))
1435 sv_utf8_downgrade(buffer_sv, FALSE);
1437 buffer = SvGROW(buffer_sv, size+1);
1438 result = i_io_read(ig, buffer, size);
1440 SvCUR_set(buffer_sv, result);
1441 *SvEND(buffer_sv) = '\0';
1442 SvPOK_only(buffer_sv);
1444 PUSHs(sv_2mortal(newSViv(result)));
1450 i_io_read2(ig, size)
1459 croak("size zero in call to read2()");
1460 buffer_sv = newSV(size);
1461 buffer = SvGROW(buffer_sv, size+1);
1462 result = i_io_read(ig, buffer, size);
1464 SvCUR_set(buffer_sv, result);
1465 *SvEND(buffer_sv) = '\0';
1466 SvPOK_only(buffer_sv);
1468 PUSHs(sv_2mortal(buffer_sv));
1472 SvREFCNT_dec(buffer_sv);
1476 i_io_gets(ig, size = 8192, eol = NEWLINE)
1486 croak("size too small in call to gets()");
1487 buffer_sv = sv_2mortal(newSV(size+1));
1488 buffer = SvPVX(buffer_sv);
1489 result = i_io_gets(ig, buffer, size+1, eol);
1491 SvCUR_set(buffer_sv, result);
1492 *SvEND(buffer_sv) = '\0';
1493 SvPOK_only(buffer_sv);
1499 i_io_write(ig, data_sv)
1506 data = SvPVbyte(data_sv, size);
1507 RETVAL = i_io_write(ig, data, size);
1512 i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
1517 i_io_set_buffered(ig, flag = 1)
1522 i_io_is_buffered(ig)
1533 MODULE = Imager PACKAGE = Imager
1544 while( (item=i_format_list[i++]) != NULL ) {
1546 PUSHs(sv_2mortal(newSVpv(item,0)));
1550 i_sametype(im, x, y)
1556 i_sametype_chans(im, x, y, channels)
1563 i_init_log(name_sv,level)
1567 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1569 RETVAL = i_init_log(name, level);
1574 i_log_entry(string,level)
1587 i_img_info(im,info);
1589 PUSHs(sv_2mortal(newSViv(info[0])));
1590 PUSHs(sv_2mortal(newSViv(info[1])));
1591 PUSHs(sv_2mortal(newSViv(info[2])));
1592 PUSHs(sv_2mortal(newSViv(info[3])));
1598 i_img_setmask(im,ch_mask)
1607 i_img_getchannels(im)
1616 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1624 i_img_get_height(im)
1629 i_img_is_monochrome(im)
1635 result = i_img_is_monochrome(im, &zero_is_white);
1637 if (GIMME_V == G_ARRAY) {
1640 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1649 i_line(im,x1,y1,x2,y2,val,endp)
1659 i_line_aa(im,x1,y1,x2,y2,val,endp)
1669 i_box(im,x1,y1,x2,y2,val)
1678 i_box_filled(im,x1,y1,x2,y2,val)
1687 i_box_filledf(im,x1,y1,x2,y2,val)
1693 Imager::Color::Float val
1696 i_box_cfill(im,x1,y1,x2,y2,fill)
1702 Imager::FillHandle fill
1705 i_arc(im,x,y,rad,d1,d2,val)
1715 i_arc_aa(im,x,y,rad,d1,d2,val)
1725 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1732 Imager::FillHandle fill
1735 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1742 Imager::FillHandle fill
1746 i_circle_aa(im,x,y,rad,val)
1754 i_circle_out(im,x,y,rad,val)
1762 i_circle_out_aa(im,x,y,rad,val)
1770 i_arc_out(im,x,y,rad,d1,d2,val)
1780 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1791 i_bezier_multi(im,x,y,val)
1800 if (size_x != size_y)
1801 croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1802 i_bezier_multi(im,size_x,x,y,val);
1805 i_poly_aa(im,x,y,val)
1814 if (size_x != size_y)
1815 croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1816 RETVAL = i_poly_aa(im, size_x, x, y, val);
1821 i_poly_aa_cfill(im, x, y, fill)
1825 Imager::FillHandle fill
1830 if (size_x != size_y)
1831 croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1832 RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
1837 i_flood_fill(im,seedx,seedy,dcol)
1844 i_flood_cfill(im,seedx,seedy,fill)
1848 Imager::FillHandle fill
1851 i_flood_fill_border(im,seedx,seedy,dcol, border)
1856 Imager::Color border
1859 i_flood_cfill_border(im,seedx,seedy,fill, border)
1863 Imager::FillHandle fill
1864 Imager::Color border
1868 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1880 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1897 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1908 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1921 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)
1937 i_combine(src_av, channels_av = NULL)
1941 i_img **imgs = NULL;
1943 int *channels = NULL;
1948 in_count = av_len(src_av) + 1;
1950 imgs = mymalloc(sizeof(i_img*) * in_count);
1951 channels = mymalloc(sizeof(int) * in_count);
1952 for (i = 0; i < in_count; ++i) {
1953 psv = av_fetch(src_av, i, 0);
1954 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1957 croak("imgs must contain only images");
1959 tmp = SvIV((SV*)SvRV(*psv));
1960 imgs[i] = INT2PTR(i_img*, tmp);
1962 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1964 channels[i] = SvIV(*psv);
1971 RETVAL = i_combine(imgs, channels, in_count);
1978 i_flipxy(im, direction)
1983 i_rotate90(im, degrees)
1988 i_rotate_exact(im, amount, ...)
1992 i_color *backp = NULL;
1993 i_fcolor *fbackp = NULL;
1997 /* extract the bg colors if any */
1998 /* yes, this is kind of strange */
1999 for (i = 2; i < items; ++i) {
2001 if (sv_derived_from(sv1, "Imager::Color")) {
2002 IV tmp = SvIV((SV*)SvRV(sv1));
2003 backp = INT2PTR(i_color *, tmp);
2005 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2006 IV tmp = SvIV((SV*)SvRV(sv1));
2007 fbackp = INT2PTR(i_fcolor *, tmp);
2010 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
2015 i_matrix_transform(im, xsize, ysize, matrix_av, ...)
2025 i_color *backp = NULL;
2026 i_fcolor *fbackp = NULL;
2028 len=av_len(matrix_av)+1;
2031 for (i = 0; i < len; ++i) {
2032 sv1=(*(av_fetch(matrix_av,i,0)));
2033 matrix[i] = SvNV(sv1);
2037 /* extract the bg colors if any */
2038 /* yes, this is kind of strange */
2039 for (i = 4; i < items; ++i) {
2041 if (sv_derived_from(sv1, "Imager::Color")) {
2042 IV tmp = SvIV((SV*)SvRV(sv1));
2043 backp = INT2PTR(i_color *, tmp);
2045 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2046 IV tmp = SvIV((SV*)SvRV(sv1));
2047 fbackp = INT2PTR(i_fcolor *, tmp);
2050 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2055 i_gaussian(im,stdev)
2060 i_unsharp_mask(im,stdev,scale)
2075 len = av_len(coef) + 1;
2076 c_coef=mymalloc( len * sizeof(double) );
2077 for(i = 0; i < len; i++) {
2078 sv1 = (*(av_fetch(coef, i, 0)));
2079 c_coef[i] = (double)SvNV(sv1);
2081 RETVAL = i_conv(im, c_coef, len);
2087 i_convert(src, avmain)
2099 outchan = av_len(avmain)+1;
2100 /* find the biggest */
2102 for (j=0; j < outchan; ++j) {
2103 temp = av_fetch(avmain, j, 0);
2104 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2105 avsub = (AV*)SvRV(*temp);
2106 len = av_len(avsub)+1;
2111 i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2115 coeff = mymalloc(sizeof(double) * outchan * inchan);
2116 for (j = 0; j < outchan; ++j) {
2117 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2118 len = av_len(avsub)+1;
2119 for (i = 0; i < len; ++i) {
2120 temp = av_fetch(avsub, i, 0);
2122 coeff[i+j*inchan] = SvNV(*temp);
2124 coeff[i+j*inchan] = 0;
2127 coeff[i++ + j*inchan] = 0;
2129 RETVAL = i_convert(src, coeff, outchan, inchan);
2140 unsigned int mask = 0;
2145 unsigned char (*maps)[256];
2147 len = av_len(pmaps_av)+1;
2148 if (im->channels < len)
2150 maps = mymalloc( len * sizeof(unsigned char [256]) );
2151 for (j=0; j<len ; j++) {
2152 temp = av_fetch(pmaps_av, j, 0);
2153 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2154 avsub = (AV*)SvRV(*temp);
2155 if(av_len(avsub) != 255)
2158 for (i=0; i<256 ; i++) {
2160 temp = av_fetch(avsub, i, 0);
2161 val = temp ? SvIV(*temp) : 0;
2163 if (val>255) val = 255;
2168 i_map(im, maps, mask);
2180 i_img_diffd(im1,im2)
2185 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2195 _is_color_object(sv)
2199 RETVAL = SvOK(sv) && SvROK(sv) &&
2200 (sv_derived_from(sv, "Imager::Color")
2201 || sv_derived_from(sv, "Imager::Color::Float"));
2213 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2215 #define TT_DESTROY(handle) i_tt_destroy(handle)
2219 Imager::Font::TT handle
2224 (void)items; /* avoid unused warning */
2230 MODULE = Imager PACKAGE = Imager
2234 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
2235 Imager::Font::TT handle
2249 str = SvPV(str_sv, len);
2254 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2255 len, smooth, utf8, align);
2261 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
2262 Imager::Font::TT handle
2276 str = SvPV(str_sv, len);
2281 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2282 smooth, utf8, align);
2288 i_tt_bbox(handle,point,str_sv,utf8)
2289 Imager::Font::TT handle
2294 i_img_dim cords[BOUNDING_BOX_COUNT];
2300 str = SvPV(str_sv, len);
2305 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2307 for (i = 0; i < rc; ++i) {
2308 PUSHs(sv_2mortal(newSViv(cords[i])));
2313 i_tt_has_chars(handle, text_sv, utf8)
2314 Imager::Font::TT handle
2325 text = SvPV(text_sv, len);
2327 if (SvUTF8(text_sv))
2330 work = mymalloc(len);
2331 count = i_tt_has_chars(handle, text, len, utf8, work);
2332 if (GIMME_V == G_ARRAY) {
2334 for (i = 0; i < count; ++i) {
2335 PUSHs(boolSV(work[i]));
2340 PUSHs(sv_2mortal(newSVpv(work, count)));
2345 i_tt_dump_names(handle)
2346 Imager::Font::TT handle
2349 i_tt_face_name(handle)
2350 Imager::Font::TT handle
2355 len = i_tt_face_name(handle, name, sizeof(name));
2358 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2362 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2363 Imager::Font::TT handle
2375 text = SvPV(text_sv, work_len);
2377 if (SvUTF8(text_sv))
2384 ch = i_utf8_advance(&text, &len);
2386 i_push_error(0, "invalid UTF8 character");
2394 EXTEND(SP, count+1);
2395 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2396 ST(count) = sv_2mortal(newSVpv(name, 0));
2399 ST(count) = &PL_sv_undef;
2408 i_test_format_probe(ig, length)
2413 i_readpnm_wiol(ig, allow_incomplete)
2415 int allow_incomplete
2419 i_readpnm_multi_wiol(ig, allow_incomplete)
2421 int allow_incomplete
2427 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2430 for (i = 0; i < count; ++i) {
2431 SV *sv = sv_newmortal();
2432 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2439 i_writeppm_wiol(im, ig)
2448 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2457 i_writeraw_wiol(im,ig)
2462 i_writebmp_wiol(im,ig)
2467 i_readbmp_wiol(ig, allow_incomplete=0)
2469 int allow_incomplete
2473 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2482 idlen = SvCUR(ST(4));
2483 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2489 i_readtga_wiol(ig, length)
2497 i_scaleaxis(im,Value,Axis)
2503 i_scale_nn(im,scx,scy)
2509 i_scale_mixing(im, width, height)
2519 i_count_colors(im,maxc)
2524 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2529 unsigned int * col_usage = NULL;
2532 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2533 EXTEND(SP, col_cnt);
2534 for (i = 0; i < col_cnt; i++) {
2535 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2542 i_transform(im, opx, opy, parm)
2548 STRLEN size_opx, size_opy, size_parm;
2551 result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
2553 SV *result_sv = sv_newmortal();
2555 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2560 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2586 in_imgs_count = av_len(av_in_imgs)+1;
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("sv_in_img must contain only images");
2593 if (in_imgs_count > 0) {
2594 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2595 for (i = 0; i < in_imgs_count; ++i) {
2596 sv1 = *av_fetch(av_in_imgs,i,0);
2597 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2598 croak("Parameter 5 must contain only images");
2600 tmp = SvIV((SV*)SvRV(sv1));
2601 in_imgs[i] = INT2PTR(i_img*, tmp);
2605 /* no input images */
2608 /* default the output size from the first input if possible */
2610 width = SvIV(sv_width);
2611 else if (in_imgs_count)
2612 width = in_imgs[0]->xsize;
2614 croak("No output image width supplied");
2616 if (SvOK(sv_height))
2617 height = SvIV(sv_height);
2618 else if (in_imgs_count)
2619 height = in_imgs[0]->ysize;
2621 croak("No output image height supplied");
2623 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2624 if (ops_len % sizeof(struct rm_op))
2625 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2626 ops_count = ops_len / sizeof(struct rm_op);
2628 n_regs_count = av_len(av_n_regs)+1;
2629 n_regs = mymalloc(n_regs_count * sizeof(double));
2630 for (i = 0; i < n_regs_count; ++i) {
2631 sv1 = *av_fetch(av_n_regs,i,0);
2633 n_regs[i] = SvNV(sv1);
2635 c_regs_count = av_len(av_c_regs)+1;
2636 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2637 /* I don't bother initializing the colou?r registers */
2639 result=i_transform2(width, height, channels, ops, ops_count,
2640 n_regs, n_regs_count,
2641 c_regs, c_regs_count, in_imgs, in_imgs_count);
2647 SV *result_sv = sv_newmortal();
2649 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2655 i_contrast(im,intensity)
2668 i_noise(im,amount,type)
2674 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2684 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2703 i_postlevels(im,levels)
2713 i_watermark(im,wmark,tx,ty,pixdiff)
2715 Imager::ImgRaw wmark
2722 i_autolevels(im,lsat,usat,skew)
2729 i_autolevels_mono(im,lsat,usat)
2735 i_radnoise(im,xo,yo,rscale,ascale)
2743 i_turbnoise(im, xo, yo, scale)
2751 i_gradgen(im, xo, yo, ac, dmeasure)
2762 if (size_xo != size_yo || size_xo != size_ac)
2763 croak("i_gradgen: x, y and color arrays must be the same size");
2765 croak("Usage: i_gradgen array refs must have more than 1 entry each");
2766 i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
2769 i_diff_image(im, im2, mindist=0)
2775 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2785 double ssample_param
2789 i_fountain_seg *segs;
2791 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2792 croak("i_fountain: argument 11 must be an array ref");
2794 asegs = (AV *)SvRV(ST(10));
2795 segs = load_fount_segs(aTHX_ asegs, &count);
2796 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2797 super_sample, ssample_param, count, segs);
2803 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2812 double ssample_param
2816 i_fountain_seg *segs;
2818 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2819 croak("i_fountain: argument 11 must be an array ref");
2821 asegs = (AV *)SvRV(ST(9));
2822 segs = load_fount_segs(aTHX_ asegs, &count);
2823 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2824 super_sample, ssample_param, count, segs);
2830 i_new_fill_opacity(other_fill, alpha_mult)
2831 Imager::FillHandle other_fill
2842 errors = i_errors();
2844 while (errors[i].msg) {
2846 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2847 if (!av_store(av, 0, sv)) {
2850 sv = newSViv(errors[i].code);
2851 if (!av_store(av, 1, sv)) {
2854 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2862 i_push_error(code, msg)
2867 i_nearest_color(im, ...)
2882 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2883 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2884 croak("i_nearest_color: Second argument must be an array ref");
2885 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2886 croak("i_nearest_color: Third argument must be an array ref");
2887 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2888 croak("i_nearest_color: Fourth argument must be an array ref");
2889 axx = (AV *)SvRV(ST(1));
2890 ayy = (AV *)SvRV(ST(2));
2891 ac = (AV *)SvRV(ST(3));
2892 dmeasure = (int)SvIV(ST(4));
2894 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2895 num = num <= av_len(ac) ? num : av_len(ac);
2897 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2898 xo = mymalloc( sizeof(i_img_dim) * num );
2899 yo = mymalloc( sizeof(i_img_dim) * num );
2900 ival = mymalloc( sizeof(i_color) * num );
2901 for(i = 0; i<num; i++) {
2902 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2903 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2904 sv = *av_fetch(ac, i, 0);
2905 if ( !sv_derived_from(sv, "Imager::Color") ) {
2906 free(axx); free(ayy); free(ac);
2907 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2909 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2911 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2925 rc=DSO_open(filename,&evstr);
2929 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2930 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2933 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2939 DSO_close(dso_handle)
2943 DSO_funclist(dso_handle_v)
2947 DSO_handle *dso_handle;
2948 func_ptr *functions;
2950 dso_handle=(DSO_handle*)dso_handle_v;
2951 functions = DSO_funclist(dso_handle);
2953 while( functions[i].name != NULL) {
2955 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2957 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2961 DSO_call(handle,func_index,hv)
2966 DSO_call( (DSO_handle *)handle,func_index,hv);
2969 i_get_pixel(im, x, y)
2974 RETVAL = (i_color *)mymalloc(sizeof(i_color));
2975 if (i_gpix(im, x, y, RETVAL) != 0) {
2984 i_ppix(im, x, y, cl)
2991 i_img_pal_new(x, y, channels, maxpal)
2998 i_img_to_pal(src, quant)
3004 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3005 croak("i_img_to_pal: second argument must be a hash ref");
3006 hv = (HV *)SvRV(ST(1));
3007 memset(&quant, 0, sizeof(quant));
3009 quant.mc_size = 256;
3010 ip_handle_quant_opts(aTHX_ &quant, hv);
3011 RETVAL = i_img_to_pal(src, &quant);
3013 ip_copy_colors_back(aTHX_ hv, &quant);
3015 ip_cleanup_quant_opts(aTHX_ &quant);
3024 i_img_make_palette(HV *quant_hv, ...)
3026 size_t count = items - 1;
3028 i_img **imgs = NULL;
3032 croak("Please supply at least one image (%d)", (int)count);
3033 imgs = mymalloc(sizeof(i_img *) * count);
3034 for (i = 0; i < count; ++i) {
3035 SV *img_sv = ST(i + 1);
3036 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3037 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3041 croak("Image %d is not an image object", (int)i+1);
3044 memset(&quant, 0, sizeof(quant));
3046 quant.mc_size = 256;
3047 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3048 i_quant_makemap(&quant, imgs, count);
3049 EXTEND(SP, quant.mc_count);
3050 for (i = 0; i < quant.mc_count; ++i) {
3051 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3054 ip_cleanup_quant_opts(aTHX_ &quant);
3068 work = mymalloc((r-l) * sizeof(i_palidx));
3069 count = i_gpal(im, l, r, y, work);
3070 if (GIMME_V == G_ARRAY) {
3072 for (i = 0; i < count; ++i) {
3073 PUSHs(sv_2mortal(newSViv(work[i])));
3078 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3083 if (GIMME_V != G_ARRAY) {
3085 PUSHs(&PL_sv_undef);
3090 i_ppal(im, l, y, ...)
3099 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3100 for (i=0; i < items-3; ++i) {
3101 work[i] = SvIV(ST(i+3));
3103 validate_i_ppal(im, work, items - 3);
3104 RETVAL = i_ppal(im, l, l+items-3, y, work);
3113 i_ppal_p(im, l, y, data)
3119 i_palidx const *work;
3122 work = (i_palidx const *)SvPV(data, len);
3123 len /= sizeof(i_palidx);
3125 validate_i_ppal(im, work, len);
3126 RETVAL = i_ppal(im, l, l+len, y, work);
3135 i_addcolors(im, ...)
3142 croak("i_addcolors: no colors to add");
3143 colors = mymalloc((items-1) * sizeof(i_color));
3144 for (i=0; i < items-1; ++i) {
3145 if (sv_isobject(ST(i+1))
3146 && sv_derived_from(ST(i+1), "Imager::Color")) {
3147 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3148 colors[i] = *INT2PTR(i_color *, tmp);
3152 croak("i_addcolor: pixels must be Imager::Color objects");
3155 RETVAL = i_addcolors(im, colors, items-1);
3160 i_setcolors(im, index, ...)
3168 croak("i_setcolors: no colors to add");
3169 colors = mymalloc((items-2) * sizeof(i_color));
3170 for (i=0; i < items-2; ++i) {
3171 if (sv_isobject(ST(i+2))
3172 && sv_derived_from(ST(i+2), "Imager::Color")) {
3173 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3174 colors[i] = *INT2PTR(i_color *, tmp);
3178 croak("i_setcolors: pixels must be Imager::Color objects");
3181 RETVAL = i_setcolors(im, index, colors, items-2);
3187 i_getcolors(im, index, count=1)
3196 croak("i_getcolors: count must be positive");
3197 colors = malloc_temp(aTHX_ sizeof(i_color) * count);
3198 if (i_getcolors(im, index, colors, count)) {
3200 for (i = 0; i < count; ++i) {
3201 SV *sv = make_i_color_sv(aTHX_ colors+i);
3215 i_findcolor(im, color)
3219 if (!i_findcolor(im, color, &RETVAL)) {
3238 i_gsamp(im, l, r, y, channels)
3243 i_channel_list channels
3249 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count);
3250 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3251 if (GIMME_V == G_ARRAY) {
3253 for (i = 0; i < count; ++i)
3254 PUSHs(sv_2mortal(newSViv(data[i])));
3258 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3263 if (GIMME_V != G_ARRAY) {
3269 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3277 i_channel_list channels
3284 croak("No channel numbers supplied to g_samp()");
3286 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3287 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3288 for (i = 0; i < count; ++i) {
3289 av_store(target, i+offset, newSVuv(data[i]));
3301 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3306 i_channel_list channels
3308 i_img_dim data_offset
3309 i_img_dim pixel_count
3318 data_count = av_len(data_av) + 1;
3319 if (data_offset < 0) {
3320 croak("data_offset must be non-negative");
3322 if (data_offset > data_count) {
3323 croak("data_offset greater than number of samples supplied");
3325 if (pixel_count == -1 ||
3326 data_offset + pixel_count * channels.count > data_count) {
3327 pixel_count = (data_count - data_offset) / channels.count;
3330 data_used = pixel_count * channels.count;
3331 data = mymalloc(sizeof(unsigned) * data_count);
3332 for (i = 0; i < data_used; ++i)
3333 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3335 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3336 channels.count, bits);
3344 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3348 i_channel_list channels
3357 i_push_error(0, "offset must be non-negative");
3361 if (offset > data.count) {
3362 i_push_error(0, "offset greater than number of samples supplied");
3365 data.samples += offset;
3366 data.count -= offset;
3369 width * channels.count > data.count) {
3370 width = data.count / channels.count;
3373 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3378 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3382 i_channel_list channels
3391 i_push_error(0, "offset must be non-negative");
3395 if (offset > data.count) {
3396 i_push_error(0, "offset greater than number of samples supplied");
3399 data.samples += offset;
3400 data.count -= offset;
3403 width * channels.count > data.count) {
3404 width = data.count / channels.count;
3407 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3412 i_img_masked_new(targ, mask, x, y, w, h)
3422 if (!sv_isobject(ST(1))
3423 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3424 croak("i_img_masked_new: parameter 2 must undef or an image");
3426 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3430 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3435 i_plin(im, l, y, ...)
3446 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3447 /* supplied as a byte string */
3448 work = (i_color *)SvPV(ST(3), len);
3449 count = len / sizeof(i_color);
3450 if (count * sizeof(i_color) != len) {
3451 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3453 RETVAL = i_plin(im, l, l+count, y, work);
3456 work = mymalloc(sizeof(i_color) * (items-3));
3457 for (i=0; i < items-3; ++i) {
3458 if (sv_isobject(ST(i+3))
3459 && sv_derived_from(ST(i+3), "Imager::Color")) {
3460 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3461 work[i] = *INT2PTR(i_color *, tmp);
3465 croak("i_plin: pixels must be Imager::Color objects");
3468 RETVAL = i_plin(im, l, l+items-3, y, work);
3479 i_ppixf(im, x, y, cl)
3483 Imager::Color::Float cl
3486 i_gsampf(im, l, r, y, channels)
3491 i_channel_list channels
3497 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3498 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3499 if (GIMME_V == G_ARRAY) {
3501 for (i = 0; i < count; ++i)
3502 PUSHs(sv_2mortal(newSVnv(data[i])));
3506 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3511 if (GIMME_V != G_ARRAY) {
3517 i_plinf(im, l, y, ...)
3528 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3529 /* supplied as a byte string */
3530 work = (i_fcolor *)SvPV(ST(3), len);
3531 count = len / sizeof(i_fcolor);
3532 if (count * sizeof(i_fcolor) != len) {
3533 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3535 RETVAL = i_plinf(im, l, l+count, y, work);
3538 work = mymalloc(sizeof(i_fcolor) * (items-3));
3539 for (i=0; i < items-3; ++i) {
3540 if (sv_isobject(ST(i+3))
3541 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3542 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3543 work[i] = *INT2PTR(i_fcolor *, tmp);
3547 croak("i_plinf: pixels must be Imager::Color::Float objects");
3551 RETVAL = i_plinf(im, l, l+items-3, y, work);
3561 Imager::Color::Float
3567 RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3568 if (i_gpixf(im, x, y, RETVAL) != 0) {
3586 vals = mymalloc((r-l) * sizeof(i_color));
3587 memset(vals, 0, (r-l) * sizeof(i_color));
3588 count = i_glin(im, l, r, y, vals);
3589 if (GIMME_V == G_ARRAY) {
3591 for (i = 0; i < count; ++i) {
3592 SV *sv = make_i_color_sv(aTHX_ vals+i);
3598 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3604 i_glinf(im, l, r, y)
3614 for (i = 0; i < MAXCHANNELS; ++i)
3615 zero.channel[i] = 0;
3617 vals = mymalloc((r-l) * sizeof(i_fcolor));
3618 for (i = 0; i < r-l; ++i)
3620 count = i_glinf(im, l, r, y, vals);
3621 if (GIMME_V == G_ARRAY) {
3623 for (i = 0; i < count; ++i) {
3625 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3627 sv = sv_newmortal();
3628 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3634 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3640 i_img_8_new(x, y, ch)
3646 i_img_16_new(x, y, ch)
3656 i_img_double_new(x, y, ch)
3666 i_tags_addn(im, name_sv, code, idata)
3675 SvGETMAGIC(name_sv);
3677 name = SvPV_nomg(name_sv, len);
3680 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3685 i_tags_add(im, name_sv, code, data_sv, idata)
3696 SvGETMAGIC(name_sv);
3698 name = SvPV_nomg(name_sv, len);
3701 SvGETMAGIC(data_sv);
3703 data = SvPV(data_sv, len);
3708 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3713 i_tags_find(im, name, start)
3720 if (i_tags_find(&im->tags, name, start, &entry)) {
3729 i_tags_findn(im, code, start)
3736 if (i_tags_findn(&im->tags, code, start, &entry)) {
3746 i_tags_delete(im, entry)
3750 RETVAL = i_tags_delete(&im->tags, entry);
3755 i_tags_delbyname(im, name)
3759 RETVAL = i_tags_delbyname(&im->tags, name);
3764 i_tags_delbycode(im, code)
3768 RETVAL = i_tags_delbycode(&im->tags, code);
3773 i_tags_get(im, index)
3777 if (index >= 0 && index < im->tags.count) {
3778 i_img_tag *entry = im->tags.tags + index;
3782 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3785 PUSHs(sv_2mortal(newSViv(entry->code)));
3788 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3791 PUSHs(sv_2mortal(newSViv(entry->idata)));
3796 i_tags_get_string(im, what_sv)
3800 char const *name = NULL;
3804 if (SvIOK(what_sv)) {
3805 code = SvIV(what_sv);
3809 name = SvPV_nolen(what_sv);
3812 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3814 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3821 RETVAL = im->tags.count;
3827 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3831 Imager::FillHandle fill
3834 IFILL_CLONE_SKIP(...)
3836 (void)items; /* avoid unused warning for XS variable */
3841 MODULE = Imager PACKAGE = Imager
3844 i_new_fill_solid(cl, combine)
3849 i_new_fill_solidf(cl, combine)
3850 Imager::Color::Float cl
3854 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3863 unsigned char *cust_hatch;
3866 SvGETMAGIC(cust_hatch_sv);
3867 if (SvOK(cust_hatch_sv)) {
3868 cust_hatch = (unsigned char *)SvPV_nomg(cust_hatch_sv, len);
3872 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3877 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3878 Imager::Color::Float fg
3879 Imager::Color::Float bg
3886 unsigned char *cust_hatch;
3889 SvGETMAGIC(cust_hatch_sv);
3890 if (SvOK(cust_hatch_sv)) {
3891 cust_hatch = (unsigned char *)SvPV(cust_hatch_sv, len);
3895 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3900 i_new_fill_image(src, matrix_sv, xoff, yoff, combine)
3914 SvGETMAGIC(matrix_sv);
3915 if (!SvOK(matrix_sv)) {
3919 if (!SvROK(matrix_sv) || SvTYPE(SvRV(matrix_sv)) != SVt_PVAV)
3920 croak("i_new_fill_image: matrix parameter must be an arrayref or undef");
3921 av=(AV*)SvRV(matrix_sv);
3925 for (i = 0; i < len; ++i) {
3926 sv1=(*(av_fetch(av,i,0)));
3927 matrix[i] = SvNV(sv1);
3933 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3937 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3939 # this class is only exposed for testing
3942 i_int_hlines_testing()
3944 #if i_int_hlines_testing()
3946 Imager::Internal::Hlines
3947 i_int_hlines_new(start_y, count_y, start_x, count_x)
3953 Imager::Internal::Hlines
3954 i_int_hlines_new_img(im)
3958 i_int_hlines_add(hlines, y, minx, width)
3959 Imager::Internal::Hlines hlines
3965 i_int_hlines_DESTROY(hlines)
3966 Imager::Internal::Hlines hlines
3969 i_int_hlines_dump(hlines)
3970 Imager::Internal::Hlines hlines
3973 i_int_hlines_CLONE_SKIP(cls)
3977 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
3980 im_context_DESTROY(ctx)
3983 #ifdef PERL_IMPLICIT_CONTEXT
3986 im_context_CLONE(...)
3990 /* the following sv_setref_pv() will free this inc */
3991 im_context_refinc(MY_CXT.ctx, "CLONE");
3992 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
3993 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
3998 PERL_SET_GLOBAL_CALLBACKS;
3999 PERL_PL_SET_GLOBAL_CALLBACKS;
4000 #ifdef PERL_IMPLICIT_CONTEXT
4006 start_context(aTHX);
4007 im_get_context = perl_get_context;