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
935 #define i_exif_enabled() 1
937 #define i_exif_enabled() 0
940 /* trying to use more C style names, map them here */
941 #define i_io_DESTROY(ig) io_glue_destroy(ig)
943 #define i_img_get_width(im) ((im)->xsize)
944 #define i_img_get_height(im) ((im)->ysize)
946 #define i_img_epsilonf() (DBL_EPSILON * 4)
948 /* avoid some xsubpp strangeness */
951 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
954 ICL_new_internal(r,g,b,a)
966 ICL_set_internal(cl,r,g,b,a)
973 ICL_set_internal(cl, r, g, b, a);
987 PUSHs(sv_2mortal(newSViv(cl->rgba.r)));
988 PUSHs(sv_2mortal(newSViv(cl->rgba.g)));
989 PUSHs(sv_2mortal(newSViv(cl->rgba.b)));
990 PUSHs(sv_2mortal(newSViv(cl->rgba.a)));
996 RETVAL = mymalloc(sizeof(i_color));
998 i_hsv_to_rgb(RETVAL);
1006 RETVAL = mymalloc(sizeof(i_color));
1008 i_rgb_to_hsv(RETVAL);
1014 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
1016 Imager::Color::Float
1017 ICLF_new_internal(r, g, b, a)
1025 Imager::Color::Float cl
1029 Imager::Color::Float cl
1033 EXTEND(SP, MAXCHANNELS);
1034 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1035 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1036 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1040 ICLF_set_internal(cl,r,g,b,a)
1041 Imager::Color::Float cl
1054 Imager::Color::Float
1056 Imager::Color::Float c
1058 RETVAL = mymalloc(sizeof(i_fcolor));
1060 i_hsv_to_rgbf(RETVAL);
1064 Imager::Color::Float
1066 Imager::Color::Float c
1068 RETVAL = mymalloc(sizeof(i_fcolor));
1070 i_rgb_to_hsvf(RETVAL);
1074 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1088 MODULE = Imager PACKAGE = Imager
1102 io_new_buffer(data_sv)
1105 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1110 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1117 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1125 unsigned char* data;
1129 tlength = io_slurp(ig, &data);
1130 RETVAL = newSVpv((char *)data,tlength);
1137 i_set_image_file_limits(width, height, bytes)
1143 i_get_image_file_limits()
1145 i_img_dim width, height;
1148 if (i_get_image_file_limits(&width, &height, &bytes)) {
1150 PUSHs(sv_2mortal(newSViv(width)));
1151 PUSHs(sv_2mortal(newSViv(height)));
1152 PUSHs(sv_2mortal(newSVuv(bytes)));
1156 i_int_check_image_file_limits(width, height, channels, sample_size)
1163 MODULE = Imager PACKAGE = Imager::IO PREFIX = io_
1166 io_new_fd(class, fd)
1169 RETVAL = io_new_fd(fd);
1174 io_new_buffer(class, data_sv)
1177 RETVAL = do_io_new_buffer(aTHX_ data_sv);
1182 io_new_cb(class, writecb, readcb, seekcb, closecb)
1188 RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1193 io_new_bufchain(class)
1195 RETVAL = io_new_bufchain();
1200 io__new_perlio(class, io)
1203 RETVAL = im_io_new_perlio(aTHX_ io);
1211 unsigned char* data;
1215 tlength = io_slurp(ig, &data);
1216 RETVAL = newSVpv((char *)data,tlength);
1221 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1224 i_io_raw_write(ig, data_sv)
1231 data = SvPVbyte(data_sv, size);
1232 RETVAL = i_io_raw_write(ig, data, size);
1237 i_io_raw_read(ig, buffer_sv, size)
1246 croak("size negative in call to i_io_raw_read()");
1247 /* prevent an undefined value warning if they supplied an
1249 Orginally conditional on !SvOK(), but this will prevent the
1250 downgrade from croaking */
1251 sv_setpvn(buffer_sv, "", 0);
1253 if (SvUTF8(buffer_sv))
1254 sv_utf8_downgrade(buffer_sv, FALSE);
1256 buffer = SvGROW(buffer_sv, size+1);
1257 result = i_io_raw_read(ig, buffer, size);
1259 SvCUR_set(buffer_sv, result);
1260 *SvEND(buffer_sv) = '\0';
1261 SvPOK_only(buffer_sv);
1263 PUSHs(sv_2mortal(newSViv(result)));
1269 i_io_raw_read2(ig, size)
1278 croak("size negative in call to i_io_read2()");
1279 buffer_sv = newSV(size);
1280 buffer = SvGROW(buffer_sv, size+1);
1281 result = i_io_raw_read(ig, buffer, size);
1283 SvCUR_set(buffer_sv, result);
1284 *SvEND(buffer_sv) = '\0';
1285 SvPOK_only(buffer_sv);
1287 PUSHs(sv_2mortal(buffer_sv));
1291 SvREFCNT_dec(buffer_sv);
1295 i_io_raw_seek(ig, position, whence)
1309 i_io_CLONE_SKIP(...)
1311 (void)items; /* avoid unused warning for XS variable */
1338 i_io_seek(ig, off, whence)
1344 i_io_peekn(ig, size)
1352 buffer_sv = newSV(size+1);
1353 buffer = SvGROW(buffer_sv, size+1);
1354 result = i_io_peekn(ig, buffer, size);
1356 SvCUR_set(buffer_sv, result);
1357 *SvEND(buffer_sv) = '\0';
1358 SvPOK_only(buffer_sv);
1360 PUSHs(sv_2mortal(buffer_sv));
1364 SvREFCNT_dec(buffer_sv);
1368 i_io_read(ig, buffer_sv, size)
1377 croak("size negative in call to i_io_read()");
1378 /* prevent an undefined value warning if they supplied an
1380 Orginally conditional on !SvOK(), but this will prevent the
1381 downgrade from croaking */
1382 sv_setpvn(buffer_sv, "", 0);
1384 if (SvUTF8(buffer_sv))
1385 sv_utf8_downgrade(buffer_sv, FALSE);
1387 buffer = SvGROW(buffer_sv, size+1);
1388 result = i_io_read(ig, buffer, size);
1390 SvCUR_set(buffer_sv, result);
1391 *SvEND(buffer_sv) = '\0';
1392 SvPOK_only(buffer_sv);
1394 PUSHs(sv_2mortal(newSViv(result)));
1400 i_io_read2(ig, size)
1409 croak("size zero in call to read2()");
1410 buffer_sv = newSV(size);
1411 buffer = SvGROW(buffer_sv, size+1);
1412 result = i_io_read(ig, buffer, size);
1414 SvCUR_set(buffer_sv, result);
1415 *SvEND(buffer_sv) = '\0';
1416 SvPOK_only(buffer_sv);
1418 PUSHs(sv_2mortal(buffer_sv));
1422 SvREFCNT_dec(buffer_sv);
1426 i_io_gets(ig, size = 8192, eol = NEWLINE)
1436 croak("size too small in call to gets()");
1437 buffer_sv = sv_2mortal(newSV(size+1));
1438 buffer = SvPVX(buffer_sv);
1439 result = i_io_gets(ig, buffer, size+1, eol);
1441 SvCUR_set(buffer_sv, result);
1442 *SvEND(buffer_sv) = '\0';
1443 SvPOK_only(buffer_sv);
1449 i_io_write(ig, data_sv)
1456 data = SvPVbyte(data_sv, size);
1457 RETVAL = i_io_write(ig, data, size);
1462 i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
1467 i_io_set_buffered(ig, flag = 1)
1472 i_io_is_buffered(ig)
1483 MODULE = Imager PACKAGE = Imager
1494 while( (item=i_format_list[i++]) != NULL ) {
1496 PUSHs(sv_2mortal(newSVpv(item,0)));
1500 i_sametype(im, x, y)
1506 i_sametype_chans(im, x, y, channels)
1513 i_init_log(name_sv,level)
1517 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1519 RETVAL = i_init_log(name, level);
1524 i_log_entry(string,level)
1537 i_img_info(im,info);
1539 PUSHs(sv_2mortal(newSViv(info[0])));
1540 PUSHs(sv_2mortal(newSViv(info[1])));
1541 PUSHs(sv_2mortal(newSViv(info[2])));
1542 PUSHs(sv_2mortal(newSViv(info[3])));
1548 i_img_setmask(im,ch_mask)
1557 i_img_getchannels(im)
1566 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1574 i_img_get_height(im)
1579 i_img_is_monochrome(im)
1585 result = i_img_is_monochrome(im, &zero_is_white);
1587 if (GIMME_V == G_ARRAY) {
1590 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1599 i_line(im,x1,y1,x2,y2,val,endp)
1609 i_line_aa(im,x1,y1,x2,y2,val,endp)
1619 i_box(im,x1,y1,x2,y2,val)
1628 i_box_filled(im,x1,y1,x2,y2,val)
1637 i_box_filledf(im,x1,y1,x2,y2,val)
1643 Imager::Color::Float val
1646 i_box_cfill(im,x1,y1,x2,y2,fill)
1652 Imager::FillHandle fill
1655 i_arc(im,x,y,rad,d1,d2,val)
1665 i_arc_aa(im,x,y,rad,d1,d2,val)
1675 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1682 Imager::FillHandle fill
1685 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1692 Imager::FillHandle fill
1696 i_circle_aa(im,x,y,rad,val)
1704 i_circle_out(im,x,y,rad,val)
1712 i_circle_out_aa(im,x,y,rad,val)
1720 i_arc_out(im,x,y,rad,d1,d2,val)
1730 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1741 i_bezier_multi(im,xc,yc,val)
1754 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1755 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1756 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1757 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1758 av1=(AV*)SvRV(ST(1));
1759 av2=(AV*)SvRV(ST(2));
1760 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1762 x=mymalloc( len*sizeof(double) );
1763 y=mymalloc( len*sizeof(double) );
1764 for(i=0;i<len;i++) {
1765 sv1=(*(av_fetch(av1,i,0)));
1766 sv2=(*(av_fetch(av2,i,0)));
1767 x[i]=(double)SvNV(sv1);
1768 y[i]=(double)SvNV(sv2);
1770 i_bezier_multi(im,len,x,y,val);
1776 i_poly_aa(im,x,y,val)
1785 if (size_x != size_y)
1786 croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1787 RETVAL = i_poly_aa(im, size_x, x, y, val);
1792 i_poly_aa_cfill(im, x, y, fill)
1796 Imager::FillHandle fill
1801 if (size_x != size_y)
1802 croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1803 RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
1808 i_flood_fill(im,seedx,seedy,dcol)
1815 i_flood_cfill(im,seedx,seedy,fill)
1819 Imager::FillHandle fill
1822 i_flood_fill_border(im,seedx,seedy,dcol, border)
1827 Imager::Color border
1830 i_flood_cfill_border(im,seedx,seedy,fill, border)
1834 Imager::FillHandle fill
1835 Imager::Color border
1839 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1851 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1868 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1879 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1892 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)
1908 i_combine(src_av, channels_av = NULL)
1912 i_img **imgs = NULL;
1914 int *channels = NULL;
1919 in_count = av_len(src_av) + 1;
1921 imgs = mymalloc(sizeof(i_img*) * in_count);
1922 channels = mymalloc(sizeof(int) * in_count);
1923 for (i = 0; i < in_count; ++i) {
1924 psv = av_fetch(src_av, i, 0);
1925 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1928 croak("imgs must contain only images");
1930 tmp = SvIV((SV*)SvRV(*psv));
1931 imgs[i] = INT2PTR(i_img*, tmp);
1933 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1935 channels[i] = SvIV(*psv);
1942 RETVAL = i_combine(imgs, channels, in_count);
1949 i_flipxy(im, direction)
1954 i_rotate90(im, degrees)
1959 i_rotate_exact(im, amount, ...)
1963 i_color *backp = NULL;
1964 i_fcolor *fbackp = NULL;
1968 /* extract the bg colors if any */
1969 /* yes, this is kind of strange */
1970 for (i = 2; i < items; ++i) {
1972 if (sv_derived_from(sv1, "Imager::Color")) {
1973 IV tmp = SvIV((SV*)SvRV(sv1));
1974 backp = INT2PTR(i_color *, tmp);
1976 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1977 IV tmp = SvIV((SV*)SvRV(sv1));
1978 fbackp = INT2PTR(i_fcolor *, tmp);
1981 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1986 i_matrix_transform(im, xsize, ysize, matrix_av, ...)
1996 i_color *backp = NULL;
1997 i_fcolor *fbackp = NULL;
1999 len=av_len(matrix_av)+1;
2002 for (i = 0; i < len; ++i) {
2003 sv1=(*(av_fetch(matrix_av,i,0)));
2004 matrix[i] = SvNV(sv1);
2008 /* extract the bg colors if any */
2009 /* yes, this is kind of strange */
2010 for (i = 4; i < items; ++i) {
2012 if (sv_derived_from(sv1, "Imager::Color")) {
2013 IV tmp = SvIV((SV*)SvRV(sv1));
2014 backp = INT2PTR(i_color *, tmp);
2016 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2017 IV tmp = SvIV((SV*)SvRV(sv1));
2018 fbackp = INT2PTR(i_fcolor *, tmp);
2021 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2026 i_gaussian(im,stdev)
2031 i_unsharp_mask(im,stdev,scale)
2046 len = av_len(coef) + 1;
2047 c_coef=mymalloc( len * sizeof(double) );
2048 for(i = 0; i < len; i++) {
2049 sv1 = (*(av_fetch(coef, i, 0)));
2050 c_coef[i] = (double)SvNV(sv1);
2052 RETVAL = i_conv(im, c_coef, len);
2058 i_convert(src, avmain)
2070 outchan = av_len(avmain)+1;
2071 /* find the biggest */
2073 for (j=0; j < outchan; ++j) {
2074 temp = av_fetch(avmain, j, 0);
2075 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2076 avsub = (AV*)SvRV(*temp);
2077 len = av_len(avsub)+1;
2082 i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2086 coeff = mymalloc(sizeof(double) * outchan * inchan);
2087 for (j = 0; j < outchan; ++j) {
2088 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2089 len = av_len(avsub)+1;
2090 for (i = 0; i < len; ++i) {
2091 temp = av_fetch(avsub, i, 0);
2093 coeff[i+j*inchan] = SvNV(*temp);
2095 coeff[i+j*inchan] = 0;
2098 coeff[i++ + j*inchan] = 0;
2100 RETVAL = i_convert(src, coeff, outchan, inchan);
2111 unsigned int mask = 0;
2117 unsigned char (*maps)[256];
2119 len = av_len(pmaps_av)+1;
2120 if (im->channels < len)
2122 maps = mymalloc( len * sizeof(unsigned char [256]) );
2123 for (j=0; j<len ; j++) {
2124 temp = av_fetch(pmaps_av, j, 0);
2125 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2126 avsub = (AV*)SvRV(*temp);
2127 if(av_len(avsub) != 255)
2130 for (i=0; i<256 ; i++) {
2132 temp = av_fetch(avsub, i, 0);
2133 val = temp ? SvIV(*temp) : 0;
2135 if (val>255) val = 255;
2140 i_map(im, maps, mask);
2152 i_img_diffd(im1,im2)
2157 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2167 _is_color_object(sv)
2171 RETVAL = SvOK(sv) && SvROK(sv) &&
2172 (sv_derived_from(sv, "Imager::Color")
2173 || sv_derived_from(sv, "Imager::Color::Float"));
2185 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2187 #define TT_DESTROY(handle) i_tt_destroy(handle)
2191 Imager::Font::TT handle
2196 (void)items; /* avoid unused warning */
2202 MODULE = Imager PACKAGE = Imager
2206 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
2207 Imager::Font::TT handle
2221 str = SvPV(str_sv, len);
2226 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2227 len, smooth, utf8, align);
2233 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
2234 Imager::Font::TT handle
2248 str = SvPV(str_sv, len);
2253 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2254 smooth, utf8, align);
2260 i_tt_bbox(handle,point,str_sv,utf8)
2261 Imager::Font::TT handle
2266 i_img_dim cords[BOUNDING_BOX_COUNT];
2272 str = SvPV(str_sv, len);
2277 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2279 for (i = 0; i < rc; ++i) {
2280 PUSHs(sv_2mortal(newSViv(cords[i])));
2285 i_tt_has_chars(handle, text_sv, utf8)
2286 Imager::Font::TT handle
2297 text = SvPV(text_sv, len);
2299 if (SvUTF8(text_sv))
2302 work = mymalloc(len);
2303 count = i_tt_has_chars(handle, text, len, utf8, work);
2304 if (GIMME_V == G_ARRAY) {
2306 for (i = 0; i < count; ++i) {
2307 PUSHs(boolSV(work[i]));
2312 PUSHs(sv_2mortal(newSVpv(work, count)));
2317 i_tt_dump_names(handle)
2318 Imager::Font::TT handle
2321 i_tt_face_name(handle)
2322 Imager::Font::TT handle
2327 len = i_tt_face_name(handle, name, sizeof(name));
2330 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2334 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2335 Imager::Font::TT handle
2347 text = SvPV(text_sv, work_len);
2349 if (SvUTF8(text_sv))
2356 ch = i_utf8_advance(&text, &len);
2358 i_push_error(0, "invalid UTF8 character");
2366 EXTEND(SP, count+1);
2367 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2368 ST(count) = sv_2mortal(newSVpv(name, 0));
2371 ST(count) = &PL_sv_undef;
2380 i_test_format_probe(ig, length)
2385 i_readpnm_wiol(ig, allow_incomplete)
2387 int allow_incomplete
2391 i_readpnm_multi_wiol(ig, allow_incomplete)
2393 int allow_incomplete
2399 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2402 for (i = 0; i < count; ++i) {
2403 SV *sv = sv_newmortal();
2404 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2411 i_writeppm_wiol(im, ig)
2420 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2429 i_writeraw_wiol(im,ig)
2434 i_writebmp_wiol(im,ig)
2439 i_readbmp_wiol(ig, allow_incomplete=0)
2441 int allow_incomplete
2445 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2454 idlen = SvCUR(ST(4));
2455 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2461 i_readtga_wiol(ig, length)
2469 i_scaleaxis(im,Value,Axis)
2475 i_scale_nn(im,scx,scy)
2481 i_scale_mixing(im, width, height)
2491 i_count_colors(im,maxc)
2496 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2501 unsigned int * col_usage = NULL;
2504 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2505 EXTEND(SP, col_cnt);
2506 for (i = 0; i < col_cnt; i++) {
2507 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2514 i_transform(im, opx, opy, parm)
2520 STRLEN size_opx, size_opy, size_parm;
2523 result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
2525 SV *result_sv = sv_newmortal();
2527 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2532 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2558 in_imgs_count = av_len(av_in_imgs)+1;
2559 for (i = 0; i < in_imgs_count; ++i) {
2560 sv1 = *av_fetch(av_in_imgs, i, 0);
2561 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2562 croak("sv_in_img must contain only images");
2565 if (in_imgs_count > 0) {
2566 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2567 for (i = 0; i < in_imgs_count; ++i) {
2568 sv1 = *av_fetch(av_in_imgs,i,0);
2569 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2570 croak("Parameter 5 must contain only images");
2572 tmp = SvIV((SV*)SvRV(sv1));
2573 in_imgs[i] = INT2PTR(i_img*, tmp);
2577 /* no input images */
2580 /* default the output size from the first input if possible */
2582 width = SvIV(sv_width);
2583 else if (in_imgs_count)
2584 width = in_imgs[0]->xsize;
2586 croak("No output image width supplied");
2588 if (SvOK(sv_height))
2589 height = SvIV(sv_height);
2590 else if (in_imgs_count)
2591 height = in_imgs[0]->ysize;
2593 croak("No output image height supplied");
2595 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2596 if (ops_len % sizeof(struct rm_op))
2597 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2598 ops_count = ops_len / sizeof(struct rm_op);
2600 n_regs_count = av_len(av_n_regs)+1;
2601 n_regs = mymalloc(n_regs_count * sizeof(double));
2602 for (i = 0; i < n_regs_count; ++i) {
2603 sv1 = *av_fetch(av_n_regs,i,0);
2605 n_regs[i] = SvNV(sv1);
2607 c_regs_count = av_len(av_c_regs)+1;
2608 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2609 /* I don't bother initializing the colou?r registers */
2611 result=i_transform2(width, height, channels, ops, ops_count,
2612 n_regs, n_regs_count,
2613 c_regs, c_regs_count, in_imgs, in_imgs_count);
2619 SV *result_sv = sv_newmortal();
2621 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2627 i_contrast(im,intensity)
2640 i_noise(im,amount,type)
2646 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2656 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2675 i_postlevels(im,levels)
2685 i_watermark(im,wmark,tx,ty,pixdiff)
2687 Imager::ImgRaw wmark
2694 i_autolevels(im,lsat,usat,skew)
2701 i_radnoise(im,xo,yo,rscale,ascale)
2709 i_turbnoise(im, xo, yo, scale)
2717 i_gradgen(im, xo, yo, ac, dmeasure)
2728 if (size_xo != size_yo || size_xo != size_ac)
2729 croak("i_gradgen: x, y and color arrays must be the same size");
2731 croak("Usage: i_gradgen array refs must have more than 1 entry each");
2732 i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
2735 i_diff_image(im, im2, mindist=0)
2741 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2751 double ssample_param
2755 i_fountain_seg *segs;
2757 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2758 croak("i_fountain: argument 11 must be an array ref");
2760 asegs = (AV *)SvRV(ST(10));
2761 segs = load_fount_segs(aTHX_ asegs, &count);
2762 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2763 super_sample, ssample_param, count, segs);
2769 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2778 double ssample_param
2782 i_fountain_seg *segs;
2784 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2785 croak("i_fountain: argument 11 must be an array ref");
2787 asegs = (AV *)SvRV(ST(9));
2788 segs = load_fount_segs(aTHX_ asegs, &count);
2789 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2790 super_sample, ssample_param, count, segs);
2796 i_new_fill_opacity(other_fill, alpha_mult)
2797 Imager::FillHandle other_fill
2808 errors = i_errors();
2810 while (errors[i].msg) {
2812 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2813 if (!av_store(av, 0, sv)) {
2816 sv = newSViv(errors[i].code);
2817 if (!av_store(av, 1, sv)) {
2820 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2828 i_push_error(code, msg)
2833 i_nearest_color(im, ...)
2848 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2849 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2850 croak("i_nearest_color: Second argument must be an array ref");
2851 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2852 croak("i_nearest_color: Third argument must be an array ref");
2853 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2854 croak("i_nearest_color: Fourth argument must be an array ref");
2855 axx = (AV *)SvRV(ST(1));
2856 ayy = (AV *)SvRV(ST(2));
2857 ac = (AV *)SvRV(ST(3));
2858 dmeasure = (int)SvIV(ST(4));
2860 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2861 num = num <= av_len(ac) ? num : av_len(ac);
2863 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2864 xo = mymalloc( sizeof(i_img_dim) * num );
2865 yo = mymalloc( sizeof(i_img_dim) * num );
2866 ival = mymalloc( sizeof(i_color) * num );
2867 for(i = 0; i<num; i++) {
2868 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2869 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2870 sv = *av_fetch(ac, i, 0);
2871 if ( !sv_derived_from(sv, "Imager::Color") ) {
2872 free(axx); free(ayy); free(ac);
2873 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2875 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2877 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2891 rc=DSO_open(filename,&evstr);
2895 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2896 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2899 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2905 DSO_close(dso_handle)
2909 DSO_funclist(dso_handle_v)
2913 DSO_handle *dso_handle;
2914 func_ptr *functions;
2916 dso_handle=(DSO_handle*)dso_handle_v;
2917 functions = DSO_funclist(dso_handle);
2919 while( functions[i].name != NULL) {
2921 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2923 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2927 DSO_call(handle,func_index,hv)
2932 DSO_call( (DSO_handle *)handle,func_index,hv);
2935 i_get_pixel(im, x, y)
2942 color = (i_color *)mymalloc(sizeof(i_color));
2943 if (i_gpix(im, x, y, color) == 0) {
2944 RETVAL = NEWSV(0, 0);
2945 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
2949 RETVAL = &PL_sv_undef;
2956 i_ppix(im, x, y, cl)
2963 i_img_pal_new(x, y, channels, maxpal)
2970 i_img_to_pal(src, quant)
2976 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2977 croak("i_img_to_pal: second argument must be a hash ref");
2978 hv = (HV *)SvRV(ST(1));
2979 memset(&quant, 0, sizeof(quant));
2981 quant.mc_size = 256;
2982 ip_handle_quant_opts(aTHX_ &quant, hv);
2983 RETVAL = i_img_to_pal(src, &quant);
2985 ip_copy_colors_back(aTHX_ hv, &quant);
2987 ip_cleanup_quant_opts(aTHX_ &quant);
2996 i_img_make_palette(HV *quant_hv, ...)
2998 size_t count = items - 1;
3000 i_img **imgs = NULL;
3004 croak("Please supply at least one image (%d)", (int)count);
3005 imgs = mymalloc(sizeof(i_img *) * count);
3006 for (i = 0; i < count; ++i) {
3007 SV *img_sv = ST(i + 1);
3008 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3009 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3013 croak("Image %d is not an image object", (int)i+1);
3016 memset(&quant, 0, sizeof(quant));
3018 quant.mc_size = 256;
3019 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3020 i_quant_makemap(&quant, imgs, count);
3021 EXTEND(SP, quant.mc_count);
3022 for (i = 0; i < quant.mc_count; ++i) {
3023 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3026 ip_cleanup_quant_opts(aTHX_ &quant);
3040 work = mymalloc((r-l) * sizeof(i_palidx));
3041 count = i_gpal(im, l, r, y, work);
3042 if (GIMME_V == G_ARRAY) {
3044 for (i = 0; i < count; ++i) {
3045 PUSHs(sv_2mortal(newSViv(work[i])));
3050 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3055 if (GIMME_V != G_ARRAY) {
3057 PUSHs(&PL_sv_undef);
3062 i_ppal(im, l, y, ...)
3071 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3072 for (i=0; i < items-3; ++i) {
3073 work[i] = SvIV(ST(i+3));
3075 validate_i_ppal(im, work, items - 3);
3076 RETVAL = i_ppal(im, l, l+items-3, y, work);
3085 i_ppal_p(im, l, y, data)
3091 i_palidx const *work;
3094 work = (i_palidx const *)SvPV(data, len);
3095 len /= sizeof(i_palidx);
3097 validate_i_ppal(im, work, len);
3098 RETVAL = i_ppal(im, l, l+len, y, work);
3107 i_addcolors(im, ...)
3115 croak("i_addcolors: no colors to add");
3116 colors = mymalloc((items-1) * sizeof(i_color));
3117 for (i=0; i < items-1; ++i) {
3118 if (sv_isobject(ST(i+1))
3119 && sv_derived_from(ST(i+1), "Imager::Color")) {
3120 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3121 colors[i] = *INT2PTR(i_color *, tmp);
3125 croak("i_addcolor: pixels must be Imager::Color objects");
3128 index = i_addcolors(im, colors, items-1);
3131 RETVAL = newSVpv("0 but true", 0);
3133 else if (index == -1) {
3134 RETVAL = &PL_sv_undef;
3137 RETVAL = newSViv(index);
3143 i_setcolors(im, index, ...)
3151 croak("i_setcolors: no colors to add");
3152 colors = mymalloc((items-2) * sizeof(i_color));
3153 for (i=0; i < items-2; ++i) {
3154 if (sv_isobject(ST(i+2))
3155 && sv_derived_from(ST(i+2), "Imager::Color")) {
3156 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3157 colors[i] = *INT2PTR(i_color *, tmp);
3161 croak("i_setcolors: pixels must be Imager::Color objects");
3164 RETVAL = i_setcolors(im, index, colors, items-2);
3170 i_getcolors(im, index, ...)
3179 croak("i_getcolors: too many arguments");
3181 count = SvIV(ST(2));
3183 croak("i_getcolors: count must be positive");
3184 colors = mymalloc(sizeof(i_color) * count);
3185 if (i_getcolors(im, index, colors, count)) {
3186 for (i = 0; i < count; ++i) {
3187 SV *sv = make_i_color_sv(aTHX_ colors+i);
3203 i_findcolor(im, color)
3209 if (i_findcolor(im, color, &index)) {
3210 RETVAL = newSViv(index);
3213 RETVAL = &PL_sv_undef;
3231 i_gsamp(im, l, r, y, channels)
3236 i_channel_list channels
3242 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count); /* XXX: memleak? */
3243 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3244 if (GIMME_V == G_ARRAY) {
3246 for (i = 0; i < count; ++i)
3247 PUSHs(sv_2mortal(newSViv(data[i])));
3251 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3256 if (GIMME_V != G_ARRAY) {
3258 PUSHs(&PL_sv_undef);
3263 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3271 i_channel_list channels
3278 croak("No channel numbers supplied to g_samp()");
3280 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3281 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3282 for (i = 0; i < count; ++i) {
3283 av_store(target, i+offset, newSVuv(data[i]));
3295 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3300 i_channel_list channels
3302 i_img_dim data_offset
3303 i_img_dim pixel_count
3312 data_count = av_len(data_av) + 1;
3313 if (data_offset < 0) {
3314 croak("data_offset must be non-negative");
3316 if (data_offset > data_count) {
3317 croak("data_offset greater than number of samples supplied");
3319 if (pixel_count == -1 ||
3320 data_offset + pixel_count * channels.count > data_count) {
3321 pixel_count = (data_count - data_offset) / channels.count;
3324 data_used = pixel_count * channels.count;
3325 data = mymalloc(sizeof(unsigned) * data_count);
3326 for (i = 0; i < data_used; ++i)
3327 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3329 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3330 channels.count, bits);
3338 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3342 i_channel_list channels
3351 i_push_error(0, "offset must be non-negative");
3355 if (offset > data.count) {
3356 i_push_error(0, "offset greater than number of samples supplied");
3359 data.samples += offset;
3360 data.count -= offset;
3363 width * channels.count > data.count) {
3364 width = data.count / channels.count;
3367 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3372 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3376 i_channel_list channels
3385 i_push_error(0, "offset must be non-negative");
3389 if (offset > data.count) {
3390 i_push_error(0, "offset greater than number of samples supplied");
3393 data.samples += offset;
3394 data.count -= offset;
3397 width * channels.count > data.count) {
3398 width = data.count / channels.count;
3401 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3406 i_img_masked_new(targ, mask, x, y, w, h)
3416 if (!sv_isobject(ST(1))
3417 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3418 croak("i_img_masked_new: parameter 2 must undef or an image");
3420 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3424 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3429 i_plin(im, l, y, ...)
3440 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3441 /* supplied as a byte string */
3442 work = (i_color *)SvPV(ST(3), len);
3443 count = len / sizeof(i_color);
3444 if (count * sizeof(i_color) != len) {
3445 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3447 RETVAL = i_plin(im, l, l+count, y, work);
3450 work = mymalloc(sizeof(i_color) * (items-3));
3451 for (i=0; i < items-3; ++i) {
3452 if (sv_isobject(ST(i+3))
3453 && sv_derived_from(ST(i+3), "Imager::Color")) {
3454 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3455 work[i] = *INT2PTR(i_color *, tmp);
3459 croak("i_plin: pixels must be Imager::Color objects");
3462 RETVAL = i_plin(im, l, l+items-3, y, work);
3473 i_ppixf(im, x, y, cl)
3477 Imager::Color::Float cl
3480 i_gsampf(im, l, r, y, channels)
3485 i_channel_list channels
3491 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3492 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3493 if (GIMME_V == G_ARRAY) {
3495 for (i = 0; i < count; ++i)
3496 PUSHs(sv_2mortal(newSVnv(data[i])));
3500 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3505 if (GIMME_V != G_ARRAY) {
3507 PUSHs(&PL_sv_undef);
3512 i_plinf(im, l, y, ...)
3523 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3524 /* supplied as a byte string */
3525 work = (i_fcolor *)SvPV(ST(3), len);
3526 count = len / sizeof(i_fcolor);
3527 if (count * sizeof(i_fcolor) != len) {
3528 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3530 RETVAL = i_plinf(im, l, l+count, y, work);
3533 work = mymalloc(sizeof(i_fcolor) * (items-3));
3534 for (i=0; i < items-3; ++i) {
3535 if (sv_isobject(ST(i+3))
3536 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3537 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3538 work[i] = *INT2PTR(i_fcolor *, tmp);
3542 croak("i_plinf: pixels must be Imager::Color::Float objects");
3546 RETVAL = i_plinf(im, l, l+items-3, y, work);
3564 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3565 if (i_gpixf(im, x, y, color) == 0) {
3566 RETVAL = NEWSV(0,0);
3567 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
3571 RETVAL = &PL_sv_undef;
3587 vals = mymalloc((r-l) * sizeof(i_color));
3588 memset(vals, 0, (r-l) * sizeof(i_color));
3589 count = i_glin(im, l, r, y, vals);
3590 if (GIMME_V == G_ARRAY) {
3592 for (i = 0; i < count; ++i) {
3593 SV *sv = make_i_color_sv(aTHX_ vals+i);
3599 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3605 i_glinf(im, l, r, y)
3615 for (i = 0; i < MAXCHANNELS; ++i)
3616 zero.channel[i] = 0;
3618 vals = mymalloc((r-l) * sizeof(i_fcolor));
3619 for (i = 0; i < r-l; ++i)
3621 count = i_glinf(im, l, r, y, vals);
3622 if (GIMME_V == G_ARRAY) {
3624 for (i = 0; i < count; ++i) {
3626 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3628 sv = sv_newmortal();
3629 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3635 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3641 i_img_8_new(x, y, ch)
3647 i_img_16_new(x, y, ch)
3657 i_img_double_new(x, y, ch)
3667 i_tags_addn(im, name, code, idata)
3676 name = SvPV(ST(1), len);
3679 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3684 i_tags_add(im, name, code, data, idata)
3694 name = SvPV(ST(1), len);
3698 data = SvPV(ST(3), len);
3703 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3708 i_tags_find(im, name, start)
3715 if (i_tags_find(&im->tags, name, start, &entry)) {
3717 RETVAL = newSVpv("0 but true", 0);
3719 RETVAL = newSViv(entry);
3721 RETVAL = &PL_sv_undef;
3727 i_tags_findn(im, code, start)
3734 if (i_tags_findn(&im->tags, code, start, &entry)) {
3736 RETVAL = newSVpv("0 but true", 0);
3738 RETVAL = newSViv(entry);
3741 RETVAL = &PL_sv_undef;
3747 i_tags_delete(im, entry)
3751 RETVAL = i_tags_delete(&im->tags, entry);
3756 i_tags_delbyname(im, name)
3760 RETVAL = i_tags_delbyname(&im->tags, name);
3765 i_tags_delbycode(im, code)
3769 RETVAL = i_tags_delbycode(&im->tags, code);
3774 i_tags_get(im, index)
3778 if (index >= 0 && index < im->tags.count) {
3779 i_img_tag *entry = im->tags.tags + index;
3783 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3786 PUSHs(sv_2mortal(newSViv(entry->code)));
3789 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3792 PUSHs(sv_2mortal(newSViv(entry->idata)));
3797 i_tags_get_string(im, what_sv)
3801 char const *name = NULL;
3805 if (SvIOK(what_sv)) {
3806 code = SvIV(what_sv);
3810 name = SvPV_nolen(what_sv);
3813 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3815 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3822 RETVAL = im->tags.count;
3828 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3832 Imager::FillHandle fill
3835 IFILL_CLONE_SKIP(...)
3837 (void)items; /* avoid unused warning for XS variable */
3842 MODULE = Imager PACKAGE = Imager
3845 i_new_fill_solid(cl, combine)
3850 i_new_fill_solidf(cl, combine)
3851 Imager::Color::Float cl
3855 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3863 unsigned char *cust_hatch;
3867 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3871 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3876 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3877 Imager::Color::Float fg
3878 Imager::Color::Float bg
3884 unsigned char *cust_hatch;
3888 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3892 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3897 i_new_fill_image(src, matrix, xoff, yoff, combine)
3914 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3915 croak("i_new_fill_image: parameter must be an arrayref");
3916 av=(AV*)SvRV(ST(1));
3920 for (i = 0; i < len; ++i) {
3921 sv1=(*(av_fetch(av,i,0)));
3922 matrix[i] = SvNV(sv1);
3928 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3932 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3934 # this class is only exposed for testing
3937 i_int_hlines_testing()
3939 #if i_int_hlines_testing()
3941 Imager::Internal::Hlines
3942 i_int_hlines_new(start_y, count_y, start_x, count_x)
3948 Imager::Internal::Hlines
3949 i_int_hlines_new_img(im)
3953 i_int_hlines_add(hlines, y, minx, width)
3954 Imager::Internal::Hlines hlines
3960 i_int_hlines_DESTROY(hlines)
3961 Imager::Internal::Hlines hlines
3964 i_int_hlines_dump(hlines)
3965 Imager::Internal::Hlines hlines
3968 i_int_hlines_CLONE_SKIP(cls)
3972 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
3975 im_context_DESTROY(ctx)
3978 #ifdef PERL_IMPLICIT_CONTEXT
3981 im_context_CLONE(...)
3985 /* the following sv_setref_pv() will free this inc */
3986 im_context_refinc(MY_CXT.ctx, "CLONE");
3987 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
3988 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
3993 PERL_SET_GLOBAL_CALLBACKS;
3994 PERL_PL_SET_GLOBAL_CALLBACKS;
3995 #ifdef PERL_IMPLICIT_CONTEXT
4001 start_context(aTHX);
4002 im_get_context = perl_get_context;