1 #define PERL_NO_GET_CONTEXT
8 #define NEED_newRV_noinc
9 #define NEED_sv_2pv_nolen
10 #define NEED_sv_2pvbyte
16 #define i_int_hlines_testing() 1
23 #include "imextpltypes.h"
27 #if i_int_hlines_testing()
33 #ifndef SV_COW_DROP_PV
34 #define SV_COW_DROP_PV 0
39 Context object management
43 typedef im_context_t Imager__Context;
45 #define im_context_DESTROY(ctx) im_context_refdec((ctx), "DESTROY")
47 #ifdef PERL_IMPLICIT_CONTEXT
49 #define MY_CXT_KEY "Imager::_context" XS_VERSION
57 im_context_t fallback_context;
62 MY_CXT.ctx = im_context_new();
63 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
65 /* Ideally we'd free this reference, but the error message memory
66 was never released on exit, so the associated memory here is reasonable
68 With logging enabled we always need at least one context, since
69 objects may be released fairly late and attempt to get the log file.
71 im_context_refinc(MY_CXT.ctx, "start_context");
72 fallback_context = MY_CXT.ctx;
76 perl_get_context(void) {
80 return MY_CXT.ctx ? MY_CXT.ctx : fallback_context;
85 static im_context_t perl_context;
89 perl_context = im_context_new();
90 im_context_refinc(perl_context, "start_context");
94 perl_get_context(void) {
100 /* used to represent channel lists parameters */
101 typedef struct i_channel_list_tag {
108 const i_sample_t *samples;
113 const i_fsample_t *samples;
118 Allocate memory that will be discarded when mortals are discarded.
123 malloc_temp(pTHX_ size_t size) {
124 SV *sv = sv_2mortal(newSV(size));
130 calloc_temp(pTHX_ size_t size) {
131 void *result = malloc_temp(aTHX_ size);
132 memset(result, 0, size);
137 /* for use with the T_AVARRAY typemap */
138 #define doublePtr(size) ((double *)calloc_temp(aTHX_ sizeof(double) * (size)))
139 #define SvDouble(sv, pname) (SvNV(sv))
141 #define intPtr(size) ((int *)calloc_temp(aTHX_ sizeof(int) * (size)))
142 #define SvInt(sv, pname) (SvIV(sv))
144 #define i_img_dimPtr(size) ((i_img_dim *)calloc_temp(aTHX_ sizeof(i_img_dim) * (size)))
145 #define SvI_img_dim(sv, pname) (SvIV(sv))
147 #define i_colorPtr(size) ((i_color *)calloc_temp(aTHX_ sizeof(i_color *) * (size)))
149 #define SvI_color(sv, pname) S_sv_to_i_color(aTHX_ sv, pname)
152 S_sv_to_i_color(pTHX_ SV *sv, const char *pname) {
153 if (!sv_derived_from(sv, "Imager::Color")) {
154 croak("%s: not a color object", pname);
156 return *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
159 /* These functions are all shared - then comes platform dependant code */
160 static int getstr(void *hv_t,char *key,char **store) {
165 mm_log((1,"getstr(hv_t %p, key %s, store %p)\n",hv_t,key,store));
167 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
169 svpp=hv_fetch(hv, key, strlen(key), 0);
170 *store=SvPV(*svpp, PL_na );
175 static int getint(void *hv_t,char *key,int *store) {
180 mm_log((1,"getint(hv_t %p, key %s, store %p)\n",hv_t,key,store));
182 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
184 svpp=hv_fetch(hv, key, strlen(key), 0);
185 *store=(int)SvIV(*svpp);
189 static int getdouble(void *hv_t,char* key,double *store) {
194 mm_log((1,"getdouble(hv_t %p, key %s, store %p)\n",hv_t,key,store));
196 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
197 svpp=hv_fetch(hv, key, strlen(key), 0);
198 *store=(double)SvNV(*svpp);
202 static int getvoid(void *hv_t,char* key,void **store) {
207 mm_log((1,"getvoid(hv_t %p, key %s, store %p)\n",hv_t,key,store));
209 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
211 svpp=hv_fetch(hv, key, strlen(key), 0);
212 *store = INT2PTR(void*, SvIV(*svpp));
217 static int getobj(void *hv_t,char *key,char *type,void **store) {
222 mm_log((1,"getobj(hv_t %p, key %s,type %s, store %p)\n",hv_t,key,type,store));
224 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
226 svpp=hv_fetch(hv, key, strlen(key), 0);
228 if (sv_derived_from(*svpp,type)) {
229 IV tmp = SvIV((SV*)SvRV(*svpp));
230 *store = INT2PTR(void*, tmp);
232 mm_log((1,"getobj: key exists in hash but is not of correct type"));
239 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
242 free_buffer(void *p) {
248 i_log_entry(char *string, int level) {
249 mm_log((level, "%s", string));
253 make_i_color_sv(pTHX_ const i_color *c) {
255 i_color *col = mymalloc(sizeof(i_color));
258 sv_setref_pv(sv, "Imager::Color", (void *)col);
263 #define CBDATA_BUFSIZE 8192
266 /* the SVs we use to call back to Perl */
274 call_reader(struct cbdata *cbd, void *buf, size_t size,
282 if (!SvOK(cbd->readcb)) {
283 mm_log((1, "read callback called but no readcb supplied\n"));
284 i_push_error(0, "read callback called but no readcb supplied");
292 PUSHs(sv_2mortal(newSViv(size)));
293 PUSHs(sv_2mortal(newSViv(maxread)));
296 count = perl_call_sv(cbd->readcb, G_SCALAR);
301 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
307 char *ptr = SvPVbyte(data, len);
309 croak("Too much data returned in reader callback (wanted %d, got %d, expected %d)",
310 (int)size, (int)len, (int)maxread);
312 memcpy(buf, ptr, len);
327 io_seeker(void *p, off_t offset, int whence) {
329 struct cbdata *cbd = p;
334 if (!SvOK(cbd->seekcb)) {
335 mm_log((1, "seek callback called but no seekcb supplied\n"));
336 i_push_error(0, "seek callback called but no seekcb supplied");
344 PUSHs(sv_2mortal(newSViv(offset)));
345 PUSHs(sv_2mortal(newSViv(whence)));
348 count = perl_call_sv(cbd->seekcb, G_SCALAR);
353 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
365 io_writer(void *p, void const *data, size_t size) {
367 struct cbdata *cbd = p;
373 if (!SvOK(cbd->writecb)) {
374 mm_log((1, "write callback called but no writecb supplied\n"));
375 i_push_error(0, "write callback called but no writecb supplied");
383 PUSHs(sv_2mortal(newSVpv((char *)data, size)));
386 count = perl_call_sv(cbd->writecb, G_SCALAR);
390 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
393 success = SvTRUE(sv);
400 return success ? size : -1;
404 io_reader(void *p, void *data, size_t size) {
405 struct cbdata *cbd = p;
407 return call_reader(cbd, data, size, size);
410 static int io_closer(void *p) {
412 struct cbdata *cbd = p;
415 if (SvOK(cbd->closecb)) {
424 count = perl_call_sv(cbd->closecb, G_SCALAR);
430 success = SvTRUE(sv);
440 return success ? 0 : -1;
443 static void io_destroyer(void *p) {
445 struct cbdata *cbd = p;
447 SvREFCNT_dec(cbd->writecb);
448 SvREFCNT_dec(cbd->readcb);
449 SvREFCNT_dec(cbd->seekcb);
450 SvREFCNT_dec(cbd->closecb);
455 im_SvREFSCALAR(SV *sv) {
456 svtype type = SvTYPE(sv);
457 return type == SVt_PV || type == SVt_PVIV || type == SVt_PVNV
458 || type == SVt_PVMG || type == SVt_IV || type == SVt_NV
459 || type == SVt_PVLV || type == SVt_REGEXP;
463 do_io_new_buffer(pTHX_ SV *data_sv) {
470 if (SvROK(data_sv)) {
471 if (im_SvREFSCALAR(data_sv)) {
475 i_push_error(0, "data is not a scalar or a reference to scalar");
483 /* previously this would keep the SV around, but this is unsafe in
484 many ways, so always copy the bytes */
485 data = SvPVbyte(sv, length);
486 data_copy = mymalloc(length);
487 memcpy(data_copy, data, length);
488 return io_new_buffer(data_copy, length, free_buffer, data_copy);
492 describe_sv(SV *sv) {
495 svtype type = SvTYPE(SvRV(sv));
497 case SVt_PVCV: return "CV";
498 case SVt_PVGV: return "GV";
499 case SVt_PVLV: return "LV";
500 default: return "some reference";
504 return "non-reference scalar";
513 do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) {
516 cbd = mymalloc(sizeof(struct cbdata));
517 cbd->writecb = newSVsv(writecb);
518 cbd->readcb = newSVsv(readcb);
519 cbd->seekcb = newSVsv(seekcb);
520 cbd->closecb = newSVsv(closecb);
522 mm_log((1, "do_io_new_cb(writecb %p (%s), readcb %p (%s), seekcb %p (%s), closecb %p (%s))\n", writecb, describe_sv(writecb), readcb, describe_sv(readcb), seekcb, describe_sv(seekcb), closecb, describe_sv(closecb)));
524 return io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
532 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
535 for (i = 0; i < count; ++i)
536 if (strEQ(names[i].name, name))
537 return names[i].value;
541 static struct value_name transp_names[] =
544 { "threshold", tr_threshold },
545 { "errdiff", tr_errdiff },
546 { "ordered", tr_ordered, },
549 static struct value_name make_color_names[] =
551 { "none", mc_none, },
552 { "webmap", mc_web_map, },
553 { "addi", mc_addi, },
554 { "mediancut", mc_median_cut, },
555 { "mono", mc_mono, },
556 { "monochrome", mc_mono, },
557 { "gray", mc_gray, },
558 { "gray4", mc_gray4, },
559 { "gray16", mc_gray16, },
562 static struct value_name translate_names[] =
564 { "giflib", pt_giflib, },
565 { "closest", pt_closest, },
566 { "perturb", pt_perturb, },
567 { "errdiff", pt_errdiff, },
570 static struct value_name errdiff_names[] =
572 { "floyd", ed_floyd, },
573 { "jarvis", ed_jarvis, },
574 { "stucki", ed_stucki, },
575 { "custom", ed_custom, },
578 static struct value_name orddith_names[] =
580 { "random", od_random, },
581 { "dot8", od_dot8, },
582 { "dot4", od_dot4, },
583 { "hline", od_hline, },
584 { "vline", od_vline, },
585 { "/line", od_slashline, },
586 { "slashline", od_slashline, },
587 { "\\line", od_backline, },
588 { "backline", od_backline, },
589 { "tiny", od_tiny, },
590 { "custom", od_custom, },
593 /* look through the hash for quantization options */
595 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
597 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
603 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
605 sv = hv_fetch(hv, "transp", 6, 0);
606 if (sv && *sv && (str = SvPV(*sv, len))) {
608 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
610 if (quant->transp != tr_none) {
611 quant->tr_threshold = 127;
612 sv = hv_fetch(hv, "tr_threshold", 12, 0);
614 quant->tr_threshold = SvIV(*sv);
616 if (quant->transp == tr_errdiff) {
617 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
618 if (sv && *sv && (str = SvPV(*sv, len)))
619 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
621 if (quant->transp == tr_ordered) {
622 quant->tr_orddith = od_tiny;
623 sv = hv_fetch(hv, "tr_orddith", 10, 0);
624 if (sv && *sv && (str = SvPV(*sv, len)))
625 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
627 if (quant->tr_orddith == od_custom) {
628 sv = hv_fetch(hv, "tr_map", 6, 0);
629 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
630 AV *av = (AV*)SvRV(*sv);
631 len = av_len(av) + 1;
632 if (len > sizeof(quant->tr_custom))
633 len = sizeof(quant->tr_custom);
634 for (i = 0; i < len; ++i) {
635 SV **sv2 = av_fetch(av, i, 0);
637 quant->tr_custom[i] = SvIV(*sv2);
640 while (i < sizeof(quant->tr_custom))
641 quant->tr_custom[i++] = 0;
646 quant->make_colors = mc_median_cut;
647 sv = hv_fetch(hv, "make_colors", 11, 0);
648 if (sv && *sv && (str = SvPV(*sv, len))) {
650 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
652 sv = hv_fetch(hv, "colors", 6, 0);
653 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
654 /* needs to be an array of Imager::Color
655 note that the caller allocates the mc_color array and sets mc_size
657 AV *av = (AV *)SvRV(*sv);
658 quant->mc_count = av_len(av)+1;
659 if (quant->mc_count > quant->mc_size)
660 quant->mc_count = quant->mc_size;
661 for (i = 0; i < quant->mc_count; ++i) {
662 SV **sv1 = av_fetch(av, i, 0);
663 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
664 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
665 quant->mc_colors[i] = *col;
669 sv = hv_fetch(hv, "max_colors", 10, 0);
672 if (i <= quant->mc_size && i >= quant->mc_count)
676 quant->translate = pt_closest;
677 sv = hv_fetch(hv, "translate", 9, 0);
678 if (sv && *sv && (str = SvPV(*sv, len))) {
679 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
681 sv = hv_fetch(hv, "errdiff", 7, 0);
682 if (sv && *sv && (str = SvPV(*sv, len))) {
683 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
685 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
686 /* get the error diffusion map */
687 sv = hv_fetch(hv, "errdiff_width", 13, 0);
689 quant->ed_width = SvIV(*sv);
690 sv = hv_fetch(hv, "errdiff_height", 14, 0);
692 quant->ed_height = SvIV(*sv);
693 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
695 quant->ed_orig = SvIV(*sv);
696 if (quant->ed_width > 0 && quant->ed_height > 0) {
698 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
699 sv = hv_fetch(hv, "errdiff_map", 11, 0);
700 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
701 AV *av = (AV*)SvRV(*sv);
702 len = av_len(av) + 1;
703 if (len > quant->ed_width * quant->ed_height)
704 len = quant->ed_width * quant->ed_height;
705 for (i = 0; i < len; ++i) {
706 SV **sv2 = av_fetch(av, i, 0);
708 quant->ed_map[i] = SvIV(*sv2);
709 sum += quant->ed_map[i];
715 myfree(quant->ed_map);
717 quant->errdiff = ed_floyd;
721 sv = hv_fetch(hv, "perturb", 7, 0);
723 quant->perturb = SvIV(*sv);
727 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
728 myfree(quant->mc_colors);
730 myfree(quant->ed_map);
733 /* copies the color map from the hv into the colors member of the HV */
735 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
741 sv = hv_fetch(hv, "colors", 6, 0);
742 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
747 av = (AV *)SvRV(*sv);
749 av_extend(av, quant->mc_count+1);
750 for (i = 0; i < quant->mc_count; ++i) {
751 i_color *in = quant->mc_colors+i;
752 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
753 work = sv_newmortal();
754 sv_setref_pv(work, "Imager::Color", (void *)c);
760 /* loads the segments of a fountain fill into an array */
761 static i_fountain_seg *
762 load_fount_segs(pTHX_ AV *asegs, int *count) {
763 /* Each element of segs must contain:
764 [ start, middle, end, c0, c1, segtype, colortrans ]
765 start, middle, end are doubles from 0 to 1
766 c0, c1 are Imager::Color::Float or Imager::Color objects
767 segtype, colortrans are ints
771 i_fountain_seg *segs;
775 *count = av_len(asegs)+1;
777 croak("i_fountain must have at least one segment");
778 segs = mymalloc(sizeof(i_fountain_seg) * *count);
779 for(i = 0; i < *count; i++) {
780 SV **sv1 = av_fetch(asegs, i, 0);
781 if (!sv1 || !*sv1 || !SvROK(*sv1)
782 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
784 croak("i_fountain: segs must be an arrayref of arrayrefs");
786 aseg = (AV *)SvRV(*sv1);
787 if (av_len(aseg) != 7-1) {
789 croak("i_fountain: a segment must have 7 members");
791 for (j = 0; j < 3; ++j) {
792 SV **sv2 = av_fetch(aseg, j, 0);
795 croak("i_fountain: XS error");
797 work[j] = SvNV(*sv2);
799 segs[i].start = work[0];
800 segs[i].middle = work[1];
801 segs[i].end = work[2];
802 for (j = 0; j < 2; ++j) {
803 SV **sv3 = av_fetch(aseg, 3+j, 0);
804 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
805 (!sv_derived_from(*sv3, "Imager::Color")
806 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
808 croak("i_fountain: segs must contain colors in elements 3 and 4");
810 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
811 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
814 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
816 for (ch = 0; ch < MAXCHANNELS; ++ch) {
817 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
821 for (j = 0; j < 2; ++j) {
822 SV **sv2 = av_fetch(aseg, j+5, 0);
825 croak("i_fountain: XS error");
827 worki[j] = SvIV(*sv2);
829 segs[i].type = worki[0];
830 segs[i].color = worki[1];
836 /* validates the indexes supplied to i_ppal
838 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
843 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
844 int color_count = i_colorcount(im);
847 if (color_count == -1)
848 croak("i_plin() called on direct color image");
850 for (i = 0; i < count; ++i) {
851 if (indexes[i] >= color_count) {
852 croak("i_plin() called with out of range color index %d (max %d)",
853 indexes[i], color_count-1);
858 /* I don't think ICLF_* names belong at the C interface
859 this makes the XS code think we have them, to let us avoid
860 putting function bodies in the XS code
862 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
863 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
866 #define i_log_enabled() 1
868 #define i_log_enabled() 0
871 #if i_int_hlines_testing()
873 typedef i_int_hlines *Imager__Internal__Hlines;
875 static i_int_hlines *
876 i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
877 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
878 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
883 static i_int_hlines *
884 i_int_hlines_new_img(i_img *im) {
885 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
886 i_int_init_hlines_img(result, im);
892 i_int_hlines_DESTROY(i_int_hlines *hlines) {
893 i_int_hlines_destroy(hlines);
897 #define i_int_hlines_CLONE_SKIP(cls) 1
899 static int seg_compare(const void *vleft, const void *vright) {
900 const i_int_hline_seg *left = vleft;
901 const i_int_hline_seg *right = vright;
903 return left->minx - right->minx;
907 i_int_hlines_dump(i_int_hlines *hlines) {
909 SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
910 i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
913 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
914 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
917 /* sort the segments, if any */
919 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
921 sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
922 for (i = 0; i < entry->count; ++i) {
923 sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx),
924 i_DFc(entry->segs[i].x_limit));
926 sv_catpv(dump, "\n");
936 i_sv_off_t(pTHX_ SV *sv) {
937 #if LSEEKSIZE > IVSIZE
938 return (off_t)SvNV(sv);
940 return (off_t)SvIV(sv);
945 i_new_sv_off_t(pTHX_ off_t off) {
946 #if LSEEKSIZE > IVSIZE
953 static im_pl_ext_funcs im_perl_funcs =
955 IMAGER_PL_API_VERSION,
957 ip_handle_quant_opts,
958 ip_cleanup_quant_opts,
962 #define PERL_PL_SET_GLOBAL_CALLBACKS \
963 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
965 #define IIM_new i_img_8_new
966 #define IIM_DESTROY i_img_destroy
970 #define i_exif_enabled() 1
972 #define i_exif_enabled() 0
975 /* trying to use more C style names, map them here */
976 #define i_io_DESTROY(ig) io_glue_destroy(ig)
978 #define i_img_get_width(im) ((im)->xsize)
979 #define i_img_get_height(im) ((im)->ysize)
981 #define i_img_epsilonf() (DBL_EPSILON * 4)
983 /* avoid some xsubpp strangeness */
986 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
989 ICL_new_internal(r,g,b,a)
1001 ICL_set_internal(cl,r,g,b,a)
1008 ICL_set_internal(cl, r, g, b, a);
1022 PUSHs(sv_2mortal(newSViv(cl->rgba.r)));
1023 PUSHs(sv_2mortal(newSViv(cl->rgba.g)));
1024 PUSHs(sv_2mortal(newSViv(cl->rgba.b)));
1025 PUSHs(sv_2mortal(newSViv(cl->rgba.a)));
1031 RETVAL = mymalloc(sizeof(i_color));
1033 i_hsv_to_rgb(RETVAL);
1041 RETVAL = mymalloc(sizeof(i_color));
1043 i_rgb_to_hsv(RETVAL);
1049 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
1051 Imager::Color::Float
1052 ICLF_new_internal(r, g, b, a)
1060 Imager::Color::Float cl
1064 Imager::Color::Float cl
1068 EXTEND(SP, MAXCHANNELS);
1069 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1070 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1071 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1075 ICLF_set_internal(cl,r,g,b,a)
1076 Imager::Color::Float cl
1089 Imager::Color::Float
1091 Imager::Color::Float c
1093 RETVAL = mymalloc(sizeof(i_fcolor));
1095 i_hsv_to_rgbf(RETVAL);
1099 Imager::Color::Float
1101 Imager::Color::Float c
1103 RETVAL = mymalloc(sizeof(i_fcolor));
1105 i_rgb_to_hsvf(RETVAL);
1109 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1123 MODULE = Imager PACKAGE = Imager
1137 io_new_buffer(data_sv)
1141 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1148 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1154 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1162 unsigned char* data;
1166 tlength = io_slurp(ig, &data);
1167 RETVAL = newSVpv((char *)data,tlength);
1174 i_set_image_file_limits(width, height, bytes)
1180 i_get_image_file_limits()
1182 i_img_dim width, height;
1185 if (i_get_image_file_limits(&width, &height, &bytes)) {
1187 PUSHs(sv_2mortal(newSViv(width)));
1188 PUSHs(sv_2mortal(newSViv(height)));
1189 PUSHs(sv_2mortal(newSVuv(bytes)));
1193 i_int_check_image_file_limits(width, height, channels, sample_size)
1200 MODULE = Imager PACKAGE = Imager::IO PREFIX = io_
1203 io_new_fd(class, fd)
1206 RETVAL = io_new_fd(fd);
1211 io_new_buffer(class, data_sv)
1215 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1222 io_new_cb(class, writecb, readcb, seekcb, closecb)
1228 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1233 io_new_bufchain(class)
1235 RETVAL = io_new_bufchain();
1240 io__new_perlio(class, io)
1243 RETVAL = im_io_new_perlio(aTHX_ io);
1251 unsigned char* data;
1255 tlength = io_slurp(ig, &data);
1256 RETVAL = newSVpv((char *)data,tlength);
1261 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1264 i_io_raw_write(ig, data_sv)
1271 data = SvPVbyte(data_sv, size);
1272 RETVAL = i_io_raw_write(ig, data, size);
1277 i_io_raw_read(ig, buffer_sv, size)
1286 croak("size negative in call to i_io_raw_read()");
1287 if (SvTHINKFIRST(buffer_sv))
1288 sv_force_normal_flags(buffer_sv, SV_COW_DROP_PV);
1289 SvUPGRADE(buffer_sv, SVt_PV);
1290 buffer = SvGROW(buffer_sv, size+1);
1291 result = i_io_raw_read(ig, buffer, size);
1293 SvCUR_set(buffer_sv, result);
1294 *SvEND(buffer_sv) = '\0';
1295 SvPOK_only(buffer_sv);
1297 PUSHs(sv_2mortal(newSViv(result)));
1303 i_io_raw_read2(ig, size)
1312 croak("size negative in call to i_io_read2()");
1313 buffer_sv = newSV(size);
1314 buffer = SvGROW(buffer_sv, size+1);
1315 result = i_io_raw_read(ig, buffer, size);
1317 SvCUR_set(buffer_sv, result);
1318 *SvEND(buffer_sv) = '\0';
1319 SvPOK_only(buffer_sv);
1321 PUSHs(sv_2mortal(buffer_sv));
1325 SvREFCNT_dec(buffer_sv);
1329 i_io_raw_seek(ig, position, whence)
1343 i_io_CLONE_SKIP(...)
1345 (void)items; /* avoid unused warning for XS variable */
1372 i_io_seek(ig, off, whence)
1378 i_io_peekn(ig, size)
1386 buffer_sv = newSV(size+1);
1387 buffer = SvGROW(buffer_sv, size+1);
1388 result = i_io_peekn(ig, buffer, size);
1390 SvCUR_set(buffer_sv, result);
1391 *SvEND(buffer_sv) = '\0';
1392 SvPOK_only(buffer_sv);
1394 PUSHs(sv_2mortal(buffer_sv));
1398 SvREFCNT_dec(buffer_sv);
1402 i_io_read(ig, buffer_sv, size)
1411 croak("size negative in call to i_io_read()");
1412 if (SvTHINKFIRST(buffer_sv))
1413 sv_force_normal_flags(buffer_sv, SV_COW_DROP_PV);
1414 SvUPGRADE(buffer_sv, SVt_PV);
1415 buffer = SvGROW(buffer_sv, size+1);
1416 result = i_io_read(ig, buffer, size);
1418 SvCUR_set(buffer_sv, result);
1419 *SvEND(buffer_sv) = '\0';
1420 SvPOK_only(buffer_sv);
1422 PUSHs(sv_2mortal(newSViv(result)));
1428 i_io_read2(ig, size)
1437 croak("size zero in call to read2()");
1438 buffer_sv = newSV(size);
1439 buffer = SvGROW(buffer_sv, size+1);
1440 result = i_io_read(ig, buffer, size);
1442 SvCUR_set(buffer_sv, result);
1443 *SvEND(buffer_sv) = '\0';
1444 SvPOK_only(buffer_sv);
1446 PUSHs(sv_2mortal(buffer_sv));
1450 SvREFCNT_dec(buffer_sv);
1454 i_io_gets(ig, size = 8192, eol = NEWLINE)
1464 croak("size too small in call to gets()");
1465 buffer_sv = sv_2mortal(newSV(size+1));
1466 buffer = SvPVX(buffer_sv);
1467 result = i_io_gets(ig, buffer, size+1, eol);
1469 SvCUR_set(buffer_sv, result);
1470 *SvEND(buffer_sv) = '\0';
1471 SvPOK_only(buffer_sv);
1477 i_io_write(ig, data_sv)
1484 data = SvPVbyte(data_sv, size);
1485 RETVAL = i_io_write(ig, data, size);
1490 i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
1495 i_io_set_buffered(ig, flag = 1)
1500 i_io_is_buffered(ig)
1511 MODULE = Imager PACKAGE = Imager
1522 while( (item=i_format_list[i++]) != NULL ) {
1524 PUSHs(sv_2mortal(newSVpv(item,0)));
1528 i_sametype(im, x, y)
1534 i_sametype_chans(im, x, y, channels)
1541 i_init_log(name_sv,level)
1545 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1547 RETVAL = i_init_log(name, level);
1552 i_log_entry(string,level)
1565 i_img_info(im,info);
1567 PUSHs(sv_2mortal(newSViv(info[0])));
1568 PUSHs(sv_2mortal(newSViv(info[1])));
1569 PUSHs(sv_2mortal(newSViv(info[2])));
1570 PUSHs(sv_2mortal(newSViv(info[3])));
1576 i_img_setmask(im,ch_mask)
1585 i_img_getchannels(im)
1594 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1602 i_img_get_height(im)
1607 i_img_is_monochrome(im)
1613 result = i_img_is_monochrome(im, &zero_is_white);
1615 if (GIMME_V == G_ARRAY) {
1618 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1627 i_line(im,x1,y1,x2,y2,val,endp)
1637 i_line_aa(im,x1,y1,x2,y2,val,endp)
1647 i_box(im,x1,y1,x2,y2,val)
1656 i_box_filled(im,x1,y1,x2,y2,val)
1665 i_box_filledf(im,x1,y1,x2,y2,val)
1671 Imager::Color::Float val
1674 i_box_cfill(im,x1,y1,x2,y2,fill)
1680 Imager::FillHandle fill
1683 i_arc(im,x,y,rad,d1,d2,val)
1693 i_arc_aa(im,x,y,rad,d1,d2,val)
1703 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1710 Imager::FillHandle fill
1713 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1720 Imager::FillHandle fill
1724 i_circle_aa(im,x,y,rad,val)
1732 i_circle_out(im,x,y,rad,val)
1740 i_circle_out_aa(im,x,y,rad,val)
1748 i_arc_out(im,x,y,rad,d1,d2,val)
1758 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1769 i_bezier_multi(im,x,y,val)
1778 if (size_x != size_y)
1779 croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1780 i_bezier_multi(im,size_x,x,y,val);
1783 i_poly_aa(im,x,y,val)
1792 if (size_x != size_y)
1793 croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1794 RETVAL = i_poly_aa(im, size_x, x, y, val);
1799 i_poly_aa_cfill(im, x, y, fill)
1803 Imager::FillHandle fill
1808 if (size_x != size_y)
1809 croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1810 RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
1815 i_flood_fill(im,seedx,seedy,dcol)
1822 i_flood_cfill(im,seedx,seedy,fill)
1826 Imager::FillHandle fill
1829 i_flood_fill_border(im,seedx,seedy,dcol, border)
1834 Imager::Color border
1837 i_flood_cfill_border(im,seedx,seedy,fill, border)
1841 Imager::FillHandle fill
1842 Imager::Color border
1846 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1858 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1875 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1886 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1899 i_compose_mask(out, src, mask, out_left, out_top, src_left, src_top, mask_left, mask_top, width, height, combine = ic_normal, opacity = 0.0)
1915 i_combine(src_av, channels_av = NULL)
1919 i_img **imgs = NULL;
1921 int *channels = NULL;
1926 in_count = av_len(src_av) + 1;
1928 imgs = mymalloc(sizeof(i_img*) * in_count);
1929 channels = mymalloc(sizeof(int) * in_count);
1930 for (i = 0; i < in_count; ++i) {
1931 psv = av_fetch(src_av, i, 0);
1932 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1935 croak("imgs must contain only images");
1937 tmp = SvIV((SV*)SvRV(*psv));
1938 imgs[i] = INT2PTR(i_img*, tmp);
1940 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1942 channels[i] = SvIV(*psv);
1949 RETVAL = i_combine(imgs, channels, in_count);
1956 i_flipxy(im, direction)
1961 i_rotate90(im, degrees)
1966 i_rotate_exact(im, amount, ...)
1970 i_color *backp = NULL;
1971 i_fcolor *fbackp = NULL;
1975 /* extract the bg colors if any */
1976 /* yes, this is kind of strange */
1977 for (i = 2; i < items; ++i) {
1979 if (sv_derived_from(sv1, "Imager::Color")) {
1980 IV tmp = SvIV((SV*)SvRV(sv1));
1981 backp = INT2PTR(i_color *, tmp);
1983 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1984 IV tmp = SvIV((SV*)SvRV(sv1));
1985 fbackp = INT2PTR(i_fcolor *, tmp);
1988 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1993 i_matrix_transform(im, xsize, ysize, matrix_av, ...)
2003 i_color *backp = NULL;
2004 i_fcolor *fbackp = NULL;
2006 len=av_len(matrix_av)+1;
2009 for (i = 0; i < len; ++i) {
2010 sv1=(*(av_fetch(matrix_av,i,0)));
2011 matrix[i] = SvNV(sv1);
2015 /* extract the bg colors if any */
2016 /* yes, this is kind of strange */
2017 for (i = 4; i < items; ++i) {
2019 if (sv_derived_from(sv1, "Imager::Color")) {
2020 IV tmp = SvIV((SV*)SvRV(sv1));
2021 backp = INT2PTR(i_color *, tmp);
2023 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2024 IV tmp = SvIV((SV*)SvRV(sv1));
2025 fbackp = INT2PTR(i_fcolor *, tmp);
2028 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2033 i_gaussian(im,stdev)
2038 i_unsharp_mask(im,stdev,scale)
2053 len = av_len(coef) + 1;
2054 c_coef=mymalloc( len * sizeof(double) );
2055 for(i = 0; i < len; i++) {
2056 sv1 = (*(av_fetch(coef, i, 0)));
2057 c_coef[i] = (double)SvNV(sv1);
2059 RETVAL = i_conv(im, c_coef, len);
2065 i_convert(src, avmain)
2077 outchan = av_len(avmain)+1;
2078 /* find the biggest */
2080 for (j=0; j < outchan; ++j) {
2081 temp = av_fetch(avmain, j, 0);
2082 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2083 avsub = (AV*)SvRV(*temp);
2084 len = av_len(avsub)+1;
2089 i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2093 coeff = mymalloc(sizeof(double) * outchan * inchan);
2094 for (j = 0; j < outchan; ++j) {
2095 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2096 len = av_len(avsub)+1;
2097 for (i = 0; i < len; ++i) {
2098 temp = av_fetch(avsub, i, 0);
2100 coeff[i+j*inchan] = SvNV(*temp);
2102 coeff[i+j*inchan] = 0;
2105 coeff[i++ + j*inchan] = 0;
2107 RETVAL = i_convert(src, coeff, outchan, inchan);
2118 unsigned int mask = 0;
2123 unsigned char (*maps)[256];
2125 len = av_len(pmaps_av)+1;
2126 if (im->channels < len)
2128 maps = mymalloc( len * sizeof(unsigned char [256]) );
2129 for (j=0; j<len ; j++) {
2130 temp = av_fetch(pmaps_av, j, 0);
2131 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2132 avsub = (AV*)SvRV(*temp);
2133 if(av_len(avsub) != 255)
2136 for (i=0; i<256 ; i++) {
2138 temp = av_fetch(avsub, i, 0);
2139 val = temp ? SvIV(*temp) : 0;
2141 if (val>255) val = 255;
2146 i_map(im, maps, mask);
2158 i_img_diffd(im1,im2)
2163 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2173 _is_color_object(sv)
2177 RETVAL = SvOK(sv) && SvROK(sv) &&
2178 (sv_derived_from(sv, "Imager::Color")
2179 || sv_derived_from(sv, "Imager::Color::Float"));
2191 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2193 #define TT_DESTROY(handle) i_tt_destroy(handle)
2197 Imager::Font::TT handle
2202 (void)items; /* avoid unused warning */
2208 MODULE = Imager PACKAGE = Imager
2212 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
2213 Imager::Font::TT handle
2227 str = SvPV(str_sv, len);
2232 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2233 len, smooth, utf8, align);
2239 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
2240 Imager::Font::TT handle
2254 str = SvPV(str_sv, len);
2259 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2260 smooth, utf8, align);
2266 i_tt_bbox(handle,point,str_sv,utf8)
2267 Imager::Font::TT handle
2272 i_img_dim cords[BOUNDING_BOX_COUNT];
2278 str = SvPV(str_sv, len);
2283 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2285 for (i = 0; i < rc; ++i) {
2286 PUSHs(sv_2mortal(newSViv(cords[i])));
2291 i_tt_has_chars(handle, text_sv, utf8)
2292 Imager::Font::TT handle
2303 text = SvPV(text_sv, len);
2305 if (SvUTF8(text_sv))
2308 work = mymalloc(len);
2309 count = i_tt_has_chars(handle, text, len, utf8, work);
2310 if (GIMME_V == G_ARRAY) {
2312 for (i = 0; i < count; ++i) {
2313 PUSHs(boolSV(work[i]));
2318 PUSHs(sv_2mortal(newSVpv(work, count)));
2323 i_tt_dump_names(handle)
2324 Imager::Font::TT handle
2327 i_tt_face_name(handle)
2328 Imager::Font::TT handle
2333 len = i_tt_face_name(handle, name, sizeof(name));
2336 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2340 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2341 Imager::Font::TT handle
2353 text = SvPV(text_sv, work_len);
2355 if (SvUTF8(text_sv))
2362 ch = i_utf8_advance(&text, &len);
2364 i_push_error(0, "invalid UTF8 character");
2372 EXTEND(SP, count+1);
2373 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2374 ST(count) = sv_2mortal(newSVpv(name, 0));
2377 ST(count) = &PL_sv_undef;
2386 i_test_format_probe(ig, length)
2391 i_readpnm_wiol(ig, allow_incomplete)
2393 int allow_incomplete
2397 i_readpnm_multi_wiol(ig, allow_incomplete)
2399 int allow_incomplete
2405 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2408 for (i = 0; i < count; ++i) {
2409 SV *sv = sv_newmortal();
2410 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2417 i_writeppm_wiol(im, ig)
2426 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2435 i_writeraw_wiol(im,ig)
2440 i_writebmp_wiol(im,ig)
2445 i_readbmp_wiol(ig, allow_incomplete=0)
2447 int allow_incomplete
2451 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2460 idlen = SvCUR(ST(4));
2461 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2467 i_readtga_wiol(ig, length)
2475 i_scaleaxis(im,Value,Axis)
2481 i_scale_nn(im,scx,scy)
2487 i_scale_mixing(im, width, height)
2497 i_count_colors(im,maxc)
2502 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2507 unsigned int * col_usage = NULL;
2510 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2511 EXTEND(SP, col_cnt);
2512 for (i = 0; i < col_cnt; i++) {
2513 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2520 i_transform(im, opx, opy, parm)
2526 STRLEN size_opx, size_opy, size_parm;
2529 result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
2531 SV *result_sv = sv_newmortal();
2533 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2538 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2564 in_imgs_count = av_len(av_in_imgs)+1;
2565 for (i = 0; i < in_imgs_count; ++i) {
2566 sv1 = *av_fetch(av_in_imgs, i, 0);
2567 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2568 croak("sv_in_img must contain only images");
2571 if (in_imgs_count > 0) {
2572 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2573 for (i = 0; i < in_imgs_count; ++i) {
2574 sv1 = *av_fetch(av_in_imgs,i,0);
2575 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2576 croak("Parameter 5 must contain only images");
2578 tmp = SvIV((SV*)SvRV(sv1));
2579 in_imgs[i] = INT2PTR(i_img*, tmp);
2583 /* no input images */
2586 /* default the output size from the first input if possible */
2588 width = SvIV(sv_width);
2589 else if (in_imgs_count)
2590 width = in_imgs[0]->xsize;
2592 croak("No output image width supplied");
2594 if (SvOK(sv_height))
2595 height = SvIV(sv_height);
2596 else if (in_imgs_count)
2597 height = in_imgs[0]->ysize;
2599 croak("No output image height supplied");
2601 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2602 if (ops_len % sizeof(struct rm_op))
2603 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2604 ops_count = ops_len / sizeof(struct rm_op);
2606 n_regs_count = av_len(av_n_regs)+1;
2607 n_regs = mymalloc(n_regs_count * sizeof(double));
2608 for (i = 0; i < n_regs_count; ++i) {
2609 sv1 = *av_fetch(av_n_regs,i,0);
2611 n_regs[i] = SvNV(sv1);
2613 c_regs_count = av_len(av_c_regs)+1;
2614 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2615 /* I don't bother initializing the colou?r registers */
2617 result=i_transform2(width, height, channels, ops, ops_count,
2618 n_regs, n_regs_count,
2619 c_regs, c_regs_count, in_imgs, in_imgs_count);
2625 SV *result_sv = sv_newmortal();
2627 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2633 i_contrast(im,intensity)
2646 i_noise(im,amount,type)
2652 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2662 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2681 i_postlevels(im,levels)
2691 i_watermark(im,wmark,tx,ty,pixdiff)
2693 Imager::ImgRaw wmark
2700 i_autolevels(im,lsat,usat,skew)
2707 i_autolevels_mono(im,lsat,usat)
2713 i_radnoise(im,xo,yo,rscale,ascale)
2721 i_turbnoise(im, xo, yo, scale)
2729 i_gradgen(im, xo, yo, ac, dmeasure)
2740 if (size_xo != size_yo || size_xo != size_ac)
2741 croak("i_gradgen: x, y and color arrays must be the same size");
2743 croak("Usage: i_gradgen array refs must have more than 1 entry each");
2744 i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
2747 i_diff_image(im, im2, mindist=0)
2753 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2763 double ssample_param
2767 i_fountain_seg *segs;
2769 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2770 croak("i_fountain: argument 11 must be an array ref");
2772 asegs = (AV *)SvRV(ST(10));
2773 segs = load_fount_segs(aTHX_ asegs, &count);
2774 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2775 super_sample, ssample_param, count, segs);
2781 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2790 double ssample_param
2794 i_fountain_seg *segs;
2796 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2797 croak("i_fountain: argument 11 must be an array ref");
2799 asegs = (AV *)SvRV(ST(9));
2800 segs = load_fount_segs(aTHX_ asegs, &count);
2801 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2802 super_sample, ssample_param, count, segs);
2808 i_new_fill_opacity(other_fill, alpha_mult)
2809 Imager::FillHandle other_fill
2820 errors = i_errors();
2822 while (errors[i].msg) {
2824 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2825 if (!av_store(av, 0, sv)) {
2828 sv = newSViv(errors[i].code);
2829 if (!av_store(av, 1, sv)) {
2832 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2840 i_push_error(code, msg)
2845 i_nearest_color(im, ...)
2860 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2861 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2862 croak("i_nearest_color: Second argument must be an array ref");
2863 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2864 croak("i_nearest_color: Third argument must be an array ref");
2865 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2866 croak("i_nearest_color: Fourth argument must be an array ref");
2867 axx = (AV *)SvRV(ST(1));
2868 ayy = (AV *)SvRV(ST(2));
2869 ac = (AV *)SvRV(ST(3));
2870 dmeasure = (int)SvIV(ST(4));
2872 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2873 num = num <= av_len(ac) ? num : av_len(ac);
2875 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2876 xo = mymalloc( sizeof(i_img_dim) * num );
2877 yo = mymalloc( sizeof(i_img_dim) * num );
2878 ival = mymalloc( sizeof(i_color) * num );
2879 for(i = 0; i<num; i++) {
2880 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2881 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2882 sv = *av_fetch(ac, i, 0);
2883 if ( !sv_derived_from(sv, "Imager::Color") ) {
2884 free(axx); free(ayy); free(ac);
2885 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2887 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2889 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2903 rc=DSO_open(filename,&evstr);
2907 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2908 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2911 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2917 DSO_close(dso_handle)
2921 DSO_funclist(dso_handle_v)
2925 DSO_handle *dso_handle;
2926 func_ptr *functions;
2928 dso_handle=(DSO_handle*)dso_handle_v;
2929 functions = DSO_funclist(dso_handle);
2931 while( functions[i].name != NULL) {
2933 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2935 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2939 DSO_call(handle,func_index,hv)
2944 DSO_call( (DSO_handle *)handle,func_index,hv);
2947 i_get_pixel(im, x, y)
2952 RETVAL = (i_color *)mymalloc(sizeof(i_color));
2953 if (i_gpix(im, x, y, RETVAL) != 0) {
2962 i_ppix(im, x, y, cl)
2969 i_img_pal_new(x, y, channels, maxpal)
2976 i_img_to_pal(src, quant)
2982 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2983 croak("i_img_to_pal: second argument must be a hash ref");
2984 hv = (HV *)SvRV(ST(1));
2985 memset(&quant, 0, sizeof(quant));
2987 quant.mc_size = 256;
2988 ip_handle_quant_opts(aTHX_ &quant, hv);
2989 RETVAL = i_img_to_pal(src, &quant);
2991 ip_copy_colors_back(aTHX_ hv, &quant);
2993 ip_cleanup_quant_opts(aTHX_ &quant);
3002 i_img_make_palette(HV *quant_hv, ...)
3004 size_t count = items - 1;
3006 i_img **imgs = NULL;
3010 croak("Please supply at least one image (%d)", (int)count);
3011 imgs = mymalloc(sizeof(i_img *) * count);
3012 for (i = 0; i < count; ++i) {
3013 SV *img_sv = ST(i + 1);
3014 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3015 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3019 croak("Image %d is not an image object", (int)i+1);
3022 memset(&quant, 0, sizeof(quant));
3024 quant.mc_size = 256;
3025 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3026 i_quant_makemap(&quant, imgs, count);
3027 EXTEND(SP, quant.mc_count);
3028 for (i = 0; i < quant.mc_count; ++i) {
3029 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3032 ip_cleanup_quant_opts(aTHX_ &quant);
3046 work = mymalloc((r-l) * sizeof(i_palidx));
3047 count = i_gpal(im, l, r, y, work);
3048 if (GIMME_V == G_ARRAY) {
3050 for (i = 0; i < count; ++i) {
3051 PUSHs(sv_2mortal(newSViv(work[i])));
3056 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3061 if (GIMME_V != G_ARRAY) {
3063 PUSHs(&PL_sv_undef);
3068 i_ppal(im, l, y, ...)
3077 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3078 for (i=0; i < items-3; ++i) {
3079 work[i] = SvIV(ST(i+3));
3081 validate_i_ppal(im, work, items - 3);
3082 RETVAL = i_ppal(im, l, l+items-3, y, work);
3091 i_ppal_p(im, l, y, data)
3097 i_palidx const *work;
3100 work = (i_palidx const *)SvPV(data, len);
3101 len /= sizeof(i_palidx);
3103 validate_i_ppal(im, work, len);
3104 RETVAL = i_ppal(im, l, l+len, y, work);
3113 i_addcolors(im, ...)
3120 croak("i_addcolors: no colors to add");
3121 colors = mymalloc((items-1) * sizeof(i_color));
3122 for (i=0; i < items-1; ++i) {
3123 if (sv_isobject(ST(i+1))
3124 && sv_derived_from(ST(i+1), "Imager::Color")) {
3125 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3126 colors[i] = *INT2PTR(i_color *, tmp);
3130 croak("i_addcolor: pixels must be Imager::Color objects");
3133 RETVAL = i_addcolors(im, colors, items-1);
3138 i_setcolors(im, index, ...)
3146 croak("i_setcolors: no colors to add");
3147 colors = mymalloc((items-2) * sizeof(i_color));
3148 for (i=0; i < items-2; ++i) {
3149 if (sv_isobject(ST(i+2))
3150 && sv_derived_from(ST(i+2), "Imager::Color")) {
3151 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3152 colors[i] = *INT2PTR(i_color *, tmp);
3156 croak("i_setcolors: pixels must be Imager::Color objects");
3159 RETVAL = i_setcolors(im, index, colors, items-2);
3165 i_getcolors(im, index, count=1)
3174 croak("i_getcolors: count must be positive");
3175 colors = malloc_temp(aTHX_ sizeof(i_color) * count);
3176 if (i_getcolors(im, index, colors, count)) {
3178 for (i = 0; i < count; ++i) {
3179 SV *sv = make_i_color_sv(aTHX_ colors+i);
3193 i_findcolor(im, color)
3197 if (!i_findcolor(im, color, &RETVAL)) {
3216 i_gsamp(im, l, r, y, channels)
3221 i_channel_list channels
3227 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count);
3228 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3229 if (GIMME_V == G_ARRAY) {
3231 for (i = 0; i < count; ++i)
3232 PUSHs(sv_2mortal(newSViv(data[i])));
3236 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3241 if (GIMME_V != G_ARRAY) {
3247 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3255 i_channel_list channels
3262 croak("No channel numbers supplied to g_samp()");
3264 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3265 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3266 for (i = 0; i < count; ++i) {
3267 av_store(target, i+offset, newSVuv(data[i]));
3279 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3284 i_channel_list channels
3286 i_img_dim data_offset
3287 i_img_dim pixel_count
3296 data_count = av_len(data_av) + 1;
3297 if (data_offset < 0) {
3298 croak("data_offset must be non-negative");
3300 if (data_offset > data_count) {
3301 croak("data_offset greater than number of samples supplied");
3303 if (pixel_count == -1 ||
3304 data_offset + pixel_count * channels.count > data_count) {
3305 pixel_count = (data_count - data_offset) / channels.count;
3308 data_used = pixel_count * channels.count;
3309 data = mymalloc(sizeof(unsigned) * data_count);
3310 for (i = 0; i < data_used; ++i)
3311 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3313 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3314 channels.count, bits);
3322 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3326 i_channel_list channels
3335 i_push_error(0, "offset must be non-negative");
3339 if (offset > data.count) {
3340 i_push_error(0, "offset greater than number of samples supplied");
3343 data.samples += offset;
3344 data.count -= offset;
3347 width * channels.count > data.count) {
3348 width = data.count / channels.count;
3351 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3356 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3360 i_channel_list channels
3369 i_push_error(0, "offset must be non-negative");
3373 if (offset > data.count) {
3374 i_push_error(0, "offset greater than number of samples supplied");
3377 data.samples += offset;
3378 data.count -= offset;
3381 width * channels.count > data.count) {
3382 width = data.count / channels.count;
3385 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3390 i_img_masked_new(targ, mask, x, y, w, h)
3400 if (!sv_isobject(ST(1))
3401 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3402 croak("i_img_masked_new: parameter 2 must undef or an image");
3404 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3408 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3413 i_plin(im, l, y, ...)
3424 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3425 /* supplied as a byte string */
3426 work = (i_color *)SvPV(ST(3), len);
3427 count = len / sizeof(i_color);
3428 if (count * sizeof(i_color) != len) {
3429 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3431 RETVAL = i_plin(im, l, l+count, y, work);
3434 work = mymalloc(sizeof(i_color) * (items-3));
3435 for (i=0; i < items-3; ++i) {
3436 if (sv_isobject(ST(i+3))
3437 && sv_derived_from(ST(i+3), "Imager::Color")) {
3438 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3439 work[i] = *INT2PTR(i_color *, tmp);
3443 croak("i_plin: pixels must be Imager::Color objects");
3446 RETVAL = i_plin(im, l, l+items-3, y, work);
3457 i_ppixf(im, x, y, cl)
3461 Imager::Color::Float cl
3464 i_gsampf(im, l, r, y, channels)
3469 i_channel_list channels
3475 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3476 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3477 if (GIMME_V == G_ARRAY) {
3479 for (i = 0; i < count; ++i)
3480 PUSHs(sv_2mortal(newSVnv(data[i])));
3484 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3489 if (GIMME_V != G_ARRAY) {
3495 i_plinf(im, l, y, ...)
3506 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3507 /* supplied as a byte string */
3508 work = (i_fcolor *)SvPV(ST(3), len);
3509 count = len / sizeof(i_fcolor);
3510 if (count * sizeof(i_fcolor) != len) {
3511 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3513 RETVAL = i_plinf(im, l, l+count, y, work);
3516 work = mymalloc(sizeof(i_fcolor) * (items-3));
3517 for (i=0; i < items-3; ++i) {
3518 if (sv_isobject(ST(i+3))
3519 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3520 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3521 work[i] = *INT2PTR(i_fcolor *, tmp);
3525 croak("i_plinf: pixels must be Imager::Color::Float objects");
3529 RETVAL = i_plinf(im, l, l+items-3, y, work);
3539 Imager::Color::Float
3545 RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3546 if (i_gpixf(im, x, y, RETVAL) != 0) {
3564 vals = mymalloc((r-l) * sizeof(i_color));
3565 memset(vals, 0, (r-l) * sizeof(i_color));
3566 count = i_glin(im, l, r, y, vals);
3567 if (GIMME_V == G_ARRAY) {
3569 for (i = 0; i < count; ++i) {
3570 SV *sv = make_i_color_sv(aTHX_ vals+i);
3576 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3582 i_glinf(im, l, r, y)
3592 for (i = 0; i < MAXCHANNELS; ++i)
3593 zero.channel[i] = 0;
3595 vals = mymalloc((r-l) * sizeof(i_fcolor));
3596 for (i = 0; i < r-l; ++i)
3598 count = i_glinf(im, l, r, y, vals);
3599 if (GIMME_V == G_ARRAY) {
3601 for (i = 0; i < count; ++i) {
3603 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3605 sv = sv_newmortal();
3606 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3612 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3618 i_img_8_new(x, y, ch)
3624 i_img_16_new(x, y, ch)
3634 i_img_double_new(x, y, ch)
3644 i_tags_addn(im, name_sv, code, idata)
3653 SvGETMAGIC(name_sv);
3655 name = SvPV_nomg(name_sv, len);
3658 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3663 i_tags_add(im, name_sv, code, data_sv, idata)
3674 SvGETMAGIC(name_sv);
3676 name = SvPV_nomg(name_sv, len);
3679 SvGETMAGIC(data_sv);
3681 data = SvPV(data_sv, len);
3686 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3691 i_tags_find(im, name, start)
3698 if (i_tags_find(&im->tags, name, start, &entry)) {
3707 i_tags_findn(im, code, start)
3714 if (i_tags_findn(&im->tags, code, start, &entry)) {
3724 i_tags_delete(im, entry)
3728 RETVAL = i_tags_delete(&im->tags, entry);
3733 i_tags_delbyname(im, name)
3737 RETVAL = i_tags_delbyname(&im->tags, name);
3742 i_tags_delbycode(im, code)
3746 RETVAL = i_tags_delbycode(&im->tags, code);
3751 i_tags_get(im, index)
3755 if (index >= 0 && index < im->tags.count) {
3756 i_img_tag *entry = im->tags.tags + index;
3760 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3763 PUSHs(sv_2mortal(newSViv(entry->code)));
3766 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3769 PUSHs(sv_2mortal(newSViv(entry->idata)));
3774 i_tags_get_string(im, what_sv)
3778 char const *name = NULL;
3782 if (SvIOK(what_sv)) {
3783 code = SvIV(what_sv);
3787 name = SvPV_nolen(what_sv);
3790 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3792 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3799 RETVAL = im->tags.count;
3805 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3809 Imager::FillHandle fill
3812 IFILL_CLONE_SKIP(...)
3814 (void)items; /* avoid unused warning for XS variable */
3819 MODULE = Imager PACKAGE = Imager
3822 i_new_fill_solid(cl, combine)
3827 i_new_fill_solidf(cl, combine)
3828 Imager::Color::Float cl
3832 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3841 unsigned char *cust_hatch;
3844 SvGETMAGIC(cust_hatch_sv);
3845 if (SvOK(cust_hatch_sv)) {
3846 cust_hatch = (unsigned char *)SvPV_nomg(cust_hatch_sv, len);
3850 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3855 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3856 Imager::Color::Float fg
3857 Imager::Color::Float bg
3864 unsigned char *cust_hatch;
3867 SvGETMAGIC(cust_hatch_sv);
3868 if (SvOK(cust_hatch_sv)) {
3869 cust_hatch = (unsigned char *)SvPV(cust_hatch_sv, len);
3873 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3878 i_new_fill_image(src, matrix_sv, xoff, yoff, combine)
3892 SvGETMAGIC(matrix_sv);
3893 if (!SvOK(matrix_sv)) {
3897 if (!SvROK(matrix_sv) || SvTYPE(SvRV(matrix_sv)) != SVt_PVAV)
3898 croak("i_new_fill_image: matrix parameter must be an arrayref or undef");
3899 av=(AV*)SvRV(matrix_sv);
3903 for (i = 0; i < len; ++i) {
3904 sv1=(*(av_fetch(av,i,0)));
3905 matrix[i] = SvNV(sv1);
3911 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3915 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3917 # this class is only exposed for testing
3920 i_int_hlines_testing()
3922 #if i_int_hlines_testing()
3924 Imager::Internal::Hlines
3925 i_int_hlines_new(start_y, count_y, start_x, count_x)
3931 Imager::Internal::Hlines
3932 i_int_hlines_new_img(im)
3936 i_int_hlines_add(hlines, y, minx, width)
3937 Imager::Internal::Hlines hlines
3943 i_int_hlines_DESTROY(hlines)
3944 Imager::Internal::Hlines hlines
3947 i_int_hlines_dump(hlines)
3948 Imager::Internal::Hlines hlines
3951 i_int_hlines_CLONE_SKIP(cls)
3955 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
3958 im_context_DESTROY(ctx)
3961 #ifdef PERL_IMPLICIT_CONTEXT
3964 im_context_CLONE(...)
3968 /* the following sv_setref_pv() will free this inc */
3969 im_context_refinc(MY_CXT.ctx, "CLONE");
3970 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
3971 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
3976 PERL_SET_GLOBAL_CALLBACKS;
3977 PERL_PL_SET_GLOBAL_CALLBACKS;
3978 #ifdef PERL_IMPLICIT_CONTEXT
3984 start_context(aTHX);
3985 im_get_context = perl_get_context;