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)
2941 RETVAL = (i_color *)mymalloc(sizeof(i_color));
2942 if (i_gpix(im, x, y, RETVAL) != 0) {
2951 i_ppix(im, x, y, cl)
2958 i_img_pal_new(x, y, channels, maxpal)
2965 i_img_to_pal(src, quant)
2971 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2972 croak("i_img_to_pal: second argument must be a hash ref");
2973 hv = (HV *)SvRV(ST(1));
2974 memset(&quant, 0, sizeof(quant));
2976 quant.mc_size = 256;
2977 ip_handle_quant_opts(aTHX_ &quant, hv);
2978 RETVAL = i_img_to_pal(src, &quant);
2980 ip_copy_colors_back(aTHX_ hv, &quant);
2982 ip_cleanup_quant_opts(aTHX_ &quant);
2991 i_img_make_palette(HV *quant_hv, ...)
2993 size_t count = items - 1;
2995 i_img **imgs = NULL;
2999 croak("Please supply at least one image (%d)", (int)count);
3000 imgs = mymalloc(sizeof(i_img *) * count);
3001 for (i = 0; i < count; ++i) {
3002 SV *img_sv = ST(i + 1);
3003 if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
3004 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
3008 croak("Image %d is not an image object", (int)i+1);
3011 memset(&quant, 0, sizeof(quant));
3013 quant.mc_size = 256;
3014 ip_handle_quant_opts(aTHX_ &quant, quant_hv);
3015 i_quant_makemap(&quant, imgs, count);
3016 EXTEND(SP, quant.mc_count);
3017 for (i = 0; i < quant.mc_count; ++i) {
3018 SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
3021 ip_cleanup_quant_opts(aTHX_ &quant);
3035 work = mymalloc((r-l) * sizeof(i_palidx));
3036 count = i_gpal(im, l, r, y, work);
3037 if (GIMME_V == G_ARRAY) {
3039 for (i = 0; i < count; ++i) {
3040 PUSHs(sv_2mortal(newSViv(work[i])));
3045 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3050 if (GIMME_V != G_ARRAY) {
3052 PUSHs(&PL_sv_undef);
3057 i_ppal(im, l, y, ...)
3066 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3067 for (i=0; i < items-3; ++i) {
3068 work[i] = SvIV(ST(i+3));
3070 validate_i_ppal(im, work, items - 3);
3071 RETVAL = i_ppal(im, l, l+items-3, y, work);
3080 i_ppal_p(im, l, y, data)
3086 i_palidx const *work;
3089 work = (i_palidx const *)SvPV(data, len);
3090 len /= sizeof(i_palidx);
3092 validate_i_ppal(im, work, len);
3093 RETVAL = i_ppal(im, l, l+len, y, work);
3102 i_addcolors(im, ...)
3109 croak("i_addcolors: no colors to add");
3110 colors = mymalloc((items-1) * sizeof(i_color));
3111 for (i=0; i < items-1; ++i) {
3112 if (sv_isobject(ST(i+1))
3113 && sv_derived_from(ST(i+1), "Imager::Color")) {
3114 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3115 colors[i] = *INT2PTR(i_color *, tmp);
3119 croak("i_addcolor: pixels must be Imager::Color objects");
3122 RETVAL = i_addcolors(im, colors, items-1);
3127 i_setcolors(im, index, ...)
3135 croak("i_setcolors: no colors to add");
3136 colors = mymalloc((items-2) * sizeof(i_color));
3137 for (i=0; i < items-2; ++i) {
3138 if (sv_isobject(ST(i+2))
3139 && sv_derived_from(ST(i+2), "Imager::Color")) {
3140 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3141 colors[i] = *INT2PTR(i_color *, tmp);
3145 croak("i_setcolors: pixels must be Imager::Color objects");
3148 RETVAL = i_setcolors(im, index, colors, items-2);
3154 i_getcolors(im, index, count=1)
3163 croak("i_getcolors: count must be positive");
3164 colors = malloc_temp(aTHX_ sizeof(i_color) * count);
3165 if (i_getcolors(im, index, colors, count)) {
3167 for (i = 0; i < count; ++i) {
3168 SV *sv = make_i_color_sv(aTHX_ colors+i);
3182 i_findcolor(im, color)
3186 if (!i_findcolor(im, color, &RETVAL)) {
3205 i_gsamp(im, l, r, y, channels)
3210 i_channel_list channels
3216 data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count);
3217 count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3218 if (GIMME_V == G_ARRAY) {
3220 for (i = 0; i < count; ++i)
3221 PUSHs(sv_2mortal(newSViv(data[i])));
3225 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3230 if (GIMME_V != G_ARRAY) {
3236 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3244 i_channel_list channels
3251 croak("No channel numbers supplied to g_samp()");
3253 data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3254 count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3255 for (i = 0; i < count; ++i) {
3256 av_store(target, i+offset, newSVuv(data[i]));
3268 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3273 i_channel_list channels
3275 i_img_dim data_offset
3276 i_img_dim pixel_count
3285 data_count = av_len(data_av) + 1;
3286 if (data_offset < 0) {
3287 croak("data_offset must be non-negative");
3289 if (data_offset > data_count) {
3290 croak("data_offset greater than number of samples supplied");
3292 if (pixel_count == -1 ||
3293 data_offset + pixel_count * channels.count > data_count) {
3294 pixel_count = (data_count - data_offset) / channels.count;
3297 data_used = pixel_count * channels.count;
3298 data = mymalloc(sizeof(unsigned) * data_count);
3299 for (i = 0; i < data_used; ++i)
3300 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3302 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels,
3303 channels.count, bits);
3311 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3315 i_channel_list channels
3324 i_push_error(0, "offset must be non-negative");
3328 if (offset > data.count) {
3329 i_push_error(0, "offset greater than number of samples supplied");
3332 data.samples += offset;
3333 data.count -= offset;
3336 width * channels.count > data.count) {
3337 width = data.count / channels.count;
3340 RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3345 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3349 i_channel_list channels
3358 i_push_error(0, "offset must be non-negative");
3362 if (offset > data.count) {
3363 i_push_error(0, "offset greater than number of samples supplied");
3366 data.samples += offset;
3367 data.count -= offset;
3370 width * channels.count > data.count) {
3371 width = data.count / channels.count;
3374 RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3379 i_img_masked_new(targ, mask, x, y, w, h)
3389 if (!sv_isobject(ST(1))
3390 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3391 croak("i_img_masked_new: parameter 2 must undef or an image");
3393 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3397 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3402 i_plin(im, l, y, ...)
3413 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3414 /* supplied as a byte string */
3415 work = (i_color *)SvPV(ST(3), len);
3416 count = len / sizeof(i_color);
3417 if (count * sizeof(i_color) != len) {
3418 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3420 RETVAL = i_plin(im, l, l+count, y, work);
3423 work = mymalloc(sizeof(i_color) * (items-3));
3424 for (i=0; i < items-3; ++i) {
3425 if (sv_isobject(ST(i+3))
3426 && sv_derived_from(ST(i+3), "Imager::Color")) {
3427 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3428 work[i] = *INT2PTR(i_color *, tmp);
3432 croak("i_plin: pixels must be Imager::Color objects");
3435 RETVAL = i_plin(im, l, l+items-3, y, work);
3446 i_ppixf(im, x, y, cl)
3450 Imager::Color::Float cl
3453 i_gsampf(im, l, r, y, channels)
3458 i_channel_list channels
3464 data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3465 count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3466 if (GIMME_V == G_ARRAY) {
3468 for (i = 0; i < count; ++i)
3469 PUSHs(sv_2mortal(newSVnv(data[i])));
3473 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3478 if (GIMME_V != G_ARRAY) {
3484 i_plinf(im, l, y, ...)
3495 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3496 /* supplied as a byte string */
3497 work = (i_fcolor *)SvPV(ST(3), len);
3498 count = len / sizeof(i_fcolor);
3499 if (count * sizeof(i_fcolor) != len) {
3500 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3502 RETVAL = i_plinf(im, l, l+count, y, work);
3505 work = mymalloc(sizeof(i_fcolor) * (items-3));
3506 for (i=0; i < items-3; ++i) {
3507 if (sv_isobject(ST(i+3))
3508 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3509 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3510 work[i] = *INT2PTR(i_fcolor *, tmp);
3514 croak("i_plinf: pixels must be Imager::Color::Float objects");
3518 RETVAL = i_plinf(im, l, l+items-3, y, work);
3528 Imager::Color::Float
3534 RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3535 if (i_gpixf(im, x, y, RETVAL) != 0) {
3553 vals = mymalloc((r-l) * sizeof(i_color));
3554 memset(vals, 0, (r-l) * sizeof(i_color));
3555 count = i_glin(im, l, r, y, vals);
3556 if (GIMME_V == G_ARRAY) {
3558 for (i = 0; i < count; ++i) {
3559 SV *sv = make_i_color_sv(aTHX_ vals+i);
3565 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3571 i_glinf(im, l, r, y)
3581 for (i = 0; i < MAXCHANNELS; ++i)
3582 zero.channel[i] = 0;
3584 vals = mymalloc((r-l) * sizeof(i_fcolor));
3585 for (i = 0; i < r-l; ++i)
3587 count = i_glinf(im, l, r, y, vals);
3588 if (GIMME_V == G_ARRAY) {
3590 for (i = 0; i < count; ++i) {
3592 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3594 sv = sv_newmortal();
3595 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3601 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3607 i_img_8_new(x, y, ch)
3613 i_img_16_new(x, y, ch)
3623 i_img_double_new(x, y, ch)
3633 i_tags_addn(im, name_sv, code, idata)
3642 SvGETMAGIC(name_sv);
3644 name = SvPV_nomg(name_sv, len);
3647 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3652 i_tags_add(im, name_sv, code, data_sv, idata)
3663 SvGETMAGIC(name_sv);
3665 name = SvPV_nomg(name_sv, len);
3668 SvGETMAGIC(data_sv);
3670 data = SvPV(data_sv, len);
3675 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3680 i_tags_find(im, name, start)
3687 if (i_tags_find(&im->tags, name, start, &entry)) {
3696 i_tags_findn(im, code, start)
3703 if (i_tags_findn(&im->tags, code, start, &entry)) {
3713 i_tags_delete(im, entry)
3717 RETVAL = i_tags_delete(&im->tags, entry);
3722 i_tags_delbyname(im, name)
3726 RETVAL = i_tags_delbyname(&im->tags, name);
3731 i_tags_delbycode(im, code)
3735 RETVAL = i_tags_delbycode(&im->tags, code);
3740 i_tags_get(im, index)
3744 if (index >= 0 && index < im->tags.count) {
3745 i_img_tag *entry = im->tags.tags + index;
3749 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3752 PUSHs(sv_2mortal(newSViv(entry->code)));
3755 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3758 PUSHs(sv_2mortal(newSViv(entry->idata)));
3763 i_tags_get_string(im, what_sv)
3767 char const *name = NULL;
3771 if (SvIOK(what_sv)) {
3772 code = SvIV(what_sv);
3776 name = SvPV_nolen(what_sv);
3779 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3781 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3788 RETVAL = im->tags.count;
3794 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3798 Imager::FillHandle fill
3801 IFILL_CLONE_SKIP(...)
3803 (void)items; /* avoid unused warning for XS variable */
3808 MODULE = Imager PACKAGE = Imager
3811 i_new_fill_solid(cl, combine)
3816 i_new_fill_solidf(cl, combine)
3817 Imager::Color::Float cl
3821 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3829 unsigned char *cust_hatch;
3833 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3837 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3842 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3843 Imager::Color::Float fg
3844 Imager::Color::Float bg
3850 unsigned char *cust_hatch;
3854 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3858 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3863 i_new_fill_image(src, matrix, xoff, yoff, combine)
3880 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3881 croak("i_new_fill_image: parameter must be an arrayref");
3882 av=(AV*)SvRV(ST(1));
3886 for (i = 0; i < len; ++i) {
3887 sv1=(*(av_fetch(av,i,0)));
3888 matrix[i] = SvNV(sv1);
3894 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3898 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3900 # this class is only exposed for testing
3903 i_int_hlines_testing()
3905 #if i_int_hlines_testing()
3907 Imager::Internal::Hlines
3908 i_int_hlines_new(start_y, count_y, start_x, count_x)
3914 Imager::Internal::Hlines
3915 i_int_hlines_new_img(im)
3919 i_int_hlines_add(hlines, y, minx, width)
3920 Imager::Internal::Hlines hlines
3926 i_int_hlines_DESTROY(hlines)
3927 Imager::Internal::Hlines hlines
3930 i_int_hlines_dump(hlines)
3931 Imager::Internal::Hlines hlines
3934 i_int_hlines_CLONE_SKIP(cls)
3938 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
3941 im_context_DESTROY(ctx)
3944 #ifdef PERL_IMPLICIT_CONTEXT
3947 im_context_CLONE(...)
3951 /* the following sv_setref_pv() will free this inc */
3952 im_context_refinc(MY_CXT.ctx, "CLONE");
3953 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
3954 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
3959 PERL_SET_GLOBAL_CALLBACKS;
3960 PERL_PL_SET_GLOBAL_CALLBACKS;
3961 #ifdef PERL_IMPLICIT_CONTEXT
3967 start_context(aTHX);
3968 im_get_context = perl_get_context;