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,xc,yc,val)
1755 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1756 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1757 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1758 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1759 av1=(AV*)SvRV(ST(1));
1760 av2=(AV*)SvRV(ST(2));
1761 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1763 x=mymalloc( len*sizeof(double) );
1764 y=mymalloc( len*sizeof(double) );
1765 for(i=0;i<len;i++) {
1766 sv1=(*(av_fetch(av1,i,0)));
1767 sv2=(*(av_fetch(av2,i,0)));
1768 x[i]=(double)SvNV(sv1);
1769 y[i]=(double)SvNV(sv2);
1771 i_bezier_multi(im,len,x,y,val);
1777 i_poly_aa(im,x,y,val)
1786 if (size_x != size_y)
1787 croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1788 RETVAL = i_poly_aa(im, size_x, x, y, val);
1793 i_poly_aa_cfill(im, x, y, fill)
1797 Imager::FillHandle fill
1802 if (size_x != size_y)
1803 croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1804 RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
1809 i_flood_fill(im,seedx,seedy,dcol)
1816 i_flood_cfill(im,seedx,seedy,fill)
1820 Imager::FillHandle fill
1823 i_flood_fill_border(im,seedx,seedy,dcol, border)
1828 Imager::Color border
1831 i_flood_cfill_border(im,seedx,seedy,fill, border)
1835 Imager::FillHandle fill
1836 Imager::Color border
1840 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1852 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1869 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1880 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1893 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)
1909 i_combine(src_av, channels_av = NULL)
1913 i_img **imgs = NULL;
1915 int *channels = NULL;
1920 in_count = av_len(src_av) + 1;
1922 imgs = mymalloc(sizeof(i_img*) * in_count);
1923 channels = mymalloc(sizeof(int) * in_count);
1924 for (i = 0; i < in_count; ++i) {
1925 psv = av_fetch(src_av, i, 0);
1926 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1929 croak("imgs must contain only images");
1931 tmp = SvIV((SV*)SvRV(*psv));
1932 imgs[i] = INT2PTR(i_img*, tmp);
1934 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1936 channels[i] = SvIV(*psv);
1943 RETVAL = i_combine(imgs, channels, in_count);
1950 i_flipxy(im, direction)
1955 i_rotate90(im, degrees)
1960 i_rotate_exact(im, amount, ...)
1964 i_color *backp = NULL;
1965 i_fcolor *fbackp = NULL;
1969 /* extract the bg colors if any */
1970 /* yes, this is kind of strange */
1971 for (i = 2; i < items; ++i) {
1973 if (sv_derived_from(sv1, "Imager::Color")) {
1974 IV tmp = SvIV((SV*)SvRV(sv1));
1975 backp = INT2PTR(i_color *, tmp);
1977 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1978 IV tmp = SvIV((SV*)SvRV(sv1));
1979 fbackp = INT2PTR(i_fcolor *, tmp);
1982 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1987 i_matrix_transform(im, xsize, ysize, matrix_av, ...)
1997 i_color *backp = NULL;
1998 i_fcolor *fbackp = NULL;
2000 len=av_len(matrix_av)+1;
2003 for (i = 0; i < len; ++i) {
2004 sv1=(*(av_fetch(matrix_av,i,0)));
2005 matrix[i] = SvNV(sv1);
2009 /* extract the bg colors if any */
2010 /* yes, this is kind of strange */
2011 for (i = 4; i < items; ++i) {
2013 if (sv_derived_from(sv1, "Imager::Color")) {
2014 IV tmp = SvIV((SV*)SvRV(sv1));
2015 backp = INT2PTR(i_color *, tmp);
2017 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
2018 IV tmp = SvIV((SV*)SvRV(sv1));
2019 fbackp = INT2PTR(i_fcolor *, tmp);
2022 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2027 i_gaussian(im,stdev)
2032 i_unsharp_mask(im,stdev,scale)
2047 len = av_len(coef) + 1;
2048 c_coef=mymalloc( len * sizeof(double) );
2049 for(i = 0; i < len; i++) {
2050 sv1 = (*(av_fetch(coef, i, 0)));
2051 c_coef[i] = (double)SvNV(sv1);
2053 RETVAL = i_conv(im, c_coef, len);
2059 i_convert(src, avmain)
2071 outchan = av_len(avmain)+1;
2072 /* find the biggest */
2074 for (j=0; j < outchan; ++j) {
2075 temp = av_fetch(avmain, j, 0);
2076 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2077 avsub = (AV*)SvRV(*temp);
2078 len = av_len(avsub)+1;
2083 i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2087 coeff = mymalloc(sizeof(double) * outchan * inchan);
2088 for (j = 0; j < outchan; ++j) {
2089 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2090 len = av_len(avsub)+1;
2091 for (i = 0; i < len; ++i) {
2092 temp = av_fetch(avsub, i, 0);
2094 coeff[i+j*inchan] = SvNV(*temp);
2096 coeff[i+j*inchan] = 0;
2099 coeff[i++ + j*inchan] = 0;
2101 RETVAL = i_convert(src, coeff, outchan, inchan);
2112 unsigned int mask = 0;
2118 unsigned char (*maps)[256];
2120 len = av_len(pmaps_av)+1;
2121 if (im->channels < len)
2123 maps = mymalloc( len * sizeof(unsigned char [256]) );
2124 for (j=0; j<len ; j++) {
2125 temp = av_fetch(pmaps_av, j, 0);
2126 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2127 avsub = (AV*)SvRV(*temp);
2128 if(av_len(avsub) != 255)
2131 for (i=0; i<256 ; i++) {
2133 temp = av_fetch(avsub, i, 0);
2134 val = temp ? SvIV(*temp) : 0;
2136 if (val>255) val = 255;
2141 i_map(im, maps, mask);
2153 i_img_diffd(im1,im2)
2158 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2168 _is_color_object(sv)
2172 RETVAL = SvOK(sv) && SvROK(sv) &&
2173 (sv_derived_from(sv, "Imager::Color")
2174 || sv_derived_from(sv, "Imager::Color::Float"));
2186 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2188 #define TT_DESTROY(handle) i_tt_destroy(handle)
2192 Imager::Font::TT handle
2197 (void)items; /* avoid unused warning */
2203 MODULE = Imager PACKAGE = Imager
2207 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
2208 Imager::Font::TT handle
2222 str = SvPV(str_sv, len);
2227 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2228 len, smooth, utf8, align);
2234 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
2235 Imager::Font::TT handle
2249 str = SvPV(str_sv, len);
2254 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2255 smooth, utf8, align);
2261 i_tt_bbox(handle,point,str_sv,utf8)
2262 Imager::Font::TT handle
2267 i_img_dim cords[BOUNDING_BOX_COUNT];
2273 str = SvPV(str_sv, len);
2278 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2280 for (i = 0; i < rc; ++i) {
2281 PUSHs(sv_2mortal(newSViv(cords[i])));
2286 i_tt_has_chars(handle, text_sv, utf8)
2287 Imager::Font::TT handle
2298 text = SvPV(text_sv, len);
2300 if (SvUTF8(text_sv))
2303 work = mymalloc(len);
2304 count = i_tt_has_chars(handle, text, len, utf8, work);
2305 if (GIMME_V == G_ARRAY) {
2307 for (i = 0; i < count; ++i) {
2308 PUSHs(boolSV(work[i]));
2313 PUSHs(sv_2mortal(newSVpv(work, count)));
2318 i_tt_dump_names(handle)
2319 Imager::Font::TT handle
2322 i_tt_face_name(handle)
2323 Imager::Font::TT handle
2328 len = i_tt_face_name(handle, name, sizeof(name));
2331 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2335 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2336 Imager::Font::TT handle
2348 text = SvPV(text_sv, work_len);
2350 if (SvUTF8(text_sv))
2357 ch = i_utf8_advance(&text, &len);
2359 i_push_error(0, "invalid UTF8 character");
2367 EXTEND(SP, count+1);
2368 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2369 ST(count) = sv_2mortal(newSVpv(name, 0));
2372 ST(count) = &PL_sv_undef;
2381 i_test_format_probe(ig, length)
2386 i_readpnm_wiol(ig, allow_incomplete)
2388 int allow_incomplete
2392 i_readpnm_multi_wiol(ig, allow_incomplete)
2394 int allow_incomplete
2400 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2403 for (i = 0; i < count; ++i) {
2404 SV *sv = sv_newmortal();
2405 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2412 i_writeppm_wiol(im, ig)
2421 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2430 i_writeraw_wiol(im,ig)
2435 i_writebmp_wiol(im,ig)
2440 i_readbmp_wiol(ig, allow_incomplete=0)
2442 int allow_incomplete
2446 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2455 idlen = SvCUR(ST(4));
2456 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2462 i_readtga_wiol(ig, length)
2470 i_scaleaxis(im,Value,Axis)
2476 i_scale_nn(im,scx,scy)
2482 i_scale_mixing(im, width, height)
2492 i_count_colors(im,maxc)
2497 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2502 unsigned int * col_usage = NULL;
2505 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2506 EXTEND(SP, col_cnt);
2507 for (i = 0; i < col_cnt; i++) {
2508 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2515 i_transform(im, opx, opy, parm)
2521 STRLEN size_opx, size_opy, size_parm;
2524 result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
2526 SV *result_sv = sv_newmortal();
2528 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2533 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2559 in_imgs_count = av_len(av_in_imgs)+1;
2560 for (i = 0; i < in_imgs_count; ++i) {
2561 sv1 = *av_fetch(av_in_imgs, i, 0);
2562 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2563 croak("sv_in_img must contain only images");
2566 if (in_imgs_count > 0) {
2567 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2568 for (i = 0; i < in_imgs_count; ++i) {
2569 sv1 = *av_fetch(av_in_imgs,i,0);
2570 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2571 croak("Parameter 5 must contain only images");
2573 tmp = SvIV((SV*)SvRV(sv1));
2574 in_imgs[i] = INT2PTR(i_img*, tmp);
2578 /* no input images */
2581 /* default the output size from the first input if possible */
2583 width = SvIV(sv_width);
2584 else if (in_imgs_count)
2585 width = in_imgs[0]->xsize;
2587 croak("No output image width supplied");
2589 if (SvOK(sv_height))
2590 height = SvIV(sv_height);
2591 else if (in_imgs_count)
2592 height = in_imgs[0]->ysize;
2594 croak("No output image height supplied");
2596 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2597 if (ops_len % sizeof(struct rm_op))
2598 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2599 ops_count = ops_len / sizeof(struct rm_op);
2601 n_regs_count = av_len(av_n_regs)+1;
2602 n_regs = mymalloc(n_regs_count * sizeof(double));
2603 for (i = 0; i < n_regs_count; ++i) {
2604 sv1 = *av_fetch(av_n_regs,i,0);
2606 n_regs[i] = SvNV(sv1);
2608 c_regs_count = av_len(av_c_regs)+1;
2609 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2610 /* I don't bother initializing the colou?r registers */
2612 result=i_transform2(width, height, channels, ops, ops_count,
2613 n_regs, n_regs_count,
2614 c_regs, c_regs_count, in_imgs, in_imgs_count);
2620 SV *result_sv = sv_newmortal();
2622 sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2628 i_contrast(im,intensity)
2641 i_noise(im,amount,type)
2647 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2657 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2676 i_postlevels(im,levels)
2686 i_watermark(im,wmark,tx,ty,pixdiff)
2688 Imager::ImgRaw wmark
2695 i_autolevels(im,lsat,usat,skew)
2702 i_radnoise(im,xo,yo,rscale,ascale)
2710 i_turbnoise(im, xo, yo, scale)
2718 i_gradgen(im, xo, yo, ac, dmeasure)
2729 if (size_xo != size_yo || size_xo != size_ac)
2730 croak("i_gradgen: x, y and color arrays must be the same size");
2732 croak("Usage: i_gradgen array refs must have more than 1 entry each");
2733 i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
2736 i_diff_image(im, im2, mindist=0)
2742 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2752 double ssample_param
2756 i_fountain_seg *segs;
2758 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2759 croak("i_fountain: argument 11 must be an array ref");
2761 asegs = (AV *)SvRV(ST(10));
2762 segs = load_fount_segs(aTHX_ asegs, &count);
2763 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2764 super_sample, ssample_param, count, segs);
2770 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2779 double ssample_param
2783 i_fountain_seg *segs;
2785 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2786 croak("i_fountain: argument 11 must be an array ref");
2788 asegs = (AV *)SvRV(ST(9));
2789 segs = load_fount_segs(aTHX_ asegs, &count);
2790 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2791 super_sample, ssample_param, count, segs);
2797 i_new_fill_opacity(other_fill, alpha_mult)
2798 Imager::FillHandle other_fill
2809 errors = i_errors();
2811 while (errors[i].msg) {
2813 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2814 if (!av_store(av, 0, sv)) {
2817 sv = newSViv(errors[i].code);
2818 if (!av_store(av, 1, sv)) {
2821 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2829 i_push_error(code, msg)
2834 i_nearest_color(im, ...)
2849 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2850 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2851 croak("i_nearest_color: Second argument must be an array ref");
2852 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2853 croak("i_nearest_color: Third argument must be an array ref");
2854 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2855 croak("i_nearest_color: Fourth argument must be an array ref");
2856 axx = (AV *)SvRV(ST(1));
2857 ayy = (AV *)SvRV(ST(2));
2858 ac = (AV *)SvRV(ST(3));
2859 dmeasure = (int)SvIV(ST(4));
2861 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2862 num = num <= av_len(ac) ? num : av_len(ac);
2864 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2865 xo = mymalloc( sizeof(i_img_dim) * num );
2866 yo = mymalloc( sizeof(i_img_dim) * num );
2867 ival = mymalloc( sizeof(i_color) * num );
2868 for(i = 0; i<num; i++) {
2869 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2870 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2871 sv = *av_fetch(ac, i, 0);
2872 if ( !sv_derived_from(sv, "Imager::Color") ) {
2873 free(axx); free(ayy); free(ac);
2874 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2876 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2878 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2892 rc=DSO_open(filename,&evstr);
2896 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2897 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2900 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2906 DSO_close(dso_handle)
2910 DSO_funclist(dso_handle_v)
2914 DSO_handle *dso_handle;
2915 func_ptr *functions;
2917 dso_handle=(DSO_handle*)dso_handle_v;
2918 functions = DSO_funclist(dso_handle);
2920 while( functions[i].name != NULL) {
2922 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2924 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2928 DSO_call(handle,func_index,hv)
2933 DSO_call( (DSO_handle *)handle,func_index,hv);
2936 i_get_pixel(im, x, y)
2943 color = (i_color *)mymalloc(sizeof(i_color));
2944 if (i_gpix(im, x, y, color) == 0) {
2945 RETVAL = NEWSV(0, 0);
2946 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
2950 RETVAL = &PL_sv_undef;
2957 i_ppix(im, x, y, cl)
2964 i_img_pal_new(x, y, channels, maxpal)
2971 i_img_to_pal(src, quant)
2977 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2978 croak("i_img_to_pal: second argument must be a hash ref");
2979 hv = (HV *)SvRV(ST(1));
2980 memset(&quant, 0, sizeof(quant));
2982 quant.mc_size = 256;
2983 ip_handle_quant_opts(aTHX_ &quant, hv);
2984 RETVAL = i_img_to_pal(src, &quant);
2986 ip_copy_colors_back(aTHX_ hv, &quant);
2988 ip_cleanup_quant_opts(aTHX_ &quant);
2997 i_img_make_palette(HV *quant_hv, ...)
2999 size_t count = items - 1;
3001 i_img **imgs = NULL;
3005 croak("Please supply at least one image (%d)", (int)count);
3006 imgs = mymalloc(sizeof(i_img *) * count);
3007 for (i = 0; i < count; ++i) {
3008 SV *img_sv = ST(i + 1);
3009 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3010 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3014 croak("Image %d is not an image object", (int)i+1);
3017 memset(&quant, 0, sizeof(quant));
3019 quant.mc_size = 256;
3020 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3021 i_quant_makemap(&quant, imgs, count);
3022 EXTEND(SP, quant.mc_count);
3023 for (i = 0; i < quant.mc_count; ++i) {
3024 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3027 ip_cleanup_quant_opts(aTHX_ &quant);
3041 work = mymalloc((r-l) * sizeof(i_palidx));
3042 count = i_gpal(im, l, r, y, work);
3043 if (GIMME_V == G_ARRAY) {
3045 for (i = 0; i < count; ++i) {
3046 PUSHs(sv_2mortal(newSViv(work[i])));
3051 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3056 if (GIMME_V != G_ARRAY) {
3058 PUSHs(&PL_sv_undef);
3063 i_ppal(im, l, y, ...)
3072 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3073 for (i=0; i < items-3; ++i) {
3074 work[i] = SvIV(ST(i+3));
3076 validate_i_ppal(im, work, items - 3);
3077 RETVAL = i_ppal(im, l, l+items-3, y, work);
3086 i_ppal_p(im, l, y, data)
3092 i_palidx const *work;
3095 work = (i_palidx const *)SvPV(data, len);
3096 len /= sizeof(i_palidx);
3098 validate_i_ppal(im, work, len);
3099 RETVAL = i_ppal(im, l, l+len, y, work);
3108 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 RETVAL = i_addcolors(im, colors, items-1);
3133 i_setcolors(im, index, ...)
3141 croak("i_setcolors: no colors to add");
3142 colors = mymalloc((items-2) * sizeof(i_color));
3143 for (i=0; i < items-2; ++i) {
3144 if (sv_isobject(ST(i+2))
3145 && sv_derived_from(ST(i+2), "Imager::Color")) {
3146 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3147 colors[i] = *INT2PTR(i_color *, tmp);
3151 croak("i_setcolors: pixels must be Imager::Color objects");
3154 RETVAL = i_setcolors(im, index, colors, items-2);
3160 i_getcolors(im, index, ...)
3169 croak("i_getcolors: too many arguments");
3171 count = SvIV(ST(2));
3173 croak("i_getcolors: count must be positive");
3174 colors = mymalloc(sizeof(i_color) * count);
3175 if (i_getcolors(im, index, colors, count)) {
3176 for (i = 0; i < count; ++i) {
3177 SV *sv = make_i_color_sv(aTHX_ colors+i);
3193 i_findcolor(im, color)
3199 if (i_findcolor(im, color, &index)) {
3200 RETVAL = newSViv(index);
3203 RETVAL = &PL_sv_undef;
3221 i_gsamp(im, l, r, y, channels)
3226 i_channel_list channels
3232 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count); /* XXX: memleak? */
3233 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3234 if (GIMME_V == G_ARRAY) {
3236 for (i = 0; i < count; ++i)
3237 PUSHs(sv_2mortal(newSViv(data[i])));
3241 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3246 if (GIMME_V != G_ARRAY) {
3248 PUSHs(&PL_sv_undef);
3253 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3261 i_channel_list channels
3268 croak("No channel numbers supplied to g_samp()");
3270 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3271 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3272 for (i = 0; i < count; ++i) {
3273 av_store(target, i+offset, newSVuv(data[i]));
3285 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3290 i_channel_list channels
3292 i_img_dim data_offset
3293 i_img_dim pixel_count
3302 data_count = av_len(data_av) + 1;
3303 if (data_offset < 0) {
3304 croak("data_offset must be non-negative");
3306 if (data_offset > data_count) {
3307 croak("data_offset greater than number of samples supplied");
3309 if (pixel_count == -1 ||
3310 data_offset + pixel_count * channels.count > data_count) {
3311 pixel_count = (data_count - data_offset) / channels.count;
3314 data_used = pixel_count * channels.count;
3315 data = mymalloc(sizeof(unsigned) * data_count);
3316 for (i = 0; i < data_used; ++i)
3317 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3319 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3320 channels.count, bits);
3328 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3332 i_channel_list channels
3341 i_push_error(0, "offset must be non-negative");
3345 if (offset > data.count) {
3346 i_push_error(0, "offset greater than number of samples supplied");
3349 data.samples += offset;
3350 data.count -= offset;
3353 width * channels.count > data.count) {
3354 width = data.count / channels.count;
3357 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3362 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3366 i_channel_list channels
3375 i_push_error(0, "offset must be non-negative");
3379 if (offset > data.count) {
3380 i_push_error(0, "offset greater than number of samples supplied");
3383 data.samples += offset;
3384 data.count -= offset;
3387 width * channels.count > data.count) {
3388 width = data.count / channels.count;
3391 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3396 i_img_masked_new(targ, mask, x, y, w, h)
3406 if (!sv_isobject(ST(1))
3407 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3408 croak("i_img_masked_new: parameter 2 must undef or an image");
3410 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3414 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3419 i_plin(im, l, y, ...)
3430 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3431 /* supplied as a byte string */
3432 work = (i_color *)SvPV(ST(3), len);
3433 count = len / sizeof(i_color);
3434 if (count * sizeof(i_color) != len) {
3435 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3437 RETVAL = i_plin(im, l, l+count, y, work);
3440 work = mymalloc(sizeof(i_color) * (items-3));
3441 for (i=0; i < items-3; ++i) {
3442 if (sv_isobject(ST(i+3))
3443 && sv_derived_from(ST(i+3), "Imager::Color")) {
3444 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3445 work[i] = *INT2PTR(i_color *, tmp);
3449 croak("i_plin: pixels must be Imager::Color objects");
3452 RETVAL = i_plin(im, l, l+items-3, y, work);
3463 i_ppixf(im, x, y, cl)
3467 Imager::Color::Float cl
3470 i_gsampf(im, l, r, y, channels)
3475 i_channel_list channels
3481 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3482 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3483 if (GIMME_V == G_ARRAY) {
3485 for (i = 0; i < count; ++i)
3486 PUSHs(sv_2mortal(newSVnv(data[i])));
3490 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3495 if (GIMME_V != G_ARRAY) {
3497 PUSHs(&PL_sv_undef);
3502 i_plinf(im, l, y, ...)
3513 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3514 /* supplied as a byte string */
3515 work = (i_fcolor *)SvPV(ST(3), len);
3516 count = len / sizeof(i_fcolor);
3517 if (count * sizeof(i_fcolor) != len) {
3518 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3520 RETVAL = i_plinf(im, l, l+count, y, work);
3523 work = mymalloc(sizeof(i_fcolor) * (items-3));
3524 for (i=0; i < items-3; ++i) {
3525 if (sv_isobject(ST(i+3))
3526 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3527 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3528 work[i] = *INT2PTR(i_fcolor *, tmp);
3532 croak("i_plinf: pixels must be Imager::Color::Float objects");
3536 RETVAL = i_plinf(im, l, l+items-3, y, work);
3554 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3555 if (i_gpixf(im, x, y, color) == 0) {
3556 RETVAL = NEWSV(0,0);
3557 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
3561 RETVAL = &PL_sv_undef;
3577 vals = mymalloc((r-l) * sizeof(i_color));
3578 memset(vals, 0, (r-l) * sizeof(i_color));
3579 count = i_glin(im, l, r, y, vals);
3580 if (GIMME_V == G_ARRAY) {
3582 for (i = 0; i < count; ++i) {
3583 SV *sv = make_i_color_sv(aTHX_ vals+i);
3589 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3595 i_glinf(im, l, r, y)
3605 for (i = 0; i < MAXCHANNELS; ++i)
3606 zero.channel[i] = 0;
3608 vals = mymalloc((r-l) * sizeof(i_fcolor));
3609 for (i = 0; i < r-l; ++i)
3611 count = i_glinf(im, l, r, y, vals);
3612 if (GIMME_V == G_ARRAY) {
3614 for (i = 0; i < count; ++i) {
3616 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3618 sv = sv_newmortal();
3619 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3625 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3631 i_img_8_new(x, y, ch)
3637 i_img_16_new(x, y, ch)
3647 i_img_double_new(x, y, ch)
3657 i_tags_addn(im, name, code, idata)
3666 name = SvPV(ST(1), len);
3669 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3674 i_tags_add(im, name, code, data, idata)
3684 name = SvPV(ST(1), len);
3688 data = SvPV(ST(3), len);
3693 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3698 i_tags_find(im, name, start)
3705 if (i_tags_find(&im->tags, name, start, &entry)) {
3707 RETVAL = newSVpv("0 but true", 0);
3709 RETVAL = newSViv(entry);
3711 RETVAL = &PL_sv_undef;
3717 i_tags_findn(im, code, start)
3724 if (i_tags_findn(&im->tags, code, start, &entry)) {
3726 RETVAL = newSVpv("0 but true", 0);
3728 RETVAL = newSViv(entry);
3731 RETVAL = &PL_sv_undef;
3737 i_tags_delete(im, entry)
3741 RETVAL = i_tags_delete(&im->tags, entry);
3746 i_tags_delbyname(im, name)
3750 RETVAL = i_tags_delbyname(&im->tags, name);
3755 i_tags_delbycode(im, code)
3759 RETVAL = i_tags_delbycode(&im->tags, code);
3764 i_tags_get(im, index)
3768 if (index >= 0 && index < im->tags.count) {
3769 i_img_tag *entry = im->tags.tags + index;
3773 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3776 PUSHs(sv_2mortal(newSViv(entry->code)));
3779 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3782 PUSHs(sv_2mortal(newSViv(entry->idata)));
3787 i_tags_get_string(im, what_sv)
3791 char const *name = NULL;
3795 if (SvIOK(what_sv)) {
3796 code = SvIV(what_sv);
3800 name = SvPV_nolen(what_sv);
3803 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3805 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3812 RETVAL = im->tags.count;
3818 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3822 Imager::FillHandle fill
3825 IFILL_CLONE_SKIP(...)
3827 (void)items; /* avoid unused warning for XS variable */
3832 MODULE = Imager PACKAGE = Imager
3835 i_new_fill_solid(cl, combine)
3840 i_new_fill_solidf(cl, combine)
3841 Imager::Color::Float cl
3845 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3853 unsigned char *cust_hatch;
3857 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3861 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3866 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3867 Imager::Color::Float fg
3868 Imager::Color::Float bg
3874 unsigned char *cust_hatch;
3878 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3882 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3887 i_new_fill_image(src, matrix, xoff, yoff, combine)
3904 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3905 croak("i_new_fill_image: parameter must be an arrayref");
3906 av=(AV*)SvRV(ST(1));
3910 for (i = 0; i < len; ++i) {
3911 sv1=(*(av_fetch(av,i,0)));
3912 matrix[i] = SvNV(sv1);
3918 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3922 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3924 # this class is only exposed for testing
3927 i_int_hlines_testing()
3929 #if i_int_hlines_testing()
3931 Imager::Internal::Hlines
3932 i_int_hlines_new(start_y, count_y, start_x, count_x)
3938 Imager::Internal::Hlines
3939 i_int_hlines_new_img(im)
3943 i_int_hlines_add(hlines, y, minx, width)
3944 Imager::Internal::Hlines hlines
3950 i_int_hlines_DESTROY(hlines)
3951 Imager::Internal::Hlines hlines
3954 i_int_hlines_dump(hlines)
3955 Imager::Internal::Hlines hlines
3958 i_int_hlines_CLONE_SKIP(cls)
3962 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
3965 im_context_DESTROY(ctx)
3968 #ifdef PERL_IMPLICIT_CONTEXT
3971 im_context_CLONE(...)
3975 /* the following sv_setref_pv() will free this inc */
3976 im_context_refinc(MY_CXT.ctx, "CLONE");
3977 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
3978 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
3983 PERL_SET_GLOBAL_CALLBACKS;
3984 PERL_PL_SET_GLOBAL_CALLBACKS;
3985 #ifdef PERL_IMPLICIT_CONTEXT
3991 start_context(aTHX);
3992 im_get_context = perl_get_context;