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};
237 void my_SvREFCNT_dec(void *p) {
239 SvREFCNT_dec((SV*)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 do_io_new_buffer(pTHX_ SV *data_sv) {
455 data = SvPVbyte(data_sv, length);
456 SvREFCNT_inc(data_sv);
457 return io_new_buffer(data, length, my_SvREFCNT_dec, data_sv);
461 describe_sv(SV *sv) {
464 svtype type = SvTYPE(SvRV(sv));
466 case SVt_PVCV: return "CV";
467 case SVt_PVGV: return "GV";
468 case SVt_PVLV: return "LV";
469 default: return "some reference";
473 return "non-reference scalar";
482 do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) {
485 cbd = mymalloc(sizeof(struct cbdata));
486 cbd->writecb = newSVsv(writecb);
487 cbd->readcb = newSVsv(readcb);
488 cbd->seekcb = newSVsv(seekcb);
489 cbd->closecb = newSVsv(closecb);
491 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)));
493 return io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
501 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
504 for (i = 0; i < count; ++i)
505 if (strEQ(names[i].name, name))
506 return names[i].value;
510 static struct value_name transp_names[] =
513 { "threshold", tr_threshold },
514 { "errdiff", tr_errdiff },
515 { "ordered", tr_ordered, },
518 static struct value_name make_color_names[] =
520 { "none", mc_none, },
521 { "webmap", mc_web_map, },
522 { "addi", mc_addi, },
523 { "mediancut", mc_median_cut, },
524 { "mono", mc_mono, },
525 { "monochrome", mc_mono, },
526 { "gray", mc_gray, },
527 { "gray4", mc_gray4, },
528 { "gray16", mc_gray16, },
531 static struct value_name translate_names[] =
533 { "giflib", pt_giflib, },
534 { "closest", pt_closest, },
535 { "perturb", pt_perturb, },
536 { "errdiff", pt_errdiff, },
539 static struct value_name errdiff_names[] =
541 { "floyd", ed_floyd, },
542 { "jarvis", ed_jarvis, },
543 { "stucki", ed_stucki, },
544 { "custom", ed_custom, },
547 static struct value_name orddith_names[] =
549 { "random", od_random, },
550 { "dot8", od_dot8, },
551 { "dot4", od_dot4, },
552 { "hline", od_hline, },
553 { "vline", od_vline, },
554 { "/line", od_slashline, },
555 { "slashline", od_slashline, },
556 { "\\line", od_backline, },
557 { "backline", od_backline, },
558 { "tiny", od_tiny, },
559 { "custom", od_custom, },
562 /* look through the hash for quantization options */
564 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
566 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
572 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
574 sv = hv_fetch(hv, "transp", 6, 0);
575 if (sv && *sv && (str = SvPV(*sv, len))) {
577 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
579 if (quant->transp != tr_none) {
580 quant->tr_threshold = 127;
581 sv = hv_fetch(hv, "tr_threshold", 12, 0);
583 quant->tr_threshold = SvIV(*sv);
585 if (quant->transp == tr_errdiff) {
586 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
587 if (sv && *sv && (str = SvPV(*sv, len)))
588 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
590 if (quant->transp == tr_ordered) {
591 quant->tr_orddith = od_tiny;
592 sv = hv_fetch(hv, "tr_orddith", 10, 0);
593 if (sv && *sv && (str = SvPV(*sv, len)))
594 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
596 if (quant->tr_orddith == od_custom) {
597 sv = hv_fetch(hv, "tr_map", 6, 0);
598 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
599 AV *av = (AV*)SvRV(*sv);
600 len = av_len(av) + 1;
601 if (len > sizeof(quant->tr_custom))
602 len = sizeof(quant->tr_custom);
603 for (i = 0; i < len; ++i) {
604 SV **sv2 = av_fetch(av, i, 0);
606 quant->tr_custom[i] = SvIV(*sv2);
609 while (i < sizeof(quant->tr_custom))
610 quant->tr_custom[i++] = 0;
615 quant->make_colors = mc_median_cut;
616 sv = hv_fetch(hv, "make_colors", 11, 0);
617 if (sv && *sv && (str = SvPV(*sv, len))) {
619 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
621 sv = hv_fetch(hv, "colors", 6, 0);
622 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
623 /* needs to be an array of Imager::Color
624 note that the caller allocates the mc_color array and sets mc_size
626 AV *av = (AV *)SvRV(*sv);
627 quant->mc_count = av_len(av)+1;
628 if (quant->mc_count > quant->mc_size)
629 quant->mc_count = quant->mc_size;
630 for (i = 0; i < quant->mc_count; ++i) {
631 SV **sv1 = av_fetch(av, i, 0);
632 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
633 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
634 quant->mc_colors[i] = *col;
638 sv = hv_fetch(hv, "max_colors", 10, 0);
641 if (i <= quant->mc_size && i >= quant->mc_count)
645 quant->translate = pt_closest;
646 sv = hv_fetch(hv, "translate", 9, 0);
647 if (sv && *sv && (str = SvPV(*sv, len))) {
648 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
650 sv = hv_fetch(hv, "errdiff", 7, 0);
651 if (sv && *sv && (str = SvPV(*sv, len))) {
652 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
654 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
655 /* get the error diffusion map */
656 sv = hv_fetch(hv, "errdiff_width", 13, 0);
658 quant->ed_width = SvIV(*sv);
659 sv = hv_fetch(hv, "errdiff_height", 14, 0);
661 quant->ed_height = SvIV(*sv);
662 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
664 quant->ed_orig = SvIV(*sv);
665 if (quant->ed_width > 0 && quant->ed_height > 0) {
667 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
668 sv = hv_fetch(hv, "errdiff_map", 11, 0);
669 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
670 AV *av = (AV*)SvRV(*sv);
671 len = av_len(av) + 1;
672 if (len > quant->ed_width * quant->ed_height)
673 len = quant->ed_width * quant->ed_height;
674 for (i = 0; i < len; ++i) {
675 SV **sv2 = av_fetch(av, i, 0);
677 quant->ed_map[i] = SvIV(*sv2);
678 sum += quant->ed_map[i];
684 myfree(quant->ed_map);
686 quant->errdiff = ed_floyd;
690 sv = hv_fetch(hv, "perturb", 7, 0);
692 quant->perturb = SvIV(*sv);
696 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
697 myfree(quant->mc_colors);
699 myfree(quant->ed_map);
702 /* copies the color map from the hv into the colors member of the HV */
704 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
710 sv = hv_fetch(hv, "colors", 6, 0);
711 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
716 av = (AV *)SvRV(*sv);
718 av_extend(av, quant->mc_count+1);
719 for (i = 0; i < quant->mc_count; ++i) {
720 i_color *in = quant->mc_colors+i;
721 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
722 work = sv_newmortal();
723 sv_setref_pv(work, "Imager::Color", (void *)c);
729 /* loads the segments of a fountain fill into an array */
730 static i_fountain_seg *
731 load_fount_segs(pTHX_ AV *asegs, int *count) {
732 /* Each element of segs must contain:
733 [ start, middle, end, c0, c1, segtype, colortrans ]
734 start, middle, end are doubles from 0 to 1
735 c0, c1 are Imager::Color::Float or Imager::Color objects
736 segtype, colortrans are ints
740 i_fountain_seg *segs;
744 *count = av_len(asegs)+1;
746 croak("i_fountain must have at least one segment");
747 segs = mymalloc(sizeof(i_fountain_seg) * *count);
748 for(i = 0; i < *count; i++) {
749 SV **sv1 = av_fetch(asegs, i, 0);
750 if (!sv1 || !*sv1 || !SvROK(*sv1)
751 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
753 croak("i_fountain: segs must be an arrayref of arrayrefs");
755 aseg = (AV *)SvRV(*sv1);
756 if (av_len(aseg) != 7-1) {
758 croak("i_fountain: a segment must have 7 members");
760 for (j = 0; j < 3; ++j) {
761 SV **sv2 = av_fetch(aseg, j, 0);
764 croak("i_fountain: XS error");
766 work[j] = SvNV(*sv2);
768 segs[i].start = work[0];
769 segs[i].middle = work[1];
770 segs[i].end = work[2];
771 for (j = 0; j < 2; ++j) {
772 SV **sv3 = av_fetch(aseg, 3+j, 0);
773 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
774 (!sv_derived_from(*sv3, "Imager::Color")
775 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
777 croak("i_fountain: segs must contain colors in elements 3 and 4");
779 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
780 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
783 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
785 for (ch = 0; ch < MAXCHANNELS; ++ch) {
786 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
790 for (j = 0; j < 2; ++j) {
791 SV **sv2 = av_fetch(aseg, j+5, 0);
794 croak("i_fountain: XS error");
796 worki[j] = SvIV(*sv2);
798 segs[i].type = worki[0];
799 segs[i].color = worki[1];
805 /* validates the indexes supplied to i_ppal
807 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
812 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
813 int color_count = i_colorcount(im);
816 if (color_count == -1)
817 croak("i_plin() called on direct color image");
819 for (i = 0; i < count; ++i) {
820 if (indexes[i] >= color_count) {
821 croak("i_plin() called with out of range color index %d (max %d)",
822 indexes[i], color_count-1);
827 /* I don't think ICLF_* names belong at the C interface
828 this makes the XS code think we have them, to let us avoid
829 putting function bodies in the XS code
831 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
832 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
835 #define i_log_enabled() 1
837 #define i_log_enabled() 0
840 #if i_int_hlines_testing()
842 typedef i_int_hlines *Imager__Internal__Hlines;
844 static i_int_hlines *
845 i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
846 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
847 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
852 static i_int_hlines *
853 i_int_hlines_new_img(i_img *im) {
854 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
855 i_int_init_hlines_img(result, im);
861 i_int_hlines_DESTROY(i_int_hlines *hlines) {
862 i_int_hlines_destroy(hlines);
866 #define i_int_hlines_CLONE_SKIP(cls) 1
868 static int seg_compare(const void *vleft, const void *vright) {
869 const i_int_hline_seg *left = vleft;
870 const i_int_hline_seg *right = vright;
872 return left->minx - right->minx;
876 i_int_hlines_dump(i_int_hlines *hlines) {
878 SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
879 i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
882 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
883 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
886 /* sort the segments, if any */
888 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
890 sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
891 for (i = 0; i < entry->count; ++i) {
892 sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx),
893 i_DFc(entry->segs[i].x_limit));
895 sv_catpv(dump, "\n");
905 i_sv_off_t(pTHX_ SV *sv) {
906 #if LSEEKSIZE > IVSIZE
907 return (off_t)SvNV(sv);
909 return (off_t)SvIV(sv);
914 i_new_sv_off_t(pTHX_ off_t off) {
915 #if LSEEKSIZE > IVSIZE
922 static im_pl_ext_funcs im_perl_funcs =
924 IMAGER_PL_API_VERSION,
926 ip_handle_quant_opts,
927 ip_cleanup_quant_opts,
931 #define PERL_PL_SET_GLOBAL_CALLBACKS \
932 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
934 #define IIM_new i_img_8_new
935 #define IIM_DESTROY i_img_destroy
939 #define i_exif_enabled() 1
941 #define i_exif_enabled() 0
944 /* trying to use more C style names, map them here */
945 #define i_io_DESTROY(ig) io_glue_destroy(ig)
947 #define i_img_get_width(im) ((im)->xsize)
948 #define i_img_get_height(im) ((im)->ysize)
950 #define i_img_epsilonf() (DBL_EPSILON * 4)
952 /* avoid some xsubpp strangeness */
955 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
958 ICL_new_internal(r,g,b,a)
970 ICL_set_internal(cl,r,g,b,a)
977 ICL_set_internal(cl, r, g, b, a);
991 PUSHs(sv_2mortal(newSViv(cl->rgba.r)));
992 PUSHs(sv_2mortal(newSViv(cl->rgba.g)));
993 PUSHs(sv_2mortal(newSViv(cl->rgba.b)));
994 PUSHs(sv_2mortal(newSViv(cl->rgba.a)));
1000 RETVAL = mymalloc(sizeof(i_color));
1002 i_hsv_to_rgb(RETVAL);
1010 RETVAL = mymalloc(sizeof(i_color));
1012 i_rgb_to_hsv(RETVAL);
1018 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
1020 Imager::Color::Float
1021 ICLF_new_internal(r, g, b, a)
1029 Imager::Color::Float cl
1033 Imager::Color::Float cl
1037 EXTEND(SP, MAXCHANNELS);
1038 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1039 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1040 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1044 ICLF_set_internal(cl,r,g,b,a)
1045 Imager::Color::Float cl
1058 Imager::Color::Float
1060 Imager::Color::Float c
1062 RETVAL = mymalloc(sizeof(i_fcolor));
1064 i_hsv_to_rgbf(RETVAL);
1068 Imager::Color::Float
1070 Imager::Color::Float c
1072 RETVAL = mymalloc(sizeof(i_fcolor));
1074 i_rgb_to_hsvf(RETVAL);
1078 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1092 MODULE = Imager PACKAGE = Imager
1106 io_new_buffer(data_sv)
1109 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1114 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1120 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1128 unsigned char* data;
1132 tlength = io_slurp(ig, &data);
1133 RETVAL = newSVpv((char *)data,tlength);
1140 i_set_image_file_limits(width, height, bytes)
1146 i_get_image_file_limits()
1148 i_img_dim width, height;
1151 if (i_get_image_file_limits(&width, &height, &bytes)) {
1153 PUSHs(sv_2mortal(newSViv(width)));
1154 PUSHs(sv_2mortal(newSViv(height)));
1155 PUSHs(sv_2mortal(newSVuv(bytes)));
1159 i_int_check_image_file_limits(width, height, channels, sample_size)
1166 MODULE = Imager PACKAGE = Imager::IO PREFIX = io_
1169 io_new_fd(class, fd)
1172 RETVAL = io_new_fd(fd);
1177 io_new_buffer(class, data_sv)
1180 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1185 io_new_cb(class, writecb, readcb, seekcb, closecb)
1191 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1196 io_new_bufchain(class)
1198 RETVAL = io_new_bufchain();
1203 io__new_perlio(class, io)
1206 RETVAL = im_io_new_perlio(aTHX_ io);
1214 unsigned char* data;
1218 tlength = io_slurp(ig, &data);
1219 RETVAL = newSVpv((char *)data,tlength);
1224 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1227 i_io_raw_write(ig, data_sv)
1234 data = SvPVbyte(data_sv, size);
1235 RETVAL = i_io_raw_write(ig, data, size);
1240 i_io_raw_read(ig, buffer_sv, size)
1249 croak("size negative in call to i_io_raw_read()");
1250 /* prevent an undefined value warning if they supplied an
1252 Orginally conditional on !SvOK(), but this will prevent the
1253 downgrade from croaking */
1254 sv_setpvn(buffer_sv, "", 0);
1256 if (SvUTF8(buffer_sv))
1257 sv_utf8_downgrade(buffer_sv, FALSE);
1259 buffer = SvGROW(buffer_sv, size+1);
1260 result = i_io_raw_read(ig, buffer, size);
1262 SvCUR_set(buffer_sv, result);
1263 *SvEND(buffer_sv) = '\0';
1264 SvPOK_only(buffer_sv);
1266 PUSHs(sv_2mortal(newSViv(result)));
1272 i_io_raw_read2(ig, size)
1281 croak("size negative in call to i_io_read2()");
1282 buffer_sv = newSV(size);
1283 buffer = SvGROW(buffer_sv, size+1);
1284 result = i_io_raw_read(ig, buffer, size);
1286 SvCUR_set(buffer_sv, result);
1287 *SvEND(buffer_sv) = '\0';
1288 SvPOK_only(buffer_sv);
1290 PUSHs(sv_2mortal(buffer_sv));
1294 SvREFCNT_dec(buffer_sv);
1298 i_io_raw_seek(ig, position, whence)
1312 i_io_CLONE_SKIP(...)
1314 (void)items; /* avoid unused warning for XS variable */
1341 i_io_seek(ig, off, whence)
1347 i_io_peekn(ig, size)
1355 buffer_sv = newSV(size+1);
1356 buffer = SvGROW(buffer_sv, size+1);
1357 result = i_io_peekn(ig, buffer, size);
1359 SvCUR_set(buffer_sv, result);
1360 *SvEND(buffer_sv) = '\0';
1361 SvPOK_only(buffer_sv);
1363 PUSHs(sv_2mortal(buffer_sv));
1367 SvREFCNT_dec(buffer_sv);
1371 i_io_read(ig, buffer_sv, size)
1380 croak("size negative in call to i_io_read()");
1381 /* prevent an undefined value warning if they supplied an
1383 Orginally conditional on !SvOK(), but this will prevent the
1384 downgrade from croaking */
1385 sv_setpvn(buffer_sv, "", 0);
1387 if (SvUTF8(buffer_sv))
1388 sv_utf8_downgrade(buffer_sv, FALSE);
1390 buffer = SvGROW(buffer_sv, size+1);
1391 result = i_io_read(ig, buffer, size);
1393 SvCUR_set(buffer_sv, result);
1394 *SvEND(buffer_sv) = '\0';
1395 SvPOK_only(buffer_sv);
1397 PUSHs(sv_2mortal(newSViv(result)));
1403 i_io_read2(ig, size)
1412 croak("size zero in call to read2()");
1413 buffer_sv = newSV(size);
1414 buffer = SvGROW(buffer_sv, size+1);
1415 result = i_io_read(ig, buffer, size);
1417 SvCUR_set(buffer_sv, result);
1418 *SvEND(buffer_sv) = '\0';
1419 SvPOK_only(buffer_sv);
1421 PUSHs(sv_2mortal(buffer_sv));
1425 SvREFCNT_dec(buffer_sv);
1429 i_io_gets(ig, size = 8192, eol = NEWLINE)
1439 croak("size too small in call to gets()");
1440 buffer_sv = sv_2mortal(newSV(size+1));
1441 buffer = SvPVX(buffer_sv);
1442 result = i_io_gets(ig, buffer, size+1, eol);
1444 SvCUR_set(buffer_sv, result);
1445 *SvEND(buffer_sv) = '\0';
1446 SvPOK_only(buffer_sv);
1452 i_io_write(ig, data_sv)
1459 data = SvPVbyte(data_sv, size);
1460 RETVAL = i_io_write(ig, data, size);
1465 i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
1470 i_io_set_buffered(ig, flag = 1)
1475 i_io_is_buffered(ig)
1486 MODULE = Imager PACKAGE = Imager
1497 while( (item=i_format_list[i++]) != NULL ) {
1499 PUSHs(sv_2mortal(newSVpv(item,0)));
1503 i_sametype(im, x, y)
1509 i_sametype_chans(im, x, y, channels)
1516 i_init_log(name_sv,level)
1520 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1522 RETVAL = i_init_log(name, level);
1527 i_log_entry(string,level)
1540 i_img_info(im,info);
1542 PUSHs(sv_2mortal(newSViv(info[0])));
1543 PUSHs(sv_2mortal(newSViv(info[1])));
1544 PUSHs(sv_2mortal(newSViv(info[2])));
1545 PUSHs(sv_2mortal(newSViv(info[3])));
1551 i_img_setmask(im,ch_mask)
1560 i_img_getchannels(im)
1569 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1577 i_img_get_height(im)
1582 i_img_is_monochrome(im)
1588 result = i_img_is_monochrome(im, &zero_is_white);
1590 if (GIMME_V == G_ARRAY) {
1593 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1602 i_line(im,x1,y1,x2,y2,val,endp)
1612 i_line_aa(im,x1,y1,x2,y2,val,endp)
1622 i_box(im,x1,y1,x2,y2,val)
1631 i_box_filled(im,x1,y1,x2,y2,val)
1640 i_box_filledf(im,x1,y1,x2,y2,val)
1646 Imager::Color::Float val
1649 i_box_cfill(im,x1,y1,x2,y2,fill)
1655 Imager::FillHandle fill
1658 i_arc(im,x,y,rad,d1,d2,val)
1668 i_arc_aa(im,x,y,rad,d1,d2,val)
1678 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1685 Imager::FillHandle fill
1688 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1695 Imager::FillHandle fill
1699 i_circle_aa(im,x,y,rad,val)
1707 i_circle_out(im,x,y,rad,val)
1715 i_circle_out_aa(im,x,y,rad,val)
1723 i_arc_out(im,x,y,rad,d1,d2,val)
1733 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1744 i_bezier_multi(im,x,y,val)
1753 if (size_x != size_y)
1754 croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1755 i_bezier_multi(im,size_x,x,y,val);
1758 i_poly_aa(im,x,y,val)
1767 if (size_x != size_y)
1768 croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1769 RETVAL = i_poly_aa(im, size_x, x, y, val);
1774 i_poly_aa_cfill(im, x, y, fill)
1778 Imager::FillHandle fill
1783 if (size_x != size_y)
1784 croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1785 RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
1790 i_flood_fill(im,seedx,seedy,dcol)
1797 i_flood_cfill(im,seedx,seedy,fill)
1801 Imager::FillHandle fill
1804 i_flood_fill_border(im,seedx,seedy,dcol, border)
1809 Imager::Color border
1812 i_flood_cfill_border(im,seedx,seedy,fill, border)
1816 Imager::FillHandle fill
1817 Imager::Color border
1821 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1833 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1850 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1861 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1874 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)
1890 i_combine(src_av, channels_av = NULL)
1894 i_img **imgs = NULL;
1896 int *channels = NULL;
1901 in_count = av_len(src_av) + 1;
1903 imgs = mymalloc(sizeof(i_img*) * in_count);
1904 channels = mymalloc(sizeof(int) * in_count);
1905 for (i = 0; i < in_count; ++i) {
1906 psv = av_fetch(src_av, i, 0);
1907 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1910 croak("imgs must contain only images");
1912 tmp = SvIV((SV*)SvRV(*psv));
1913 imgs[i] = INT2PTR(i_img*, tmp);
1915 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1917 channels[i] = SvIV(*psv);
1924 RETVAL = i_combine(imgs, channels, in_count);
1931 i_flipxy(im, direction)
1936 i_rotate90(im, degrees)
1941 i_rotate_exact(im, amount, ...)
1945 i_color *backp = NULL;
1946 i_fcolor *fbackp = NULL;
1950 /* extract the bg colors if any */
1951 /* yes, this is kind of strange */
1952 for (i = 2; i < items; ++i) {
1954 if (sv_derived_from(sv1, "Imager::Color")) {
1955 IV tmp = SvIV((SV*)SvRV(sv1));
1956 backp = INT2PTR(i_color *, tmp);
1958 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1959 IV tmp = SvIV((SV*)SvRV(sv1));
1960 fbackp = INT2PTR(i_fcolor *, tmp);
1963 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1968 i_matrix_transform(im, xsize, ysize, matrix_av, ...)
1978 i_color *backp = NULL;
1979 i_fcolor *fbackp = NULL;
1981 len=av_len(matrix_av)+1;
1984 for (i = 0; i < len; ++i) {
1985 sv1=(*(av_fetch(matrix_av,i,0)));
1986 matrix[i] = SvNV(sv1);
1990 /* extract the bg colors if any */
1991 /* yes, this is kind of strange */
1992 for (i = 4; i < items; ++i) {
1994 if (sv_derived_from(sv1, "Imager::Color")) {
1995 IV tmp = SvIV((SV*)SvRV(sv1));
1996 backp = INT2PTR(i_color *, tmp);
1998 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1999 IV tmp = SvIV((SV*)SvRV(sv1));
2000 fbackp = INT2PTR(i_fcolor *, tmp);
2003 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2008 i_gaussian(im,stdev)
2013 i_unsharp_mask(im,stdev,scale)
2028 len = av_len(coef) + 1;
2029 c_coef=mymalloc( len * sizeof(double) );
2030 for(i = 0; i < len; i++) {
2031 sv1 = (*(av_fetch(coef, i, 0)));
2032 c_coef[i] = (double)SvNV(sv1);
2034 RETVAL = i_conv(im, c_coef, len);
2040 i_convert(src, avmain)
2052 outchan = av_len(avmain)+1;
2053 /* find the biggest */
2055 for (j=0; j < outchan; ++j) {
2056 temp = av_fetch(avmain, j, 0);
2057 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2058 avsub = (AV*)SvRV(*temp);
2059 len = av_len(avsub)+1;
2064 i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2068 coeff = mymalloc(sizeof(double) * outchan * inchan);
2069 for (j = 0; j < outchan; ++j) {
2070 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2071 len = av_len(avsub)+1;
2072 for (i = 0; i < len; ++i) {
2073 temp = av_fetch(avsub, i, 0);
2075 coeff[i+j*inchan] = SvNV(*temp);
2077 coeff[i+j*inchan] = 0;
2080 coeff[i++ + j*inchan] = 0;
2082 RETVAL = i_convert(src, coeff, outchan, inchan);
2093 unsigned int mask = 0;
2098 unsigned char (*maps)[256];
2100 len = av_len(pmaps_av)+1;
2101 if (im->channels < len)
2103 maps = mymalloc( len * sizeof(unsigned char [256]) );
2104 for (j=0; j<len ; j++) {
2105 temp = av_fetch(pmaps_av, j, 0);
2106 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2107 avsub = (AV*)SvRV(*temp);
2108 if(av_len(avsub) != 255)
2111 for (i=0; i<256 ; i++) {
2113 temp = av_fetch(avsub, i, 0);
2114 val = temp ? SvIV(*temp) : 0;
2116 if (val>255) val = 255;
2121 i_map(im, maps, mask);
2133 i_img_diffd(im1,im2)
2138 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2148 _is_color_object(sv)
2152 RETVAL = SvOK(sv) && SvROK(sv) &&
2153 (sv_derived_from(sv, "Imager::Color")
2154 || sv_derived_from(sv, "Imager::Color::Float"));
2166 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2168 #define TT_DESTROY(handle) i_tt_destroy(handle)
2172 Imager::Font::TT handle
2177 (void)items; /* avoid unused warning */
2183 MODULE = Imager PACKAGE = Imager
2187 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
2188 Imager::Font::TT handle
2202 str = SvPV(str_sv, len);
2207 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2208 len, smooth, utf8, align);
2214 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
2215 Imager::Font::TT handle
2229 str = SvPV(str_sv, len);
2234 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2235 smooth, utf8, align);
2241 i_tt_bbox(handle,point,str_sv,utf8)
2242 Imager::Font::TT handle
2247 i_img_dim cords[BOUNDING_BOX_COUNT];
2253 str = SvPV(str_sv, len);
2258 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2260 for (i = 0; i < rc; ++i) {
2261 PUSHs(sv_2mortal(newSViv(cords[i])));
2266 i_tt_has_chars(handle, text_sv, utf8)
2267 Imager::Font::TT handle
2278 text = SvPV(text_sv, len);
2280 if (SvUTF8(text_sv))
2283 work = mymalloc(len);
2284 count = i_tt_has_chars(handle, text, len, utf8, work);
2285 if (GIMME_V == G_ARRAY) {
2287 for (i = 0; i < count; ++i) {
2288 PUSHs(boolSV(work[i]));
2293 PUSHs(sv_2mortal(newSVpv(work, count)));
2298 i_tt_dump_names(handle)
2299 Imager::Font::TT handle
2302 i_tt_face_name(handle)
2303 Imager::Font::TT handle
2308 len = i_tt_face_name(handle, name, sizeof(name));
2311 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2315 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2316 Imager::Font::TT handle
2328 text = SvPV(text_sv, work_len);
2330 if (SvUTF8(text_sv))
2337 ch = i_utf8_advance(&text, &len);
2339 i_push_error(0, "invalid UTF8 character");
2347 EXTEND(SP, count+1);
2348 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2349 ST(count) = sv_2mortal(newSVpv(name, 0));
2352 ST(count) = &PL_sv_undef;
2361 i_test_format_probe(ig, length)
2366 i_readpnm_wiol(ig, allow_incomplete)
2368 int allow_incomplete
2372 i_readpnm_multi_wiol(ig, allow_incomplete)
2374 int allow_incomplete
2380 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2383 for (i = 0; i < count; ++i) {
2384 SV *sv = sv_newmortal();
2385 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2392 i_writeppm_wiol(im, ig)
2401 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2410 i_writeraw_wiol(im,ig)
2415 i_writebmp_wiol(im,ig)
2420 i_readbmp_wiol(ig, allow_incomplete=0)
2422 int allow_incomplete
2426 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2435 idlen = SvCUR(ST(4));
2436 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2442 i_readtga_wiol(ig, length)
2450 i_scaleaxis(im,Value,Axis)
2456 i_scale_nn(im,scx,scy)
2462 i_scale_mixing(im, width, height)
2472 i_count_colors(im,maxc)
2477 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2482 unsigned int * col_usage = NULL;
2485 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2486 EXTEND(SP, col_cnt);
2487 for (i = 0; i < col_cnt; i++) {
2488 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2495 i_transform(im, opx, opy, parm)
2501 STRLEN size_opx, size_opy, size_parm;
2504 result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
2506 SV *result_sv = sv_newmortal();
2508 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2513 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2539 in_imgs_count = av_len(av_in_imgs)+1;
2540 for (i = 0; i < in_imgs_count; ++i) {
2541 sv1 = *av_fetch(av_in_imgs, i, 0);
2542 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2543 croak("sv_in_img must contain only images");
2546 if (in_imgs_count > 0) {
2547 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2548 for (i = 0; i < in_imgs_count; ++i) {
2549 sv1 = *av_fetch(av_in_imgs,i,0);
2550 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2551 croak("Parameter 5 must contain only images");
2553 tmp = SvIV((SV*)SvRV(sv1));
2554 in_imgs[i] = INT2PTR(i_img*, tmp);
2558 /* no input images */
2561 /* default the output size from the first input if possible */
2563 width = SvIV(sv_width);
2564 else if (in_imgs_count)
2565 width = in_imgs[0]->xsize;
2567 croak("No output image width supplied");
2569 if (SvOK(sv_height))
2570 height = SvIV(sv_height);
2571 else if (in_imgs_count)
2572 height = in_imgs[0]->ysize;
2574 croak("No output image height supplied");
2576 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2577 if (ops_len % sizeof(struct rm_op))
2578 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2579 ops_count = ops_len / sizeof(struct rm_op);
2581 n_regs_count = av_len(av_n_regs)+1;
2582 n_regs = mymalloc(n_regs_count * sizeof(double));
2583 for (i = 0; i < n_regs_count; ++i) {
2584 sv1 = *av_fetch(av_n_regs,i,0);
2586 n_regs[i] = SvNV(sv1);
2588 c_regs_count = av_len(av_c_regs)+1;
2589 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2590 /* I don't bother initializing the colou?r registers */
2592 result=i_transform2(width, height, channels, ops, ops_count,
2593 n_regs, n_regs_count,
2594 c_regs, c_regs_count, in_imgs, in_imgs_count);
2600 SV *result_sv = sv_newmortal();
2602 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2608 i_contrast(im,intensity)
2621 i_noise(im,amount,type)
2627 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2637 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2656 i_postlevels(im,levels)
2666 i_watermark(im,wmark,tx,ty,pixdiff)
2668 Imager::ImgRaw wmark
2675 i_autolevels(im,lsat,usat,skew)
2682 i_radnoise(im,xo,yo,rscale,ascale)
2690 i_turbnoise(im, xo, yo, scale)
2698 i_gradgen(im, xo, yo, ac, dmeasure)
2709 if (size_xo != size_yo || size_xo != size_ac)
2710 croak("i_gradgen: x, y and color arrays must be the same size");
2712 croak("Usage: i_gradgen array refs must have more than 1 entry each");
2713 i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
2716 i_diff_image(im, im2, mindist=0)
2722 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2732 double ssample_param
2736 i_fountain_seg *segs;
2738 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2739 croak("i_fountain: argument 11 must be an array ref");
2741 asegs = (AV *)SvRV(ST(10));
2742 segs = load_fount_segs(aTHX_ asegs, &count);
2743 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2744 super_sample, ssample_param, count, segs);
2750 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2759 double ssample_param
2763 i_fountain_seg *segs;
2765 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2766 croak("i_fountain: argument 11 must be an array ref");
2768 asegs = (AV *)SvRV(ST(9));
2769 segs = load_fount_segs(aTHX_ asegs, &count);
2770 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2771 super_sample, ssample_param, count, segs);
2777 i_new_fill_opacity(other_fill, alpha_mult)
2778 Imager::FillHandle other_fill
2789 errors = i_errors();
2791 while (errors[i].msg) {
2793 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2794 if (!av_store(av, 0, sv)) {
2797 sv = newSViv(errors[i].code);
2798 if (!av_store(av, 1, sv)) {
2801 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2809 i_push_error(code, msg)
2814 i_nearest_color(im, ...)
2829 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2830 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2831 croak("i_nearest_color: Second argument must be an array ref");
2832 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2833 croak("i_nearest_color: Third argument must be an array ref");
2834 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2835 croak("i_nearest_color: Fourth argument must be an array ref");
2836 axx = (AV *)SvRV(ST(1));
2837 ayy = (AV *)SvRV(ST(2));
2838 ac = (AV *)SvRV(ST(3));
2839 dmeasure = (int)SvIV(ST(4));
2841 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2842 num = num <= av_len(ac) ? num : av_len(ac);
2844 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2845 xo = mymalloc( sizeof(i_img_dim) * num );
2846 yo = mymalloc( sizeof(i_img_dim) * num );
2847 ival = mymalloc( sizeof(i_color) * num );
2848 for(i = 0; i<num; i++) {
2849 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2850 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2851 sv = *av_fetch(ac, i, 0);
2852 if ( !sv_derived_from(sv, "Imager::Color") ) {
2853 free(axx); free(ayy); free(ac);
2854 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2856 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2858 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2872 rc=DSO_open(filename,&evstr);
2876 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2877 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2880 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2886 DSO_close(dso_handle)
2890 DSO_funclist(dso_handle_v)
2894 DSO_handle *dso_handle;
2895 func_ptr *functions;
2897 dso_handle=(DSO_handle*)dso_handle_v;
2898 functions = DSO_funclist(dso_handle);
2900 while( functions[i].name != NULL) {
2902 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2904 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2908 DSO_call(handle,func_index,hv)
2913 DSO_call( (DSO_handle *)handle,func_index,hv);
2916 i_get_pixel(im, x, y)
2921 RETVAL = (i_color *)mymalloc(sizeof(i_color));
2922 if (i_gpix(im, x, y, RETVAL) != 0) {
2931 i_ppix(im, x, y, cl)
2938 i_img_pal_new(x, y, channels, maxpal)
2945 i_img_to_pal(src, quant)
2951 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2952 croak("i_img_to_pal: second argument must be a hash ref");
2953 hv = (HV *)SvRV(ST(1));
2954 memset(&quant, 0, sizeof(quant));
2956 quant.mc_size = 256;
2957 ip_handle_quant_opts(aTHX_ &quant, hv);
2958 RETVAL = i_img_to_pal(src, &quant);
2960 ip_copy_colors_back(aTHX_ hv, &quant);
2962 ip_cleanup_quant_opts(aTHX_ &quant);
2971 i_img_make_palette(HV *quant_hv, ...)
2973 size_t count = items - 1;
2975 i_img **imgs = NULL;
2979 croak("Please supply at least one image (%d)", (int)count);
2980 imgs = mymalloc(sizeof(i_img *) * count);
2981 for (i = 0; i < count; ++i) {
2982 SV *img_sv = ST(i + 1);
2983 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
2984 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
2988 croak("Image %d is not an image object", (int)i+1);
2991 memset(&quant, 0, sizeof(quant));
2993 quant.mc_size = 256;
2994 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
2995 i_quant_makemap(&quant, imgs, count);
2996 EXTEND(SP, quant.mc_count);
2997 for (i = 0; i < quant.mc_count; ++i) {
2998 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3001 ip_cleanup_quant_opts(aTHX_ &quant);
3015 work = mymalloc((r-l) * sizeof(i_palidx));
3016 count = i_gpal(im, l, r, y, work);
3017 if (GIMME_V == G_ARRAY) {
3019 for (i = 0; i < count; ++i) {
3020 PUSHs(sv_2mortal(newSViv(work[i])));
3025 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3030 if (GIMME_V != G_ARRAY) {
3032 PUSHs(&PL_sv_undef);
3037 i_ppal(im, l, y, ...)
3046 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3047 for (i=0; i < items-3; ++i) {
3048 work[i] = SvIV(ST(i+3));
3050 validate_i_ppal(im, work, items - 3);
3051 RETVAL = i_ppal(im, l, l+items-3, y, work);
3060 i_ppal_p(im, l, y, data)
3066 i_palidx const *work;
3069 work = (i_palidx const *)SvPV(data, len);
3070 len /= sizeof(i_palidx);
3072 validate_i_ppal(im, work, len);
3073 RETVAL = i_ppal(im, l, l+len, y, work);
3082 i_addcolors(im, ...)
3089 croak("i_addcolors: no colors to add");
3090 colors = mymalloc((items-1) * sizeof(i_color));
3091 for (i=0; i < items-1; ++i) {
3092 if (sv_isobject(ST(i+1))
3093 && sv_derived_from(ST(i+1), "Imager::Color")) {
3094 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3095 colors[i] = *INT2PTR(i_color *, tmp);
3099 croak("i_addcolor: pixels must be Imager::Color objects");
3102 RETVAL = i_addcolors(im, colors, items-1);
3107 i_setcolors(im, index, ...)
3115 croak("i_setcolors: no colors to add");
3116 colors = mymalloc((items-2) * sizeof(i_color));
3117 for (i=0; i < items-2; ++i) {
3118 if (sv_isobject(ST(i+2))
3119 && sv_derived_from(ST(i+2), "Imager::Color")) {
3120 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3121 colors[i] = *INT2PTR(i_color *, tmp);
3125 croak("i_setcolors: pixels must be Imager::Color objects");
3128 RETVAL = i_setcolors(im, index, colors, items-2);
3134 i_getcolors(im, index, count=1)
3143 croak("i_getcolors: count must be positive");
3144 colors = malloc_temp(aTHX_ sizeof(i_color) * count);
3145 if (i_getcolors(im, index, colors, count)) {
3147 for (i = 0; i < count; ++i) {
3148 SV *sv = make_i_color_sv(aTHX_ colors+i);
3162 i_findcolor(im, color)
3166 if (!i_findcolor(im, color, &RETVAL)) {
3185 i_gsamp(im, l, r, y, channels)
3190 i_channel_list channels
3196 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count);
3197 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3198 if (GIMME_V == G_ARRAY) {
3200 for (i = 0; i < count; ++i)
3201 PUSHs(sv_2mortal(newSViv(data[i])));
3205 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3210 if (GIMME_V != G_ARRAY) {
3216 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3224 i_channel_list channels
3231 croak("No channel numbers supplied to g_samp()");
3233 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3234 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3235 for (i = 0; i < count; ++i) {
3236 av_store(target, i+offset, newSVuv(data[i]));
3248 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3253 i_channel_list channels
3255 i_img_dim data_offset
3256 i_img_dim pixel_count
3265 data_count = av_len(data_av) + 1;
3266 if (data_offset < 0) {
3267 croak("data_offset must be non-negative");
3269 if (data_offset > data_count) {
3270 croak("data_offset greater than number of samples supplied");
3272 if (pixel_count == -1 ||
3273 data_offset + pixel_count * channels.count > data_count) {
3274 pixel_count = (data_count - data_offset) / channels.count;
3277 data_used = pixel_count * channels.count;
3278 data = mymalloc(sizeof(unsigned) * data_count);
3279 for (i = 0; i < data_used; ++i)
3280 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3282 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3283 channels.count, bits);
3291 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3295 i_channel_list channels
3304 i_push_error(0, "offset must be non-negative");
3308 if (offset > data.count) {
3309 i_push_error(0, "offset greater than number of samples supplied");
3312 data.samples += offset;
3313 data.count -= offset;
3316 width * channels.count > data.count) {
3317 width = data.count / channels.count;
3320 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3325 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3329 i_channel_list channels
3338 i_push_error(0, "offset must be non-negative");
3342 if (offset > data.count) {
3343 i_push_error(0, "offset greater than number of samples supplied");
3346 data.samples += offset;
3347 data.count -= offset;
3350 width * channels.count > data.count) {
3351 width = data.count / channels.count;
3354 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3359 i_img_masked_new(targ, mask, x, y, w, h)
3369 if (!sv_isobject(ST(1))
3370 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3371 croak("i_img_masked_new: parameter 2 must undef or an image");
3373 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3377 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3382 i_plin(im, l, y, ...)
3393 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3394 /* supplied as a byte string */
3395 work = (i_color *)SvPV(ST(3), len);
3396 count = len / sizeof(i_color);
3397 if (count * sizeof(i_color) != len) {
3398 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3400 RETVAL = i_plin(im, l, l+count, y, work);
3403 work = mymalloc(sizeof(i_color) * (items-3));
3404 for (i=0; i < items-3; ++i) {
3405 if (sv_isobject(ST(i+3))
3406 && sv_derived_from(ST(i+3), "Imager::Color")) {
3407 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3408 work[i] = *INT2PTR(i_color *, tmp);
3412 croak("i_plin: pixels must be Imager::Color objects");
3415 RETVAL = i_plin(im, l, l+items-3, y, work);
3426 i_ppixf(im, x, y, cl)
3430 Imager::Color::Float cl
3433 i_gsampf(im, l, r, y, channels)
3438 i_channel_list channels
3444 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3445 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3446 if (GIMME_V == G_ARRAY) {
3448 for (i = 0; i < count; ++i)
3449 PUSHs(sv_2mortal(newSVnv(data[i])));
3453 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3458 if (GIMME_V != G_ARRAY) {
3464 i_plinf(im, l, y, ...)
3475 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3476 /* supplied as a byte string */
3477 work = (i_fcolor *)SvPV(ST(3), len);
3478 count = len / sizeof(i_fcolor);
3479 if (count * sizeof(i_fcolor) != len) {
3480 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3482 RETVAL = i_plinf(im, l, l+count, y, work);
3485 work = mymalloc(sizeof(i_fcolor) * (items-3));
3486 for (i=0; i < items-3; ++i) {
3487 if (sv_isobject(ST(i+3))
3488 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3489 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3490 work[i] = *INT2PTR(i_fcolor *, tmp);
3494 croak("i_plinf: pixels must be Imager::Color::Float objects");
3498 RETVAL = i_plinf(im, l, l+items-3, y, work);
3508 Imager::Color::Float
3514 RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3515 if (i_gpixf(im, x, y, RETVAL) != 0) {
3533 vals = mymalloc((r-l) * sizeof(i_color));
3534 memset(vals, 0, (r-l) * sizeof(i_color));
3535 count = i_glin(im, l, r, y, vals);
3536 if (GIMME_V == G_ARRAY) {
3538 for (i = 0; i < count; ++i) {
3539 SV *sv = make_i_color_sv(aTHX_ vals+i);
3545 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3551 i_glinf(im, l, r, y)
3561 for (i = 0; i < MAXCHANNELS; ++i)
3562 zero.channel[i] = 0;
3564 vals = mymalloc((r-l) * sizeof(i_fcolor));
3565 for (i = 0; i < r-l; ++i)
3567 count = i_glinf(im, l, r, y, vals);
3568 if (GIMME_V == G_ARRAY) {
3570 for (i = 0; i < count; ++i) {
3572 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3574 sv = sv_newmortal();
3575 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3581 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3587 i_img_8_new(x, y, ch)
3593 i_img_16_new(x, y, ch)
3603 i_img_double_new(x, y, ch)
3613 i_tags_addn(im, name_sv, code, idata)
3622 SvGETMAGIC(name_sv);
3624 name = SvPV_nomg(name_sv, len);
3627 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3632 i_tags_add(im, name_sv, code, data_sv, idata)
3643 SvGETMAGIC(name_sv);
3645 name = SvPV_nomg(name_sv, len);
3648 SvGETMAGIC(data_sv);
3650 data = SvPV(data_sv, len);
3655 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3660 i_tags_find(im, name, start)
3667 if (i_tags_find(&im->tags, name, start, &entry)) {
3676 i_tags_findn(im, code, start)
3683 if (i_tags_findn(&im->tags, code, start, &entry)) {
3693 i_tags_delete(im, entry)
3697 RETVAL = i_tags_delete(&im->tags, entry);
3702 i_tags_delbyname(im, name)
3706 RETVAL = i_tags_delbyname(&im->tags, name);
3711 i_tags_delbycode(im, code)
3715 RETVAL = i_tags_delbycode(&im->tags, code);
3720 i_tags_get(im, index)
3724 if (index >= 0 && index < im->tags.count) {
3725 i_img_tag *entry = im->tags.tags + index;
3729 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3732 PUSHs(sv_2mortal(newSViv(entry->code)));
3735 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3738 PUSHs(sv_2mortal(newSViv(entry->idata)));
3743 i_tags_get_string(im, what_sv)
3747 char const *name = NULL;
3751 if (SvIOK(what_sv)) {
3752 code = SvIV(what_sv);
3756 name = SvPV_nolen(what_sv);
3759 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3761 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3768 RETVAL = im->tags.count;
3774 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3778 Imager::FillHandle fill
3781 IFILL_CLONE_SKIP(...)
3783 (void)items; /* avoid unused warning for XS variable */
3788 MODULE = Imager PACKAGE = Imager
3791 i_new_fill_solid(cl, combine)
3796 i_new_fill_solidf(cl, combine)
3797 Imager::Color::Float cl
3801 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3810 unsigned char *cust_hatch;
3813 SvGETMAGIC(cust_hatch_sv);
3814 if (SvOK(cust_hatch_sv)) {
3815 cust_hatch = (unsigned char *)SvPV_nomg(cust_hatch_sv, len);
3819 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3824 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3825 Imager::Color::Float fg
3826 Imager::Color::Float bg
3833 unsigned char *cust_hatch;
3836 SvGETMAGIC(cust_hatch_sv);
3837 if (SvOK(cust_hatch_sv)) {
3838 cust_hatch = (unsigned char *)SvPV(cust_hatch_sv, len);
3842 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3847 i_new_fill_image(src, matrix_sv, xoff, yoff, combine)
3861 SvGETMAGIC(matrix_sv);
3862 if (!SvOK(matrix_sv)) {
3866 if (!SvROK(matrix_sv) || SvTYPE(SvRV(matrix_sv)) != SVt_PVAV)
3867 croak("i_new_fill_image: matrix parameter must be an arrayref or undef");
3868 av=(AV*)SvRV(matrix_sv);
3872 for (i = 0; i < len; ++i) {
3873 sv1=(*(av_fetch(av,i,0)));
3874 matrix[i] = SvNV(sv1);
3880 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3884 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3886 # this class is only exposed for testing
3889 i_int_hlines_testing()
3891 #if i_int_hlines_testing()
3893 Imager::Internal::Hlines
3894 i_int_hlines_new(start_y, count_y, start_x, count_x)
3900 Imager::Internal::Hlines
3901 i_int_hlines_new_img(im)
3905 i_int_hlines_add(hlines, y, minx, width)
3906 Imager::Internal::Hlines hlines
3912 i_int_hlines_DESTROY(hlines)
3913 Imager::Internal::Hlines hlines
3916 i_int_hlines_dump(hlines)
3917 Imager::Internal::Hlines hlines
3920 i_int_hlines_CLONE_SKIP(cls)
3924 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
3927 im_context_DESTROY(ctx)
3930 #ifdef PERL_IMPLICIT_CONTEXT
3933 im_context_CLONE(...)
3937 /* the following sv_setref_pv() will free this inc */
3938 im_context_refinc(MY_CXT.ctx, "CLONE");
3939 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
3940 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
3945 PERL_SET_GLOBAL_CALLBACKS;
3946 PERL_PL_SET_GLOBAL_CALLBACKS;
3947 #ifdef PERL_IMPLICIT_CONTEXT
3953 start_context(aTHX);
3954 im_get_context = perl_get_context;