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_aa_fill(im,x,y,rad,fill)
1759 Imager::FillHandle fill
1762 i_circle_out(im,x,y,rad,val)
1770 i_circle_out_aa(im,x,y,rad,val)
1778 i_arc_out(im,x,y,rad,d1,d2,val)
1788 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1799 i_bezier_multi(im,x,y,val)
1808 if (size_x != size_y)
1809 croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1810 i_bezier_multi(im,size_x,x,y,val);
1813 i_poly_aa(im,x,y,val)
1822 if (size_x != size_y)
1823 croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1824 RETVAL = i_poly_aa(im, size_x, x, y, val);
1829 i_poly_aa_cfill(im, x, y, fill)
1833 Imager::FillHandle fill
1838 if (size_x != size_y)
1839 croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1840 RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
1845 i_flood_fill(im,seedx,seedy,dcol)
1852 i_flood_cfill(im,seedx,seedy,fill)
1856 Imager::FillHandle fill
1859 i_flood_fill_border(im,seedx,seedy,dcol, border)
1864 Imager::Color border
1867 i_flood_cfill_border(im,seedx,seedy,fill, border)
1871 Imager::FillHandle fill
1872 Imager::Color border
1876 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1888 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1905 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1916 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1929 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)
1945 i_combine(src_av, channels_av = NULL)
1949 i_img **imgs = NULL;
1951 int *channels = NULL;
1956 in_count = av_len(src_av) + 1;
1958 imgs = mymalloc(sizeof(i_img*) * in_count);
1959 channels = mymalloc(sizeof(int) * in_count);
1960 for (i = 0; i < in_count; ++i) {
1961 psv = av_fetch(src_av, i, 0);
1962 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1965 croak("imgs must contain only images");
1967 tmp = SvIV((SV*)SvRV(*psv));
1968 imgs[i] = INT2PTR(i_img*, tmp);
1970 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1972 channels[i] = SvIV(*psv);
1979 RETVAL = i_combine(imgs, channels, in_count);
1986 i_flipxy(im, direction)
1991 i_rotate90(im, degrees)
1996 i_rotate_exact(im, amount, ...)
2000 i_color *backp = NULL;
2001 i_fcolor *fbackp = NULL;
2005 /* extract the bg colors if any */
2006 /* yes, this is kind of strange */
2007 for (i = 2; i < items; ++i) {
2009 if (sv_derived_from(sv1, "Imager::Color")) {
2010 IV tmp = SvIV((SV*)SvRV(sv1));
2011 backp = INT2PTR(i_color *, tmp);
2013 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2014 IV tmp = SvIV((SV*)SvRV(sv1));
2015 fbackp = INT2PTR(i_fcolor *, tmp);
2018 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
2023 i_matrix_transform(im, xsize, ysize, matrix_av, ...)
2033 i_color *backp = NULL;
2034 i_fcolor *fbackp = NULL;
2036 len=av_len(matrix_av)+1;
2039 for (i = 0; i < len; ++i) {
2040 sv1=(*(av_fetch(matrix_av,i,0)));
2041 matrix[i] = SvNV(sv1);
2045 /* extract the bg colors if any */
2046 /* yes, this is kind of strange */
2047 for (i = 4; i < items; ++i) {
2049 if (sv_derived_from(sv1, "Imager::Color")) {
2050 IV tmp = SvIV((SV*)SvRV(sv1));
2051 backp = INT2PTR(i_color *, tmp);
2053 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2054 IV tmp = SvIV((SV*)SvRV(sv1));
2055 fbackp = INT2PTR(i_fcolor *, tmp);
2058 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2063 i_gaussian(im,stdev)
2068 i_unsharp_mask(im,stdev,scale)
2083 len = av_len(coef) + 1;
2084 c_coef=mymalloc( len * sizeof(double) );
2085 for(i = 0; i < len; i++) {
2086 sv1 = (*(av_fetch(coef, i, 0)));
2087 c_coef[i] = (double)SvNV(sv1);
2089 RETVAL = i_conv(im, c_coef, len);
2095 i_convert(src, avmain)
2107 outchan = av_len(avmain)+1;
2108 /* find the biggest */
2110 for (j=0; j < outchan; ++j) {
2111 temp = av_fetch(avmain, j, 0);
2112 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2113 avsub = (AV*)SvRV(*temp);
2114 len = av_len(avsub)+1;
2119 i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2123 coeff = mymalloc(sizeof(double) * outchan * inchan);
2124 for (j = 0; j < outchan; ++j) {
2125 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2126 len = av_len(avsub)+1;
2127 for (i = 0; i < len; ++i) {
2128 temp = av_fetch(avsub, i, 0);
2130 coeff[i+j*inchan] = SvNV(*temp);
2132 coeff[i+j*inchan] = 0;
2135 coeff[i++ + j*inchan] = 0;
2137 RETVAL = i_convert(src, coeff, outchan, inchan);
2148 unsigned int mask = 0;
2153 unsigned char (*maps)[256];
2155 len = av_len(pmaps_av)+1;
2156 if (im->channels < len)
2158 maps = mymalloc( len * sizeof(unsigned char [256]) );
2159 for (j=0; j<len ; j++) {
2160 temp = av_fetch(pmaps_av, j, 0);
2161 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2162 avsub = (AV*)SvRV(*temp);
2163 if(av_len(avsub) != 255)
2166 for (i=0; i<256 ; i++) {
2168 temp = av_fetch(avsub, i, 0);
2169 val = temp ? SvIV(*temp) : 0;
2171 if (val>255) val = 255;
2176 i_map(im, maps, mask);
2188 i_img_diffd(im1,im2)
2193 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2203 _is_color_object(sv)
2207 RETVAL = SvOK(sv) && SvROK(sv) &&
2208 (sv_derived_from(sv, "Imager::Color")
2209 || sv_derived_from(sv, "Imager::Color::Float"));
2221 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2223 #define TT_DESTROY(handle) i_tt_destroy(handle)
2227 Imager::Font::TT handle
2232 (void)items; /* avoid unused warning */
2238 MODULE = Imager PACKAGE = Imager
2242 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
2243 Imager::Font::TT handle
2257 str = SvPV(str_sv, len);
2262 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2263 len, smooth, utf8, align);
2269 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
2270 Imager::Font::TT handle
2284 str = SvPV(str_sv, len);
2289 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2290 smooth, utf8, align);
2296 i_tt_bbox(handle,point,str_sv,utf8)
2297 Imager::Font::TT handle
2302 i_img_dim cords[BOUNDING_BOX_COUNT];
2308 str = SvPV(str_sv, len);
2313 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2315 for (i = 0; i < rc; ++i) {
2316 PUSHs(sv_2mortal(newSViv(cords[i])));
2321 i_tt_has_chars(handle, text_sv, utf8)
2322 Imager::Font::TT handle
2333 text = SvPV(text_sv, len);
2335 if (SvUTF8(text_sv))
2338 work = mymalloc(len);
2339 count = i_tt_has_chars(handle, text, len, utf8, work);
2340 if (GIMME_V == G_ARRAY) {
2342 for (i = 0; i < count; ++i) {
2343 PUSHs(boolSV(work[i]));
2348 PUSHs(sv_2mortal(newSVpv(work, count)));
2353 i_tt_dump_names(handle)
2354 Imager::Font::TT handle
2357 i_tt_face_name(handle)
2358 Imager::Font::TT handle
2363 len = i_tt_face_name(handle, name, sizeof(name));
2366 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2370 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2371 Imager::Font::TT handle
2383 text = SvPV(text_sv, work_len);
2385 if (SvUTF8(text_sv))
2392 ch = i_utf8_advance(&text, &len);
2394 i_push_error(0, "invalid UTF8 character");
2402 EXTEND(SP, count+1);
2403 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2404 ST(count) = sv_2mortal(newSVpv(name, 0));
2407 ST(count) = &PL_sv_undef;
2416 i_test_format_probe(ig, length)
2421 i_readpnm_wiol(ig, allow_incomplete)
2423 int allow_incomplete
2427 i_readpnm_multi_wiol(ig, allow_incomplete)
2429 int allow_incomplete
2435 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2438 for (i = 0; i < count; ++i) {
2439 SV *sv = sv_newmortal();
2440 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2447 i_writeppm_wiol(im, ig)
2456 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2465 i_writeraw_wiol(im,ig)
2470 i_writebmp_wiol(im,ig)
2475 i_readbmp_wiol(ig, allow_incomplete=0)
2477 int allow_incomplete
2481 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2490 idlen = SvCUR(ST(4));
2491 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2497 i_readtga_wiol(ig, length)
2505 i_scaleaxis(im,Value,Axis)
2511 i_scale_nn(im,scx,scy)
2517 i_scale_mixing(im, width, height)
2527 i_count_colors(im,maxc)
2532 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2537 unsigned int * col_usage = NULL;
2540 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2541 EXTEND(SP, col_cnt);
2542 for (i = 0; i < col_cnt; i++) {
2543 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2550 i_transform(im, opx, opy, parm)
2556 STRLEN size_opx, size_opy, size_parm;
2559 result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
2561 SV *result_sv = sv_newmortal();
2563 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2568 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2594 in_imgs_count = av_len(av_in_imgs)+1;
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("sv_in_img must contain only images");
2601 if (in_imgs_count > 0) {
2602 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2603 for (i = 0; i < in_imgs_count; ++i) {
2604 sv1 = *av_fetch(av_in_imgs,i,0);
2605 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2606 croak("Parameter 5 must contain only images");
2608 tmp = SvIV((SV*)SvRV(sv1));
2609 in_imgs[i] = INT2PTR(i_img*, tmp);
2613 /* no input images */
2616 /* default the output size from the first input if possible */
2618 width = SvIV(sv_width);
2619 else if (in_imgs_count)
2620 width = in_imgs[0]->xsize;
2622 croak("No output image width supplied");
2624 if (SvOK(sv_height))
2625 height = SvIV(sv_height);
2626 else if (in_imgs_count)
2627 height = in_imgs[0]->ysize;
2629 croak("No output image height supplied");
2631 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2632 if (ops_len % sizeof(struct rm_op))
2633 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2634 ops_count = ops_len / sizeof(struct rm_op);
2636 n_regs_count = av_len(av_n_regs)+1;
2637 n_regs = mymalloc(n_regs_count * sizeof(double));
2638 for (i = 0; i < n_regs_count; ++i) {
2639 sv1 = *av_fetch(av_n_regs,i,0);
2641 n_regs[i] = SvNV(sv1);
2643 c_regs_count = av_len(av_c_regs)+1;
2644 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2645 /* I don't bother initializing the colou?r registers */
2647 result=i_transform2(width, height, channels, ops, ops_count,
2648 n_regs, n_regs_count,
2649 c_regs, c_regs_count, in_imgs, in_imgs_count);
2655 SV *result_sv = sv_newmortal();
2657 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2663 i_contrast(im,intensity)
2676 i_noise(im,amount,type)
2682 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2692 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2711 i_postlevels(im,levels)
2721 i_watermark(im,wmark,tx,ty,pixdiff)
2723 Imager::ImgRaw wmark
2730 i_autolevels(im,lsat,usat,skew)
2737 i_autolevels_mono(im,lsat,usat)
2743 i_radnoise(im,xo,yo,rscale,ascale)
2751 i_turbnoise(im, xo, yo, scale)
2759 i_gradgen(im, xo, yo, ac, dmeasure)
2770 if (size_xo != size_yo || size_xo != size_ac)
2771 croak("i_gradgen: x, y and color arrays must be the same size");
2773 croak("Usage: i_gradgen array refs must have more than 1 entry each");
2774 i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
2777 i_diff_image(im, im2, mindist=0)
2783 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2793 double ssample_param
2797 i_fountain_seg *segs;
2799 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2800 croak("i_fountain: argument 11 must be an array ref");
2802 asegs = (AV *)SvRV(ST(10));
2803 segs = load_fount_segs(aTHX_ asegs, &count);
2804 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2805 super_sample, ssample_param, count, segs);
2811 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2820 double ssample_param
2824 i_fountain_seg *segs;
2826 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2827 croak("i_fountain: argument 11 must be an array ref");
2829 asegs = (AV *)SvRV(ST(9));
2830 segs = load_fount_segs(aTHX_ asegs, &count);
2831 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2832 super_sample, ssample_param, count, segs);
2838 i_new_fill_opacity(other_fill, alpha_mult)
2839 Imager::FillHandle other_fill
2850 errors = i_errors();
2852 while (errors[i].msg) {
2854 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2855 if (!av_store(av, 0, sv)) {
2858 sv = newSViv(errors[i].code);
2859 if (!av_store(av, 1, sv)) {
2862 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2870 i_push_error(code, msg)
2875 i_nearest_color(im, ...)
2890 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2891 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2892 croak("i_nearest_color: Second argument must be an array ref");
2893 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2894 croak("i_nearest_color: Third argument must be an array ref");
2895 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2896 croak("i_nearest_color: Fourth argument must be an array ref");
2897 axx = (AV *)SvRV(ST(1));
2898 ayy = (AV *)SvRV(ST(2));
2899 ac = (AV *)SvRV(ST(3));
2900 dmeasure = (int)SvIV(ST(4));
2902 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2903 num = num <= av_len(ac) ? num : av_len(ac);
2905 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2906 xo = mymalloc( sizeof(i_img_dim) * num );
2907 yo = mymalloc( sizeof(i_img_dim) * num );
2908 ival = mymalloc( sizeof(i_color) * num );
2909 for(i = 0; i<num; i++) {
2910 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2911 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2912 sv = *av_fetch(ac, i, 0);
2913 if ( !sv_derived_from(sv, "Imager::Color") ) {
2914 free(axx); free(ayy); free(ac);
2915 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2917 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2919 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2933 rc=DSO_open(filename,&evstr);
2937 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2938 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2941 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2947 DSO_close(dso_handle)
2951 DSO_funclist(dso_handle_v)
2955 DSO_handle *dso_handle;
2956 func_ptr *functions;
2958 dso_handle=(DSO_handle*)dso_handle_v;
2959 functions = DSO_funclist(dso_handle);
2961 while( functions[i].name != NULL) {
2963 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2965 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2969 DSO_call(handle,func_index,hv)
2974 DSO_call( (DSO_handle *)handle,func_index,hv);
2977 i_get_pixel(im, x, y)
2982 RETVAL = (i_color *)mymalloc(sizeof(i_color));
2983 if (i_gpix(im, x, y, RETVAL) != 0) {
2992 i_ppix(im, x, y, cl)
2999 i_img_pal_new(x, y, channels, maxpal)
3006 i_img_to_pal(src, quant)
3012 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3013 croak("i_img_to_pal: second argument must be a hash ref");
3014 hv = (HV *)SvRV(ST(1));
3015 memset(&quant, 0, sizeof(quant));
3017 quant.mc_size = 256;
3018 ip_handle_quant_opts(aTHX_ &quant, hv);
3019 RETVAL = i_img_to_pal(src, &quant);
3021 ip_copy_colors_back(aTHX_ hv, &quant);
3023 ip_cleanup_quant_opts(aTHX_ &quant);
3032 i_img_make_palette(HV *quant_hv, ...)
3034 size_t count = items - 1;
3036 i_img **imgs = NULL;
3040 croak("Please supply at least one image (%d)", (int)count);
3041 imgs = mymalloc(sizeof(i_img *) * count);
3042 for (i = 0; i < count; ++i) {
3043 SV *img_sv = ST(i + 1);
3044 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3045 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3049 croak("Image %d is not an image object", (int)i+1);
3052 memset(&quant, 0, sizeof(quant));
3054 quant.mc_size = 256;
3055 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3056 i_quant_makemap(&quant, imgs, count);
3057 EXTEND(SP, quant.mc_count);
3058 for (i = 0; i < quant.mc_count; ++i) {
3059 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3062 ip_cleanup_quant_opts(aTHX_ &quant);
3076 work = mymalloc((r-l) * sizeof(i_palidx));
3077 count = i_gpal(im, l, r, y, work);
3078 if (GIMME_V == G_ARRAY) {
3080 for (i = 0; i < count; ++i) {
3081 PUSHs(sv_2mortal(newSViv(work[i])));
3086 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3091 if (GIMME_V != G_ARRAY) {
3093 PUSHs(&PL_sv_undef);
3098 i_ppal(im, l, y, ...)
3107 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3108 for (i=0; i < items-3; ++i) {
3109 work[i] = SvIV(ST(i+3));
3111 validate_i_ppal(im, work, items - 3);
3112 RETVAL = i_ppal(im, l, l+items-3, y, work);
3121 i_ppal_p(im, l, y, data)
3127 i_palidx const *work;
3130 work = (i_palidx const *)SvPV(data, len);
3131 len /= sizeof(i_palidx);
3133 validate_i_ppal(im, work, len);
3134 RETVAL = i_ppal(im, l, l+len, y, work);
3143 i_addcolors(im, ...)
3150 croak("i_addcolors: no colors to add");
3151 colors = mymalloc((items-1) * sizeof(i_color));
3152 for (i=0; i < items-1; ++i) {
3153 if (sv_isobject(ST(i+1))
3154 && sv_derived_from(ST(i+1), "Imager::Color")) {
3155 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3156 colors[i] = *INT2PTR(i_color *, tmp);
3160 croak("i_addcolor: pixels must be Imager::Color objects");
3163 RETVAL = i_addcolors(im, colors, items-1);
3168 i_setcolors(im, index, ...)
3176 croak("i_setcolors: no colors to add");
3177 colors = mymalloc((items-2) * sizeof(i_color));
3178 for (i=0; i < items-2; ++i) {
3179 if (sv_isobject(ST(i+2))
3180 && sv_derived_from(ST(i+2), "Imager::Color")) {
3181 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3182 colors[i] = *INT2PTR(i_color *, tmp);
3186 croak("i_setcolors: pixels must be Imager::Color objects");
3189 RETVAL = i_setcolors(im, index, colors, items-2);
3195 i_getcolors(im, index, count=1)
3204 croak("i_getcolors: count must be positive");
3205 colors = malloc_temp(aTHX_ sizeof(i_color) * count);
3206 if (i_getcolors(im, index, colors, count)) {
3208 for (i = 0; i < count; ++i) {
3209 SV *sv = make_i_color_sv(aTHX_ colors+i);
3223 i_findcolor(im, color)
3227 if (!i_findcolor(im, color, &RETVAL)) {
3246 i_gsamp(im, l, r, y, channels)
3251 i_channel_list channels
3257 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count);
3258 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3259 if (GIMME_V == G_ARRAY) {
3261 for (i = 0; i < count; ++i)
3262 PUSHs(sv_2mortal(newSViv(data[i])));
3266 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3271 if (GIMME_V != G_ARRAY) {
3277 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3285 i_channel_list channels
3292 croak("No channel numbers supplied to g_samp()");
3294 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3295 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3296 for (i = 0; i < count; ++i) {
3297 av_store(target, i+offset, newSVuv(data[i]));
3309 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3314 i_channel_list channels
3316 i_img_dim data_offset
3317 i_img_dim pixel_count
3326 data_count = av_len(data_av) + 1;
3327 if (data_offset < 0) {
3328 croak("data_offset must be non-negative");
3330 if (data_offset > data_count) {
3331 croak("data_offset greater than number of samples supplied");
3333 if (pixel_count == -1 ||
3334 data_offset + pixel_count * channels.count > data_count) {
3335 pixel_count = (data_count - data_offset) / channels.count;
3338 data_used = pixel_count * channels.count;
3339 data = mymalloc(sizeof(unsigned) * data_count);
3340 for (i = 0; i < data_used; ++i)
3341 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3343 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3344 channels.count, bits);
3352 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3356 i_channel_list channels
3365 i_push_error(0, "offset must be non-negative");
3369 if (offset > data.count) {
3370 i_push_error(0, "offset greater than number of samples supplied");
3373 data.samples += offset;
3374 data.count -= offset;
3377 width * channels.count > data.count) {
3378 width = data.count / channels.count;
3381 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3386 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3390 i_channel_list channels
3399 i_push_error(0, "offset must be non-negative");
3403 if (offset > data.count) {
3404 i_push_error(0, "offset greater than number of samples supplied");
3407 data.samples += offset;
3408 data.count -= offset;
3411 width * channels.count > data.count) {
3412 width = data.count / channels.count;
3415 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3420 i_img_masked_new(targ, mask, x, y, w, h)
3430 if (!sv_isobject(ST(1))
3431 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3432 croak("i_img_masked_new: parameter 2 must undef or an image");
3434 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3438 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3443 i_plin(im, l, y, ...)
3454 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3455 /* supplied as a byte string */
3456 work = (i_color *)SvPV(ST(3), len);
3457 count = len / sizeof(i_color);
3458 if (count * sizeof(i_color) != len) {
3459 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3461 RETVAL = i_plin(im, l, l+count, y, work);
3464 work = mymalloc(sizeof(i_color) * (items-3));
3465 for (i=0; i < items-3; ++i) {
3466 if (sv_isobject(ST(i+3))
3467 && sv_derived_from(ST(i+3), "Imager::Color")) {
3468 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3469 work[i] = *INT2PTR(i_color *, tmp);
3473 croak("i_plin: pixels must be Imager::Color objects");
3476 RETVAL = i_plin(im, l, l+items-3, y, work);
3487 i_ppixf(im, x, y, cl)
3491 Imager::Color::Float cl
3494 i_gsampf(im, l, r, y, channels)
3499 i_channel_list channels
3505 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3506 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3507 if (GIMME_V == G_ARRAY) {
3509 for (i = 0; i < count; ++i)
3510 PUSHs(sv_2mortal(newSVnv(data[i])));
3514 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3519 if (GIMME_V != G_ARRAY) {
3525 i_plinf(im, l, y, ...)
3536 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3537 /* supplied as a byte string */
3538 work = (i_fcolor *)SvPV(ST(3), len);
3539 count = len / sizeof(i_fcolor);
3540 if (count * sizeof(i_fcolor) != len) {
3541 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3543 RETVAL = i_plinf(im, l, l+count, y, work);
3546 work = mymalloc(sizeof(i_fcolor) * (items-3));
3547 for (i=0; i < items-3; ++i) {
3548 if (sv_isobject(ST(i+3))
3549 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3550 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3551 work[i] = *INT2PTR(i_fcolor *, tmp);
3555 croak("i_plinf: pixels must be Imager::Color::Float objects");
3559 RETVAL = i_plinf(im, l, l+items-3, y, work);
3569 Imager::Color::Float
3575 RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3576 if (i_gpixf(im, x, y, RETVAL) != 0) {
3594 vals = mymalloc((r-l) * sizeof(i_color));
3595 memset(vals, 0, (r-l) * sizeof(i_color));
3596 count = i_glin(im, l, r, y, vals);
3597 if (GIMME_V == G_ARRAY) {
3599 for (i = 0; i < count; ++i) {
3600 SV *sv = make_i_color_sv(aTHX_ vals+i);
3606 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3612 i_glinf(im, l, r, y)
3622 for (i = 0; i < MAXCHANNELS; ++i)
3623 zero.channel[i] = 0;
3625 vals = mymalloc((r-l) * sizeof(i_fcolor));
3626 for (i = 0; i < r-l; ++i)
3628 count = i_glinf(im, l, r, y, vals);
3629 if (GIMME_V == G_ARRAY) {
3631 for (i = 0; i < count; ++i) {
3633 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3635 sv = sv_newmortal();
3636 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3642 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3648 i_img_8_new(x, y, ch)
3654 i_img_16_new(x, y, ch)
3664 i_img_double_new(x, y, ch)
3674 i_tags_addn(im, name_sv, code, idata)
3683 SvGETMAGIC(name_sv);
3685 name = SvPV_nomg(name_sv, len);
3688 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3693 i_tags_add(im, name_sv, code, data_sv, idata)
3704 SvGETMAGIC(name_sv);
3706 name = SvPV_nomg(name_sv, len);
3709 SvGETMAGIC(data_sv);
3711 data = SvPV(data_sv, len);
3716 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3721 i_tags_find(im, name, start)
3728 if (i_tags_find(&im->tags, name, start, &entry)) {
3737 i_tags_findn(im, code, start)
3744 if (i_tags_findn(&im->tags, code, start, &entry)) {
3754 i_tags_delete(im, entry)
3758 RETVAL = i_tags_delete(&im->tags, entry);
3763 i_tags_delbyname(im, name)
3767 RETVAL = i_tags_delbyname(&im->tags, name);
3772 i_tags_delbycode(im, code)
3776 RETVAL = i_tags_delbycode(&im->tags, code);
3781 i_tags_get(im, index)
3785 if (index >= 0 && index < im->tags.count) {
3786 i_img_tag *entry = im->tags.tags + index;
3790 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3793 PUSHs(sv_2mortal(newSViv(entry->code)));
3796 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3799 PUSHs(sv_2mortal(newSViv(entry->idata)));
3804 i_tags_get_string(im, what_sv)
3808 char const *name = NULL;
3812 if (SvIOK(what_sv)) {
3813 code = SvIV(what_sv);
3817 name = SvPV_nolen(what_sv);
3820 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3822 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3829 RETVAL = im->tags.count;
3835 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3839 Imager::FillHandle fill
3842 IFILL_CLONE_SKIP(...)
3844 (void)items; /* avoid unused warning for XS variable */
3849 MODULE = Imager PACKAGE = Imager
3852 i_new_fill_solid(cl, combine)
3857 i_new_fill_solidf(cl, combine)
3858 Imager::Color::Float cl
3862 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3871 unsigned char *cust_hatch;
3874 SvGETMAGIC(cust_hatch_sv);
3875 if (SvOK(cust_hatch_sv)) {
3876 cust_hatch = (unsigned char *)SvPV_nomg(cust_hatch_sv, len);
3880 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3885 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3886 Imager::Color::Float fg
3887 Imager::Color::Float bg
3894 unsigned char *cust_hatch;
3897 SvGETMAGIC(cust_hatch_sv);
3898 if (SvOK(cust_hatch_sv)) {
3899 cust_hatch = (unsigned char *)SvPV(cust_hatch_sv, len);
3903 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3908 i_new_fill_image(src, matrix_sv, xoff, yoff, combine)
3922 SvGETMAGIC(matrix_sv);
3923 if (!SvOK(matrix_sv)) {
3927 if (!SvROK(matrix_sv) || SvTYPE(SvRV(matrix_sv)) != SVt_PVAV)
3928 croak("i_new_fill_image: matrix parameter must be an arrayref or undef");
3929 av=(AV*)SvRV(matrix_sv);
3933 for (i = 0; i < len; ++i) {
3934 sv1=(*(av_fetch(av,i,0)));
3935 matrix[i] = SvNV(sv1);
3941 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3945 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3947 # this class is only exposed for testing
3950 i_int_hlines_testing()
3952 #if i_int_hlines_testing()
3954 Imager::Internal::Hlines
3955 i_int_hlines_new(start_y, count_y, start_x, count_x)
3961 Imager::Internal::Hlines
3962 i_int_hlines_new_img(im)
3966 i_int_hlines_add(hlines, y, minx, width)
3967 Imager::Internal::Hlines hlines
3973 i_int_hlines_DESTROY(hlines)
3974 Imager::Internal::Hlines hlines
3977 i_int_hlines_dump(hlines)
3978 Imager::Internal::Hlines hlines
3981 i_int_hlines_CLONE_SKIP(cls)
3985 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
3988 im_context_DESTROY(ctx)
3991 #ifdef PERL_IMPLICIT_CONTEXT
3994 im_context_CLONE(...)
3998 /* the following sv_setref_pv() will free this inc */
3999 im_context_refinc(MY_CXT.ctx, "CLONE");
4000 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
4001 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
4006 PERL_SET_GLOBAL_CALLBACKS;
4007 PERL_PL_SET_GLOBAL_CALLBACKS;
4008 #ifdef PERL_IMPLICIT_CONTEXT
4014 start_context(aTHX);
4015 im_get_context = perl_get_context;