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");
152 return *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
155 /* These functions are all shared - then comes platform dependant code */
156 static int getstr(void *hv_t,char *key,char **store) {
161 mm_log((1,"getstr(hv_t %p, key %s, store %p)\n",hv_t,key,store));
163 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
165 svpp=hv_fetch(hv, key, strlen(key), 0);
166 *store=SvPV(*svpp, PL_na );
171 static int getint(void *hv_t,char *key,int *store) {
176 mm_log((1,"getint(hv_t %p, key %s, store %p)\n",hv_t,key,store));
178 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
180 svpp=hv_fetch(hv, key, strlen(key), 0);
181 *store=(int)SvIV(*svpp);
185 static int getdouble(void *hv_t,char* key,double *store) {
190 mm_log((1,"getdouble(hv_t %p, key %s, store %p)\n",hv_t,key,store));
192 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
193 svpp=hv_fetch(hv, key, strlen(key), 0);
194 *store=(double)SvNV(*svpp);
198 static int getvoid(void *hv_t,char* key,void **store) {
203 mm_log((1,"getvoid(hv_t %p, key %s, store %p)\n",hv_t,key,store));
205 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
207 svpp=hv_fetch(hv, key, strlen(key), 0);
208 *store = INT2PTR(void*, SvIV(*svpp));
213 static int getobj(void *hv_t,char *key,char *type,void **store) {
218 mm_log((1,"getobj(hv_t %p, key %s,type %s, store %p)\n",hv_t,key,type,store));
220 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
222 svpp=hv_fetch(hv, key, strlen(key), 0);
224 if (sv_derived_from(*svpp,type)) {
225 IV tmp = SvIV((SV*)SvRV(*svpp));
226 *store = INT2PTR(void*, tmp);
228 mm_log((1,"getobj: key exists in hash but is not of correct type"));
235 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
237 void my_SvREFCNT_dec(void *p) {
239 SvREFCNT_dec((SV*)p);
244 i_log_entry(char *string, int level) {
245 mm_log((level, "%s", string));
249 make_i_color_sv(pTHX_ const i_color *c) {
251 i_color *col = mymalloc(sizeof(i_color));
254 sv_setref_pv(sv, "Imager::Color", (void *)col);
259 #define CBDATA_BUFSIZE 8192
262 /* the SVs we use to call back to Perl */
270 call_reader(struct cbdata *cbd, void *buf, size_t size,
278 if (!SvOK(cbd->readcb)) {
279 mm_log((1, "read callback called but no readcb supplied\n"));
280 i_push_error(0, "read callback called but no readcb supplied");
288 PUSHs(sv_2mortal(newSViv(size)));
289 PUSHs(sv_2mortal(newSViv(maxread)));
292 count = perl_call_sv(cbd->readcb, G_SCALAR);
297 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
303 char *ptr = SvPVbyte(data, len);
305 croak("Too much data returned in reader callback (wanted %d, got %d, expected %d)",
306 (int)size, (int)len, (int)maxread);
308 memcpy(buf, ptr, len);
323 io_seeker(void *p, off_t offset, int whence) {
325 struct cbdata *cbd = p;
330 if (!SvOK(cbd->seekcb)) {
331 mm_log((1, "seek callback called but no seekcb supplied\n"));
332 i_push_error(0, "seek callback called but no seekcb supplied");
340 PUSHs(sv_2mortal(newSViv(offset)));
341 PUSHs(sv_2mortal(newSViv(whence)));
344 count = perl_call_sv(cbd->seekcb, G_SCALAR);
349 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
361 io_writer(void *p, void const *data, size_t size) {
363 struct cbdata *cbd = p;
369 if (!SvOK(cbd->writecb)) {
370 mm_log((1, "write callback called but no writecb supplied\n"));
371 i_push_error(0, "write callback called but no writecb supplied");
379 PUSHs(sv_2mortal(newSVpv((char *)data, size)));
382 count = perl_call_sv(cbd->writecb, G_SCALAR);
386 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
389 success = SvTRUE(sv);
396 return success ? size : -1;
400 io_reader(void *p, void *data, size_t size) {
401 struct cbdata *cbd = p;
403 return call_reader(cbd, data, size, size);
406 static int io_closer(void *p) {
408 struct cbdata *cbd = p;
411 if (SvOK(cbd->closecb)) {
421 count = perl_call_sv(cbd->closecb, G_SCALAR);
426 success = SvTRUE(sv);
433 return success ? 0 : -1;
436 static void io_destroyer(void *p) {
438 struct cbdata *cbd = p;
440 SvREFCNT_dec(cbd->writecb);
441 SvREFCNT_dec(cbd->readcb);
442 SvREFCNT_dec(cbd->seekcb);
443 SvREFCNT_dec(cbd->closecb);
448 do_io_new_buffer(pTHX_ SV *data_sv) {
452 data = SvPVbyte(data_sv, length);
453 SvREFCNT_inc(data_sv);
454 return io_new_buffer(data, length, my_SvREFCNT_dec, data_sv);
458 describe_sv(SV *sv) {
461 svtype type = SvTYPE(SvRV(sv));
463 case SVt_PVCV: return "CV";
464 case SVt_PVGV: return "GV";
465 case SVt_PVLV: return "LV";
466 default: return "some reference";
470 return "non-reference scalar";
479 do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) {
482 cbd = mymalloc(sizeof(struct cbdata));
483 cbd->writecb = newSVsv(writecb);
484 cbd->readcb = newSVsv(readcb);
485 cbd->seekcb = newSVsv(seekcb);
486 cbd->closecb = newSVsv(closecb);
488 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)));
490 return io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
498 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
501 for (i = 0; i < count; ++i)
502 if (strEQ(names[i].name, name))
503 return names[i].value;
507 static struct value_name transp_names[] =
510 { "threshold", tr_threshold },
511 { "errdiff", tr_errdiff },
512 { "ordered", tr_ordered, },
515 static struct value_name make_color_names[] =
517 { "none", mc_none, },
518 { "webmap", mc_web_map, },
519 { "addi", mc_addi, },
520 { "mediancut", mc_median_cut, },
521 { "mono", mc_mono, },
522 { "monochrome", mc_mono, },
523 { "gray", mc_gray, },
524 { "gray4", mc_gray4, },
525 { "gray16", mc_gray16, },
528 static struct value_name translate_names[] =
530 { "giflib", pt_giflib, },
531 { "closest", pt_closest, },
532 { "perturb", pt_perturb, },
533 { "errdiff", pt_errdiff, },
536 static struct value_name errdiff_names[] =
538 { "floyd", ed_floyd, },
539 { "jarvis", ed_jarvis, },
540 { "stucki", ed_stucki, },
541 { "custom", ed_custom, },
544 static struct value_name orddith_names[] =
546 { "random", od_random, },
547 { "dot8", od_dot8, },
548 { "dot4", od_dot4, },
549 { "hline", od_hline, },
550 { "vline", od_vline, },
551 { "/line", od_slashline, },
552 { "slashline", od_slashline, },
553 { "\\line", od_backline, },
554 { "backline", od_backline, },
555 { "tiny", od_tiny, },
556 { "custom", od_custom, },
559 /* look through the hash for quantization options */
561 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
563 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
569 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
571 sv = hv_fetch(hv, "transp", 6, 0);
572 if (sv && *sv && (str = SvPV(*sv, len))) {
574 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
576 if (quant->transp != tr_none) {
577 quant->tr_threshold = 127;
578 sv = hv_fetch(hv, "tr_threshold", 12, 0);
580 quant->tr_threshold = SvIV(*sv);
582 if (quant->transp == tr_errdiff) {
583 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
584 if (sv && *sv && (str = SvPV(*sv, len)))
585 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
587 if (quant->transp == tr_ordered) {
588 quant->tr_orddith = od_tiny;
589 sv = hv_fetch(hv, "tr_orddith", 10, 0);
590 if (sv && *sv && (str = SvPV(*sv, len)))
591 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
593 if (quant->tr_orddith == od_custom) {
594 sv = hv_fetch(hv, "tr_map", 6, 0);
595 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
596 AV *av = (AV*)SvRV(*sv);
597 len = av_len(av) + 1;
598 if (len > sizeof(quant->tr_custom))
599 len = sizeof(quant->tr_custom);
600 for (i = 0; i < len; ++i) {
601 SV **sv2 = av_fetch(av, i, 0);
603 quant->tr_custom[i] = SvIV(*sv2);
606 while (i < sizeof(quant->tr_custom))
607 quant->tr_custom[i++] = 0;
612 quant->make_colors = mc_median_cut;
613 sv = hv_fetch(hv, "make_colors", 11, 0);
614 if (sv && *sv && (str = SvPV(*sv, len))) {
616 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
618 sv = hv_fetch(hv, "colors", 6, 0);
619 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
620 /* needs to be an array of Imager::Color
621 note that the caller allocates the mc_color array and sets mc_size
623 AV *av = (AV *)SvRV(*sv);
624 quant->mc_count = av_len(av)+1;
625 if (quant->mc_count > quant->mc_size)
626 quant->mc_count = quant->mc_size;
627 for (i = 0; i < quant->mc_count; ++i) {
628 SV **sv1 = av_fetch(av, i, 0);
629 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
630 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
631 quant->mc_colors[i] = *col;
635 sv = hv_fetch(hv, "max_colors", 10, 0);
638 if (i <= quant->mc_size && i >= quant->mc_count)
642 quant->translate = pt_closest;
643 sv = hv_fetch(hv, "translate", 9, 0);
644 if (sv && *sv && (str = SvPV(*sv, len))) {
645 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
647 sv = hv_fetch(hv, "errdiff", 7, 0);
648 if (sv && *sv && (str = SvPV(*sv, len))) {
649 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
651 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
652 /* get the error diffusion map */
653 sv = hv_fetch(hv, "errdiff_width", 13, 0);
655 quant->ed_width = SvIV(*sv);
656 sv = hv_fetch(hv, "errdiff_height", 14, 0);
658 quant->ed_height = SvIV(*sv);
659 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
661 quant->ed_orig = SvIV(*sv);
662 if (quant->ed_width > 0 && quant->ed_height > 0) {
664 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
665 sv = hv_fetch(hv, "errdiff_map", 11, 0);
666 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
667 AV *av = (AV*)SvRV(*sv);
668 len = av_len(av) + 1;
669 if (len > quant->ed_width * quant->ed_height)
670 len = quant->ed_width * quant->ed_height;
671 for (i = 0; i < len; ++i) {
672 SV **sv2 = av_fetch(av, i, 0);
674 quant->ed_map[i] = SvIV(*sv2);
675 sum += quant->ed_map[i];
681 myfree(quant->ed_map);
683 quant->errdiff = ed_floyd;
687 sv = hv_fetch(hv, "perturb", 7, 0);
689 quant->perturb = SvIV(*sv);
693 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
694 myfree(quant->mc_colors);
696 myfree(quant->ed_map);
699 /* copies the color map from the hv into the colors member of the HV */
701 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
707 sv = hv_fetch(hv, "colors", 6, 0);
708 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
713 av = (AV *)SvRV(*sv);
715 av_extend(av, quant->mc_count+1);
716 for (i = 0; i < quant->mc_count; ++i) {
717 i_color *in = quant->mc_colors+i;
718 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
719 work = sv_newmortal();
720 sv_setref_pv(work, "Imager::Color", (void *)c);
726 /* loads the segments of a fountain fill into an array */
727 static i_fountain_seg *
728 load_fount_segs(pTHX_ AV *asegs, int *count) {
729 /* Each element of segs must contain:
730 [ start, middle, end, c0, c1, segtype, colortrans ]
731 start, middle, end are doubles from 0 to 1
732 c0, c1 are Imager::Color::Float or Imager::Color objects
733 segtype, colortrans are ints
737 i_fountain_seg *segs;
741 *count = av_len(asegs)+1;
743 croak("i_fountain must have at least one segment");
744 segs = mymalloc(sizeof(i_fountain_seg) * *count);
745 for(i = 0; i < *count; i++) {
746 SV **sv1 = av_fetch(asegs, i, 0);
747 if (!sv1 || !*sv1 || !SvROK(*sv1)
748 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
750 croak("i_fountain: segs must be an arrayref of arrayrefs");
752 aseg = (AV *)SvRV(*sv1);
753 if (av_len(aseg) != 7-1) {
755 croak("i_fountain: a segment must have 7 members");
757 for (j = 0; j < 3; ++j) {
758 SV **sv2 = av_fetch(aseg, j, 0);
761 croak("i_fountain: XS error");
763 work[j] = SvNV(*sv2);
765 segs[i].start = work[0];
766 segs[i].middle = work[1];
767 segs[i].end = work[2];
768 for (j = 0; j < 2; ++j) {
769 SV **sv3 = av_fetch(aseg, 3+j, 0);
770 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
771 (!sv_derived_from(*sv3, "Imager::Color")
772 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
774 croak("i_fountain: segs must contain colors in elements 3 and 4");
776 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
777 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
780 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
782 for (ch = 0; ch < MAXCHANNELS; ++ch) {
783 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
787 for (j = 0; j < 2; ++j) {
788 SV **sv2 = av_fetch(aseg, j+5, 0);
791 croak("i_fountain: XS error");
793 worki[j] = SvIV(*sv2);
795 segs[i].type = worki[0];
796 segs[i].color = worki[1];
802 /* validates the indexes supplied to i_ppal
804 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
809 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
810 int color_count = i_colorcount(im);
813 if (color_count == -1)
814 croak("i_plin() called on direct color image");
816 for (i = 0; i < count; ++i) {
817 if (indexes[i] >= color_count) {
818 croak("i_plin() called with out of range color index %d (max %d)",
819 indexes[i], color_count-1);
824 /* I don't think ICLF_* names belong at the C interface
825 this makes the XS code think we have them, to let us avoid
826 putting function bodies in the XS code
828 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
829 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
832 #define i_log_enabled() 1
834 #define i_log_enabled() 0
837 #if i_int_hlines_testing()
839 typedef i_int_hlines *Imager__Internal__Hlines;
841 static i_int_hlines *
842 i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
843 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
844 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
849 static i_int_hlines *
850 i_int_hlines_new_img(i_img *im) {
851 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
852 i_int_init_hlines_img(result, im);
858 i_int_hlines_DESTROY(i_int_hlines *hlines) {
859 i_int_hlines_destroy(hlines);
863 #define i_int_hlines_CLONE_SKIP(cls) 1
865 static int seg_compare(const void *vleft, const void *vright) {
866 const i_int_hline_seg *left = vleft;
867 const i_int_hline_seg *right = vright;
869 return left->minx - right->minx;
873 i_int_hlines_dump(i_int_hlines *hlines) {
875 SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
876 i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
879 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
880 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
883 /* sort the segments, if any */
885 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
887 sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
888 for (i = 0; i < entry->count; ++i) {
889 sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx),
890 i_DFc(entry->segs[i].x_limit));
892 sv_catpv(dump, "\n");
902 i_sv_off_t(pTHX_ SV *sv) {
903 #if LSEEKSIZE > IVSIZE
904 return (off_t)SvNV(sv);
906 return (off_t)SvIV(sv);
911 i_new_sv_off_t(pTHX_ off_t off) {
912 #if LSEEKSIZE > IVSIZE
919 static im_pl_ext_funcs im_perl_funcs =
921 IMAGER_PL_API_VERSION,
923 ip_handle_quant_opts,
924 ip_cleanup_quant_opts,
928 #define PERL_PL_SET_GLOBAL_CALLBACKS \
929 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
931 #define IIM_new i_img_8_new
932 #define IIM_DESTROY i_img_destroy
936 #define i_exif_enabled() 1
938 #define i_exif_enabled() 0
941 /* trying to use more C style names, map them here */
942 #define i_io_DESTROY(ig) io_glue_destroy(ig)
944 #define i_img_get_width(im) ((im)->xsize)
945 #define i_img_get_height(im) ((im)->ysize)
947 #define i_img_epsilonf() (DBL_EPSILON * 4)
949 /* avoid some xsubpp strangeness */
952 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
955 ICL_new_internal(r,g,b,a)
967 ICL_set_internal(cl,r,g,b,a)
974 ICL_set_internal(cl, r, g, b, a);
988 PUSHs(sv_2mortal(newSViv(cl->rgba.r)));
989 PUSHs(sv_2mortal(newSViv(cl->rgba.g)));
990 PUSHs(sv_2mortal(newSViv(cl->rgba.b)));
991 PUSHs(sv_2mortal(newSViv(cl->rgba.a)));
997 RETVAL = mymalloc(sizeof(i_color));
999 i_hsv_to_rgb(RETVAL);
1007 RETVAL = mymalloc(sizeof(i_color));
1009 i_rgb_to_hsv(RETVAL);
1015 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
1017 Imager::Color::Float
1018 ICLF_new_internal(r, g, b, a)
1026 Imager::Color::Float cl
1030 Imager::Color::Float cl
1034 EXTEND(SP, MAXCHANNELS);
1035 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1036 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1037 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1041 ICLF_set_internal(cl,r,g,b,a)
1042 Imager::Color::Float cl
1055 Imager::Color::Float
1057 Imager::Color::Float c
1059 RETVAL = mymalloc(sizeof(i_fcolor));
1061 i_hsv_to_rgbf(RETVAL);
1065 Imager::Color::Float
1067 Imager::Color::Float c
1069 RETVAL = mymalloc(sizeof(i_fcolor));
1071 i_rgb_to_hsvf(RETVAL);
1075 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1089 MODULE = Imager PACKAGE = Imager
1103 io_new_buffer(data_sv)
1106 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1111 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1118 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1126 unsigned char* data;
1130 tlength = io_slurp(ig, &data);
1131 RETVAL = newSVpv((char *)data,tlength);
1138 i_set_image_file_limits(width, height, bytes)
1144 i_get_image_file_limits()
1146 i_img_dim width, height;
1149 if (i_get_image_file_limits(&width, &height, &bytes)) {
1151 PUSHs(sv_2mortal(newSViv(width)));
1152 PUSHs(sv_2mortal(newSViv(height)));
1153 PUSHs(sv_2mortal(newSVuv(bytes)));
1157 i_int_check_image_file_limits(width, height, channels, sample_size)
1164 MODULE = Imager PACKAGE = Imager::IO PREFIX = io_
1167 io_new_fd(class, fd)
1170 RETVAL = io_new_fd(fd);
1175 io_new_buffer(class, data_sv)
1178 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1183 io_new_cb(class, writecb, readcb, seekcb, closecb)
1189 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1194 io_new_bufchain(class)
1196 RETVAL = io_new_bufchain();
1201 io__new_perlio(class, io)
1204 RETVAL = im_io_new_perlio(aTHX_ io);
1212 unsigned char* data;
1216 tlength = io_slurp(ig, &data);
1217 RETVAL = newSVpv((char *)data,tlength);
1222 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1225 i_io_raw_write(ig, data_sv)
1232 data = SvPVbyte(data_sv, size);
1233 RETVAL = i_io_raw_write(ig, data, size);
1238 i_io_raw_read(ig, buffer_sv, size)
1247 croak("size negative in call to i_io_raw_read()");
1248 /* prevent an undefined value warning if they supplied an
1250 Orginally conditional on !SvOK(), but this will prevent the
1251 downgrade from croaking */
1252 sv_setpvn(buffer_sv, "", 0);
1254 if (SvUTF8(buffer_sv))
1255 sv_utf8_downgrade(buffer_sv, FALSE);
1257 buffer = SvGROW(buffer_sv, size+1);
1258 result = i_io_raw_read(ig, buffer, size);
1260 SvCUR_set(buffer_sv, result);
1261 *SvEND(buffer_sv) = '\0';
1262 SvPOK_only(buffer_sv);
1264 PUSHs(sv_2mortal(newSViv(result)));
1270 i_io_raw_read2(ig, size)
1279 croak("size negative in call to i_io_read2()");
1280 buffer_sv = newSV(size);
1281 buffer = SvGROW(buffer_sv, size+1);
1282 result = i_io_raw_read(ig, buffer, size);
1284 SvCUR_set(buffer_sv, result);
1285 *SvEND(buffer_sv) = '\0';
1286 SvPOK_only(buffer_sv);
1288 PUSHs(sv_2mortal(buffer_sv));
1292 SvREFCNT_dec(buffer_sv);
1296 i_io_raw_seek(ig, position, whence)
1310 i_io_CLONE_SKIP(...)
1312 (void)items; /* avoid unused warning for XS variable */
1339 i_io_seek(ig, off, whence)
1345 i_io_peekn(ig, size)
1353 buffer_sv = newSV(size+1);
1354 buffer = SvGROW(buffer_sv, size+1);
1355 result = i_io_peekn(ig, buffer, size);
1357 SvCUR_set(buffer_sv, result);
1358 *SvEND(buffer_sv) = '\0';
1359 SvPOK_only(buffer_sv);
1361 PUSHs(sv_2mortal(buffer_sv));
1365 SvREFCNT_dec(buffer_sv);
1369 i_io_read(ig, buffer_sv, size)
1378 croak("size negative in call to i_io_read()");
1379 /* prevent an undefined value warning if they supplied an
1381 Orginally conditional on !SvOK(), but this will prevent the
1382 downgrade from croaking */
1383 sv_setpvn(buffer_sv, "", 0);
1385 if (SvUTF8(buffer_sv))
1386 sv_utf8_downgrade(buffer_sv, FALSE);
1388 buffer = SvGROW(buffer_sv, size+1);
1389 result = i_io_read(ig, buffer, size);
1391 SvCUR_set(buffer_sv, result);
1392 *SvEND(buffer_sv) = '\0';
1393 SvPOK_only(buffer_sv);
1395 PUSHs(sv_2mortal(newSViv(result)));
1401 i_io_read2(ig, size)
1410 croak("size zero in call to read2()");
1411 buffer_sv = newSV(size);
1412 buffer = SvGROW(buffer_sv, size+1);
1413 result = i_io_read(ig, buffer, size);
1415 SvCUR_set(buffer_sv, result);
1416 *SvEND(buffer_sv) = '\0';
1417 SvPOK_only(buffer_sv);
1419 PUSHs(sv_2mortal(buffer_sv));
1423 SvREFCNT_dec(buffer_sv);
1427 i_io_gets(ig, size = 8192, eol = NEWLINE)
1437 croak("size too small in call to gets()");
1438 buffer_sv = sv_2mortal(newSV(size+1));
1439 buffer = SvPVX(buffer_sv);
1440 result = i_io_gets(ig, buffer, size+1, eol);
1442 SvCUR_set(buffer_sv, result);
1443 *SvEND(buffer_sv) = '\0';
1444 SvPOK_only(buffer_sv);
1450 i_io_write(ig, data_sv)
1457 data = SvPVbyte(data_sv, size);
1458 RETVAL = i_io_write(ig, data, size);
1463 i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
1468 i_io_set_buffered(ig, flag = 1)
1473 i_io_is_buffered(ig)
1484 MODULE = Imager PACKAGE = Imager
1495 while( (item=i_format_list[i++]) != NULL ) {
1497 PUSHs(sv_2mortal(newSVpv(item,0)));
1501 i_sametype(im, x, y)
1507 i_sametype_chans(im, x, y, channels)
1514 i_init_log(name_sv,level)
1518 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1520 RETVAL = i_init_log(name, level);
1525 i_log_entry(string,level)
1538 i_img_info(im,info);
1540 PUSHs(sv_2mortal(newSViv(info[0])));
1541 PUSHs(sv_2mortal(newSViv(info[1])));
1542 PUSHs(sv_2mortal(newSViv(info[2])));
1543 PUSHs(sv_2mortal(newSViv(info[3])));
1549 i_img_setmask(im,ch_mask)
1558 i_img_getchannels(im)
1567 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1575 i_img_get_height(im)
1580 i_img_is_monochrome(im)
1586 result = i_img_is_monochrome(im, &zero_is_white);
1588 if (GIMME_V == G_ARRAY) {
1591 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1600 i_line(im,x1,y1,x2,y2,val,endp)
1610 i_line_aa(im,x1,y1,x2,y2,val,endp)
1620 i_box(im,x1,y1,x2,y2,val)
1629 i_box_filled(im,x1,y1,x2,y2,val)
1638 i_box_filledf(im,x1,y1,x2,y2,val)
1644 Imager::Color::Float val
1647 i_box_cfill(im,x1,y1,x2,y2,fill)
1653 Imager::FillHandle fill
1656 i_arc(im,x,y,rad,d1,d2,val)
1666 i_arc_aa(im,x,y,rad,d1,d2,val)
1676 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1683 Imager::FillHandle fill
1686 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1693 Imager::FillHandle fill
1697 i_circle_aa(im,x,y,rad,val)
1705 i_circle_out(im,x,y,rad,val)
1713 i_circle_out_aa(im,x,y,rad,val)
1721 i_arc_out(im,x,y,rad,d1,d2,val)
1731 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1742 i_bezier_multi(im,x,y,val)
1751 if (size_x != size_y)
1752 croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1753 i_bezier_multi(im,size_x,x,y,val);
1756 i_poly_aa(im,x,y,val)
1765 if (size_x != size_y)
1766 croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1767 RETVAL = i_poly_aa(im, size_x, x, y, val);
1772 i_poly_aa_cfill(im, x, y, fill)
1776 Imager::FillHandle fill
1781 if (size_x != size_y)
1782 croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1783 RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
1788 i_flood_fill(im,seedx,seedy,dcol)
1795 i_flood_cfill(im,seedx,seedy,fill)
1799 Imager::FillHandle fill
1802 i_flood_fill_border(im,seedx,seedy,dcol, border)
1807 Imager::Color border
1810 i_flood_cfill_border(im,seedx,seedy,fill, border)
1814 Imager::FillHandle fill
1815 Imager::Color border
1819 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1831 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1848 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1859 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1872 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)
1888 i_combine(src_av, channels_av = NULL)
1892 i_img **imgs = NULL;
1894 int *channels = NULL;
1899 in_count = av_len(src_av) + 1;
1901 imgs = mymalloc(sizeof(i_img*) * in_count);
1902 channels = mymalloc(sizeof(int) * in_count);
1903 for (i = 0; i < in_count; ++i) {
1904 psv = av_fetch(src_av, i, 0);
1905 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1908 croak("imgs must contain only images");
1910 tmp = SvIV((SV*)SvRV(*psv));
1911 imgs[i] = INT2PTR(i_img*, tmp);
1913 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1915 channels[i] = SvIV(*psv);
1922 RETVAL = i_combine(imgs, channels, in_count);
1929 i_flipxy(im, direction)
1934 i_rotate90(im, degrees)
1939 i_rotate_exact(im, amount, ...)
1943 i_color *backp = NULL;
1944 i_fcolor *fbackp = NULL;
1948 /* extract the bg colors if any */
1949 /* yes, this is kind of strange */
1950 for (i = 2; i < items; ++i) {
1952 if (sv_derived_from(sv1, "Imager::Color")) {
1953 IV tmp = SvIV((SV*)SvRV(sv1));
1954 backp = INT2PTR(i_color *, tmp);
1956 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1957 IV tmp = SvIV((SV*)SvRV(sv1));
1958 fbackp = INT2PTR(i_fcolor *, tmp);
1961 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1966 i_matrix_transform(im, xsize, ysize, matrix_av, ...)
1976 i_color *backp = NULL;
1977 i_fcolor *fbackp = NULL;
1979 len=av_len(matrix_av)+1;
1982 for (i = 0; i < len; ++i) {
1983 sv1=(*(av_fetch(matrix_av,i,0)));
1984 matrix[i] = SvNV(sv1);
1988 /* extract the bg colors if any */
1989 /* yes, this is kind of strange */
1990 for (i = 4; i < items; ++i) {
1992 if (sv_derived_from(sv1, "Imager::Color")) {
1993 IV tmp = SvIV((SV*)SvRV(sv1));
1994 backp = INT2PTR(i_color *, tmp);
1996 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1997 IV tmp = SvIV((SV*)SvRV(sv1));
1998 fbackp = INT2PTR(i_fcolor *, tmp);
2001 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2006 i_gaussian(im,stdev)
2011 i_unsharp_mask(im,stdev,scale)
2026 len = av_len(coef) + 1;
2027 c_coef=mymalloc( len * sizeof(double) );
2028 for(i = 0; i < len; i++) {
2029 sv1 = (*(av_fetch(coef, i, 0)));
2030 c_coef[i] = (double)SvNV(sv1);
2032 RETVAL = i_conv(im, c_coef, len);
2038 i_convert(src, avmain)
2050 outchan = av_len(avmain)+1;
2051 /* find the biggest */
2053 for (j=0; j < outchan; ++j) {
2054 temp = av_fetch(avmain, j, 0);
2055 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2056 avsub = (AV*)SvRV(*temp);
2057 len = av_len(avsub)+1;
2062 i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2066 coeff = mymalloc(sizeof(double) * outchan * inchan);
2067 for (j = 0; j < outchan; ++j) {
2068 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2069 len = av_len(avsub)+1;
2070 for (i = 0; i < len; ++i) {
2071 temp = av_fetch(avsub, i, 0);
2073 coeff[i+j*inchan] = SvNV(*temp);
2075 coeff[i+j*inchan] = 0;
2078 coeff[i++ + j*inchan] = 0;
2080 RETVAL = i_convert(src, coeff, outchan, inchan);
2091 unsigned int mask = 0;
2097 unsigned char (*maps)[256];
2099 len = av_len(pmaps_av)+1;
2100 if (im->channels < len)
2102 maps = mymalloc( len * sizeof(unsigned char [256]) );
2103 for (j=0; j<len ; j++) {
2104 temp = av_fetch(pmaps_av, j, 0);
2105 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2106 avsub = (AV*)SvRV(*temp);
2107 if(av_len(avsub) != 255)
2110 for (i=0; i<256 ; i++) {
2112 temp = av_fetch(avsub, i, 0);
2113 val = temp ? SvIV(*temp) : 0;
2115 if (val>255) val = 255;
2120 i_map(im, maps, mask);
2132 i_img_diffd(im1,im2)
2137 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2147 _is_color_object(sv)
2151 RETVAL = SvOK(sv) && SvROK(sv) &&
2152 (sv_derived_from(sv, "Imager::Color")
2153 || sv_derived_from(sv, "Imager::Color::Float"));
2165 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2167 #define TT_DESTROY(handle) i_tt_destroy(handle)
2171 Imager::Font::TT handle
2176 (void)items; /* avoid unused warning */
2182 MODULE = Imager PACKAGE = Imager
2186 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
2187 Imager::Font::TT handle
2201 str = SvPV(str_sv, len);
2206 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2207 len, smooth, utf8, align);
2213 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
2214 Imager::Font::TT handle
2228 str = SvPV(str_sv, len);
2233 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2234 smooth, utf8, align);
2240 i_tt_bbox(handle,point,str_sv,utf8)
2241 Imager::Font::TT handle
2246 i_img_dim cords[BOUNDING_BOX_COUNT];
2252 str = SvPV(str_sv, len);
2257 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2259 for (i = 0; i < rc; ++i) {
2260 PUSHs(sv_2mortal(newSViv(cords[i])));
2265 i_tt_has_chars(handle, text_sv, utf8)
2266 Imager::Font::TT handle
2277 text = SvPV(text_sv, len);
2279 if (SvUTF8(text_sv))
2282 work = mymalloc(len);
2283 count = i_tt_has_chars(handle, text, len, utf8, work);
2284 if (GIMME_V == G_ARRAY) {
2286 for (i = 0; i < count; ++i) {
2287 PUSHs(boolSV(work[i]));
2292 PUSHs(sv_2mortal(newSVpv(work, count)));
2297 i_tt_dump_names(handle)
2298 Imager::Font::TT handle
2301 i_tt_face_name(handle)
2302 Imager::Font::TT handle
2307 len = i_tt_face_name(handle, name, sizeof(name));
2310 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2314 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2315 Imager::Font::TT handle
2327 text = SvPV(text_sv, work_len);
2329 if (SvUTF8(text_sv))
2336 ch = i_utf8_advance(&text, &len);
2338 i_push_error(0, "invalid UTF8 character");
2346 EXTEND(SP, count+1);
2347 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2348 ST(count) = sv_2mortal(newSVpv(name, 0));
2351 ST(count) = &PL_sv_undef;
2360 i_test_format_probe(ig, length)
2365 i_readpnm_wiol(ig, allow_incomplete)
2367 int allow_incomplete
2371 i_readpnm_multi_wiol(ig, allow_incomplete)
2373 int allow_incomplete
2379 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2382 for (i = 0; i < count; ++i) {
2383 SV *sv = sv_newmortal();
2384 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2391 i_writeppm_wiol(im, ig)
2400 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2409 i_writeraw_wiol(im,ig)
2414 i_writebmp_wiol(im,ig)
2419 i_readbmp_wiol(ig, allow_incomplete=0)
2421 int allow_incomplete
2425 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2434 idlen = SvCUR(ST(4));
2435 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2441 i_readtga_wiol(ig, length)
2449 i_scaleaxis(im,Value,Axis)
2455 i_scale_nn(im,scx,scy)
2461 i_scale_mixing(im, width, height)
2471 i_count_colors(im,maxc)
2476 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2481 unsigned int * col_usage = NULL;
2484 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2485 EXTEND(SP, col_cnt);
2486 for (i = 0; i < col_cnt; i++) {
2487 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2494 i_transform(im, opx, opy, parm)
2500 STRLEN size_opx, size_opy, size_parm;
2503 result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
2505 SV *result_sv = sv_newmortal();
2507 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2512 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2538 in_imgs_count = av_len(av_in_imgs)+1;
2539 for (i = 0; i < in_imgs_count; ++i) {
2540 sv1 = *av_fetch(av_in_imgs, i, 0);
2541 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2542 croak("sv_in_img must contain only images");
2545 if (in_imgs_count > 0) {
2546 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2547 for (i = 0; i < in_imgs_count; ++i) {
2548 sv1 = *av_fetch(av_in_imgs,i,0);
2549 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2550 croak("Parameter 5 must contain only images");
2552 tmp = SvIV((SV*)SvRV(sv1));
2553 in_imgs[i] = INT2PTR(i_img*, tmp);
2557 /* no input images */
2560 /* default the output size from the first input if possible */
2562 width = SvIV(sv_width);
2563 else if (in_imgs_count)
2564 width = in_imgs[0]->xsize;
2566 croak("No output image width supplied");
2568 if (SvOK(sv_height))
2569 height = SvIV(sv_height);
2570 else if (in_imgs_count)
2571 height = in_imgs[0]->ysize;
2573 croak("No output image height supplied");
2575 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2576 if (ops_len % sizeof(struct rm_op))
2577 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2578 ops_count = ops_len / sizeof(struct rm_op);
2580 n_regs_count = av_len(av_n_regs)+1;
2581 n_regs = mymalloc(n_regs_count * sizeof(double));
2582 for (i = 0; i < n_regs_count; ++i) {
2583 sv1 = *av_fetch(av_n_regs,i,0);
2585 n_regs[i] = SvNV(sv1);
2587 c_regs_count = av_len(av_c_regs)+1;
2588 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2589 /* I don't bother initializing the colou?r registers */
2591 result=i_transform2(width, height, channels, ops, ops_count,
2592 n_regs, n_regs_count,
2593 c_regs, c_regs_count, in_imgs, in_imgs_count);
2599 SV *result_sv = sv_newmortal();
2601 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2607 i_contrast(im,intensity)
2620 i_noise(im,amount,type)
2626 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2636 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2655 i_postlevels(im,levels)
2665 i_watermark(im,wmark,tx,ty,pixdiff)
2667 Imager::ImgRaw wmark
2674 i_autolevels(im,lsat,usat,skew)
2681 i_radnoise(im,xo,yo,rscale,ascale)
2689 i_turbnoise(im, xo, yo, scale)
2697 i_gradgen(im, xo, yo, ac, dmeasure)
2708 if (size_xo != size_yo || size_xo != size_ac)
2709 croak("i_gradgen: x, y and color arrays must be the same size");
2711 croak("Usage: i_gradgen array refs must have more than 1 entry each");
2712 i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
2715 i_diff_image(im, im2, mindist=0)
2721 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2731 double ssample_param
2735 i_fountain_seg *segs;
2737 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2738 croak("i_fountain: argument 11 must be an array ref");
2740 asegs = (AV *)SvRV(ST(10));
2741 segs = load_fount_segs(aTHX_ asegs, &count);
2742 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2743 super_sample, ssample_param, count, segs);
2749 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2758 double ssample_param
2762 i_fountain_seg *segs;
2764 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2765 croak("i_fountain: argument 11 must be an array ref");
2767 asegs = (AV *)SvRV(ST(9));
2768 segs = load_fount_segs(aTHX_ asegs, &count);
2769 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2770 super_sample, ssample_param, count, segs);
2776 i_new_fill_opacity(other_fill, alpha_mult)
2777 Imager::FillHandle other_fill
2788 errors = i_errors();
2790 while (errors[i].msg) {
2792 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2793 if (!av_store(av, 0, sv)) {
2796 sv = newSViv(errors[i].code);
2797 if (!av_store(av, 1, sv)) {
2800 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2808 i_push_error(code, msg)
2813 i_nearest_color(im, ...)
2828 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2829 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2830 croak("i_nearest_color: Second argument must be an array ref");
2831 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2832 croak("i_nearest_color: Third argument must be an array ref");
2833 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2834 croak("i_nearest_color: Fourth argument must be an array ref");
2835 axx = (AV *)SvRV(ST(1));
2836 ayy = (AV *)SvRV(ST(2));
2837 ac = (AV *)SvRV(ST(3));
2838 dmeasure = (int)SvIV(ST(4));
2840 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2841 num = num <= av_len(ac) ? num : av_len(ac);
2843 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2844 xo = mymalloc( sizeof(i_img_dim) * num );
2845 yo = mymalloc( sizeof(i_img_dim) * num );
2846 ival = mymalloc( sizeof(i_color) * num );
2847 for(i = 0; i<num; i++) {
2848 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2849 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2850 sv = *av_fetch(ac, i, 0);
2851 if ( !sv_derived_from(sv, "Imager::Color") ) {
2852 free(axx); free(ayy); free(ac);
2853 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2855 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2857 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2871 rc=DSO_open(filename,&evstr);
2875 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2876 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2879 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2885 DSO_close(dso_handle)
2889 DSO_funclist(dso_handle_v)
2893 DSO_handle *dso_handle;
2894 func_ptr *functions;
2896 dso_handle=(DSO_handle*)dso_handle_v;
2897 functions = DSO_funclist(dso_handle);
2899 while( functions[i].name != NULL) {
2901 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2903 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2907 DSO_call(handle,func_index,hv)
2912 DSO_call( (DSO_handle *)handle,func_index,hv);
2915 i_get_pixel(im, x, y)
2920 RETVAL = (i_color *)mymalloc(sizeof(i_color));
2921 if (i_gpix(im, x, y, RETVAL) != 0) {
2930 i_ppix(im, x, y, cl)
2937 i_img_pal_new(x, y, channels, maxpal)
2944 i_img_to_pal(src, quant)
2950 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2951 croak("i_img_to_pal: second argument must be a hash ref");
2952 hv = (HV *)SvRV(ST(1));
2953 memset(&quant, 0, sizeof(quant));
2955 quant.mc_size = 256;
2956 ip_handle_quant_opts(aTHX_ &quant, hv);
2957 RETVAL = i_img_to_pal(src, &quant);
2959 ip_copy_colors_back(aTHX_ hv, &quant);
2961 ip_cleanup_quant_opts(aTHX_ &quant);
2970 i_img_make_palette(HV *quant_hv, ...)
2972 size_t count = items - 1;
2974 i_img **imgs = NULL;
2978 croak("Please supply at least one image (%d)", (int)count);
2979 imgs = mymalloc(sizeof(i_img *) * count);
2980 for (i = 0; i < count; ++i) {
2981 SV *img_sv = ST(i + 1);
2982 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
2983 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
2987 croak("Image %d is not an image object", (int)i+1);
2990 memset(&quant, 0, sizeof(quant));
2992 quant.mc_size = 256;
2993 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
2994 i_quant_makemap(&quant, imgs, count);
2995 EXTEND(SP, quant.mc_count);
2996 for (i = 0; i < quant.mc_count; ++i) {
2997 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3000 ip_cleanup_quant_opts(aTHX_ &quant);
3014 work = mymalloc((r-l) * sizeof(i_palidx));
3015 count = i_gpal(im, l, r, y, work);
3016 if (GIMME_V == G_ARRAY) {
3018 for (i = 0; i < count; ++i) {
3019 PUSHs(sv_2mortal(newSViv(work[i])));
3024 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3029 if (GIMME_V != G_ARRAY) {
3031 PUSHs(&PL_sv_undef);
3036 i_ppal(im, l, y, ...)
3045 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3046 for (i=0; i < items-3; ++i) {
3047 work[i] = SvIV(ST(i+3));
3049 validate_i_ppal(im, work, items - 3);
3050 RETVAL = i_ppal(im, l, l+items-3, y, work);
3059 i_ppal_p(im, l, y, data)
3065 i_palidx const *work;
3068 work = (i_palidx const *)SvPV(data, len);
3069 len /= sizeof(i_palidx);
3071 validate_i_ppal(im, work, len);
3072 RETVAL = i_ppal(im, l, l+len, y, work);
3081 i_addcolors(im, ...)
3088 croak("i_addcolors: no colors to add");
3089 colors = mymalloc((items-1) * sizeof(i_color));
3090 for (i=0; i < items-1; ++i) {
3091 if (sv_isobject(ST(i+1))
3092 && sv_derived_from(ST(i+1), "Imager::Color")) {
3093 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3094 colors[i] = *INT2PTR(i_color *, tmp);
3098 croak("i_addcolor: pixels must be Imager::Color objects");
3101 RETVAL = i_addcolors(im, colors, items-1);
3106 i_setcolors(im, index, ...)
3114 croak("i_setcolors: no colors to add");
3115 colors = mymalloc((items-2) * sizeof(i_color));
3116 for (i=0; i < items-2; ++i) {
3117 if (sv_isobject(ST(i+2))
3118 && sv_derived_from(ST(i+2), "Imager::Color")) {
3119 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3120 colors[i] = *INT2PTR(i_color *, tmp);
3124 croak("i_setcolors: pixels must be Imager::Color objects");
3127 RETVAL = i_setcolors(im, index, colors, items-2);
3133 i_getcolors(im, index, count=1)
3142 croak("i_getcolors: count must be positive");
3143 colors = malloc_temp(aTHX_ sizeof(i_color) * count);
3144 if (i_getcolors(im, index, colors, count)) {
3146 for (i = 0; i < count; ++i) {
3147 SV *sv = make_i_color_sv(aTHX_ colors+i);
3161 i_findcolor(im, color)
3165 if (!i_findcolor(im, color, &RETVAL)) {
3184 i_gsamp(im, l, r, y, channels)
3189 i_channel_list channels
3195 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count);
3196 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3197 if (GIMME_V == G_ARRAY) {
3199 for (i = 0; i < count; ++i)
3200 PUSHs(sv_2mortal(newSViv(data[i])));
3204 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3209 if (GIMME_V != G_ARRAY) {
3215 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3223 i_channel_list channels
3230 croak("No channel numbers supplied to g_samp()");
3232 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3233 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3234 for (i = 0; i < count; ++i) {
3235 av_store(target, i+offset, newSVuv(data[i]));
3247 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3252 i_channel_list channels
3254 i_img_dim data_offset
3255 i_img_dim pixel_count
3264 data_count = av_len(data_av) + 1;
3265 if (data_offset < 0) {
3266 croak("data_offset must be non-negative");
3268 if (data_offset > data_count) {
3269 croak("data_offset greater than number of samples supplied");
3271 if (pixel_count == -1 ||
3272 data_offset + pixel_count * channels.count > data_count) {
3273 pixel_count = (data_count - data_offset) / channels.count;
3276 data_used = pixel_count * channels.count;
3277 data = mymalloc(sizeof(unsigned) * data_count);
3278 for (i = 0; i < data_used; ++i)
3279 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3281 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3282 channels.count, bits);
3290 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3294 i_channel_list channels
3303 i_push_error(0, "offset must be non-negative");
3307 if (offset > data.count) {
3308 i_push_error(0, "offset greater than number of samples supplied");
3311 data.samples += offset;
3312 data.count -= offset;
3315 width * channels.count > data.count) {
3316 width = data.count / channels.count;
3319 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3324 i_psampf(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_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3358 i_img_masked_new(targ, mask, x, y, w, h)
3368 if (!sv_isobject(ST(1))
3369 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3370 croak("i_img_masked_new: parameter 2 must undef or an image");
3372 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3376 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3381 i_plin(im, l, y, ...)
3392 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3393 /* supplied as a byte string */
3394 work = (i_color *)SvPV(ST(3), len);
3395 count = len / sizeof(i_color);
3396 if (count * sizeof(i_color) != len) {
3397 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3399 RETVAL = i_plin(im, l, l+count, y, work);
3402 work = mymalloc(sizeof(i_color) * (items-3));
3403 for (i=0; i < items-3; ++i) {
3404 if (sv_isobject(ST(i+3))
3405 && sv_derived_from(ST(i+3), "Imager::Color")) {
3406 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3407 work[i] = *INT2PTR(i_color *, tmp);
3411 croak("i_plin: pixels must be Imager::Color objects");
3414 RETVAL = i_plin(im, l, l+items-3, y, work);
3425 i_ppixf(im, x, y, cl)
3429 Imager::Color::Float cl
3432 i_gsampf(im, l, r, y, channels)
3437 i_channel_list channels
3443 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3444 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3445 if (GIMME_V == G_ARRAY) {
3447 for (i = 0; i < count; ++i)
3448 PUSHs(sv_2mortal(newSVnv(data[i])));
3452 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3457 if (GIMME_V != G_ARRAY) {
3463 i_plinf(im, l, y, ...)
3474 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3475 /* supplied as a byte string */
3476 work = (i_fcolor *)SvPV(ST(3), len);
3477 count = len / sizeof(i_fcolor);
3478 if (count * sizeof(i_fcolor) != len) {
3479 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3481 RETVAL = i_plinf(im, l, l+count, y, work);
3484 work = mymalloc(sizeof(i_fcolor) * (items-3));
3485 for (i=0; i < items-3; ++i) {
3486 if (sv_isobject(ST(i+3))
3487 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3488 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3489 work[i] = *INT2PTR(i_fcolor *, tmp);
3493 croak("i_plinf: pixels must be Imager::Color::Float objects");
3497 RETVAL = i_plinf(im, l, l+items-3, y, work);
3507 Imager::Color::Float
3513 RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3514 if (i_gpixf(im, x, y, RETVAL) != 0) {
3532 vals = mymalloc((r-l) * sizeof(i_color));
3533 memset(vals, 0, (r-l) * sizeof(i_color));
3534 count = i_glin(im, l, r, y, vals);
3535 if (GIMME_V == G_ARRAY) {
3537 for (i = 0; i < count; ++i) {
3538 SV *sv = make_i_color_sv(aTHX_ vals+i);
3544 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3550 i_glinf(im, l, r, y)
3560 for (i = 0; i < MAXCHANNELS; ++i)
3561 zero.channel[i] = 0;
3563 vals = mymalloc((r-l) * sizeof(i_fcolor));
3564 for (i = 0; i < r-l; ++i)
3566 count = i_glinf(im, l, r, y, vals);
3567 if (GIMME_V == G_ARRAY) {
3569 for (i = 0; i < count; ++i) {
3571 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3573 sv = sv_newmortal();
3574 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3580 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3586 i_img_8_new(x, y, ch)
3592 i_img_16_new(x, y, ch)
3602 i_img_double_new(x, y, ch)
3612 i_tags_addn(im, name_sv, code, idata)
3621 SvGETMAGIC(name_sv);
3623 name = SvPV_nomg(name_sv, len);
3626 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3631 i_tags_add(im, name_sv, code, data_sv, idata)
3642 SvGETMAGIC(name_sv);
3644 name = SvPV_nomg(name_sv, len);
3647 SvGETMAGIC(data_sv);
3649 data = SvPV(data_sv, len);
3654 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3659 i_tags_find(im, name, start)
3666 if (i_tags_find(&im->tags, name, start, &entry)) {
3675 i_tags_findn(im, code, start)
3682 if (i_tags_findn(&im->tags, code, start, &entry)) {
3692 i_tags_delete(im, entry)
3696 RETVAL = i_tags_delete(&im->tags, entry);
3701 i_tags_delbyname(im, name)
3705 RETVAL = i_tags_delbyname(&im->tags, name);
3710 i_tags_delbycode(im, code)
3714 RETVAL = i_tags_delbycode(&im->tags, code);
3719 i_tags_get(im, index)
3723 if (index >= 0 && index < im->tags.count) {
3724 i_img_tag *entry = im->tags.tags + index;
3728 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3731 PUSHs(sv_2mortal(newSViv(entry->code)));
3734 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3737 PUSHs(sv_2mortal(newSViv(entry->idata)));
3742 i_tags_get_string(im, what_sv)
3746 char const *name = NULL;
3750 if (SvIOK(what_sv)) {
3751 code = SvIV(what_sv);
3755 name = SvPV_nolen(what_sv);
3758 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3760 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3767 RETVAL = im->tags.count;
3773 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3777 Imager::FillHandle fill
3780 IFILL_CLONE_SKIP(...)
3782 (void)items; /* avoid unused warning for XS variable */
3787 MODULE = Imager PACKAGE = Imager
3790 i_new_fill_solid(cl, combine)
3795 i_new_fill_solidf(cl, combine)
3796 Imager::Color::Float cl
3800 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3809 unsigned char *cust_hatch;
3812 SvGETMAGIC(cust_hatch_sv);
3813 if (SvOK(cust_hatch_sv)) {
3814 cust_hatch = (unsigned char *)SvPV_nomg(cust_hatch_sv, len);
3818 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3823 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3824 Imager::Color::Float fg
3825 Imager::Color::Float bg
3832 unsigned char *cust_hatch;
3835 SvGETMAGIC(cust_hatch_sv);
3836 if (SvOK(cust_hatch_sv)) {
3837 cust_hatch = (unsigned char *)SvPV(cust_hatch_sv, len);
3841 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3846 i_new_fill_image(src, matrix_sv, xoff, yoff, combine)
3860 SvGETMAGIC(matrix_sv);
3861 if (!SvOK(matrix_sv)) {
3865 if (!SvROK(matrix_sv) || SvTYPE(SvRV(matrix_sv)) != SVt_PVAV)
3866 croak("i_new_fill_image: matrix parameter must be an arrayref or undef");
3867 av=(AV*)SvRV(matrix_sv);
3871 for (i = 0; i < len; ++i) {
3872 sv1=(*(av_fetch(av,i,0)));
3873 matrix[i] = SvNV(sv1);
3879 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3883 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3885 # this class is only exposed for testing
3888 i_int_hlines_testing()
3890 #if i_int_hlines_testing()
3892 Imager::Internal::Hlines
3893 i_int_hlines_new(start_y, count_y, start_x, count_x)
3899 Imager::Internal::Hlines
3900 i_int_hlines_new_img(im)
3904 i_int_hlines_add(hlines, y, minx, width)
3905 Imager::Internal::Hlines hlines
3911 i_int_hlines_DESTROY(hlines)
3912 Imager::Internal::Hlines hlines
3915 i_int_hlines_dump(hlines)
3916 Imager::Internal::Hlines hlines
3919 i_int_hlines_CLONE_SKIP(cls)
3923 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
3926 im_context_DESTROY(ctx)
3929 #ifdef PERL_IMPLICIT_CONTEXT
3932 im_context_CLONE(...)
3936 /* the following sv_setref_pv() will free this inc */
3937 im_context_refinc(MY_CXT.ctx, "CLONE");
3938 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
3939 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
3944 PERL_SET_GLOBAL_CALLBACKS;
3945 PERL_PL_SET_GLOBAL_CALLBACKS;
3946 #ifdef PERL_IMPLICIT_CONTEXT
3952 start_context(aTHX);
3953 im_get_context = perl_get_context;