1 #define PERL_NO_GET_CONTEXT
8 #define NEED_newRV_noinc
9 #define NEED_sv_2pv_nolen
15 #define i_int_hlines_testing() 1
22 #include "imextpltypes.h"
25 #if i_int_hlines_testing()
33 Allocate memory that will be discarded when mortals are discarded.
38 malloc_temp(pTHX_ size_t size) {
39 SV *sv = sv_2mortal(newSV(size));
44 /* These functions are all shared - then comes platform dependant code */
45 static int getstr(void *hv_t,char *key,char **store) {
50 mm_log((1,"getstr(hv_t %p, key %s, store %p)\n",hv_t,key,store));
52 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
54 svpp=hv_fetch(hv, key, strlen(key), 0);
55 *store=SvPV(*svpp, PL_na );
60 static int getint(void *hv_t,char *key,int *store) {
65 mm_log((1,"getint(hv_t %p, key %s, store %p)\n",hv_t,key,store));
67 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
69 svpp=hv_fetch(hv, key, strlen(key), 0);
70 *store=(int)SvIV(*svpp);
74 static int getdouble(void *hv_t,char* key,double *store) {
79 mm_log((1,"getdouble(hv_t %p, key %s, store %p)\n",hv_t,key,store));
81 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
82 svpp=hv_fetch(hv, key, strlen(key), 0);
83 *store=(double)SvNV(*svpp);
87 static int getvoid(void *hv_t,char* key,void **store) {
92 mm_log((1,"getvoid(hv_t %p, key %s, store %p)\n",hv_t,key,store));
94 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
96 svpp=hv_fetch(hv, key, strlen(key), 0);
97 *store = INT2PTR(void*, SvIV(*svpp));
102 static int getobj(void *hv_t,char *key,char *type,void **store) {
107 mm_log((1,"getobj(hv_t %p, key %s,type %s, store %p)\n",hv_t,key,type,store));
109 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
111 svpp=hv_fetch(hv, key, strlen(key), 0);
113 if (sv_derived_from(*svpp,type)) {
114 IV tmp = SvIV((SV*)SvRV(*svpp));
115 *store = INT2PTR(void*, tmp);
117 mm_log((1,"getobj: key exists in hash but is not of correct type"));
124 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
126 void my_SvREFCNT_dec(void *p) {
128 SvREFCNT_dec((SV*)p);
133 i_log_entry(char *string, int level) {
134 mm_log((level, string));
138 #define CBDATA_BUFSIZE 8192
141 /* the SVs we use to call back to Perl */
147 /* we need to remember whether the buffer contains write data or
153 /* how far we've read into the buffer (not used for writing) */
156 /* the amount of space used/data available in the buffer */
159 /* the maximum amount to fill the buffer before flushing
160 If any write is larger than this then the buffer is flushed and
161 the full write is performed. The write is _not_ split into
166 char buffer[CBDATA_BUFSIZE];
171 call_writer(cbd, buf, size)
173 Low-level function to call the perl writer callback.
177 static ssize_t call_writer(struct cbdata *cbd, void const *buf, size_t size) {
184 if (!SvOK(cbd->writecb))
191 PUSHs(sv_2mortal(newSVpv((char *)buf, size)));
194 count = perl_call_sv(cbd->writecb, G_SCALAR);
198 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
201 success = SvTRUE(sv);
208 return success ? size : -1;
211 static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
219 if (!SvOK(cbd->readcb))
226 PUSHs(sv_2mortal(newSViv(size)));
227 PUSHs(sv_2mortal(newSViv(maxread)));
230 count = perl_call_sv(cbd->readcb, G_SCALAR);
235 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
241 char *ptr = SvPV(data, len);
243 croak("Too much data returned in reader callback");
245 memcpy(buf, ptr, len);
259 static ssize_t write_flush(struct cbdata *cbd) {
264 result = call_writer(cbd, cbd->buffer, cbd->used);
269 return 1; /* success of some sort */
273 static off_t io_seeker(void *p, off_t offset, int whence) {
275 struct cbdata *cbd = p;
280 if (!SvOK(cbd->seekcb))
284 if (cbd->used && write_flush(cbd) <= 0)
288 if (whence == SEEK_CUR && cbd->reading && cbd->where != cbd->used) {
289 offset -= cbd->where - cbd->used;
292 cbd->where = cbd->used = 0;
298 PUSHs(sv_2mortal(newSViv(offset)));
299 PUSHs(sv_2mortal(newSViv(whence)));
302 count = perl_call_sv(cbd->seekcb, G_SCALAR);
307 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
318 static ssize_t io_writer(void *p, void const *data, size_t size) {
320 struct cbdata *cbd = p;
322 /* printf("io_writer(%p, %p, %u)\n", p, data, size); */
324 if (cbd->reading && cbd->where < cbd->used) {
325 /* we read past the place where the caller expected us to be
326 so adjust our position a bit */
327 if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
332 cbd->where = cbd->used = 0;
335 if (cbd->used && cbd->used + size > cbd->maxlength) {
336 int write_res = write_flush(cbd);
337 if (write_res <= 0) {
342 if (cbd->used+size <= cbd->maxlength) {
343 memcpy(cbd->buffer + cbd->used, data, size);
347 /* it doesn't fit - just pass it up */
348 return call_writer(cbd, data, size);
352 io_reader(void *p, void *data, size_t size) {
354 struct cbdata *cbd = p;
356 char *out = data; /* so we can do pointer arithmetic */
358 /* printf("io_reader(%p, %p, %d)\n", p, data, size); */
360 if (write_flush(cbd) <= 0)
366 if (size <= cbd->used - cbd->where) {
368 memcpy(data, cbd->buffer+cbd->where, size);
373 memcpy(out, cbd->buffer + cbd->where, cbd->used - cbd->where);
374 total += cbd->used - cbd->where;
375 size -= cbd->used - cbd->where;
376 out += cbd->used - cbd->where;
377 if (size < sizeof(cbd->buffer)) {
381 && (did_read = call_reader(cbd, cbd->buffer, size,
382 sizeof(cbd->buffer))) > 0) {
384 cbd->used = did_read;
386 copy_size = i_min(size, cbd->used);
387 memcpy(out, cbd->buffer, copy_size);
388 cbd->where += copy_size;
397 /* just read the rest - too big for our buffer*/
399 while ((did_read = call_reader(cbd, out, size, size)) > 0) {
411 static int io_closer(void *p) {
413 struct cbdata *cbd = p;
415 if (cbd->writing && cbd->used > 0) {
416 if (write_flush(cbd) < 0)
421 if (SvOK(cbd->closecb)) {
429 perl_call_sv(cbd->closecb, G_VOID);
440 static void io_destroyer(void *p) {
442 struct cbdata *cbd = p;
444 SvREFCNT_dec(cbd->writecb);
445 SvREFCNT_dec(cbd->readcb);
446 SvREFCNT_dec(cbd->seekcb);
447 SvREFCNT_dec(cbd->closecb);
455 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
458 for (i = 0; i < count; ++i)
459 if (strEQ(names[i].name, name))
460 return names[i].value;
464 static struct value_name transp_names[] =
467 { "threshold", tr_threshold },
468 { "errdiff", tr_errdiff },
469 { "ordered", tr_ordered, },
472 static struct value_name make_color_names[] =
474 { "none", mc_none, },
475 { "webmap", mc_web_map, },
476 { "addi", mc_addi, },
477 { "mediancut", mc_median_cut, },
478 { "mono", mc_mono, },
479 { "monochrome", mc_mono, },
482 static struct value_name translate_names[] =
484 { "giflib", pt_giflib, },
485 { "closest", pt_closest, },
486 { "perturb", pt_perturb, },
487 { "errdiff", pt_errdiff, },
490 static struct value_name errdiff_names[] =
492 { "floyd", ed_floyd, },
493 { "jarvis", ed_jarvis, },
494 { "stucki", ed_stucki, },
495 { "custom", ed_custom, },
498 static struct value_name orddith_names[] =
500 { "random", od_random, },
501 { "dot8", od_dot8, },
502 { "dot4", od_dot4, },
503 { "hline", od_hline, },
504 { "vline", od_vline, },
505 { "/line", od_slashline, },
506 { "slashline", od_slashline, },
507 { "\\line", od_backline, },
508 { "backline", od_backline, },
509 { "tiny", od_tiny, },
510 { "custom", od_custom, },
513 /* look through the hash for quantization options */
515 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
517 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
523 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
525 sv = hv_fetch(hv, "transp", 6, 0);
526 if (sv && *sv && (str = SvPV(*sv, len))) {
528 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
530 if (quant->transp != tr_none) {
531 quant->tr_threshold = 127;
532 sv = hv_fetch(hv, "tr_threshold", 12, 0);
534 quant->tr_threshold = SvIV(*sv);
536 if (quant->transp == tr_errdiff) {
537 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
538 if (sv && *sv && (str = SvPV(*sv, len)))
539 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
541 if (quant->transp == tr_ordered) {
542 quant->tr_orddith = od_tiny;
543 sv = hv_fetch(hv, "tr_orddith", 10, 0);
544 if (sv && *sv && (str = SvPV(*sv, len)))
545 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
547 if (quant->tr_orddith == od_custom) {
548 sv = hv_fetch(hv, "tr_map", 6, 0);
549 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
550 AV *av = (AV*)SvRV(*sv);
551 len = av_len(av) + 1;
552 if (len > sizeof(quant->tr_custom))
553 len = sizeof(quant->tr_custom);
554 for (i = 0; i < len; ++i) {
555 SV **sv2 = av_fetch(av, i, 0);
557 quant->tr_custom[i] = SvIV(*sv2);
560 while (i < sizeof(quant->tr_custom))
561 quant->tr_custom[i++] = 0;
566 quant->make_colors = mc_median_cut;
567 sv = hv_fetch(hv, "make_colors", 11, 0);
568 if (sv && *sv && (str = SvPV(*sv, len))) {
570 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
572 sv = hv_fetch(hv, "colors", 6, 0);
573 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
574 /* needs to be an array of Imager::Color
575 note that the caller allocates the mc_color array and sets mc_size
577 AV *av = (AV *)SvRV(*sv);
578 quant->mc_count = av_len(av)+1;
579 if (quant->mc_count > quant->mc_size)
580 quant->mc_count = quant->mc_size;
581 for (i = 0; i < quant->mc_count; ++i) {
582 SV **sv1 = av_fetch(av, i, 0);
583 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
584 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
585 quant->mc_colors[i] = *col;
589 sv = hv_fetch(hv, "max_colors", 10, 0);
592 if (i <= quant->mc_size && i >= quant->mc_count)
596 quant->translate = pt_closest;
597 sv = hv_fetch(hv, "translate", 9, 0);
598 if (sv && *sv && (str = SvPV(*sv, len))) {
599 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
601 sv = hv_fetch(hv, "errdiff", 7, 0);
602 if (sv && *sv && (str = SvPV(*sv, len))) {
603 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
605 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
606 /* get the error diffusion map */
607 sv = hv_fetch(hv, "errdiff_width", 13, 0);
609 quant->ed_width = SvIV(*sv);
610 sv = hv_fetch(hv, "errdiff_height", 14, 0);
612 quant->ed_height = SvIV(*sv);
613 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
615 quant->ed_orig = SvIV(*sv);
616 if (quant->ed_width > 0 && quant->ed_height > 0) {
618 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
619 sv = hv_fetch(hv, "errdiff_map", 11, 0);
620 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
621 AV *av = (AV*)SvRV(*sv);
622 len = av_len(av) + 1;
623 if (len > quant->ed_width * quant->ed_height)
624 len = quant->ed_width * quant->ed_height;
625 for (i = 0; i < len; ++i) {
626 SV **sv2 = av_fetch(av, i, 0);
628 quant->ed_map[i] = SvIV(*sv2);
629 sum += quant->ed_map[i];
635 myfree(quant->ed_map);
637 quant->errdiff = ed_floyd;
641 sv = hv_fetch(hv, "perturb", 7, 0);
643 quant->perturb = SvIV(*sv);
647 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
648 myfree(quant->mc_colors);
650 myfree(quant->ed_map);
653 /* copies the color map from the hv into the colors member of the HV */
655 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
661 sv = hv_fetch(hv, "colors", 6, 0);
662 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
667 av = (AV *)SvRV(*sv);
669 av_extend(av, quant->mc_count+1);
670 for (i = 0; i < quant->mc_count; ++i) {
671 i_color *in = quant->mc_colors+i;
672 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
673 work = sv_newmortal();
674 sv_setref_pv(work, "Imager::Color", (void *)c);
680 /* loads the segments of a fountain fill into an array */
681 static i_fountain_seg *
682 load_fount_segs(pTHX_ AV *asegs, int *count) {
683 /* Each element of segs must contain:
684 [ start, middle, end, c0, c1, segtype, colortrans ]
685 start, middle, end are doubles from 0 to 1
686 c0, c1 are Imager::Color::Float or Imager::Color objects
687 segtype, colortrans are ints
691 i_fountain_seg *segs;
695 *count = av_len(asegs)+1;
697 croak("i_fountain must have at least one segment");
698 segs = mymalloc(sizeof(i_fountain_seg) * *count);
699 for(i = 0; i < *count; i++) {
700 SV **sv1 = av_fetch(asegs, i, 0);
701 if (!sv1 || !*sv1 || !SvROK(*sv1)
702 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
704 croak("i_fountain: segs must be an arrayref of arrayrefs");
706 aseg = (AV *)SvRV(*sv1);
707 if (av_len(aseg) != 7-1) {
709 croak("i_fountain: a segment must have 7 members");
711 for (j = 0; j < 3; ++j) {
712 SV **sv2 = av_fetch(aseg, j, 0);
715 croak("i_fountain: XS error");
717 work[j] = SvNV(*sv2);
719 segs[i].start = work[0];
720 segs[i].middle = work[1];
721 segs[i].end = work[2];
722 for (j = 0; j < 2; ++j) {
723 SV **sv3 = av_fetch(aseg, 3+j, 0);
724 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
725 (!sv_derived_from(*sv3, "Imager::Color")
726 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
728 croak("i_fountain: segs must contain colors in elements 3 and 4");
730 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
731 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
734 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
736 for (ch = 0; ch < MAXCHANNELS; ++ch) {
737 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
741 for (j = 0; j < 2; ++j) {
742 SV **sv2 = av_fetch(aseg, j+5, 0);
745 croak("i_fountain: XS error");
747 worki[j] = SvIV(*sv2);
749 segs[i].type = worki[0];
750 segs[i].color = worki[1];
756 /* validates the indexes supplied to i_ppal
758 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
763 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
764 int color_count = i_colorcount(im);
767 if (color_count == -1)
768 croak("i_plin() called on direct color image");
770 for (i = 0; i < count; ++i) {
771 if (indexes[i] >= color_count) {
772 croak("i_plin() called with out of range color index %d (max %d)",
773 indexes[i], color_count-1);
779 /* I don't think ICLF_* names belong at the C interface
780 this makes the XS code think we have them, to let us avoid
781 putting function bodies in the XS code
783 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
784 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
787 #define i_log_enabled() 1
789 #define i_log_enabled() 0
792 #if i_int_hlines_testing()
794 typedef i_int_hlines *Imager__Internal__Hlines;
796 static i_int_hlines *
797 i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
798 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
799 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
804 static i_int_hlines *
805 i_int_hlines_new_img(i_img *im) {
806 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
807 i_int_init_hlines_img(result, im);
813 i_int_hlines_DESTROY(i_int_hlines *hlines) {
814 i_int_hlines_destroy(hlines);
818 #define i_int_hlines_CLONE_SKIP(cls) 1
820 static int seg_compare(const void *vleft, const void *vright) {
821 const i_int_hline_seg *left = vleft;
822 const i_int_hline_seg *right = vright;
824 return left->minx - right->minx;
828 i_int_hlines_dump(i_int_hlines *hlines) {
830 SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
831 i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
834 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
835 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
838 /* sort the segments, if any */
840 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
842 sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
843 for (i = 0; i < entry->count; ++i) {
844 sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx),
845 i_DFc(entry->segs[i].x_limit));
847 sv_catpv(dump, "\n");
857 i_sv_off_t(pTHX_ SV *sv) {
858 #if LSEEKSIZE > IVSIZE
859 return (off_t)SvNV(sv);
861 return (off_t)SvIV(sv);
866 i_new_sv_off_t(pTHX_ off_t off) {
867 #if LSEEKSIZE > IVSIZE
874 static im_pl_ext_funcs im_perl_funcs =
876 IMAGER_PL_API_VERSION,
878 ip_handle_quant_opts,
879 ip_cleanup_quant_opts,
883 #define PERL_PL_SET_GLOBAL_CALLBACKS \
884 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
887 #define i_exif_enabled() 1
889 #define i_exif_enabled() 0
892 /* trying to use more C style names, map them here */
893 #define i_io_DESTROY(ig) io_glue_destroy(ig)
895 #define i_img_get_width(im) ((im)->xsize)
896 #define i_img_get_height(im) ((im)->ysize)
898 #define i_img_epsilonf() (DBL_EPSILON * 4)
900 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
903 ICL_new_internal(r,g,b,a)
915 ICL_set_internal(cl,r,g,b,a)
922 ICL_set_internal(cl, r, g, b, a);
936 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
937 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
938 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
939 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
945 RETVAL = mymalloc(sizeof(i_color));
947 i_hsv_to_rgb(RETVAL);
955 RETVAL = mymalloc(sizeof(i_color));
957 i_rgb_to_hsv(RETVAL);
963 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
966 ICLF_new_internal(r, g, b, a)
974 Imager::Color::Float cl
978 Imager::Color::Float cl
982 EXTEND(SP, MAXCHANNELS);
983 for (ch = 0; ch < MAXCHANNELS; ++ch) {
984 /* printf("%d: %g\n", ch, cl->channel[ch]); */
985 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
989 ICLF_set_internal(cl,r,g,b,a)
990 Imager::Color::Float cl
1003 Imager::Color::Float
1005 Imager::Color::Float c
1007 RETVAL = mymalloc(sizeof(i_fcolor));
1009 i_hsv_to_rgbf(RETVAL);
1013 Imager::Color::Float
1015 Imager::Color::Float c
1017 RETVAL = mymalloc(sizeof(i_fcolor));
1019 i_rgb_to_hsvf(RETVAL);
1023 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1037 MODULE = Imager PACKAGE = Imager
1056 SvPV(ST(0), length);
1057 SvREFCNT_inc(ST(0));
1058 RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0));
1063 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1072 cbd = mymalloc(sizeof(struct cbdata));
1073 SvREFCNT_inc(writecb);
1074 cbd->writecb = writecb;
1075 SvREFCNT_inc(readcb);
1076 cbd->readcb = readcb;
1077 SvREFCNT_inc(seekcb);
1078 cbd->seekcb = seekcb;
1079 SvREFCNT_inc(closecb);
1080 cbd->closecb = closecb;
1081 cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
1082 if (maxwrite > CBDATA_BUFSIZE)
1083 maxwrite = CBDATA_BUFSIZE;
1084 cbd->maxlength = maxwrite;
1085 RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
1094 unsigned char* data;
1098 tlength = io_slurp(ig, &data);
1100 PUSHs(sv_2mortal(newSVpv((char *)data,tlength)));
1105 i_set_image_file_limits(width, height, bytes)
1111 i_get_image_file_limits()
1113 i_img_dim width, height;
1116 if (i_get_image_file_limits(&width, &height, &bytes)) {
1118 PUSHs(sv_2mortal(newSViv(width)));
1119 PUSHs(sv_2mortal(newSViv(height)));
1120 PUSHs(sv_2mortal(newSVuv(bytes)));
1123 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1126 i_io_write(ig, data_sv)
1134 if (SvUTF8(data_sv)) {
1135 data_sv = sv_2mortal(newSVsv(data_sv));
1136 /* yes, we want this to croak() if the SV can't be downgraded */
1137 sv_utf8_downgrade(data_sv, FALSE);
1140 data = SvPV(data_sv, size);
1141 RETVAL = i_io_write(ig, data, size);
1146 i_io_read(ig, buffer_sv, size)
1155 croak("size negative in call to i_io_read()");
1156 /* prevent an undefined value warning if they supplied an
1158 Orginally conditional on !SvOK(), but this will prevent the
1159 downgrade from croaking */
1160 sv_setpvn(buffer_sv, "", 0);
1162 if (SvUTF8(buffer_sv))
1163 sv_utf8_downgrade(buffer_sv, FALSE);
1165 buffer = SvGROW(buffer_sv, size+1);
1166 result = i_io_read(ig, buffer, size);
1168 SvCUR_set(buffer_sv, result);
1169 *SvEND(buffer_sv) = '\0';
1170 SvPOK_only(buffer_sv);
1172 PUSHs(sv_2mortal(newSViv(result)));
1178 i_io_read2(ig, size)
1187 croak("size negative in call to i_io_read2()");
1188 buffer_sv = newSV(size);
1189 buffer = SvGROW(buffer_sv, size+1);
1190 result = i_io_read(ig, buffer, size);
1192 SvCUR_set(buffer_sv, result);
1193 *SvEND(buffer_sv) = '\0';
1194 SvPOK_only(buffer_sv);
1196 PUSHs(sv_2mortal(buffer_sv));
1200 SvREFCNT_dec(buffer_sv);
1204 i_io_seek(ig, position, whence)
1218 i_io_CLONE_SKIP(...)
1220 (void)items; /* avoid unused warning for XS variable */
1225 MODULE = Imager PACKAGE = Imager
1236 while( (item=i_format_list[i++]) != NULL ) {
1238 PUSHs(sv_2mortal(newSVpv(item,0)));
1251 i_img_empty_ch(im,x,y,ch)
1258 i_sametype(im, x, y)
1264 i_sametype_chans(im, x, y, channels)
1271 i_init_log(name_sv,level)
1275 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1277 RETVAL = i_init_log(name, level);
1282 i_log_entry(string,level)
1303 i_img_info(im,info);
1305 PUSHs(sv_2mortal(newSViv(info[0])));
1306 PUSHs(sv_2mortal(newSViv(info[1])));
1307 PUSHs(sv_2mortal(newSViv(info[2])));
1308 PUSHs(sv_2mortal(newSViv(info[3])));
1314 i_img_setmask(im,ch_mask)
1323 i_img_getchannels(im)
1332 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1340 i_img_get_height(im)
1345 i_img_is_monochrome(im)
1351 result = i_img_is_monochrome(im, &zero_is_white);
1353 if (GIMME_V == G_ARRAY) {
1356 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1365 i_line(im,x1,y1,x2,y2,val,endp)
1375 i_line_aa(im,x1,y1,x2,y2,val,endp)
1385 i_box(im,x1,y1,x2,y2,val)
1394 i_box_filled(im,x1,y1,x2,y2,val)
1403 i_box_filledf(im,x1,y1,x2,y2,val)
1409 Imager::Color::Float val
1412 i_box_cfill(im,x1,y1,x2,y2,fill)
1418 Imager::FillHandle fill
1421 i_arc(im,x,y,rad,d1,d2,val)
1431 i_arc_aa(im,x,y,rad,d1,d2,val)
1441 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1448 Imager::FillHandle fill
1451 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1458 Imager::FillHandle fill
1462 i_circle_aa(im,x,y,rad,val)
1470 i_circle_out(im,x,y,rad,val)
1478 i_circle_out_aa(im,x,y,rad,val)
1486 i_arc_out(im,x,y,rad,d1,d2,val)
1496 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1507 i_bezier_multi(im,xc,yc,val)
1520 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1521 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1522 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1523 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1524 av1=(AV*)SvRV(ST(1));
1525 av2=(AV*)SvRV(ST(2));
1526 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1528 x=mymalloc( len*sizeof(double) );
1529 y=mymalloc( len*sizeof(double) );
1530 for(i=0;i<len;i++) {
1531 sv1=(*(av_fetch(av1,i,0)));
1532 sv2=(*(av_fetch(av2,i,0)));
1533 x[i]=(double)SvNV(sv1);
1534 y[i]=(double)SvNV(sv2);
1536 i_bezier_multi(im,len,x,y,val);
1542 i_poly_aa(im,xc,yc,val)
1555 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1556 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1557 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1558 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1559 av1=(AV*)SvRV(ST(1));
1560 av2=(AV*)SvRV(ST(2));
1561 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1563 x=mymalloc( len*sizeof(double) );
1564 y=mymalloc( len*sizeof(double) );
1565 for(i=0;i<len;i++) {
1566 sv1=(*(av_fetch(av1,i,0)));
1567 sv2=(*(av_fetch(av2,i,0)));
1568 x[i]=(double)SvNV(sv1);
1569 y[i]=(double)SvNV(sv2);
1571 RETVAL = i_poly_aa(im,len,x,y,val);
1578 i_poly_aa_cfill(im,xc,yc,fill)
1580 Imager::FillHandle fill
1590 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1591 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1592 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1593 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1594 av1=(AV*)SvRV(ST(1));
1595 av2=(AV*)SvRV(ST(2));
1596 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1598 x=mymalloc( len*sizeof(double) );
1599 y=mymalloc( len*sizeof(double) );
1600 for(i=0;i<len;i++) {
1601 sv1=(*(av_fetch(av1,i,0)));
1602 sv2=(*(av_fetch(av2,i,0)));
1603 x[i]=(double)SvNV(sv1);
1604 y[i]=(double)SvNV(sv2);
1606 RETVAL = i_poly_aa_cfill(im,len,x,y,fill);
1615 i_flood_fill(im,seedx,seedy,dcol)
1622 i_flood_cfill(im,seedx,seedy,fill)
1626 Imager::FillHandle fill
1629 i_flood_fill_border(im,seedx,seedy,dcol, border)
1634 Imager::Color border
1637 i_flood_cfill_border(im,seedx,seedy,fill, border)
1641 Imager::FillHandle fill
1642 Imager::Color border
1646 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1658 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1675 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1686 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1699 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)
1715 i_combine(src_av, channels_av = NULL)
1719 i_img **imgs = NULL;
1721 int *channels = NULL;
1726 in_count = av_len(src_av) + 1;
1728 imgs = mymalloc(sizeof(i_img*) * in_count);
1729 channels = mymalloc(sizeof(int) * in_count);
1730 for (i = 0; i < in_count; ++i) {
1731 psv = av_fetch(src_av, i, 0);
1732 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1735 croak("imgs must contain only images");
1737 tmp = SvIV((SV*)SvRV(*psv));
1738 imgs[i] = INT2PTR(i_img*, tmp);
1740 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1742 channels[i] = SvIV(*psv);
1749 RETVAL = i_combine(imgs, channels, in_count);
1756 i_flipxy(im, direction)
1761 i_rotate90(im, degrees)
1766 i_rotate_exact(im, amount, ...)
1770 i_color *backp = NULL;
1771 i_fcolor *fbackp = NULL;
1775 /* extract the bg colors if any */
1776 /* yes, this is kind of strange */
1777 for (i = 2; i < items; ++i) {
1779 if (sv_derived_from(sv1, "Imager::Color")) {
1780 IV tmp = SvIV((SV*)SvRV(sv1));
1781 backp = INT2PTR(i_color *, tmp);
1783 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1784 IV tmp = SvIV((SV*)SvRV(sv1));
1785 fbackp = INT2PTR(i_fcolor *, tmp);
1788 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1793 i_matrix_transform(im, xsize, ysize, matrix, ...)
1803 i_color *backp = NULL;
1804 i_fcolor *fbackp = NULL;
1806 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1807 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1808 av=(AV*)SvRV(ST(3));
1812 for (i = 0; i < len; ++i) {
1813 sv1=(*(av_fetch(av,i,0)));
1814 matrix[i] = SvNV(sv1);
1818 /* extract the bg colors if any */
1819 /* yes, this is kind of strange */
1820 for (i = 4; i < items; ++i) {
1822 if (sv_derived_from(sv1, "Imager::Color")) {
1823 IV tmp = SvIV((SV*)SvRV(sv1));
1824 backp = INT2PTR(i_color *, tmp);
1826 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1827 IV tmp = SvIV((SV*)SvRV(sv1));
1828 fbackp = INT2PTR(i_fcolor *, tmp);
1831 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
1836 i_gaussian(im,stdev)
1841 i_unsharp_mask(im,stdev,scale)
1856 len = av_len(coef) + 1;
1857 c_coef=mymalloc( len * sizeof(double) );
1858 for(i = 0; i < len; i++) {
1859 sv1 = (*(av_fetch(coef, i, 0)));
1860 c_coef[i] = (double)SvNV(sv1);
1862 RETVAL = i_conv(im, c_coef, len);
1868 i_convert(src, avmain)
1880 outchan = av_len(avmain)+1;
1881 /* find the biggest */
1883 for (j=0; j < outchan; ++j) {
1884 temp = av_fetch(avmain, j, 0);
1885 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1886 avsub = (AV*)SvRV(*temp);
1887 len = av_len(avsub)+1;
1892 coeff = mymalloc(sizeof(double) * outchan * inchan);
1893 for (j = 0; j < outchan; ++j) {
1894 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1895 len = av_len(avsub)+1;
1896 for (i = 0; i < len; ++i) {
1897 temp = av_fetch(avsub, i, 0);
1899 coeff[i+j*inchan] = SvNV(*temp);
1901 coeff[i+j*inchan] = 0;
1904 coeff[i++ + j*inchan] = 0;
1906 RETVAL = i_convert(src, coeff, outchan, inchan);
1916 unsigned int mask = 0;
1922 unsigned char (*maps)[256];
1924 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1925 croak("i_map: parameter 2 must be an arrayref\n");
1926 avmain = (AV*)SvRV(ST(1));
1927 len = av_len(avmain)+1;
1928 if (im->channels < len) len = im->channels;
1930 maps = mymalloc( len * sizeof(unsigned char [256]) );
1932 for (j=0; j<len ; j++) {
1933 temp = av_fetch(avmain, j, 0);
1934 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1935 avsub = (AV*)SvRV(*temp);
1936 if(av_len(avsub) != 255) continue;
1938 for (i=0; i<256 ; i++) {
1940 temp = av_fetch(avsub, i, 0);
1941 val = temp ? SvIV(*temp) : 0;
1943 if (val>255) val = 255;
1948 i_map(im, maps, mask);
1959 i_img_diffd(im1,im2)
1964 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
1974 _is_color_object(sv)
1978 RETVAL = SvOK(sv) && SvROK(sv) &&
1979 (sv_derived_from(sv, "Imager::Color")
1980 || sv_derived_from(sv, "Imager::Color::Float"));
1992 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
1994 #define TT_DESTROY(handle) i_tt_destroy(handle)
1998 Imager::Font::TT handle
2003 (void)items; /* avoid unused warning */
2009 MODULE = Imager PACKAGE = Imager
2013 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
2014 Imager::Font::TT handle
2032 str = SvPV(str_sv, len);
2033 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2034 len, smooth, utf8, align);
2040 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
2041 Imager::Font::TT handle
2059 str = SvPV(str_sv, len);
2060 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2061 smooth, utf8, align);
2067 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
2068 Imager::Font::TT handle
2073 i_img_dim cords[BOUNDING_BOX_COUNT];
2083 str = SvPV(str_sv, len);
2084 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2086 for (i = 0; i < rc; ++i) {
2087 PUSHs(sv_2mortal(newSViv(cords[i])));
2092 i_tt_has_chars(handle, text_sv, utf8)
2093 Imager::Font::TT handle
2104 if (SvUTF8(text_sv))
2107 text = SvPV(text_sv, len);
2108 work = mymalloc(len);
2109 count = i_tt_has_chars(handle, text, len, utf8, work);
2110 if (GIMME_V == G_ARRAY) {
2112 for (i = 0; i < count; ++i) {
2113 PUSHs(sv_2mortal(newSViv(work[i])));
2118 PUSHs(sv_2mortal(newSVpv(work, count)));
2123 i_tt_dump_names(handle)
2124 Imager::Font::TT handle
2127 i_tt_face_name(handle)
2128 Imager::Font::TT handle
2133 len = i_tt_face_name(handle, name, sizeof(name));
2136 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2140 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2141 Imager::Font::TT handle
2152 if (SvUTF8(text_sv))
2155 text = SvPV(text_sv, work_len);
2160 ch = i_utf8_advance(&text, &len);
2162 i_push_error(0, "invalid UTF8 character");
2171 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2172 PUSHs(sv_2mortal(newSVpv(name, 0)));
2175 PUSHs(&PL_sv_undef);
2182 i_test_format_probe(ig, length)
2187 i_readpnm_wiol(ig, allow_incomplete)
2189 int allow_incomplete
2193 i_readpnm_multi_wiol(ig, allow_incomplete)
2195 int allow_incomplete
2201 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2204 for (i = 0; i < count; ++i) {
2205 SV *sv = sv_newmortal();
2206 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2213 i_writeppm_wiol(im, ig)
2222 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2231 i_writeraw_wiol(im,ig)
2236 i_writebmp_wiol(im,ig)
2241 i_readbmp_wiol(ig, allow_incomplete=0)
2243 int allow_incomplete
2247 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2256 idlen = SvCUR(ST(4));
2257 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2263 i_readtga_wiol(ig, length)
2271 i_scaleaxis(im,Value,Axis)
2277 i_scale_nn(im,scx,scy)
2283 i_scale_mixing(im, width, height)
2293 i_count_colors(im,maxc)
2298 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2303 unsigned int * col_usage = NULL;
2306 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2307 EXTEND(SP, col_cnt);
2308 for (i = 0; i < col_cnt; i++) {
2309 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2316 i_transform(im,opx,opy,parm)
2329 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2330 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2331 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2332 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2333 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2334 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2335 av=(AV*)SvRV(ST(1));
2337 opx=mymalloc( opxl*sizeof(int) );
2338 for(i=0;i<opxl;i++) {
2339 sv1=(*(av_fetch(av,i,0)));
2340 opx[i]=(int)SvIV(sv1);
2342 av=(AV*)SvRV(ST(2));
2344 opy=mymalloc( opyl*sizeof(int) );
2345 for(i=0;i<opyl;i++) {
2346 sv1=(*(av_fetch(av,i,0)));
2347 opy[i]=(int)SvIV(sv1);
2349 av=(AV*)SvRV(ST(3));
2350 parmlen=av_len(av)+1;
2351 parm=mymalloc( parmlen*sizeof(double) );
2352 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2353 sv1=(*(av_fetch(av,i,0)));
2354 parm[i]=(double)SvNV(sv1);
2356 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2360 ST(0) = sv_newmortal();
2361 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2362 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2365 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2390 in_imgs_count = av_len(av_in_imgs)+1;
2391 for (i = 0; i < in_imgs_count; ++i) {
2392 sv1 = *av_fetch(av_in_imgs, i, 0);
2393 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2394 croak("sv_in_img must contain only images");
2397 if (in_imgs_count > 0) {
2398 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2399 for (i = 0; i < in_imgs_count; ++i) {
2400 sv1 = *av_fetch(av_in_imgs,i,0);
2401 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2402 croak("Parameter 5 must contain only images");
2404 tmp = SvIV((SV*)SvRV(sv1));
2405 in_imgs[i] = INT2PTR(i_img*, tmp);
2409 /* no input images */
2412 /* default the output size from the first input if possible */
2414 width = SvIV(sv_width);
2415 else if (in_imgs_count)
2416 width = in_imgs[0]->xsize;
2418 croak("No output image width supplied");
2420 if (SvOK(sv_height))
2421 height = SvIV(sv_height);
2422 else if (in_imgs_count)
2423 height = in_imgs[0]->ysize;
2425 croak("No output image height supplied");
2427 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2428 if (ops_len % sizeof(struct rm_op))
2429 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2430 ops_count = ops_len / sizeof(struct rm_op);
2432 n_regs_count = av_len(av_n_regs)+1;
2433 n_regs = mymalloc(n_regs_count * sizeof(double));
2434 for (i = 0; i < n_regs_count; ++i) {
2435 sv1 = *av_fetch(av_n_regs,i,0);
2437 n_regs[i] = SvNV(sv1);
2439 c_regs_count = av_len(av_c_regs)+1;
2440 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2441 /* I don't bother initializing the colou?r registers */
2443 RETVAL=i_transform2(width, height, channels, ops, ops_count,
2444 n_regs, n_regs_count,
2445 c_regs, c_regs_count, in_imgs, in_imgs_count);
2450 ST(0) = sv_newmortal();
2451 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2452 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2456 i_contrast(im,intensity)
2469 i_noise(im,amount,type)
2475 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2485 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2504 i_postlevels(im,levels)
2514 i_watermark(im,wmark,tx,ty,pixdiff)
2516 Imager::ImgRaw wmark
2523 i_autolevels(im,lsat,usat,skew)
2530 i_radnoise(im,xo,yo,rscale,ascale)
2538 i_turbnoise(im, xo, yo, scale)
2561 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2562 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2563 croak("i_gradgen: Second argument must be an array ref");
2564 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2565 croak("i_gradgen: Third argument must be an array ref");
2566 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2567 croak("i_gradgen: Fourth argument must be an array ref");
2568 axx = (AV *)SvRV(ST(1));
2569 ayy = (AV *)SvRV(ST(2));
2570 ac = (AV *)SvRV(ST(3));
2571 dmeasure = (int)SvIV(ST(4));
2573 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2574 num = num <= av_len(ac) ? num : av_len(ac);
2576 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2577 xo = mymalloc( sizeof(i_img_dim) * num );
2578 yo = mymalloc( sizeof(i_img_dim) * num );
2579 ival = mymalloc( sizeof(i_color) * num );
2580 for(i = 0; i<num; i++) {
2581 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2582 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2583 sv = *av_fetch(ac, i, 0);
2584 if ( !sv_derived_from(sv, "Imager::Color") ) {
2585 free(axx); free(ayy); free(ac);
2586 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2588 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2590 i_gradgen(im, num, xo, yo, ival, dmeasure);
2596 i_diff_image(im, im2, mindist=0)
2602 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2612 double ssample_param
2616 i_fountain_seg *segs;
2618 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2619 croak("i_fountain: argument 11 must be an array ref");
2621 asegs = (AV *)SvRV(ST(10));
2622 segs = load_fount_segs(aTHX_ asegs, &count);
2623 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2624 super_sample, ssample_param, count, segs);
2630 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2639 double ssample_param
2643 i_fountain_seg *segs;
2645 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2646 croak("i_fountain: argument 11 must be an array ref");
2648 asegs = (AV *)SvRV(ST(9));
2649 segs = load_fount_segs(aTHX_ asegs, &count);
2650 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2651 super_sample, ssample_param, count, segs);
2657 i_new_fill_opacity(other_fill, alpha_mult)
2658 Imager::FillHandle other_fill
2669 errors = i_errors();
2671 while (errors[i].msg) {
2673 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2674 if (!av_store(av, 0, sv)) {
2677 sv = newSViv(errors[i].code);
2678 if (!av_store(av, 1, sv)) {
2681 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2689 i_push_error(code, msg)
2694 i_nearest_color(im, ...)
2709 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2710 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2711 croak("i_nearest_color: Second argument must be an array ref");
2712 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2713 croak("i_nearest_color: Third argument must be an array ref");
2714 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2715 croak("i_nearest_color: Fourth argument must be an array ref");
2716 axx = (AV *)SvRV(ST(1));
2717 ayy = (AV *)SvRV(ST(2));
2718 ac = (AV *)SvRV(ST(3));
2719 dmeasure = (int)SvIV(ST(4));
2721 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2722 num = num <= av_len(ac) ? num : av_len(ac);
2724 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2725 xo = mymalloc( sizeof(i_img_dim) * num );
2726 yo = mymalloc( sizeof(i_img_dim) * num );
2727 ival = mymalloc( sizeof(i_color) * num );
2728 for(i = 0; i<num; i++) {
2729 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2730 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2731 sv = *av_fetch(ac, i, 0);
2732 if ( !sv_derived_from(sv, "Imager::Color") ) {
2733 free(axx); free(ayy); free(ac);
2734 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2736 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2738 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2752 rc=DSO_open(filename,&evstr);
2756 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2757 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2760 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2766 DSO_close(dso_handle)
2770 DSO_funclist(dso_handle_v)
2774 DSO_handle *dso_handle;
2775 func_ptr *functions;
2777 dso_handle=(DSO_handle*)dso_handle_v;
2778 functions = DSO_funclist(dso_handle);
2780 while( functions[i].name != NULL) {
2782 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2784 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2788 DSO_call(handle,func_index,hv)
2794 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
2795 hv=(HV*)SvRV(ST(2));
2796 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2797 DSO_call( (DSO_handle *)handle,func_index,hv);
2800 i_get_pixel(im, x, y)
2807 color = (i_color *)mymalloc(sizeof(i_color));
2808 if (i_gpix(im, x, y, color) == 0) {
2809 RETVAL = NEWSV(0, 0);
2810 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
2814 RETVAL = &PL_sv_undef;
2821 i_ppix(im, x, y, cl)
2828 i_img_pal_new(x, y, channels, maxpal)
2835 i_img_to_pal(src, quant)
2841 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2842 croak("i_img_to_pal: second argument must be a hash ref");
2843 hv = (HV *)SvRV(ST(1));
2844 memset(&quant, 0, sizeof(quant));
2846 quant.mc_size = 256;
2847 ip_handle_quant_opts(aTHX_ &quant, hv);
2848 RETVAL = i_img_to_pal(src, &quant);
2850 ip_copy_colors_back(aTHX_ hv, &quant);
2852 ip_cleanup_quant_opts(aTHX_ &quant);
2871 work = mymalloc((r-l) * sizeof(i_palidx));
2872 count = i_gpal(im, l, r, y, work);
2873 if (GIMME_V == G_ARRAY) {
2875 for (i = 0; i < count; ++i) {
2876 PUSHs(sv_2mortal(newSViv(work[i])));
2881 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
2886 if (GIMME_V != G_ARRAY) {
2888 PUSHs(&PL_sv_undef);
2893 i_ppal(im, l, y, ...)
2902 work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
2903 for (i=0; i < items-3; ++i) {
2904 work[i] = SvIV(ST(i+3));
2906 validate_i_ppal(im, work, items - 3);
2907 RETVAL = i_ppal(im, l, l+items-3, y, work);
2916 i_ppal_p(im, l, y, data)
2922 i_palidx const *work;
2925 work = (i_palidx const *)SvPV(data, len);
2926 len /= sizeof(i_palidx);
2928 validate_i_ppal(im, work, len);
2929 RETVAL = i_ppal(im, l, l+len, y, work);
2938 i_addcolors(im, ...)
2946 croak("i_addcolors: no colors to add");
2947 colors = mymalloc((items-1) * sizeof(i_color));
2948 for (i=0; i < items-1; ++i) {
2949 if (sv_isobject(ST(i+1))
2950 && sv_derived_from(ST(i+1), "Imager::Color")) {
2951 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
2952 colors[i] = *INT2PTR(i_color *, tmp);
2956 croak("i_addcolor: pixels must be Imager::Color objects");
2959 index = i_addcolors(im, colors, items-1);
2962 RETVAL = newSVpv("0 but true", 0);
2964 else if (index == -1) {
2965 RETVAL = &PL_sv_undef;
2968 RETVAL = newSViv(index);
2974 i_setcolors(im, index, ...)
2982 croak("i_setcolors: no colors to add");
2983 colors = mymalloc((items-2) * sizeof(i_color));
2984 for (i=0; i < items-2; ++i) {
2985 if (sv_isobject(ST(i+2))
2986 && sv_derived_from(ST(i+2), "Imager::Color")) {
2987 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
2988 colors[i] = *INT2PTR(i_color *, tmp);
2992 croak("i_setcolors: pixels must be Imager::Color objects");
2995 RETVAL = i_setcolors(im, index, colors, items-2);
3001 i_getcolors(im, index, ...)
3010 croak("i_getcolors: too many arguments");
3012 count = SvIV(ST(2));
3014 croak("i_getcolors: count must be positive");
3015 colors = mymalloc(sizeof(i_color) * count);
3016 if (i_getcolors(im, index, colors, count)) {
3017 for (i = 0; i < count; ++i) {
3019 SV *sv = sv_newmortal();
3020 pv = mymalloc(sizeof(i_color));
3022 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3038 i_findcolor(im, color)
3044 if (i_findcolor(im, color, &index)) {
3045 RETVAL = newSViv(index);
3048 RETVAL = &PL_sv_undef;
3066 i_gsamp(im, l, r, y, ...)
3078 croak("No channel numbers supplied to g_samp()");
3080 chan_count = items - 4;
3081 chans = mymalloc(sizeof(int) * chan_count);
3082 for (i = 0; i < chan_count; ++i)
3083 chans[i] = SvIV(ST(i+4));
3084 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
3085 count = i_gsamp(im, l, r, y, data, chans, chan_count);
3087 if (GIMME_V == G_ARRAY) {
3089 for (i = 0; i < count; ++i)
3090 PUSHs(sv_2mortal(newSViv(data[i])));
3094 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3099 if (GIMME_V != G_ARRAY) {
3101 PUSHs(&PL_sv_undef);
3106 i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3122 croak("No channel numbers supplied to g_samp()");
3124 chan_count = items - 7;
3125 chans = mymalloc(sizeof(int) * chan_count);
3126 for (i = 0; i < chan_count; ++i)
3127 chans[i] = SvIV(ST(i+7));
3128 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3129 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3131 for (i = 0; i < count; ++i) {
3132 av_store(target, i+offset, newSVuv(data[i]));
3144 i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3162 if (SvOK(channels_sv)) {
3164 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3165 croak("channels is not an array ref");
3167 channels_av = (AV *)SvRV(channels_sv);
3168 chan_count = av_len(channels_av) + 1;
3169 if (chan_count < 1) {
3170 croak("i_psamp_bits: no channels provided");
3172 channels = mymalloc(sizeof(int) * chan_count);
3173 for (i = 0; i < chan_count; ++i)
3174 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3177 chan_count = im->channels;
3181 data_count = av_len(data_av) + 1;
3182 if (data_offset < 0) {
3183 croak("data_offset must by non-negative");
3185 if (data_offset > data_count) {
3186 croak("data_offset greater than number of samples supplied");
3188 if (pixel_count == -1 ||
3189 data_offset + pixel_count * chan_count > data_count) {
3190 pixel_count = (data_count - data_offset) / chan_count;
3193 data_used = pixel_count * chan_count;
3194 data = mymalloc(sizeof(unsigned) * data_count);
3195 for (i = 0; i < data_used; ++i)
3196 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3198 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3209 i_img_masked_new(targ, mask, x, y, w, h)
3219 if (!sv_isobject(ST(1))
3220 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3221 croak("i_img_masked_new: parameter 2 must undef or an image");
3223 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3227 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3232 i_plin(im, l, y, ...)
3243 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3244 /* supplied as a byte string */
3245 work = (i_color *)SvPV(ST(3), len);
3246 count = len / sizeof(i_color);
3247 if (count * sizeof(i_color) != len) {
3248 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3250 RETVAL = i_plin(im, l, l+count, y, work);
3253 work = mymalloc(sizeof(i_color) * (items-3));
3254 for (i=0; i < items-3; ++i) {
3255 if (sv_isobject(ST(i+3))
3256 && sv_derived_from(ST(i+3), "Imager::Color")) {
3257 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3258 work[i] = *INT2PTR(i_color *, tmp);
3262 croak("i_plin: pixels must be Imager::Color objects");
3265 RETVAL = i_plin(im, l, l+items-3, y, work);
3276 i_ppixf(im, x, y, cl)
3280 Imager::Color::Float cl
3283 i_gsampf(im, l, r, y, ...)
3295 croak("No channel numbers supplied to g_sampf()");
3297 chan_count = items - 4;
3298 chans = mymalloc(sizeof(int) * chan_count);
3299 for (i = 0; i < chan_count; ++i)
3300 chans[i] = SvIV(ST(i+4));
3301 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3302 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3304 if (GIMME_V == G_ARRAY) {
3306 for (i = 0; i < count; ++i)
3307 PUSHs(sv_2mortal(newSVnv(data[i])));
3311 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3316 if (GIMME_V != G_ARRAY) {
3318 PUSHs(&PL_sv_undef);
3323 i_plinf(im, l, y, ...)
3334 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3335 /* supplied as a byte string */
3336 work = (i_fcolor *)SvPV(ST(3), len);
3337 count = len / sizeof(i_fcolor);
3338 if (count * sizeof(i_fcolor) != len) {
3339 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3341 RETVAL = i_plinf(im, l, l+count, y, work);
3344 work = mymalloc(sizeof(i_fcolor) * (items-3));
3345 for (i=0; i < items-3; ++i) {
3346 if (sv_isobject(ST(i+3))
3347 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3348 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3349 work[i] = *INT2PTR(i_fcolor *, tmp);
3353 croak("i_plinf: pixels must be Imager::Color::Float objects");
3357 RETVAL = i_plinf(im, l, l+items-3, y, work);
3375 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3376 if (i_gpixf(im, x, y, color) == 0) {
3377 RETVAL = NEWSV(0,0);
3378 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
3382 RETVAL = &PL_sv_undef;
3398 vals = mymalloc((r-l) * sizeof(i_color));
3399 memset(vals, 0, (r-l) * sizeof(i_color));
3400 count = i_glin(im, l, r, y, vals);
3401 if (GIMME_V == G_ARRAY) {
3403 for (i = 0; i < count; ++i) {
3405 i_color *col = mymalloc(sizeof(i_color));
3407 sv = sv_newmortal();
3408 sv_setref_pv(sv, "Imager::Color", (void *)col);
3414 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3420 i_glinf(im, l, r, y)
3430 for (i = 0; i < MAXCHANNELS; ++i)
3431 zero.channel[i] = 0;
3433 vals = mymalloc((r-l) * sizeof(i_fcolor));
3434 for (i = 0; i < r-l; ++i)
3436 count = i_glinf(im, l, r, y, vals);
3437 if (GIMME_V == G_ARRAY) {
3439 for (i = 0; i < count; ++i) {
3441 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3443 sv = sv_newmortal();
3444 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3450 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3456 i_img_16_new(x, y, ch)
3466 i_img_double_new(x, y, ch)
3476 i_tags_addn(im, name, code, idata)
3485 name = SvPV(ST(1), len);
3488 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3493 i_tags_add(im, name, code, data, idata)
3503 name = SvPV(ST(1), len);
3507 data = SvPV(ST(3), len);
3512 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3517 i_tags_find(im, name, start)
3524 if (i_tags_find(&im->tags, name, start, &entry)) {
3526 RETVAL = newSVpv("0 but true", 0);
3528 RETVAL = newSViv(entry);
3530 RETVAL = &PL_sv_undef;
3536 i_tags_findn(im, code, start)
3543 if (i_tags_findn(&im->tags, code, start, &entry)) {
3545 RETVAL = newSVpv("0 but true", 0);
3547 RETVAL = newSViv(entry);
3550 RETVAL = &PL_sv_undef;
3556 i_tags_delete(im, entry)
3560 RETVAL = i_tags_delete(&im->tags, entry);
3565 i_tags_delbyname(im, name)
3569 RETVAL = i_tags_delbyname(&im->tags, name);
3574 i_tags_delbycode(im, code)
3578 RETVAL = i_tags_delbycode(&im->tags, code);
3583 i_tags_get(im, index)
3587 if (index >= 0 && index < im->tags.count) {
3588 i_img_tag *entry = im->tags.tags + index;
3592 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3595 PUSHs(sv_2mortal(newSViv(entry->code)));
3598 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3601 PUSHs(sv_2mortal(newSViv(entry->idata)));
3606 i_tags_get_string(im, what_sv)
3610 char const *name = NULL;
3614 if (SvIOK(what_sv)) {
3615 code = SvIV(what_sv);
3619 name = SvPV_nolen(what_sv);
3622 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3624 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3631 RETVAL = im->tags.count;
3637 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3641 Imager::FillHandle fill
3644 IFILL_CLONE_SKIP(...)
3646 (void)items; /* avoid unused warning for XS variable */
3651 MODULE = Imager PACKAGE = Imager
3654 i_new_fill_solid(cl, combine)
3659 i_new_fill_solidf(cl, combine)
3660 Imager::Color::Float cl
3664 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3672 unsigned char *cust_hatch;
3676 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3680 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3685 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3686 Imager::Color::Float fg
3687 Imager::Color::Float bg
3693 unsigned char *cust_hatch;
3697 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3701 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3706 i_new_fill_image(src, matrix, xoff, yoff, combine)
3723 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3724 croak("i_new_fill_image: parameter must be an arrayref");
3725 av=(AV*)SvRV(ST(1));
3729 for (i = 0; i < len; ++i) {
3730 sv1=(*(av_fetch(av,i,0)));
3731 matrix[i] = SvNV(sv1);
3737 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3741 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3743 # this class is only exposed for testing
3746 i_int_hlines_testing()
3748 #if i_int_hlines_testing()
3750 Imager::Internal::Hlines
3751 i_int_hlines_new(start_y, count_y, start_x, count_x)
3757 Imager::Internal::Hlines
3758 i_int_hlines_new_img(im)
3762 i_int_hlines_add(hlines, y, minx, width)
3763 Imager::Internal::Hlines hlines
3769 i_int_hlines_DESTROY(hlines)
3770 Imager::Internal::Hlines hlines
3773 i_int_hlines_dump(hlines)
3774 Imager::Internal::Hlines hlines
3777 i_int_hlines_CLONE_SKIP(cls)
3782 PERL_SET_GLOBAL_CALLBACKS;
3783 PERL_PL_SET_GLOBAL_CALLBACKS;