1 #define PERL_NO_GET_CONTEXT
8 #define NEED_newRV_noinc
9 #define NEED_sv_2pv_nolen
10 #define NEED_sv_2pvbyte
16 #define i_int_hlines_testing() 1
23 #include "imextpltypes.h"
27 #if i_int_hlines_testing()
35 Context object management
39 typedef im_context_t Imager__Context;
41 #define im_context_DESTROY(ctx) im_context_refdec((ctx), "DESTROY")
43 #ifdef PERL_IMPLICIT_CONTEXT
45 #define MY_CXT_KEY "Imager::_context" XS_VERSION
53 im_context_t fallback_context;
58 MY_CXT.ctx = im_context_new();
59 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
61 /* Ideally we'd free this reference, but the error message memory
62 was never released on exit, so the associated memory here is reasonable
64 With logging enabled we always need at least one context, since
65 objects may be released fairly late and attempt to get the log file.
67 im_context_refinc(MY_CXT.ctx, "start_context");
68 fallback_context = MY_CXT.ctx;
72 perl_get_context(void) {
76 return MY_CXT.ctx ? MY_CXT.ctx : fallback_context;
81 static im_context_t perl_context;
85 perl_context = im_context_new();
86 im_context_refinc(perl_context, "start_context");
90 perl_get_context(void) {
96 /* used to represent channel lists parameters */
97 typedef struct i_channel_list_tag {
104 const i_sample_t *samples;
109 const i_fsample_t *samples;
114 Allocate memory that will be discarded when mortals are discarded.
119 malloc_temp(pTHX_ size_t size) {
120 SV *sv = sv_2mortal(newSV(size));
126 calloc_temp(pTHX_ size_t size) {
127 void *result = malloc_temp(aTHX_ size);
128 memset(result, 0, size);
133 /* for use with the T_AVARRAY typemap */
134 #define doublePtr(size) ((double *)calloc_temp(aTHX_ sizeof(double) * (size)))
135 #define SvDouble(sv, pname) (SvNV(sv))
137 #define intPtr(size) ((int *)calloc_temp(aTHX_ sizeof(int) * (size)))
138 #define SvInt(sv, pname) (SvIV(sv))
140 #define i_img_dimPtr(size) ((i_img_dim *)calloc_temp(aTHX_ sizeof(i_img_dim) * (size)))
141 #define SvI_img_dim(sv, pname) (SvIV(sv))
143 #define i_colorPtr(size) ((i_color *)calloc_temp(aTHX_ sizeof(i_color *) * (size)))
145 #define SvI_color(sv, pname) S_sv_to_i_color(aTHX_ sv, pname)
148 S_sv_to_i_color(pTHX_ SV *sv, const char *pname) {
149 if (!sv_derived_from(sv, "Imager::Color")) {
150 croak("%s: not a color object", pname);
152 return *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
155 /* These functions are all shared - then comes platform dependant code */
156 static int getstr(void *hv_t,char *key,char **store) {
161 mm_log((1,"getstr(hv_t %p, key %s, store %p)\n",hv_t,key,store));
163 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
165 svpp=hv_fetch(hv, key, strlen(key), 0);
166 *store=SvPV(*svpp, PL_na );
171 static int getint(void *hv_t,char *key,int *store) {
176 mm_log((1,"getint(hv_t %p, key %s, store %p)\n",hv_t,key,store));
178 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
180 svpp=hv_fetch(hv, key, strlen(key), 0);
181 *store=(int)SvIV(*svpp);
185 static int getdouble(void *hv_t,char* key,double *store) {
190 mm_log((1,"getdouble(hv_t %p, key %s, store %p)\n",hv_t,key,store));
192 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
193 svpp=hv_fetch(hv, key, strlen(key), 0);
194 *store=(double)SvNV(*svpp);
198 static int getvoid(void *hv_t,char* key,void **store) {
203 mm_log((1,"getvoid(hv_t %p, key %s, store %p)\n",hv_t,key,store));
205 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
207 svpp=hv_fetch(hv, key, strlen(key), 0);
208 *store = INT2PTR(void*, SvIV(*svpp));
213 static int getobj(void *hv_t,char *key,char *type,void **store) {
218 mm_log((1,"getobj(hv_t %p, key %s,type %s, store %p)\n",hv_t,key,type,store));
220 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
222 svpp=hv_fetch(hv, key, strlen(key), 0);
224 if (sv_derived_from(*svpp,type)) {
225 IV tmp = SvIV((SV*)SvRV(*svpp));
226 *store = INT2PTR(void*, tmp);
228 mm_log((1,"getobj: key exists in hash but is not of correct type"));
235 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
238 free_buffer(void *p) {
244 i_log_entry(char *string, int level) {
245 mm_log((level, "%s", string));
249 make_i_color_sv(pTHX_ const i_color *c) {
251 i_color *col = mymalloc(sizeof(i_color));
254 sv_setref_pv(sv, "Imager::Color", (void *)col);
259 #define CBDATA_BUFSIZE 8192
262 /* the SVs we use to call back to Perl */
270 call_reader(struct cbdata *cbd, void *buf, size_t size,
278 if (!SvOK(cbd->readcb)) {
279 mm_log((1, "read callback called but no readcb supplied\n"));
280 i_push_error(0, "read callback called but no readcb supplied");
288 PUSHs(sv_2mortal(newSViv(size)));
289 PUSHs(sv_2mortal(newSViv(maxread)));
292 count = perl_call_sv(cbd->readcb, G_SCALAR);
297 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
303 char *ptr = SvPVbyte(data, len);
305 croak("Too much data returned in reader callback (wanted %d, got %d, expected %d)",
306 (int)size, (int)len, (int)maxread);
308 memcpy(buf, ptr, len);
323 io_seeker(void *p, off_t offset, int whence) {
325 struct cbdata *cbd = p;
330 if (!SvOK(cbd->seekcb)) {
331 mm_log((1, "seek callback called but no seekcb supplied\n"));
332 i_push_error(0, "seek callback called but no seekcb supplied");
340 PUSHs(sv_2mortal(newSViv(offset)));
341 PUSHs(sv_2mortal(newSViv(whence)));
344 count = perl_call_sv(cbd->seekcb, G_SCALAR);
349 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
361 io_writer(void *p, void const *data, size_t size) {
363 struct cbdata *cbd = p;
369 if (!SvOK(cbd->writecb)) {
370 mm_log((1, "write callback called but no writecb supplied\n"));
371 i_push_error(0, "write callback called but no writecb supplied");
379 PUSHs(sv_2mortal(newSVpv((char *)data, size)));
382 count = perl_call_sv(cbd->writecb, G_SCALAR);
386 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
389 success = SvTRUE(sv);
396 return success ? size : -1;
400 io_reader(void *p, void *data, size_t size) {
401 struct cbdata *cbd = p;
403 return call_reader(cbd, data, size, size);
406 static int io_closer(void *p) {
408 struct cbdata *cbd = p;
411 if (SvOK(cbd->closecb)) {
420 count = perl_call_sv(cbd->closecb, G_SCALAR);
426 success = SvTRUE(sv);
436 return success ? 0 : -1;
439 static void io_destroyer(void *p) {
441 struct cbdata *cbd = p;
443 SvREFCNT_dec(cbd->writecb);
444 SvREFCNT_dec(cbd->readcb);
445 SvREFCNT_dec(cbd->seekcb);
446 SvREFCNT_dec(cbd->closecb);
451 im_SvREFSCALAR(SV *sv) {
452 svtype type = SvTYPE(sv);
453 return type == SVt_PV || type == SVt_PVIV || type == SVt_PVNV
454 || type == SVt_PVMG || type == SVt_IV || type == SVt_NV
455 || type == SVt_PVLV || type == SVt_REGEXP;
459 do_io_new_buffer(pTHX_ SV *data_sv) {
466 if (SvROK(data_sv)) {
467 if (im_SvREFSCALAR(data_sv)) {
471 i_push_error(0, "data is not a scalar or a reference to scalar");
479 /* previously this would keep the SV around, but this is unsafe in
480 many ways, so always copy the bytes */
481 data = SvPVbyte(sv, length);
482 data_copy = mymalloc(length);
483 memcpy(data_copy, data, length);
484 return io_new_buffer(data_copy, length, free_buffer, data_copy);
488 describe_sv(SV *sv) {
491 svtype type = SvTYPE(SvRV(sv));
493 case SVt_PVCV: return "CV";
494 case SVt_PVGV: return "GV";
495 case SVt_PVLV: return "LV";
496 default: return "some reference";
500 return "non-reference scalar";
509 do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) {
512 cbd = mymalloc(sizeof(struct cbdata));
513 cbd->writecb = newSVsv(writecb);
514 cbd->readcb = newSVsv(readcb);
515 cbd->seekcb = newSVsv(seekcb);
516 cbd->closecb = newSVsv(closecb);
518 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)));
520 return io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
528 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
531 for (i = 0; i < count; ++i)
532 if (strEQ(names[i].name, name))
533 return names[i].value;
537 static struct value_name transp_names[] =
540 { "threshold", tr_threshold },
541 { "errdiff", tr_errdiff },
542 { "ordered", tr_ordered, },
545 static struct value_name make_color_names[] =
547 { "none", mc_none, },
548 { "webmap", mc_web_map, },
549 { "addi", mc_addi, },
550 { "mediancut", mc_median_cut, },
551 { "mono", mc_mono, },
552 { "monochrome", mc_mono, },
553 { "gray", mc_gray, },
554 { "gray4", mc_gray4, },
555 { "gray16", mc_gray16, },
558 static struct value_name translate_names[] =
560 { "giflib", pt_giflib, },
561 { "closest", pt_closest, },
562 { "perturb", pt_perturb, },
563 { "errdiff", pt_errdiff, },
566 static struct value_name errdiff_names[] =
568 { "floyd", ed_floyd, },
569 { "jarvis", ed_jarvis, },
570 { "stucki", ed_stucki, },
571 { "custom", ed_custom, },
574 static struct value_name orddith_names[] =
576 { "random", od_random, },
577 { "dot8", od_dot8, },
578 { "dot4", od_dot4, },
579 { "hline", od_hline, },
580 { "vline", od_vline, },
581 { "/line", od_slashline, },
582 { "slashline", od_slashline, },
583 { "\\line", od_backline, },
584 { "backline", od_backline, },
585 { "tiny", od_tiny, },
586 { "custom", od_custom, },
589 /* look through the hash for quantization options */
591 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
593 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
599 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
601 sv = hv_fetch(hv, "transp", 6, 0);
602 if (sv && *sv && (str = SvPV(*sv, len))) {
604 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
606 if (quant->transp != tr_none) {
607 quant->tr_threshold = 127;
608 sv = hv_fetch(hv, "tr_threshold", 12, 0);
610 quant->tr_threshold = SvIV(*sv);
612 if (quant->transp == tr_errdiff) {
613 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
614 if (sv && *sv && (str = SvPV(*sv, len)))
615 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
617 if (quant->transp == tr_ordered) {
618 quant->tr_orddith = od_tiny;
619 sv = hv_fetch(hv, "tr_orddith", 10, 0);
620 if (sv && *sv && (str = SvPV(*sv, len)))
621 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
623 if (quant->tr_orddith == od_custom) {
624 sv = hv_fetch(hv, "tr_map", 6, 0);
625 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
626 AV *av = (AV*)SvRV(*sv);
627 len = av_len(av) + 1;
628 if (len > sizeof(quant->tr_custom))
629 len = sizeof(quant->tr_custom);
630 for (i = 0; i < len; ++i) {
631 SV **sv2 = av_fetch(av, i, 0);
633 quant->tr_custom[i] = SvIV(*sv2);
636 while (i < sizeof(quant->tr_custom))
637 quant->tr_custom[i++] = 0;
642 quant->make_colors = mc_median_cut;
643 sv = hv_fetch(hv, "make_colors", 11, 0);
644 if (sv && *sv && (str = SvPV(*sv, len))) {
646 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
648 sv = hv_fetch(hv, "colors", 6, 0);
649 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
650 /* needs to be an array of Imager::Color
651 note that the caller allocates the mc_color array and sets mc_size
653 AV *av = (AV *)SvRV(*sv);
654 quant->mc_count = av_len(av)+1;
655 if (quant->mc_count > quant->mc_size)
656 quant->mc_count = quant->mc_size;
657 for (i = 0; i < quant->mc_count; ++i) {
658 SV **sv1 = av_fetch(av, i, 0);
659 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
660 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
661 quant->mc_colors[i] = *col;
665 sv = hv_fetch(hv, "max_colors", 10, 0);
668 if (i <= quant->mc_size && i >= quant->mc_count)
672 quant->translate = pt_closest;
673 sv = hv_fetch(hv, "translate", 9, 0);
674 if (sv && *sv && (str = SvPV(*sv, len))) {
675 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
677 sv = hv_fetch(hv, "errdiff", 7, 0);
678 if (sv && *sv && (str = SvPV(*sv, len))) {
679 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
681 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
682 /* get the error diffusion map */
683 sv = hv_fetch(hv, "errdiff_width", 13, 0);
685 quant->ed_width = SvIV(*sv);
686 sv = hv_fetch(hv, "errdiff_height", 14, 0);
688 quant->ed_height = SvIV(*sv);
689 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
691 quant->ed_orig = SvIV(*sv);
692 if (quant->ed_width > 0 && quant->ed_height > 0) {
694 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
695 sv = hv_fetch(hv, "errdiff_map", 11, 0);
696 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
697 AV *av = (AV*)SvRV(*sv);
698 len = av_len(av) + 1;
699 if (len > quant->ed_width * quant->ed_height)
700 len = quant->ed_width * quant->ed_height;
701 for (i = 0; i < len; ++i) {
702 SV **sv2 = av_fetch(av, i, 0);
704 quant->ed_map[i] = SvIV(*sv2);
705 sum += quant->ed_map[i];
711 myfree(quant->ed_map);
713 quant->errdiff = ed_floyd;
717 sv = hv_fetch(hv, "perturb", 7, 0);
719 quant->perturb = SvIV(*sv);
723 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
724 myfree(quant->mc_colors);
726 myfree(quant->ed_map);
729 /* copies the color map from the hv into the colors member of the HV */
731 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
737 sv = hv_fetch(hv, "colors", 6, 0);
738 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
743 av = (AV *)SvRV(*sv);
745 av_extend(av, quant->mc_count+1);
746 for (i = 0; i < quant->mc_count; ++i) {
747 i_color *in = quant->mc_colors+i;
748 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
749 work = sv_newmortal();
750 sv_setref_pv(work, "Imager::Color", (void *)c);
756 /* loads the segments of a fountain fill into an array */
757 static i_fountain_seg *
758 load_fount_segs(pTHX_ AV *asegs, int *count) {
759 /* Each element of segs must contain:
760 [ start, middle, end, c0, c1, segtype, colortrans ]
761 start, middle, end are doubles from 0 to 1
762 c0, c1 are Imager::Color::Float or Imager::Color objects
763 segtype, colortrans are ints
767 i_fountain_seg *segs;
771 *count = av_len(asegs)+1;
773 croak("i_fountain must have at least one segment");
774 segs = mymalloc(sizeof(i_fountain_seg) * *count);
775 for(i = 0; i < *count; i++) {
776 SV **sv1 = av_fetch(asegs, i, 0);
777 if (!sv1 || !*sv1 || !SvROK(*sv1)
778 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
780 croak("i_fountain: segs must be an arrayref of arrayrefs");
782 aseg = (AV *)SvRV(*sv1);
783 if (av_len(aseg) != 7-1) {
785 croak("i_fountain: a segment must have 7 members");
787 for (j = 0; j < 3; ++j) {
788 SV **sv2 = av_fetch(aseg, j, 0);
791 croak("i_fountain: XS error");
793 work[j] = SvNV(*sv2);
795 segs[i].start = work[0];
796 segs[i].middle = work[1];
797 segs[i].end = work[2];
798 for (j = 0; j < 2; ++j) {
799 SV **sv3 = av_fetch(aseg, 3+j, 0);
800 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
801 (!sv_derived_from(*sv3, "Imager::Color")
802 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
804 croak("i_fountain: segs must contain colors in elements 3 and 4");
806 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
807 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
810 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
812 for (ch = 0; ch < MAXCHANNELS; ++ch) {
813 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
817 for (j = 0; j < 2; ++j) {
818 SV **sv2 = av_fetch(aseg, j+5, 0);
821 croak("i_fountain: XS error");
823 worki[j] = SvIV(*sv2);
825 segs[i].type = worki[0];
826 segs[i].color = worki[1];
832 /* validates the indexes supplied to i_ppal
834 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
839 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
840 int color_count = i_colorcount(im);
843 if (color_count == -1)
844 croak("i_plin() called on direct color image");
846 for (i = 0; i < count; ++i) {
847 if (indexes[i] >= color_count) {
848 croak("i_plin() called with out of range color index %d (max %d)",
849 indexes[i], color_count-1);
854 /* I don't think ICLF_* names belong at the C interface
855 this makes the XS code think we have them, to let us avoid
856 putting function bodies in the XS code
858 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
859 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
862 #define i_log_enabled() 1
864 #define i_log_enabled() 0
867 #if i_int_hlines_testing()
869 typedef i_int_hlines *Imager__Internal__Hlines;
871 static i_int_hlines *
872 i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
873 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
874 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
879 static i_int_hlines *
880 i_int_hlines_new_img(i_img *im) {
881 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
882 i_int_init_hlines_img(result, im);
888 i_int_hlines_DESTROY(i_int_hlines *hlines) {
889 i_int_hlines_destroy(hlines);
893 #define i_int_hlines_CLONE_SKIP(cls) 1
895 static int seg_compare(const void *vleft, const void *vright) {
896 const i_int_hline_seg *left = vleft;
897 const i_int_hline_seg *right = vright;
899 return left->minx - right->minx;
903 i_int_hlines_dump(i_int_hlines *hlines) {
905 SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
906 i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
909 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
910 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
913 /* sort the segments, if any */
915 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
917 sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
918 for (i = 0; i < entry->count; ++i) {
919 sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx),
920 i_DFc(entry->segs[i].x_limit));
922 sv_catpv(dump, "\n");
932 i_sv_off_t(pTHX_ SV *sv) {
933 #if LSEEKSIZE > IVSIZE
934 return (off_t)SvNV(sv);
936 return (off_t)SvIV(sv);
941 i_new_sv_off_t(pTHX_ off_t off) {
942 #if LSEEKSIZE > IVSIZE
949 static im_pl_ext_funcs im_perl_funcs =
951 IMAGER_PL_API_VERSION,
953 ip_handle_quant_opts,
954 ip_cleanup_quant_opts,
958 #define PERL_PL_SET_GLOBAL_CALLBACKS \
959 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
961 #define IIM_new i_img_8_new
962 #define IIM_DESTROY i_img_destroy
966 #define i_exif_enabled() 1
968 #define i_exif_enabled() 0
971 /* trying to use more C style names, map them here */
972 #define i_io_DESTROY(ig) io_glue_destroy(ig)
974 #define i_img_get_width(im) ((im)->xsize)
975 #define i_img_get_height(im) ((im)->ysize)
977 #define i_img_epsilonf() (DBL_EPSILON * 4)
979 /* avoid some xsubpp strangeness */
982 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
985 ICL_new_internal(r,g,b,a)
997 ICL_set_internal(cl,r,g,b,a)
1004 ICL_set_internal(cl, r, g, b, a);
1018 PUSHs(sv_2mortal(newSViv(cl->rgba.r)));
1019 PUSHs(sv_2mortal(newSViv(cl->rgba.g)));
1020 PUSHs(sv_2mortal(newSViv(cl->rgba.b)));
1021 PUSHs(sv_2mortal(newSViv(cl->rgba.a)));
1027 RETVAL = mymalloc(sizeof(i_color));
1029 i_hsv_to_rgb(RETVAL);
1037 RETVAL = mymalloc(sizeof(i_color));
1039 i_rgb_to_hsv(RETVAL);
1045 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
1047 Imager::Color::Float
1048 ICLF_new_internal(r, g, b, a)
1056 Imager::Color::Float cl
1060 Imager::Color::Float cl
1064 EXTEND(SP, MAXCHANNELS);
1065 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1066 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1067 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1071 ICLF_set_internal(cl,r,g,b,a)
1072 Imager::Color::Float cl
1085 Imager::Color::Float
1087 Imager::Color::Float c
1089 RETVAL = mymalloc(sizeof(i_fcolor));
1091 i_hsv_to_rgbf(RETVAL);
1095 Imager::Color::Float
1097 Imager::Color::Float c
1099 RETVAL = mymalloc(sizeof(i_fcolor));
1101 i_rgb_to_hsvf(RETVAL);
1105 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1119 MODULE = Imager PACKAGE = Imager
1133 io_new_buffer(data_sv)
1137 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1144 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1150 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1158 unsigned char* data;
1162 tlength = io_slurp(ig, &data);
1163 RETVAL = newSVpv((char *)data,tlength);
1170 i_set_image_file_limits(width, height, bytes)
1176 i_get_image_file_limits()
1178 i_img_dim width, height;
1181 if (i_get_image_file_limits(&width, &height, &bytes)) {
1183 PUSHs(sv_2mortal(newSViv(width)));
1184 PUSHs(sv_2mortal(newSViv(height)));
1185 PUSHs(sv_2mortal(newSVuv(bytes)));
1189 i_int_check_image_file_limits(width, height, channels, sample_size)
1196 MODULE = Imager PACKAGE = Imager::IO PREFIX = io_
1199 io_new_fd(class, fd)
1202 RETVAL = io_new_fd(fd);
1207 io_new_buffer(class, data_sv)
1211 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1218 io_new_cb(class, writecb, readcb, seekcb, closecb)
1224 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1229 io_new_bufchain(class)
1231 RETVAL = io_new_bufchain();
1236 io__new_perlio(class, io)
1239 RETVAL = im_io_new_perlio(aTHX_ io);
1247 unsigned char* data;
1251 tlength = io_slurp(ig, &data);
1252 RETVAL = newSVpv((char *)data,tlength);
1257 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1260 i_io_raw_write(ig, data_sv)
1267 data = SvPVbyte(data_sv, size);
1268 RETVAL = i_io_raw_write(ig, data, size);
1273 i_io_raw_read(ig, buffer_sv, size)
1282 croak("size negative in call to i_io_raw_read()");
1283 /* prevent an undefined value warning if they supplied an
1285 Orginally conditional on !SvOK(), but this will prevent the
1286 downgrade from croaking */
1287 sv_setpvn(buffer_sv, "", 0);
1289 if (SvUTF8(buffer_sv))
1290 sv_utf8_downgrade(buffer_sv, FALSE);
1292 buffer = SvGROW(buffer_sv, size+1);
1293 result = i_io_raw_read(ig, buffer, size);
1295 SvCUR_set(buffer_sv, result);
1296 *SvEND(buffer_sv) = '\0';
1297 SvPOK_only(buffer_sv);
1299 PUSHs(sv_2mortal(newSViv(result)));
1305 i_io_raw_read2(ig, size)
1314 croak("size negative in call to i_io_read2()");
1315 buffer_sv = newSV(size);
1316 buffer = SvGROW(buffer_sv, size+1);
1317 result = i_io_raw_read(ig, buffer, size);
1319 SvCUR_set(buffer_sv, result);
1320 *SvEND(buffer_sv) = '\0';
1321 SvPOK_only(buffer_sv);
1323 PUSHs(sv_2mortal(buffer_sv));
1327 SvREFCNT_dec(buffer_sv);
1331 i_io_raw_seek(ig, position, whence)
1345 i_io_CLONE_SKIP(...)
1347 (void)items; /* avoid unused warning for XS variable */
1374 i_io_seek(ig, off, whence)
1380 i_io_peekn(ig, size)
1388 buffer_sv = newSV(size+1);
1389 buffer = SvGROW(buffer_sv, size+1);
1390 result = i_io_peekn(ig, buffer, size);
1392 SvCUR_set(buffer_sv, result);
1393 *SvEND(buffer_sv) = '\0';
1394 SvPOK_only(buffer_sv);
1396 PUSHs(sv_2mortal(buffer_sv));
1400 SvREFCNT_dec(buffer_sv);
1404 i_io_read(ig, buffer_sv, size)
1413 croak("size negative in call to i_io_read()");
1414 /* prevent an undefined value warning if they supplied an
1416 Orginally conditional on !SvOK(), but this will prevent the
1417 downgrade from croaking */
1418 sv_setpvn(buffer_sv, "", 0);
1420 if (SvUTF8(buffer_sv))
1421 sv_utf8_downgrade(buffer_sv, FALSE);
1423 buffer = SvGROW(buffer_sv, size+1);
1424 result = i_io_read(ig, buffer, size);
1426 SvCUR_set(buffer_sv, result);
1427 *SvEND(buffer_sv) = '\0';
1428 SvPOK_only(buffer_sv);
1430 PUSHs(sv_2mortal(newSViv(result)));
1436 i_io_read2(ig, size)
1445 croak("size zero in call to read2()");
1446 buffer_sv = newSV(size);
1447 buffer = SvGROW(buffer_sv, size+1);
1448 result = i_io_read(ig, buffer, size);
1450 SvCUR_set(buffer_sv, result);
1451 *SvEND(buffer_sv) = '\0';
1452 SvPOK_only(buffer_sv);
1454 PUSHs(sv_2mortal(buffer_sv));
1458 SvREFCNT_dec(buffer_sv);
1462 i_io_gets(ig, size = 8192, eol = NEWLINE)
1472 croak("size too small in call to gets()");
1473 buffer_sv = sv_2mortal(newSV(size+1));
1474 buffer = SvPVX(buffer_sv);
1475 result = i_io_gets(ig, buffer, size+1, eol);
1477 SvCUR_set(buffer_sv, result);
1478 *SvEND(buffer_sv) = '\0';
1479 SvPOK_only(buffer_sv);
1485 i_io_write(ig, data_sv)
1492 data = SvPVbyte(data_sv, size);
1493 RETVAL = i_io_write(ig, data, size);
1498 i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
1503 i_io_set_buffered(ig, flag = 1)
1508 i_io_is_buffered(ig)
1519 MODULE = Imager PACKAGE = Imager
1530 while( (item=i_format_list[i++]) != NULL ) {
1532 PUSHs(sv_2mortal(newSVpv(item,0)));
1536 i_sametype(im, x, y)
1542 i_sametype_chans(im, x, y, channels)
1549 i_init_log(name_sv,level)
1553 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1555 RETVAL = i_init_log(name, level);
1560 i_log_entry(string,level)
1573 i_img_info(im,info);
1575 PUSHs(sv_2mortal(newSViv(info[0])));
1576 PUSHs(sv_2mortal(newSViv(info[1])));
1577 PUSHs(sv_2mortal(newSViv(info[2])));
1578 PUSHs(sv_2mortal(newSViv(info[3])));
1584 i_img_setmask(im,ch_mask)
1593 i_img_getchannels(im)
1602 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1610 i_img_get_height(im)
1615 i_img_is_monochrome(im)
1621 result = i_img_is_monochrome(im, &zero_is_white);
1623 if (GIMME_V == G_ARRAY) {
1626 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1635 i_line(im,x1,y1,x2,y2,val,endp)
1645 i_line_aa(im,x1,y1,x2,y2,val,endp)
1655 i_box(im,x1,y1,x2,y2,val)
1664 i_box_filled(im,x1,y1,x2,y2,val)
1673 i_box_filledf(im,x1,y1,x2,y2,val)
1679 Imager::Color::Float val
1682 i_box_cfill(im,x1,y1,x2,y2,fill)
1688 Imager::FillHandle fill
1691 i_arc(im,x,y,rad,d1,d2,val)
1701 i_arc_aa(im,x,y,rad,d1,d2,val)
1711 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1718 Imager::FillHandle fill
1721 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1728 Imager::FillHandle fill
1732 i_circle_aa(im,x,y,rad,val)
1740 i_circle_out(im,x,y,rad,val)
1748 i_circle_out_aa(im,x,y,rad,val)
1756 i_arc_out(im,x,y,rad,d1,d2,val)
1766 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1777 i_bezier_multi(im,x,y,val)
1786 if (size_x != size_y)
1787 croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1788 i_bezier_multi(im,size_x,x,y,val);
1791 i_poly_aa(im,x,y,val)
1800 if (size_x != size_y)
1801 croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1802 RETVAL = i_poly_aa(im, size_x, x, y, val);
1807 i_poly_aa_cfill(im, x, y, fill)
1811 Imager::FillHandle fill
1816 if (size_x != size_y)
1817 croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1818 RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
1823 i_flood_fill(im,seedx,seedy,dcol)
1830 i_flood_cfill(im,seedx,seedy,fill)
1834 Imager::FillHandle fill
1837 i_flood_fill_border(im,seedx,seedy,dcol, border)
1842 Imager::Color border
1845 i_flood_cfill_border(im,seedx,seedy,fill, border)
1849 Imager::FillHandle fill
1850 Imager::Color border
1854 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1866 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1883 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1894 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1907 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)
1923 i_combine(src_av, channels_av = NULL)
1927 i_img **imgs = NULL;
1929 int *channels = NULL;
1934 in_count = av_len(src_av) + 1;
1936 imgs = mymalloc(sizeof(i_img*) * in_count);
1937 channels = mymalloc(sizeof(int) * in_count);
1938 for (i = 0; i < in_count; ++i) {
1939 psv = av_fetch(src_av, i, 0);
1940 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1943 croak("imgs must contain only images");
1945 tmp = SvIV((SV*)SvRV(*psv));
1946 imgs[i] = INT2PTR(i_img*, tmp);
1948 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1950 channels[i] = SvIV(*psv);
1957 RETVAL = i_combine(imgs, channels, in_count);
1964 i_flipxy(im, direction)
1969 i_rotate90(im, degrees)
1974 i_rotate_exact(im, amount, ...)
1978 i_color *backp = NULL;
1979 i_fcolor *fbackp = NULL;
1983 /* extract the bg colors if any */
1984 /* yes, this is kind of strange */
1985 for (i = 2; i < items; ++i) {
1987 if (sv_derived_from(sv1, "Imager::Color")) {
1988 IV tmp = SvIV((SV*)SvRV(sv1));
1989 backp = INT2PTR(i_color *, tmp);
1991 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1992 IV tmp = SvIV((SV*)SvRV(sv1));
1993 fbackp = INT2PTR(i_fcolor *, tmp);
1996 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
2001 i_matrix_transform(im, xsize, ysize, matrix_av, ...)
2011 i_color *backp = NULL;
2012 i_fcolor *fbackp = NULL;
2014 len=av_len(matrix_av)+1;
2017 for (i = 0; i < len; ++i) {
2018 sv1=(*(av_fetch(matrix_av,i,0)));
2019 matrix[i] = SvNV(sv1);
2023 /* extract the bg colors if any */
2024 /* yes, this is kind of strange */
2025 for (i = 4; i < items; ++i) {
2027 if (sv_derived_from(sv1, "Imager::Color")) {
2028 IV tmp = SvIV((SV*)SvRV(sv1));
2029 backp = INT2PTR(i_color *, tmp);
2031 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2032 IV tmp = SvIV((SV*)SvRV(sv1));
2033 fbackp = INT2PTR(i_fcolor *, tmp);
2036 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2041 i_gaussian(im,stdev)
2046 i_unsharp_mask(im,stdev,scale)
2061 len = av_len(coef) + 1;
2062 c_coef=mymalloc( len * sizeof(double) );
2063 for(i = 0; i < len; i++) {
2064 sv1 = (*(av_fetch(coef, i, 0)));
2065 c_coef[i] = (double)SvNV(sv1);
2067 RETVAL = i_conv(im, c_coef, len);
2073 i_convert(src, avmain)
2085 outchan = av_len(avmain)+1;
2086 /* find the biggest */
2088 for (j=0; j < outchan; ++j) {
2089 temp = av_fetch(avmain, j, 0);
2090 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2091 avsub = (AV*)SvRV(*temp);
2092 len = av_len(avsub)+1;
2097 i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2101 coeff = mymalloc(sizeof(double) * outchan * inchan);
2102 for (j = 0; j < outchan; ++j) {
2103 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2104 len = av_len(avsub)+1;
2105 for (i = 0; i < len; ++i) {
2106 temp = av_fetch(avsub, i, 0);
2108 coeff[i+j*inchan] = SvNV(*temp);
2110 coeff[i+j*inchan] = 0;
2113 coeff[i++ + j*inchan] = 0;
2115 RETVAL = i_convert(src, coeff, outchan, inchan);
2126 unsigned int mask = 0;
2131 unsigned char (*maps)[256];
2133 len = av_len(pmaps_av)+1;
2134 if (im->channels < len)
2136 maps = mymalloc( len * sizeof(unsigned char [256]) );
2137 for (j=0; j<len ; j++) {
2138 temp = av_fetch(pmaps_av, j, 0);
2139 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2140 avsub = (AV*)SvRV(*temp);
2141 if(av_len(avsub) != 255)
2144 for (i=0; i<256 ; i++) {
2146 temp = av_fetch(avsub, i, 0);
2147 val = temp ? SvIV(*temp) : 0;
2149 if (val>255) val = 255;
2154 i_map(im, maps, mask);
2166 i_img_diffd(im1,im2)
2171 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2181 _is_color_object(sv)
2185 RETVAL = SvOK(sv) && SvROK(sv) &&
2186 (sv_derived_from(sv, "Imager::Color")
2187 || sv_derived_from(sv, "Imager::Color::Float"));
2199 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2201 #define TT_DESTROY(handle) i_tt_destroy(handle)
2205 Imager::Font::TT handle
2210 (void)items; /* avoid unused warning */
2216 MODULE = Imager PACKAGE = Imager
2220 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
2221 Imager::Font::TT handle
2235 str = SvPV(str_sv, len);
2240 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2241 len, smooth, utf8, align);
2247 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
2248 Imager::Font::TT handle
2262 str = SvPV(str_sv, len);
2267 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2268 smooth, utf8, align);
2274 i_tt_bbox(handle,point,str_sv,utf8)
2275 Imager::Font::TT handle
2280 i_img_dim cords[BOUNDING_BOX_COUNT];
2286 str = SvPV(str_sv, len);
2291 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2293 for (i = 0; i < rc; ++i) {
2294 PUSHs(sv_2mortal(newSViv(cords[i])));
2299 i_tt_has_chars(handle, text_sv, utf8)
2300 Imager::Font::TT handle
2311 text = SvPV(text_sv, len);
2313 if (SvUTF8(text_sv))
2316 work = mymalloc(len);
2317 count = i_tt_has_chars(handle, text, len, utf8, work);
2318 if (GIMME_V == G_ARRAY) {
2320 for (i = 0; i < count; ++i) {
2321 PUSHs(boolSV(work[i]));
2326 PUSHs(sv_2mortal(newSVpv(work, count)));
2331 i_tt_dump_names(handle)
2332 Imager::Font::TT handle
2335 i_tt_face_name(handle)
2336 Imager::Font::TT handle
2341 len = i_tt_face_name(handle, name, sizeof(name));
2344 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2348 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2349 Imager::Font::TT handle
2361 text = SvPV(text_sv, work_len);
2363 if (SvUTF8(text_sv))
2370 ch = i_utf8_advance(&text, &len);
2372 i_push_error(0, "invalid UTF8 character");
2380 EXTEND(SP, count+1);
2381 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2382 ST(count) = sv_2mortal(newSVpv(name, 0));
2385 ST(count) = &PL_sv_undef;
2394 i_test_format_probe(ig, length)
2399 i_readpnm_wiol(ig, allow_incomplete)
2401 int allow_incomplete
2405 i_readpnm_multi_wiol(ig, allow_incomplete)
2407 int allow_incomplete
2413 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2416 for (i = 0; i < count; ++i) {
2417 SV *sv = sv_newmortal();
2418 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2425 i_writeppm_wiol(im, ig)
2434 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2443 i_writeraw_wiol(im,ig)
2448 i_writebmp_wiol(im,ig)
2453 i_readbmp_wiol(ig, allow_incomplete=0)
2455 int allow_incomplete
2459 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2468 idlen = SvCUR(ST(4));
2469 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2475 i_readtga_wiol(ig, length)
2483 i_scaleaxis(im,Value,Axis)
2489 i_scale_nn(im,scx,scy)
2495 i_scale_mixing(im, width, height)
2505 i_count_colors(im,maxc)
2510 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2515 unsigned int * col_usage = NULL;
2518 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2519 EXTEND(SP, col_cnt);
2520 for (i = 0; i < col_cnt; i++) {
2521 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2528 i_transform(im, opx, opy, parm)
2534 STRLEN size_opx, size_opy, size_parm;
2537 result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
2539 SV *result_sv = sv_newmortal();
2541 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2546 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2572 in_imgs_count = av_len(av_in_imgs)+1;
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("sv_in_img must contain only images");
2579 if (in_imgs_count > 0) {
2580 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2581 for (i = 0; i < in_imgs_count; ++i) {
2582 sv1 = *av_fetch(av_in_imgs,i,0);
2583 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2584 croak("Parameter 5 must contain only images");
2586 tmp = SvIV((SV*)SvRV(sv1));
2587 in_imgs[i] = INT2PTR(i_img*, tmp);
2591 /* no input images */
2594 /* default the output size from the first input if possible */
2596 width = SvIV(sv_width);
2597 else if (in_imgs_count)
2598 width = in_imgs[0]->xsize;
2600 croak("No output image width supplied");
2602 if (SvOK(sv_height))
2603 height = SvIV(sv_height);
2604 else if (in_imgs_count)
2605 height = in_imgs[0]->ysize;
2607 croak("No output image height supplied");
2609 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2610 if (ops_len % sizeof(struct rm_op))
2611 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2612 ops_count = ops_len / sizeof(struct rm_op);
2614 n_regs_count = av_len(av_n_regs)+1;
2615 n_regs = mymalloc(n_regs_count * sizeof(double));
2616 for (i = 0; i < n_regs_count; ++i) {
2617 sv1 = *av_fetch(av_n_regs,i,0);
2619 n_regs[i] = SvNV(sv1);
2621 c_regs_count = av_len(av_c_regs)+1;
2622 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2623 /* I don't bother initializing the colou?r registers */
2625 result=i_transform2(width, height, channels, ops, ops_count,
2626 n_regs, n_regs_count,
2627 c_regs, c_regs_count, in_imgs, in_imgs_count);
2633 SV *result_sv = sv_newmortal();
2635 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2641 i_contrast(im,intensity)
2654 i_noise(im,amount,type)
2660 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2670 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2689 i_postlevels(im,levels)
2699 i_watermark(im,wmark,tx,ty,pixdiff)
2701 Imager::ImgRaw wmark
2708 i_autolevels(im,lsat,usat,skew)
2715 i_radnoise(im,xo,yo,rscale,ascale)
2723 i_turbnoise(im, xo, yo, scale)
2731 i_gradgen(im, xo, yo, ac, dmeasure)
2742 if (size_xo != size_yo || size_xo != size_ac)
2743 croak("i_gradgen: x, y and color arrays must be the same size");
2745 croak("Usage: i_gradgen array refs must have more than 1 entry each");
2746 i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
2749 i_diff_image(im, im2, mindist=0)
2755 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2765 double ssample_param
2769 i_fountain_seg *segs;
2771 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2772 croak("i_fountain: argument 11 must be an array ref");
2774 asegs = (AV *)SvRV(ST(10));
2775 segs = load_fount_segs(aTHX_ asegs, &count);
2776 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2777 super_sample, ssample_param, count, segs);
2783 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2792 double ssample_param
2796 i_fountain_seg *segs;
2798 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2799 croak("i_fountain: argument 11 must be an array ref");
2801 asegs = (AV *)SvRV(ST(9));
2802 segs = load_fount_segs(aTHX_ asegs, &count);
2803 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2804 super_sample, ssample_param, count, segs);
2810 i_new_fill_opacity(other_fill, alpha_mult)
2811 Imager::FillHandle other_fill
2822 errors = i_errors();
2824 while (errors[i].msg) {
2826 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2827 if (!av_store(av, 0, sv)) {
2830 sv = newSViv(errors[i].code);
2831 if (!av_store(av, 1, sv)) {
2834 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2842 i_push_error(code, msg)
2847 i_nearest_color(im, ...)
2862 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2863 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2864 croak("i_nearest_color: Second argument must be an array ref");
2865 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2866 croak("i_nearest_color: Third argument must be an array ref");
2867 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2868 croak("i_nearest_color: Fourth argument must be an array ref");
2869 axx = (AV *)SvRV(ST(1));
2870 ayy = (AV *)SvRV(ST(2));
2871 ac = (AV *)SvRV(ST(3));
2872 dmeasure = (int)SvIV(ST(4));
2874 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2875 num = num <= av_len(ac) ? num : av_len(ac);
2877 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2878 xo = mymalloc( sizeof(i_img_dim) * num );
2879 yo = mymalloc( sizeof(i_img_dim) * num );
2880 ival = mymalloc( sizeof(i_color) * num );
2881 for(i = 0; i<num; i++) {
2882 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2883 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2884 sv = *av_fetch(ac, i, 0);
2885 if ( !sv_derived_from(sv, "Imager::Color") ) {
2886 free(axx); free(ayy); free(ac);
2887 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2889 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2891 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2905 rc=DSO_open(filename,&evstr);
2909 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2910 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2913 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2919 DSO_close(dso_handle)
2923 DSO_funclist(dso_handle_v)
2927 DSO_handle *dso_handle;
2928 func_ptr *functions;
2930 dso_handle=(DSO_handle*)dso_handle_v;
2931 functions = DSO_funclist(dso_handle);
2933 while( functions[i].name != NULL) {
2935 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2937 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2941 DSO_call(handle,func_index,hv)
2946 DSO_call( (DSO_handle *)handle,func_index,hv);
2949 i_get_pixel(im, x, y)
2954 RETVAL = (i_color *)mymalloc(sizeof(i_color));
2955 if (i_gpix(im, x, y, RETVAL) != 0) {
2964 i_ppix(im, x, y, cl)
2971 i_img_pal_new(x, y, channels, maxpal)
2978 i_img_to_pal(src, quant)
2984 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2985 croak("i_img_to_pal: second argument must be a hash ref");
2986 hv = (HV *)SvRV(ST(1));
2987 memset(&quant, 0, sizeof(quant));
2989 quant.mc_size = 256;
2990 ip_handle_quant_opts(aTHX_ &quant, hv);
2991 RETVAL = i_img_to_pal(src, &quant);
2993 ip_copy_colors_back(aTHX_ hv, &quant);
2995 ip_cleanup_quant_opts(aTHX_ &quant);
3004 i_img_make_palette(HV *quant_hv, ...)
3006 size_t count = items - 1;
3008 i_img **imgs = NULL;
3012 croak("Please supply at least one image (%d)", (int)count);
3013 imgs = mymalloc(sizeof(i_img *) * count);
3014 for (i = 0; i < count; ++i) {
3015 SV *img_sv = ST(i + 1);
3016 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3017 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3021 croak("Image %d is not an image object", (int)i+1);
3024 memset(&quant, 0, sizeof(quant));
3026 quant.mc_size = 256;
3027 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3028 i_quant_makemap(&quant, imgs, count);
3029 EXTEND(SP, quant.mc_count);
3030 for (i = 0; i < quant.mc_count; ++i) {
3031 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3034 ip_cleanup_quant_opts(aTHX_ &quant);
3048 work = mymalloc((r-l) * sizeof(i_palidx));
3049 count = i_gpal(im, l, r, y, work);
3050 if (GIMME_V == G_ARRAY) {
3052 for (i = 0; i < count; ++i) {
3053 PUSHs(sv_2mortal(newSViv(work[i])));
3058 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3063 if (GIMME_V != G_ARRAY) {
3065 PUSHs(&PL_sv_undef);
3070 i_ppal(im, l, y, ...)
3079 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3080 for (i=0; i < items-3; ++i) {
3081 work[i] = SvIV(ST(i+3));
3083 validate_i_ppal(im, work, items - 3);
3084 RETVAL = i_ppal(im, l, l+items-3, y, work);
3093 i_ppal_p(im, l, y, data)
3099 i_palidx const *work;
3102 work = (i_palidx const *)SvPV(data, len);
3103 len /= sizeof(i_palidx);
3105 validate_i_ppal(im, work, len);
3106 RETVAL = i_ppal(im, l, l+len, y, work);
3115 i_addcolors(im, ...)
3122 croak("i_addcolors: no colors to add");
3123 colors = mymalloc((items-1) * sizeof(i_color));
3124 for (i=0; i < items-1; ++i) {
3125 if (sv_isobject(ST(i+1))
3126 && sv_derived_from(ST(i+1), "Imager::Color")) {
3127 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3128 colors[i] = *INT2PTR(i_color *, tmp);
3132 croak("i_addcolor: pixels must be Imager::Color objects");
3135 RETVAL = i_addcolors(im, colors, items-1);
3140 i_setcolors(im, index, ...)
3148 croak("i_setcolors: no colors to add");
3149 colors = mymalloc((items-2) * sizeof(i_color));
3150 for (i=0; i < items-2; ++i) {
3151 if (sv_isobject(ST(i+2))
3152 && sv_derived_from(ST(i+2), "Imager::Color")) {
3153 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3154 colors[i] = *INT2PTR(i_color *, tmp);
3158 croak("i_setcolors: pixels must be Imager::Color objects");
3161 RETVAL = i_setcolors(im, index, colors, items-2);
3167 i_getcolors(im, index, count=1)
3176 croak("i_getcolors: count must be positive");
3177 colors = malloc_temp(aTHX_ sizeof(i_color) * count);
3178 if (i_getcolors(im, index, colors, count)) {
3180 for (i = 0; i < count; ++i) {
3181 SV *sv = make_i_color_sv(aTHX_ colors+i);
3195 i_findcolor(im, color)
3199 if (!i_findcolor(im, color, &RETVAL)) {
3218 i_gsamp(im, l, r, y, channels)
3223 i_channel_list channels
3229 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count);
3230 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3231 if (GIMME_V == G_ARRAY) {
3233 for (i = 0; i < count; ++i)
3234 PUSHs(sv_2mortal(newSViv(data[i])));
3238 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3243 if (GIMME_V != G_ARRAY) {
3249 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3257 i_channel_list channels
3264 croak("No channel numbers supplied to g_samp()");
3266 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3267 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3268 for (i = 0; i < count; ++i) {
3269 av_store(target, i+offset, newSVuv(data[i]));
3281 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3286 i_channel_list channels
3288 i_img_dim data_offset
3289 i_img_dim pixel_count
3298 data_count = av_len(data_av) + 1;
3299 if (data_offset < 0) {
3300 croak("data_offset must be non-negative");
3302 if (data_offset > data_count) {
3303 croak("data_offset greater than number of samples supplied");
3305 if (pixel_count == -1 ||
3306 data_offset + pixel_count * channels.count > data_count) {
3307 pixel_count = (data_count - data_offset) / channels.count;
3310 data_used = pixel_count * channels.count;
3311 data = mymalloc(sizeof(unsigned) * data_count);
3312 for (i = 0; i < data_used; ++i)
3313 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3315 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3316 channels.count, bits);
3324 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3328 i_channel_list channels
3337 i_push_error(0, "offset must be non-negative");
3341 if (offset > data.count) {
3342 i_push_error(0, "offset greater than number of samples supplied");
3345 data.samples += offset;
3346 data.count -= offset;
3349 width * channels.count > data.count) {
3350 width = data.count / channels.count;
3353 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3358 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3362 i_channel_list channels
3371 i_push_error(0, "offset must be non-negative");
3375 if (offset > data.count) {
3376 i_push_error(0, "offset greater than number of samples supplied");
3379 data.samples += offset;
3380 data.count -= offset;
3383 width * channels.count > data.count) {
3384 width = data.count / channels.count;
3387 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3392 i_img_masked_new(targ, mask, x, y, w, h)
3402 if (!sv_isobject(ST(1))
3403 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3404 croak("i_img_masked_new: parameter 2 must undef or an image");
3406 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3410 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3415 i_plin(im, l, y, ...)
3426 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3427 /* supplied as a byte string */
3428 work = (i_color *)SvPV(ST(3), len);
3429 count = len / sizeof(i_color);
3430 if (count * sizeof(i_color) != len) {
3431 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3433 RETVAL = i_plin(im, l, l+count, y, work);
3436 work = mymalloc(sizeof(i_color) * (items-3));
3437 for (i=0; i < items-3; ++i) {
3438 if (sv_isobject(ST(i+3))
3439 && sv_derived_from(ST(i+3), "Imager::Color")) {
3440 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3441 work[i] = *INT2PTR(i_color *, tmp);
3445 croak("i_plin: pixels must be Imager::Color objects");
3448 RETVAL = i_plin(im, l, l+items-3, y, work);
3459 i_ppixf(im, x, y, cl)
3463 Imager::Color::Float cl
3466 i_gsampf(im, l, r, y, channels)
3471 i_channel_list channels
3477 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3478 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3479 if (GIMME_V == G_ARRAY) {
3481 for (i = 0; i < count; ++i)
3482 PUSHs(sv_2mortal(newSVnv(data[i])));
3486 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3491 if (GIMME_V != G_ARRAY) {
3497 i_plinf(im, l, y, ...)
3508 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3509 /* supplied as a byte string */
3510 work = (i_fcolor *)SvPV(ST(3), len);
3511 count = len / sizeof(i_fcolor);
3512 if (count * sizeof(i_fcolor) != len) {
3513 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3515 RETVAL = i_plinf(im, l, l+count, y, work);
3518 work = mymalloc(sizeof(i_fcolor) * (items-3));
3519 for (i=0; i < items-3; ++i) {
3520 if (sv_isobject(ST(i+3))
3521 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3522 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3523 work[i] = *INT2PTR(i_fcolor *, tmp);
3527 croak("i_plinf: pixels must be Imager::Color::Float objects");
3531 RETVAL = i_plinf(im, l, l+items-3, y, work);
3541 Imager::Color::Float
3547 RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3548 if (i_gpixf(im, x, y, RETVAL) != 0) {
3566 vals = mymalloc((r-l) * sizeof(i_color));
3567 memset(vals, 0, (r-l) * sizeof(i_color));
3568 count = i_glin(im, l, r, y, vals);
3569 if (GIMME_V == G_ARRAY) {
3571 for (i = 0; i < count; ++i) {
3572 SV *sv = make_i_color_sv(aTHX_ vals+i);
3578 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3584 i_glinf(im, l, r, y)
3594 for (i = 0; i < MAXCHANNELS; ++i)
3595 zero.channel[i] = 0;
3597 vals = mymalloc((r-l) * sizeof(i_fcolor));
3598 for (i = 0; i < r-l; ++i)
3600 count = i_glinf(im, l, r, y, vals);
3601 if (GIMME_V == G_ARRAY) {
3603 for (i = 0; i < count; ++i) {
3605 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3607 sv = sv_newmortal();
3608 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3614 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3620 i_img_8_new(x, y, ch)
3626 i_img_16_new(x, y, ch)
3636 i_img_double_new(x, y, ch)
3646 i_tags_addn(im, name_sv, code, idata)
3655 SvGETMAGIC(name_sv);
3657 name = SvPV_nomg(name_sv, len);
3660 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3665 i_tags_add(im, name_sv, code, data_sv, idata)
3676 SvGETMAGIC(name_sv);
3678 name = SvPV_nomg(name_sv, len);
3681 SvGETMAGIC(data_sv);
3683 data = SvPV(data_sv, len);
3688 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3693 i_tags_find(im, name, start)
3700 if (i_tags_find(&im->tags, name, start, &entry)) {
3709 i_tags_findn(im, code, start)
3716 if (i_tags_findn(&im->tags, code, start, &entry)) {
3726 i_tags_delete(im, entry)
3730 RETVAL = i_tags_delete(&im->tags, entry);
3735 i_tags_delbyname(im, name)
3739 RETVAL = i_tags_delbyname(&im->tags, name);
3744 i_tags_delbycode(im, code)
3748 RETVAL = i_tags_delbycode(&im->tags, code);
3753 i_tags_get(im, index)
3757 if (index >= 0 && index < im->tags.count) {
3758 i_img_tag *entry = im->tags.tags + index;
3762 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3765 PUSHs(sv_2mortal(newSViv(entry->code)));
3768 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3771 PUSHs(sv_2mortal(newSViv(entry->idata)));
3776 i_tags_get_string(im, what_sv)
3780 char const *name = NULL;
3784 if (SvIOK(what_sv)) {
3785 code = SvIV(what_sv);
3789 name = SvPV_nolen(what_sv);
3792 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3794 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3801 RETVAL = im->tags.count;
3807 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3811 Imager::FillHandle fill
3814 IFILL_CLONE_SKIP(...)
3816 (void)items; /* avoid unused warning for XS variable */
3821 MODULE = Imager PACKAGE = Imager
3824 i_new_fill_solid(cl, combine)
3829 i_new_fill_solidf(cl, combine)
3830 Imager::Color::Float cl
3834 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3843 unsigned char *cust_hatch;
3846 SvGETMAGIC(cust_hatch_sv);
3847 if (SvOK(cust_hatch_sv)) {
3848 cust_hatch = (unsigned char *)SvPV_nomg(cust_hatch_sv, len);
3852 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3857 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3858 Imager::Color::Float fg
3859 Imager::Color::Float bg
3866 unsigned char *cust_hatch;
3869 SvGETMAGIC(cust_hatch_sv);
3870 if (SvOK(cust_hatch_sv)) {
3871 cust_hatch = (unsigned char *)SvPV(cust_hatch_sv, len);
3875 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3880 i_new_fill_image(src, matrix_sv, xoff, yoff, combine)
3894 SvGETMAGIC(matrix_sv);
3895 if (!SvOK(matrix_sv)) {
3899 if (!SvROK(matrix_sv) || SvTYPE(SvRV(matrix_sv)) != SVt_PVAV)
3900 croak("i_new_fill_image: matrix parameter must be an arrayref or undef");
3901 av=(AV*)SvRV(matrix_sv);
3905 for (i = 0; i < len; ++i) {
3906 sv1=(*(av_fetch(av,i,0)));
3907 matrix[i] = SvNV(sv1);
3913 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3917 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3919 # this class is only exposed for testing
3922 i_int_hlines_testing()
3924 #if i_int_hlines_testing()
3926 Imager::Internal::Hlines
3927 i_int_hlines_new(start_y, count_y, start_x, count_x)
3933 Imager::Internal::Hlines
3934 i_int_hlines_new_img(im)
3938 i_int_hlines_add(hlines, y, minx, width)
3939 Imager::Internal::Hlines hlines
3945 i_int_hlines_DESTROY(hlines)
3946 Imager::Internal::Hlines hlines
3949 i_int_hlines_dump(hlines)
3950 Imager::Internal::Hlines hlines
3953 i_int_hlines_CLONE_SKIP(cls)
3957 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
3960 im_context_DESTROY(ctx)
3963 #ifdef PERL_IMPLICIT_CONTEXT
3966 im_context_CLONE(...)
3970 /* the following sv_setref_pv() will free this inc */
3971 im_context_refinc(MY_CXT.ctx, "CLONE");
3972 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
3973 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
3978 PERL_SET_GLOBAL_CALLBACKS;
3979 PERL_PL_SET_GLOBAL_CALLBACKS;
3980 #ifdef PERL_IMPLICIT_CONTEXT
3986 start_context(aTHX);
3987 im_get_context = perl_get_context;