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()
31 /* These functions are all shared - then comes platform dependant code */
32 static int getstr(void *hv_t,char *key,char **store) {
37 mm_log((1,"getstr(hv_t %p, key %s, store %p)\n",hv_t,key,store));
39 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
41 svpp=hv_fetch(hv, key, strlen(key), 0);
42 *store=SvPV(*svpp, PL_na );
47 static int getint(void *hv_t,char *key,int *store) {
52 mm_log((1,"getint(hv_t %p, key %s, store %p)\n",hv_t,key,store));
54 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
56 svpp=hv_fetch(hv, key, strlen(key), 0);
57 *store=(int)SvIV(*svpp);
61 static int getdouble(void *hv_t,char* key,double *store) {
66 mm_log((1,"getdouble(hv_t %p, key %s, store %p)\n",hv_t,key,store));
68 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
69 svpp=hv_fetch(hv, key, strlen(key), 0);
70 *store=(double)SvNV(*svpp);
74 static int getvoid(void *hv_t,char* key,void **store) {
79 mm_log((1,"getvoid(hv_t %p, key %s, store %p)\n",hv_t,key,store));
81 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
83 svpp=hv_fetch(hv, key, strlen(key), 0);
84 *store = INT2PTR(void*, SvIV(*svpp));
89 static int getobj(void *hv_t,char *key,char *type,void **store) {
94 mm_log((1,"getobj(hv_t %p, key %s,type %s, store %p)\n",hv_t,key,type,store));
96 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
98 svpp=hv_fetch(hv, key, strlen(key), 0);
100 if (sv_derived_from(*svpp,type)) {
101 IV tmp = SvIV((SV*)SvRV(*svpp));
102 *store = INT2PTR(void*, tmp);
104 mm_log((1,"getobj: key exists in hash but is not of correct type"));
111 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
113 void my_SvREFCNT_dec(void *p) {
115 SvREFCNT_dec((SV*)p);
120 i_log_entry(char *string, int level) {
121 mm_log((level, string));
125 #define CBDATA_BUFSIZE 8192
128 /* the SVs we use to call back to Perl */
134 /* we need to remember whether the buffer contains write data or
140 /* how far we've read into the buffer (not used for writing) */
143 /* the amount of space used/data available in the buffer */
146 /* the maximum amount to fill the buffer before flushing
147 If any write is larger than this then the buffer is flushed and
148 the full write is performed. The write is _not_ split into
153 char buffer[CBDATA_BUFSIZE];
158 call_writer(cbd, buf, size)
160 Low-level function to call the perl writer callback.
164 static ssize_t call_writer(struct cbdata *cbd, void const *buf, size_t size) {
171 if (!SvOK(cbd->writecb))
178 PUSHs(sv_2mortal(newSVpv((char *)buf, size)));
181 count = perl_call_sv(cbd->writecb, G_SCALAR);
185 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
188 success = SvTRUE(sv);
195 return success ? size : -1;
198 static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
206 if (!SvOK(cbd->readcb))
213 PUSHs(sv_2mortal(newSViv(size)));
214 PUSHs(sv_2mortal(newSViv(maxread)));
217 count = perl_call_sv(cbd->readcb, G_SCALAR);
222 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
228 char *ptr = SvPV(data, len);
230 croak("Too much data returned in reader callback");
232 memcpy(buf, ptr, len);
246 static ssize_t write_flush(struct cbdata *cbd) {
251 result = call_writer(cbd, cbd->buffer, cbd->used);
256 return 1; /* success of some sort */
260 static off_t io_seeker(void *p, off_t offset, int whence) {
262 struct cbdata *cbd = p;
267 if (!SvOK(cbd->seekcb))
271 if (cbd->used && write_flush(cbd) <= 0)
275 if (whence == SEEK_CUR && cbd->reading && cbd->where != cbd->used) {
276 offset -= cbd->where - cbd->used;
279 cbd->where = cbd->used = 0;
285 PUSHs(sv_2mortal(newSViv(offset)));
286 PUSHs(sv_2mortal(newSViv(whence)));
289 count = perl_call_sv(cbd->seekcb, G_SCALAR);
294 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
305 static ssize_t io_writer(void *p, void const *data, size_t size) {
307 struct cbdata *cbd = p;
309 /* printf("io_writer(%p, %p, %u)\n", p, data, size); */
311 if (cbd->reading && cbd->where < cbd->used) {
312 /* we read past the place where the caller expected us to be
313 so adjust our position a bit */
314 if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
319 cbd->where = cbd->used = 0;
322 if (cbd->used && cbd->used + size > cbd->maxlength) {
323 int write_res = write_flush(cbd);
324 if (write_res <= 0) {
329 if (cbd->used+size <= cbd->maxlength) {
330 memcpy(cbd->buffer + cbd->used, data, size);
334 /* it doesn't fit - just pass it up */
335 return call_writer(cbd, data, size);
339 io_reader(void *p, void *data, size_t size) {
341 struct cbdata *cbd = p;
343 char *out = data; /* so we can do pointer arithmetic */
345 /* printf("io_reader(%p, %p, %d)\n", p, data, size); */
347 if (write_flush(cbd) <= 0)
353 if (size <= cbd->used - cbd->where) {
355 memcpy(data, cbd->buffer+cbd->where, size);
360 memcpy(out, cbd->buffer + cbd->where, cbd->used - cbd->where);
361 total += cbd->used - cbd->where;
362 size -= cbd->used - cbd->where;
363 out += cbd->used - cbd->where;
364 if (size < sizeof(cbd->buffer)) {
368 && (did_read = call_reader(cbd, cbd->buffer, size,
369 sizeof(cbd->buffer))) > 0) {
371 cbd->used = did_read;
373 copy_size = i_min(size, cbd->used);
374 memcpy(out, cbd->buffer, copy_size);
375 cbd->where += copy_size;
384 /* just read the rest - too big for our buffer*/
386 while ((did_read = call_reader(cbd, out, size, size)) > 0) {
398 static int io_closer(void *p) {
400 struct cbdata *cbd = p;
402 if (cbd->writing && cbd->used > 0) {
403 if (write_flush(cbd) < 0)
408 if (SvOK(cbd->closecb)) {
416 perl_call_sv(cbd->closecb, G_VOID);
427 static void io_destroyer(void *p) {
429 struct cbdata *cbd = p;
431 SvREFCNT_dec(cbd->writecb);
432 SvREFCNT_dec(cbd->readcb);
433 SvREFCNT_dec(cbd->seekcb);
434 SvREFCNT_dec(cbd->closecb);
442 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
445 for (i = 0; i < count; ++i)
446 if (strEQ(names[i].name, name))
447 return names[i].value;
451 static struct value_name transp_names[] =
454 { "threshold", tr_threshold },
455 { "errdiff", tr_errdiff },
456 { "ordered", tr_ordered, },
459 static struct value_name make_color_names[] =
461 { "none", mc_none, },
462 { "webmap", mc_web_map, },
463 { "addi", mc_addi, },
464 { "mediancut", mc_median_cut, },
465 { "mono", mc_mono, },
466 { "monochrome", mc_mono, },
469 static struct value_name translate_names[] =
471 { "giflib", pt_giflib, },
472 { "closest", pt_closest, },
473 { "perturb", pt_perturb, },
474 { "errdiff", pt_errdiff, },
477 static struct value_name errdiff_names[] =
479 { "floyd", ed_floyd, },
480 { "jarvis", ed_jarvis, },
481 { "stucki", ed_stucki, },
482 { "custom", ed_custom, },
485 static struct value_name orddith_names[] =
487 { "random", od_random, },
488 { "dot8", od_dot8, },
489 { "dot4", od_dot4, },
490 { "hline", od_hline, },
491 { "vline", od_vline, },
492 { "/line", od_slashline, },
493 { "slashline", od_slashline, },
494 { "\\line", od_backline, },
495 { "backline", od_backline, },
496 { "tiny", od_tiny, },
497 { "custom", od_custom, },
500 /* look through the hash for quantization options */
502 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
504 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
510 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
512 sv = hv_fetch(hv, "transp", 6, 0);
513 if (sv && *sv && (str = SvPV(*sv, len))) {
515 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
517 if (quant->transp != tr_none) {
518 quant->tr_threshold = 127;
519 sv = hv_fetch(hv, "tr_threshold", 12, 0);
521 quant->tr_threshold = SvIV(*sv);
523 if (quant->transp == tr_errdiff) {
524 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
525 if (sv && *sv && (str = SvPV(*sv, len)))
526 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
528 if (quant->transp == tr_ordered) {
529 quant->tr_orddith = od_tiny;
530 sv = hv_fetch(hv, "tr_orddith", 10, 0);
531 if (sv && *sv && (str = SvPV(*sv, len)))
532 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
534 if (quant->tr_orddith == od_custom) {
535 sv = hv_fetch(hv, "tr_map", 6, 0);
536 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
537 AV *av = (AV*)SvRV(*sv);
538 len = av_len(av) + 1;
539 if (len > sizeof(quant->tr_custom))
540 len = sizeof(quant->tr_custom);
541 for (i = 0; i < len; ++i) {
542 SV **sv2 = av_fetch(av, i, 0);
544 quant->tr_custom[i] = SvIV(*sv2);
547 while (i < sizeof(quant->tr_custom))
548 quant->tr_custom[i++] = 0;
553 quant->make_colors = mc_median_cut;
554 sv = hv_fetch(hv, "make_colors", 11, 0);
555 if (sv && *sv && (str = SvPV(*sv, len))) {
557 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
559 sv = hv_fetch(hv, "colors", 6, 0);
560 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
561 /* needs to be an array of Imager::Color
562 note that the caller allocates the mc_color array and sets mc_size
564 AV *av = (AV *)SvRV(*sv);
565 quant->mc_count = av_len(av)+1;
566 if (quant->mc_count > quant->mc_size)
567 quant->mc_count = quant->mc_size;
568 for (i = 0; i < quant->mc_count; ++i) {
569 SV **sv1 = av_fetch(av, i, 0);
570 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
571 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
572 quant->mc_colors[i] = *col;
576 sv = hv_fetch(hv, "max_colors", 10, 0);
579 if (i <= quant->mc_size && i >= quant->mc_count)
583 quant->translate = pt_closest;
584 sv = hv_fetch(hv, "translate", 9, 0);
585 if (sv && *sv && (str = SvPV(*sv, len))) {
586 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
588 sv = hv_fetch(hv, "errdiff", 7, 0);
589 if (sv && *sv && (str = SvPV(*sv, len))) {
590 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
592 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
593 /* get the error diffusion map */
594 sv = hv_fetch(hv, "errdiff_width", 13, 0);
596 quant->ed_width = SvIV(*sv);
597 sv = hv_fetch(hv, "errdiff_height", 14, 0);
599 quant->ed_height = SvIV(*sv);
600 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
602 quant->ed_orig = SvIV(*sv);
603 if (quant->ed_width > 0 && quant->ed_height > 0) {
605 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
606 sv = hv_fetch(hv, "errdiff_map", 11, 0);
607 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
608 AV *av = (AV*)SvRV(*sv);
609 len = av_len(av) + 1;
610 if (len > quant->ed_width * quant->ed_height)
611 len = quant->ed_width * quant->ed_height;
612 for (i = 0; i < len; ++i) {
613 SV **sv2 = av_fetch(av, i, 0);
615 quant->ed_map[i] = SvIV(*sv2);
616 sum += quant->ed_map[i];
622 myfree(quant->ed_map);
624 quant->errdiff = ed_floyd;
628 sv = hv_fetch(hv, "perturb", 7, 0);
630 quant->perturb = SvIV(*sv);
634 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
635 myfree(quant->mc_colors);
637 myfree(quant->ed_map);
640 /* copies the color map from the hv into the colors member of the HV */
642 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
648 sv = hv_fetch(hv, "colors", 6, 0);
649 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
654 av = (AV *)SvRV(*sv);
656 av_extend(av, quant->mc_count+1);
657 for (i = 0; i < quant->mc_count; ++i) {
658 i_color *in = quant->mc_colors+i;
659 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
660 work = sv_newmortal();
661 sv_setref_pv(work, "Imager::Color", (void *)c);
667 /* loads the segments of a fountain fill into an array */
668 static i_fountain_seg *
669 load_fount_segs(pTHX_ AV *asegs, int *count) {
670 /* Each element of segs must contain:
671 [ start, middle, end, c0, c1, segtype, colortrans ]
672 start, middle, end are doubles from 0 to 1
673 c0, c1 are Imager::Color::Float or Imager::Color objects
674 segtype, colortrans are ints
678 i_fountain_seg *segs;
682 *count = av_len(asegs)+1;
684 croak("i_fountain must have at least one segment");
685 segs = mymalloc(sizeof(i_fountain_seg) * *count);
686 for(i = 0; i < *count; i++) {
687 SV **sv1 = av_fetch(asegs, i, 0);
688 if (!sv1 || !*sv1 || !SvROK(*sv1)
689 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
691 croak("i_fountain: segs must be an arrayref of arrayrefs");
693 aseg = (AV *)SvRV(*sv1);
694 if (av_len(aseg) != 7-1) {
696 croak("i_fountain: a segment must have 7 members");
698 for (j = 0; j < 3; ++j) {
699 SV **sv2 = av_fetch(aseg, j, 0);
702 croak("i_fountain: XS error");
704 work[j] = SvNV(*sv2);
706 segs[i].start = work[0];
707 segs[i].middle = work[1];
708 segs[i].end = work[2];
709 for (j = 0; j < 2; ++j) {
710 SV **sv3 = av_fetch(aseg, 3+j, 0);
711 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
712 (!sv_derived_from(*sv3, "Imager::Color")
713 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
715 croak("i_fountain: segs must contain colors in elements 3 and 4");
717 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
718 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
721 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
723 for (ch = 0; ch < MAXCHANNELS; ++ch) {
724 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
728 for (j = 0; j < 2; ++j) {
729 SV **sv2 = av_fetch(aseg, j+5, 0);
732 croak("i_fountain: XS error");
734 worki[j] = SvIV(*sv2);
736 segs[i].type = worki[0];
737 segs[i].color = worki[1];
743 /* validates the indexes supplied to i_ppal
745 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
750 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
751 int color_count = i_colorcount(im);
754 if (color_count == -1)
755 croak("i_plin() called on direct color image");
757 for (i = 0; i < count; ++i) {
758 if (indexes[i] >= color_count) {
759 croak("i_plin() called with out of range color index %d (max %d)",
760 indexes[i], color_count-1);
766 /* I don't think ICLF_* names belong at the C interface
767 this makes the XS code think we have them, to let us avoid
768 putting function bodies in the XS code
770 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
771 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
774 #define i_log_enabled() 1
776 #define i_log_enabled() 0
779 #if i_int_hlines_testing()
781 typedef i_int_hlines *Imager__Internal__Hlines;
783 static i_int_hlines *
784 i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
785 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
786 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
791 static i_int_hlines *
792 i_int_hlines_new_img(i_img *im) {
793 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
794 i_int_init_hlines_img(result, im);
800 i_int_hlines_DESTROY(i_int_hlines *hlines) {
801 i_int_hlines_destroy(hlines);
805 #define i_int_hlines_CLONE_SKIP(cls) 1
807 static int seg_compare(const void *vleft, const void *vright) {
808 const i_int_hline_seg *left = vleft;
809 const i_int_hline_seg *right = vright;
811 return left->minx - right->minx;
815 i_int_hlines_dump(i_int_hlines *hlines) {
817 SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
818 i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
821 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
822 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
825 /* sort the segments, if any */
827 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
829 sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
830 for (i = 0; i < entry->count; ++i) {
831 sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx),
832 i_DFc(entry->segs[i].x_limit));
834 sv_catpv(dump, "\n");
844 i_sv_off_t(pTHX_ SV *sv) {
845 #if LSEEKSIZE > IVSIZE
846 return (off_t)SvNV(sv);
848 return (off_t)SvIV(sv);
853 i_new_sv_off_t(pTHX_ off_t off) {
854 #if LSEEKSIZE > IVSIZE
861 static im_pl_ext_funcs im_perl_funcs =
863 IMAGER_PL_API_VERSION,
865 ip_handle_quant_opts,
866 ip_cleanup_quant_opts,
870 #define PERL_PL_SET_GLOBAL_CALLBACKS \
871 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
874 #define i_exif_enabled() 1
876 #define i_exif_enabled() 0
879 /* trying to use more C style names, map them here */
880 #define i_io_DESTROY(ig) io_glue_destroy(ig)
882 #define i_img_get_width(im) ((im)->xsize)
883 #define i_img_get_height(im) ((im)->ysize)
885 #define i_img_epsilonf() (DBL_EPSILON * 4)
887 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
890 ICL_new_internal(r,g,b,a)
902 ICL_set_internal(cl,r,g,b,a)
909 ICL_set_internal(cl, r, g, b, a);
923 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
924 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
925 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
926 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
932 RETVAL = mymalloc(sizeof(i_color));
934 i_hsv_to_rgb(RETVAL);
942 RETVAL = mymalloc(sizeof(i_color));
944 i_rgb_to_hsv(RETVAL);
950 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
953 ICLF_new_internal(r, g, b, a)
961 Imager::Color::Float cl
965 Imager::Color::Float cl
969 EXTEND(SP, MAXCHANNELS);
970 for (ch = 0; ch < MAXCHANNELS; ++ch) {
971 /* printf("%d: %g\n", ch, cl->channel[ch]); */
972 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
976 ICLF_set_internal(cl,r,g,b,a)
977 Imager::Color::Float cl
992 Imager::Color::Float c
994 RETVAL = mymalloc(sizeof(i_fcolor));
996 i_hsv_to_rgbf(RETVAL);
1000 Imager::Color::Float
1002 Imager::Color::Float c
1004 RETVAL = mymalloc(sizeof(i_fcolor));
1006 i_rgb_to_hsvf(RETVAL);
1010 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1024 MODULE = Imager PACKAGE = Imager
1043 SvPV(ST(0), length);
1044 SvREFCNT_inc(ST(0));
1045 RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0));
1050 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1059 cbd = mymalloc(sizeof(struct cbdata));
1060 SvREFCNT_inc(writecb);
1061 cbd->writecb = writecb;
1062 SvREFCNT_inc(readcb);
1063 cbd->readcb = readcb;
1064 SvREFCNT_inc(seekcb);
1065 cbd->seekcb = seekcb;
1066 SvREFCNT_inc(closecb);
1067 cbd->closecb = closecb;
1068 cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
1069 if (maxwrite > CBDATA_BUFSIZE)
1070 maxwrite = CBDATA_BUFSIZE;
1071 cbd->maxlength = maxwrite;
1072 RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
1081 unsigned char* data;
1085 tlength = io_slurp(ig, &data);
1087 PUSHs(sv_2mortal(newSVpv((char *)data,tlength)));
1092 i_set_image_file_limits(width, height, bytes)
1098 i_get_image_file_limits()
1100 i_img_dim width, height;
1103 if (i_get_image_file_limits(&width, &height, &bytes)) {
1105 PUSHs(sv_2mortal(newSViv(width)));
1106 PUSHs(sv_2mortal(newSViv(height)));
1107 PUSHs(sv_2mortal(newSVuv(bytes)));
1110 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1113 i_io_write(ig, data_sv)
1121 if (SvUTF8(data_sv)) {
1122 data_sv = sv_2mortal(newSVsv(data_sv));
1123 /* yes, we want this to croak() if the SV can't be downgraded */
1124 sv_utf8_downgrade(data_sv, FALSE);
1127 data = SvPV(data_sv, size);
1128 RETVAL = i_io_write(ig, data, size);
1133 i_io_read(ig, buffer_sv, size)
1142 croak("size negative in call to i_io_read()");
1143 /* prevent an undefined value warning if they supplied an
1145 Orginally conditional on !SvOK(), but this will prevent the
1146 downgrade from croaking */
1147 sv_setpvn(buffer_sv, "", 0);
1149 if (SvUTF8(buffer_sv))
1150 sv_utf8_downgrade(buffer_sv, FALSE);
1152 buffer = SvGROW(buffer_sv, size+1);
1153 result = i_io_read(ig, buffer, size);
1155 SvCUR_set(buffer_sv, result);
1156 *SvEND(buffer_sv) = '\0';
1157 SvPOK_only(buffer_sv);
1159 PUSHs(sv_2mortal(newSViv(result)));
1165 i_io_read2(ig, size)
1174 croak("size negative in call to i_io_read2()");
1175 buffer_sv = newSV(size);
1176 buffer = SvGROW(buffer_sv, size+1);
1177 result = i_io_read(ig, buffer, size);
1179 SvCUR_set(buffer_sv, result);
1180 *SvEND(buffer_sv) = '\0';
1181 SvPOK_only(buffer_sv);
1183 PUSHs(sv_2mortal(buffer_sv));
1187 SvREFCNT_dec(buffer_sv);
1191 i_io_seek(ig, position, whence)
1205 i_io_CLONE_SKIP(...)
1207 (void)items; /* avoid unused warning for XS variable */
1212 MODULE = Imager PACKAGE = Imager
1223 while( (item=i_format_list[i++]) != NULL ) {
1225 PUSHs(sv_2mortal(newSVpv(item,0)));
1238 i_img_empty_ch(im,x,y,ch)
1245 i_sametype(im, x, y)
1251 i_sametype_chans(im, x, y, channels)
1258 i_init_log(name_sv,level)
1262 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1264 RETVAL = i_init_log(name, level);
1269 i_log_entry(string,level)
1290 i_img_info(im,info);
1292 PUSHs(sv_2mortal(newSViv(info[0])));
1293 PUSHs(sv_2mortal(newSViv(info[1])));
1294 PUSHs(sv_2mortal(newSViv(info[2])));
1295 PUSHs(sv_2mortal(newSViv(info[3])));
1301 i_img_setmask(im,ch_mask)
1310 i_img_getchannels(im)
1319 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1327 i_img_get_height(im)
1332 i_img_is_monochrome(im)
1338 result = i_img_is_monochrome(im, &zero_is_white);
1340 if (GIMME_V == G_ARRAY) {
1343 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1352 i_line(im,x1,y1,x2,y2,val,endp)
1362 i_line_aa(im,x1,y1,x2,y2,val,endp)
1372 i_box(im,x1,y1,x2,y2,val)
1381 i_box_filled(im,x1,y1,x2,y2,val)
1390 i_box_filledf(im,x1,y1,x2,y2,val)
1396 Imager::Color::Float val
1399 i_box_cfill(im,x1,y1,x2,y2,fill)
1405 Imager::FillHandle fill
1408 i_arc(im,x,y,rad,d1,d2,val)
1418 i_arc_aa(im,x,y,rad,d1,d2,val)
1428 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1435 Imager::FillHandle fill
1438 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1445 Imager::FillHandle fill
1449 i_circle_aa(im,x,y,rad,val)
1457 i_circle_out(im,x,y,rad,val)
1465 i_circle_out_aa(im,x,y,rad,val)
1473 i_arc_out(im,x,y,rad,d1,d2,val)
1483 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1494 i_bezier_multi(im,xc,yc,val)
1507 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1508 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1509 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1510 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1511 av1=(AV*)SvRV(ST(1));
1512 av2=(AV*)SvRV(ST(2));
1513 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1515 x=mymalloc( len*sizeof(double) );
1516 y=mymalloc( len*sizeof(double) );
1517 for(i=0;i<len;i++) {
1518 sv1=(*(av_fetch(av1,i,0)));
1519 sv2=(*(av_fetch(av2,i,0)));
1520 x[i]=(double)SvNV(sv1);
1521 y[i]=(double)SvNV(sv2);
1523 i_bezier_multi(im,len,x,y,val);
1529 i_poly_aa(im,xc,yc,val)
1542 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1543 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1544 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1545 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1546 av1=(AV*)SvRV(ST(1));
1547 av2=(AV*)SvRV(ST(2));
1548 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1550 x=mymalloc( len*sizeof(double) );
1551 y=mymalloc( len*sizeof(double) );
1552 for(i=0;i<len;i++) {
1553 sv1=(*(av_fetch(av1,i,0)));
1554 sv2=(*(av_fetch(av2,i,0)));
1555 x[i]=(double)SvNV(sv1);
1556 y[i]=(double)SvNV(sv2);
1558 RETVAL = i_poly_aa(im,len,x,y,val);
1565 i_poly_aa_cfill(im,xc,yc,fill)
1567 Imager::FillHandle fill
1577 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1578 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1579 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1580 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1581 av1=(AV*)SvRV(ST(1));
1582 av2=(AV*)SvRV(ST(2));
1583 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1585 x=mymalloc( len*sizeof(double) );
1586 y=mymalloc( len*sizeof(double) );
1587 for(i=0;i<len;i++) {
1588 sv1=(*(av_fetch(av1,i,0)));
1589 sv2=(*(av_fetch(av2,i,0)));
1590 x[i]=(double)SvNV(sv1);
1591 y[i]=(double)SvNV(sv2);
1593 RETVAL = i_poly_aa_cfill(im,len,x,y,fill);
1602 i_flood_fill(im,seedx,seedy,dcol)
1609 i_flood_cfill(im,seedx,seedy,fill)
1613 Imager::FillHandle fill
1616 i_flood_fill_border(im,seedx,seedy,dcol, border)
1621 Imager::Color border
1624 i_flood_cfill_border(im,seedx,seedy,fill, border)
1628 Imager::FillHandle fill
1629 Imager::Color border
1633 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1645 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1662 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1673 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1686 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)
1702 i_combine(src_av, channels_av = NULL)
1706 i_img **imgs = NULL;
1708 int *channels = NULL;
1713 in_count = av_len(src_av) + 1;
1715 imgs = mymalloc(sizeof(i_img*) * in_count);
1716 channels = mymalloc(sizeof(int) * in_count);
1717 for (i = 0; i < in_count; ++i) {
1718 psv = av_fetch(src_av, i, 0);
1719 if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1722 croak("imgs must contain only images");
1724 tmp = SvIV((SV*)SvRV(*psv));
1725 imgs[i] = INT2PTR(i_img*, tmp);
1727 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1729 channels[i] = SvIV(*psv);
1736 RETVAL = i_combine(imgs, channels, in_count);
1743 i_flipxy(im, direction)
1748 i_rotate90(im, degrees)
1753 i_rotate_exact(im, amount, ...)
1757 i_color *backp = NULL;
1758 i_fcolor *fbackp = NULL;
1762 /* extract the bg colors if any */
1763 /* yes, this is kind of strange */
1764 for (i = 2; i < items; ++i) {
1766 if (sv_derived_from(sv1, "Imager::Color")) {
1767 IV tmp = SvIV((SV*)SvRV(sv1));
1768 backp = INT2PTR(i_color *, tmp);
1770 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1771 IV tmp = SvIV((SV*)SvRV(sv1));
1772 fbackp = INT2PTR(i_fcolor *, tmp);
1775 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1780 i_matrix_transform(im, xsize, ysize, matrix, ...)
1790 i_color *backp = NULL;
1791 i_fcolor *fbackp = NULL;
1793 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1794 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1795 av=(AV*)SvRV(ST(3));
1799 for (i = 0; i < len; ++i) {
1800 sv1=(*(av_fetch(av,i,0)));
1801 matrix[i] = SvNV(sv1);
1805 /* extract the bg colors if any */
1806 /* yes, this is kind of strange */
1807 for (i = 4; i < items; ++i) {
1809 if (sv_derived_from(sv1, "Imager::Color")) {
1810 IV tmp = SvIV((SV*)SvRV(sv1));
1811 backp = INT2PTR(i_color *, tmp);
1813 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1814 IV tmp = SvIV((SV*)SvRV(sv1));
1815 fbackp = INT2PTR(i_fcolor *, tmp);
1818 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
1823 i_gaussian(im,stdev)
1828 i_unsharp_mask(im,stdev,scale)
1843 len = av_len(coef) + 1;
1844 c_coef=mymalloc( len * sizeof(double) );
1845 for(i = 0; i < len; i++) {
1846 sv1 = (*(av_fetch(coef, i, 0)));
1847 c_coef[i] = (double)SvNV(sv1);
1849 RETVAL = i_conv(im, c_coef, len);
1855 i_convert(src, avmain)
1867 outchan = av_len(avmain)+1;
1868 /* find the biggest */
1870 for (j=0; j < outchan; ++j) {
1871 temp = av_fetch(avmain, j, 0);
1872 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1873 avsub = (AV*)SvRV(*temp);
1874 len = av_len(avsub)+1;
1879 coeff = mymalloc(sizeof(double) * outchan * inchan);
1880 for (j = 0; j < outchan; ++j) {
1881 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1882 len = av_len(avsub)+1;
1883 for (i = 0; i < len; ++i) {
1884 temp = av_fetch(avsub, i, 0);
1886 coeff[i+j*inchan] = SvNV(*temp);
1888 coeff[i+j*inchan] = 0;
1891 coeff[i++ + j*inchan] = 0;
1893 RETVAL = i_convert(src, coeff, outchan, inchan);
1903 unsigned int mask = 0;
1909 unsigned char (*maps)[256];
1911 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1912 croak("i_map: parameter 2 must be an arrayref\n");
1913 avmain = (AV*)SvRV(ST(1));
1914 len = av_len(avmain)+1;
1915 if (im->channels < len) len = im->channels;
1917 maps = mymalloc( len * sizeof(unsigned char [256]) );
1919 for (j=0; j<len ; j++) {
1920 temp = av_fetch(avmain, j, 0);
1921 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1922 avsub = (AV*)SvRV(*temp);
1923 if(av_len(avsub) != 255) continue;
1925 for (i=0; i<256 ; i++) {
1927 temp = av_fetch(avsub, i, 0);
1928 val = temp ? SvIV(*temp) : 0;
1930 if (val>255) val = 255;
1935 i_map(im, maps, mask);
1946 i_img_diffd(im1,im2)
1951 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
1961 _is_color_object(sv)
1965 RETVAL = SvOK(sv) && SvROK(sv) &&
1966 (sv_derived_from(sv, "Imager::Color")
1967 || sv_derived_from(sv, "Imager::Color::Float"));
1979 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
1981 #define TT_DESTROY(handle) i_tt_destroy(handle)
1985 Imager::Font::TT handle
1990 (void)items; /* avoid unused warning */
1996 MODULE = Imager PACKAGE = Imager
2000 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
2001 Imager::Font::TT handle
2019 str = SvPV(str_sv, len);
2020 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2021 len, smooth, utf8, align);
2027 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
2028 Imager::Font::TT handle
2046 str = SvPV(str_sv, len);
2047 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2048 smooth, utf8, align);
2054 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
2055 Imager::Font::TT handle
2060 i_img_dim cords[BOUNDING_BOX_COUNT];
2070 str = SvPV(str_sv, len);
2071 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2073 for (i = 0; i < rc; ++i) {
2074 PUSHs(sv_2mortal(newSViv(cords[i])));
2079 i_tt_has_chars(handle, text_sv, utf8)
2080 Imager::Font::TT handle
2091 if (SvUTF8(text_sv))
2094 text = SvPV(text_sv, len);
2095 work = mymalloc(len);
2096 count = i_tt_has_chars(handle, text, len, utf8, work);
2097 if (GIMME_V == G_ARRAY) {
2099 for (i = 0; i < count; ++i) {
2100 PUSHs(sv_2mortal(newSViv(work[i])));
2105 PUSHs(sv_2mortal(newSVpv(work, count)));
2110 i_tt_dump_names(handle)
2111 Imager::Font::TT handle
2114 i_tt_face_name(handle)
2115 Imager::Font::TT handle
2120 len = i_tt_face_name(handle, name, sizeof(name));
2123 PUSHs(sv_2mortal(newSVpv(name, len-1)));
2127 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2128 Imager::Font::TT handle
2139 if (SvUTF8(text_sv))
2142 text = SvPV(text_sv, work_len);
2147 ch = i_utf8_advance(&text, &len);
2149 i_push_error(0, "invalid UTF8 character");
2158 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2159 PUSHs(sv_2mortal(newSVpv(name, 0)));
2162 PUSHs(&PL_sv_undef);
2169 i_test_format_probe(ig, length)
2174 i_readpnm_wiol(ig, allow_incomplete)
2176 int allow_incomplete
2180 i_readpnm_multi_wiol(ig, allow_incomplete)
2182 int allow_incomplete
2188 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2191 for (i = 0; i < count; ++i) {
2192 SV *sv = sv_newmortal();
2193 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2200 i_writeppm_wiol(im, ig)
2209 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2218 i_writeraw_wiol(im,ig)
2223 i_writebmp_wiol(im,ig)
2228 i_readbmp_wiol(ig, allow_incomplete=0)
2230 int allow_incomplete
2234 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2243 idlen = SvCUR(ST(4));
2244 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2250 i_readtga_wiol(ig, length)
2258 i_scaleaxis(im,Value,Axis)
2264 i_scale_nn(im,scx,scy)
2270 i_scale_mixing(im, width, height)
2280 i_count_colors(im,maxc)
2285 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2290 unsigned int * col_usage = NULL;
2293 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2294 EXTEND(SP, col_cnt);
2295 for (i = 0; i < col_cnt; i++) {
2296 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2303 i_transform(im,opx,opy,parm)
2316 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2317 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2318 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2319 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2320 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2321 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2322 av=(AV*)SvRV(ST(1));
2324 opx=mymalloc( opxl*sizeof(int) );
2325 for(i=0;i<opxl;i++) {
2326 sv1=(*(av_fetch(av,i,0)));
2327 opx[i]=(int)SvIV(sv1);
2329 av=(AV*)SvRV(ST(2));
2331 opy=mymalloc( opyl*sizeof(int) );
2332 for(i=0;i<opyl;i++) {
2333 sv1=(*(av_fetch(av,i,0)));
2334 opy[i]=(int)SvIV(sv1);
2336 av=(AV*)SvRV(ST(3));
2337 parmlen=av_len(av)+1;
2338 parm=mymalloc( parmlen*sizeof(double) );
2339 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2340 sv1=(*(av_fetch(av,i,0)));
2341 parm[i]=(double)SvNV(sv1);
2343 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2347 ST(0) = sv_newmortal();
2348 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2349 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2352 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2377 in_imgs_count = av_len(av_in_imgs)+1;
2378 for (i = 0; i < in_imgs_count; ++i) {
2379 sv1 = *av_fetch(av_in_imgs, i, 0);
2380 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2381 croak("sv_in_img must contain only images");
2384 if (in_imgs_count > 0) {
2385 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2386 for (i = 0; i < in_imgs_count; ++i) {
2387 sv1 = *av_fetch(av_in_imgs,i,0);
2388 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2389 croak("Parameter 5 must contain only images");
2391 tmp = SvIV((SV*)SvRV(sv1));
2392 in_imgs[i] = INT2PTR(i_img*, tmp);
2396 /* no input images */
2399 /* default the output size from the first input if possible */
2401 width = SvIV(sv_width);
2402 else if (in_imgs_count)
2403 width = in_imgs[0]->xsize;
2405 croak("No output image width supplied");
2407 if (SvOK(sv_height))
2408 height = SvIV(sv_height);
2409 else if (in_imgs_count)
2410 height = in_imgs[0]->ysize;
2412 croak("No output image height supplied");
2414 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2415 if (ops_len % sizeof(struct rm_op))
2416 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2417 ops_count = ops_len / sizeof(struct rm_op);
2419 n_regs_count = av_len(av_n_regs)+1;
2420 n_regs = mymalloc(n_regs_count * sizeof(double));
2421 for (i = 0; i < n_regs_count; ++i) {
2422 sv1 = *av_fetch(av_n_regs,i,0);
2424 n_regs[i] = SvNV(sv1);
2426 c_regs_count = av_len(av_c_regs)+1;
2427 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2428 /* I don't bother initializing the colou?r registers */
2430 RETVAL=i_transform2(width, height, channels, ops, ops_count,
2431 n_regs, n_regs_count,
2432 c_regs, c_regs_count, in_imgs, in_imgs_count);
2437 ST(0) = sv_newmortal();
2438 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2439 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2443 i_contrast(im,intensity)
2456 i_noise(im,amount,type)
2462 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2472 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2491 i_postlevels(im,levels)
2501 i_watermark(im,wmark,tx,ty,pixdiff)
2503 Imager::ImgRaw wmark
2510 i_autolevels(im,lsat,usat,skew)
2517 i_radnoise(im,xo,yo,rscale,ascale)
2525 i_turbnoise(im, xo, yo, scale)
2548 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2549 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2550 croak("i_gradgen: Second argument must be an array ref");
2551 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2552 croak("i_gradgen: Third argument must be an array ref");
2553 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2554 croak("i_gradgen: Fourth argument must be an array ref");
2555 axx = (AV *)SvRV(ST(1));
2556 ayy = (AV *)SvRV(ST(2));
2557 ac = (AV *)SvRV(ST(3));
2558 dmeasure = (int)SvIV(ST(4));
2560 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2561 num = num <= av_len(ac) ? num : av_len(ac);
2563 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2564 xo = mymalloc( sizeof(i_img_dim) * num );
2565 yo = mymalloc( sizeof(i_img_dim) * num );
2566 ival = mymalloc( sizeof(i_color) * num );
2567 for(i = 0; i<num; i++) {
2568 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2569 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2570 sv = *av_fetch(ac, i, 0);
2571 if ( !sv_derived_from(sv, "Imager::Color") ) {
2572 free(axx); free(ayy); free(ac);
2573 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2575 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2577 i_gradgen(im, num, xo, yo, ival, dmeasure);
2583 i_diff_image(im, im2, mindist=0)
2589 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2599 double ssample_param
2603 i_fountain_seg *segs;
2605 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2606 croak("i_fountain: argument 11 must be an array ref");
2608 asegs = (AV *)SvRV(ST(10));
2609 segs = load_fount_segs(aTHX_ asegs, &count);
2610 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2611 super_sample, ssample_param, count, segs);
2617 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2626 double ssample_param
2630 i_fountain_seg *segs;
2632 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2633 croak("i_fountain: argument 11 must be an array ref");
2635 asegs = (AV *)SvRV(ST(9));
2636 segs = load_fount_segs(aTHX_ asegs, &count);
2637 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2638 super_sample, ssample_param, count, segs);
2644 i_new_fill_opacity(other_fill, alpha_mult)
2645 Imager::FillHandle other_fill
2656 errors = i_errors();
2658 while (errors[i].msg) {
2660 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2661 if (!av_store(av, 0, sv)) {
2664 sv = newSViv(errors[i].code);
2665 if (!av_store(av, 1, sv)) {
2668 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2676 i_push_error(code, msg)
2681 i_nearest_color(im, ...)
2696 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2697 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2698 croak("i_nearest_color: Second argument must be an array ref");
2699 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2700 croak("i_nearest_color: Third argument must be an array ref");
2701 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2702 croak("i_nearest_color: Fourth argument must be an array ref");
2703 axx = (AV *)SvRV(ST(1));
2704 ayy = (AV *)SvRV(ST(2));
2705 ac = (AV *)SvRV(ST(3));
2706 dmeasure = (int)SvIV(ST(4));
2708 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2709 num = num <= av_len(ac) ? num : av_len(ac);
2711 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2712 xo = mymalloc( sizeof(i_img_dim) * num );
2713 yo = mymalloc( sizeof(i_img_dim) * num );
2714 ival = mymalloc( sizeof(i_color) * num );
2715 for(i = 0; i<num; i++) {
2716 xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2717 yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2718 sv = *av_fetch(ac, i, 0);
2719 if ( !sv_derived_from(sv, "Imager::Color") ) {
2720 free(axx); free(ayy); free(ac);
2721 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2723 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2725 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2739 rc=DSO_open(filename,&evstr);
2743 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2744 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2747 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2753 DSO_close(dso_handle)
2757 DSO_funclist(dso_handle_v)
2761 DSO_handle *dso_handle;
2762 func_ptr *functions;
2764 dso_handle=(DSO_handle*)dso_handle_v;
2765 functions = DSO_funclist(dso_handle);
2767 while( functions[i].name != NULL) {
2769 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2771 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2775 DSO_call(handle,func_index,hv)
2781 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
2782 hv=(HV*)SvRV(ST(2));
2783 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2784 DSO_call( (DSO_handle *)handle,func_index,hv);
2787 i_get_pixel(im, x, y)
2794 color = (i_color *)mymalloc(sizeof(i_color));
2795 if (i_gpix(im, x, y, color) == 0) {
2796 RETVAL = NEWSV(0, 0);
2797 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
2801 RETVAL = &PL_sv_undef;
2808 i_ppix(im, x, y, cl)
2815 i_img_pal_new(x, y, channels, maxpal)
2822 i_img_to_pal(src, quant)
2828 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2829 croak("i_img_to_pal: second argument must be a hash ref");
2830 hv = (HV *)SvRV(ST(1));
2831 memset(&quant, 0, sizeof(quant));
2833 quant.mc_size = 256;
2834 ip_handle_quant_opts(aTHX_ &quant, hv);
2835 RETVAL = i_img_to_pal(src, &quant);
2837 ip_copy_colors_back(aTHX_ hv, &quant);
2839 ip_cleanup_quant_opts(aTHX_ &quant);
2858 work = mymalloc((r-l) * sizeof(i_palidx));
2859 count = i_gpal(im, l, r, y, work);
2860 if (GIMME_V == G_ARRAY) {
2862 for (i = 0; i < count; ++i) {
2863 PUSHs(sv_2mortal(newSViv(work[i])));
2868 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
2873 if (GIMME_V != G_ARRAY) {
2875 PUSHs(&PL_sv_undef);
2880 i_ppal(im, l, y, ...)
2889 work = mymalloc(sizeof(i_palidx) * (items-3));
2890 for (i=0; i < items-3; ++i) {
2891 work[i] = SvIV(ST(i+3));
2893 validate_i_ppal(im, work, items - 3);
2894 RETVAL = i_ppal(im, l, l+items-3, y, work);
2904 i_ppal_p(im, l, y, data)
2910 i_palidx const *work;
2913 work = (i_palidx const *)SvPV(data, len);
2914 len /= sizeof(i_palidx);
2916 validate_i_ppal(im, work, len);
2917 RETVAL = i_ppal(im, l, l+len, y, work);
2926 i_addcolors(im, ...)
2934 croak("i_addcolors: no colors to add");
2935 colors = mymalloc((items-1) * sizeof(i_color));
2936 for (i=0; i < items-1; ++i) {
2937 if (sv_isobject(ST(i+1))
2938 && sv_derived_from(ST(i+1), "Imager::Color")) {
2939 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
2940 colors[i] = *INT2PTR(i_color *, tmp);
2944 croak("i_addcolor: pixels must be Imager::Color objects");
2947 index = i_addcolors(im, colors, items-1);
2950 RETVAL = newSVpv("0 but true", 0);
2952 else if (index == -1) {
2953 RETVAL = &PL_sv_undef;
2956 RETVAL = newSViv(index);
2962 i_setcolors(im, index, ...)
2970 croak("i_setcolors: no colors to add");
2971 colors = mymalloc((items-2) * sizeof(i_color));
2972 for (i=0; i < items-2; ++i) {
2973 if (sv_isobject(ST(i+2))
2974 && sv_derived_from(ST(i+2), "Imager::Color")) {
2975 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
2976 colors[i] = *INT2PTR(i_color *, tmp);
2980 croak("i_setcolors: pixels must be Imager::Color objects");
2983 RETVAL = i_setcolors(im, index, colors, items-2);
2989 i_getcolors(im, index, ...)
2998 croak("i_getcolors: too many arguments");
3000 count = SvIV(ST(2));
3002 croak("i_getcolors: count must be positive");
3003 colors = mymalloc(sizeof(i_color) * count);
3004 if (i_getcolors(im, index, colors, count)) {
3005 for (i = 0; i < count; ++i) {
3007 SV *sv = sv_newmortal();
3008 pv = mymalloc(sizeof(i_color));
3010 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3026 i_findcolor(im, color)
3032 if (i_findcolor(im, color, &index)) {
3033 RETVAL = newSViv(index);
3036 RETVAL = &PL_sv_undef;
3054 i_gsamp(im, l, r, y, ...)
3066 croak("No channel numbers supplied to g_samp()");
3068 chan_count = items - 4;
3069 chans = mymalloc(sizeof(int) * chan_count);
3070 for (i = 0; i < chan_count; ++i)
3071 chans[i] = SvIV(ST(i+4));
3072 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
3073 count = i_gsamp(im, l, r, y, data, chans, chan_count);
3075 if (GIMME_V == G_ARRAY) {
3077 for (i = 0; i < count; ++i)
3078 PUSHs(sv_2mortal(newSViv(data[i])));
3082 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3087 if (GIMME_V != G_ARRAY) {
3089 PUSHs(&PL_sv_undef);
3094 i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3110 croak("No channel numbers supplied to g_samp()");
3112 chan_count = items - 7;
3113 chans = mymalloc(sizeof(int) * chan_count);
3114 for (i = 0; i < chan_count; ++i)
3115 chans[i] = SvIV(ST(i+7));
3116 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3117 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3119 for (i = 0; i < count; ++i) {
3120 av_store(target, i+offset, newSVuv(data[i]));
3132 i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3150 if (SvOK(channels_sv)) {
3152 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3153 croak("channels is not an array ref");
3155 channels_av = (AV *)SvRV(channels_sv);
3156 chan_count = av_len(channels_av) + 1;
3157 if (chan_count < 1) {
3158 croak("i_psamp_bits: no channels provided");
3160 channels = mymalloc(sizeof(int) * chan_count);
3161 for (i = 0; i < chan_count; ++i)
3162 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3165 chan_count = im->channels;
3169 data_count = av_len(data_av) + 1;
3170 if (data_offset < 0) {
3171 croak("data_offset must by non-negative");
3173 if (data_offset > data_count) {
3174 croak("data_offset greater than number of samples supplied");
3176 if (pixel_count == -1 ||
3177 data_offset + pixel_count * chan_count > data_count) {
3178 pixel_count = (data_count - data_offset) / chan_count;
3181 data_used = pixel_count * chan_count;
3182 data = mymalloc(sizeof(unsigned) * data_count);
3183 for (i = 0; i < data_used; ++i)
3184 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3186 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3197 i_img_masked_new(targ, mask, x, y, w, h)
3207 if (!sv_isobject(ST(1))
3208 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3209 croak("i_img_masked_new: parameter 2 must undef or an image");
3211 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3215 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3220 i_plin(im, l, y, ...)
3231 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3232 /* supplied as a byte string */
3233 work = (i_color *)SvPV(ST(3), len);
3234 count = len / sizeof(i_color);
3235 if (count * sizeof(i_color) != len) {
3236 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3238 RETVAL = i_plin(im, l, l+count, y, work);
3241 work = mymalloc(sizeof(i_color) * (items-3));
3242 for (i=0; i < items-3; ++i) {
3243 if (sv_isobject(ST(i+3))
3244 && sv_derived_from(ST(i+3), "Imager::Color")) {
3245 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3246 work[i] = *INT2PTR(i_color *, tmp);
3250 croak("i_plin: pixels must be Imager::Color objects");
3253 RETVAL = i_plin(im, l, l+items-3, y, work);
3264 i_ppixf(im, x, y, cl)
3268 Imager::Color::Float cl
3271 i_gsampf(im, l, r, y, ...)
3283 croak("No channel numbers supplied to g_sampf()");
3285 chan_count = items - 4;
3286 chans = mymalloc(sizeof(int) * chan_count);
3287 for (i = 0; i < chan_count; ++i)
3288 chans[i] = SvIV(ST(i+4));
3289 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3290 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3292 if (GIMME_V == G_ARRAY) {
3294 for (i = 0; i < count; ++i)
3295 PUSHs(sv_2mortal(newSVnv(data[i])));
3299 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3304 if (GIMME_V != G_ARRAY) {
3306 PUSHs(&PL_sv_undef);
3311 i_plinf(im, l, y, ...)
3322 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3323 /* supplied as a byte string */
3324 work = (i_fcolor *)SvPV(ST(3), len);
3325 count = len / sizeof(i_fcolor);
3326 if (count * sizeof(i_fcolor) != len) {
3327 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3329 RETVAL = i_plinf(im, l, l+count, y, work);
3332 work = mymalloc(sizeof(i_fcolor) * (items-3));
3333 for (i=0; i < items-3; ++i) {
3334 if (sv_isobject(ST(i+3))
3335 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3336 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3337 work[i] = *INT2PTR(i_fcolor *, tmp);
3341 croak("i_plinf: pixels must be Imager::Color::Float objects");
3345 RETVAL = i_plinf(im, l, l+items-3, y, work);
3363 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3364 if (i_gpixf(im, x, y, color) == 0) {
3365 RETVAL = NEWSV(0,0);
3366 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
3370 RETVAL = &PL_sv_undef;
3386 vals = mymalloc((r-l) * sizeof(i_color));
3387 memset(vals, 0, (r-l) * sizeof(i_color));
3388 count = i_glin(im, l, r, y, vals);
3389 if (GIMME_V == G_ARRAY) {
3391 for (i = 0; i < count; ++i) {
3393 i_color *col = mymalloc(sizeof(i_color));
3395 sv = sv_newmortal();
3396 sv_setref_pv(sv, "Imager::Color", (void *)col);
3402 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3408 i_glinf(im, l, r, y)
3418 for (i = 0; i < MAXCHANNELS; ++i)
3419 zero.channel[i] = 0;
3421 vals = mymalloc((r-l) * sizeof(i_fcolor));
3422 for (i = 0; i < r-l; ++i)
3424 count = i_glinf(im, l, r, y, vals);
3425 if (GIMME_V == G_ARRAY) {
3427 for (i = 0; i < count; ++i) {
3429 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3431 sv = sv_newmortal();
3432 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3438 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3444 i_img_16_new(x, y, ch)
3454 i_img_double_new(x, y, ch)
3464 i_tags_addn(im, name, code, idata)
3473 name = SvPV(ST(1), len);
3476 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3481 i_tags_add(im, name, code, data, idata)
3491 name = SvPV(ST(1), len);
3495 data = SvPV(ST(3), len);
3500 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3505 i_tags_find(im, name, start)
3512 if (i_tags_find(&im->tags, name, start, &entry)) {
3514 RETVAL = newSVpv("0 but true", 0);
3516 RETVAL = newSViv(entry);
3518 RETVAL = &PL_sv_undef;
3524 i_tags_findn(im, code, start)
3531 if (i_tags_findn(&im->tags, code, start, &entry)) {
3533 RETVAL = newSVpv("0 but true", 0);
3535 RETVAL = newSViv(entry);
3538 RETVAL = &PL_sv_undef;
3544 i_tags_delete(im, entry)
3548 RETVAL = i_tags_delete(&im->tags, entry);
3553 i_tags_delbyname(im, name)
3557 RETVAL = i_tags_delbyname(&im->tags, name);
3562 i_tags_delbycode(im, code)
3566 RETVAL = i_tags_delbycode(&im->tags, code);
3571 i_tags_get(im, index)
3575 if (index >= 0 && index < im->tags.count) {
3576 i_img_tag *entry = im->tags.tags + index;
3580 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3583 PUSHs(sv_2mortal(newSViv(entry->code)));
3586 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3589 PUSHs(sv_2mortal(newSViv(entry->idata)));
3594 i_tags_get_string(im, what_sv)
3598 char const *name = NULL;
3602 if (SvIOK(what_sv)) {
3603 code = SvIV(what_sv);
3607 name = SvPV_nolen(what_sv);
3610 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3612 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3619 RETVAL = im->tags.count;
3625 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
3629 Imager::FillHandle fill
3632 IFILL_CLONE_SKIP(...)
3634 (void)items; /* avoid unused warning for XS variable */
3639 MODULE = Imager PACKAGE = Imager
3642 i_new_fill_solid(cl, combine)
3647 i_new_fill_solidf(cl, combine)
3648 Imager::Color::Float cl
3652 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3660 unsigned char *cust_hatch;
3664 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3668 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3673 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
3674 Imager::Color::Float fg
3675 Imager::Color::Float bg
3681 unsigned char *cust_hatch;
3685 cust_hatch = (unsigned char *)SvPV(ST(4), len);
3689 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3694 i_new_fill_image(src, matrix, xoff, yoff, combine)
3711 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3712 croak("i_new_fill_image: parameter must be an arrayref");
3713 av=(AV*)SvRV(ST(1));
3717 for (i = 0; i < len; ++i) {
3718 sv1=(*(av_fetch(av,i,0)));
3719 matrix[i] = SvNV(sv1);
3725 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3729 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
3731 # this class is only exposed for testing
3734 i_int_hlines_testing()
3736 #if i_int_hlines_testing()
3738 Imager::Internal::Hlines
3739 i_int_hlines_new(start_y, count_y, start_x, count_x)
3745 Imager::Internal::Hlines
3746 i_int_hlines_new_img(im)
3750 i_int_hlines_add(hlines, y, minx, width)
3751 Imager::Internal::Hlines hlines
3757 i_int_hlines_DESTROY(hlines)
3758 Imager::Internal::Hlines hlines
3761 i_int_hlines_dump(hlines)
3762 Imager::Internal::Hlines hlines
3765 i_int_hlines_CLONE_SKIP(cls)
3770 PERL_SET_GLOBAL_CALLBACKS;
3771 PERL_PL_SET_GLOBAL_CALLBACKS;