7 #define NEED_newRV_noinc
8 #define NEED_sv_2pv_nolen
14 #define i_int_hlines_testing() 1
22 #if i_int_hlines_testing()
28 /* These functions are all shared - then comes platform dependant code */
29 static int getstr(void *hv_t,char *key,char **store) {
33 mm_log((1,"getstr(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
35 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
37 svpp=hv_fetch(hv, key, strlen(key), 0);
38 *store=SvPV(*svpp, PL_na );
43 static int getint(void *hv_t,char *key,int *store) {
47 mm_log((1,"getint(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
49 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
51 svpp=hv_fetch(hv, key, strlen(key), 0);
52 *store=(int)SvIV(*svpp);
56 static int getdouble(void *hv_t,char* key,double *store) {
60 mm_log((1,"getdouble(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
62 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
63 svpp=hv_fetch(hv, key, strlen(key), 0);
64 *store=(float)SvNV(*svpp);
68 static int getvoid(void *hv_t,char* key,void **store) {
72 mm_log((1,"getvoid(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
74 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
76 svpp=hv_fetch(hv, key, strlen(key), 0);
77 *store = INT2PTR(void*, SvIV(*svpp));
82 static int getobj(void *hv_t,char *key,char *type,void **store) {
86 mm_log((1,"getobj(hv_t 0x%X, key %s,type %s, store 0x%X)\n",hv_t,key,type,store));
88 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
90 svpp=hv_fetch(hv, key, strlen(key), 0);
92 if (sv_derived_from(*svpp,type)) {
93 IV tmp = SvIV((SV*)SvRV(*svpp));
94 *store = INT2PTR(void*, tmp);
96 mm_log((1,"getobj: key exists in hash but is not of correct type"));
103 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
105 void my_SvREFCNT_dec(void *p) {
106 SvREFCNT_dec((SV*)p);
111 i_log_entry(char *string, int level) {
112 mm_log((level, string));
116 typedef struct i_reader_data_tag
118 /* presumably a CODE ref or name of a sub */
122 /* used by functions that want callbacks */
123 static int read_callback(char *userdata, char *buffer, int need, int want) {
124 i_reader_data *rd = (i_reader_data *)userdata;
128 dSP; dTARG = sv_newmortal();
129 /* thanks to Simon Cozens for help with the dTARG above */
139 count = perl_call_sv(rd->sv, G_SCALAR);
144 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
150 char *ptr = SvPV(data, len);
152 croak("Too much data returned in reader callback");
154 memcpy(buffer, ptr, len);
170 SV *sv; /* a coderef or sub name */
173 /* used by functions that want callbacks */
174 static int write_callback(char *userdata, char const *data, int size) {
175 i_writer_data *wd = (i_writer_data *)userdata;
185 XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
188 count = perl_call_sv(wd->sv, G_SCALAR);
193 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
196 success = SvTRUE(sv);
206 #define CBDATA_BUFSIZE 8192
209 /* the SVs we use to call back to Perl */
215 /* we need to remember whether the buffer contains write data or
221 /* how far we've read into the buffer (not used for writing) */
224 /* the amount of space used/data available in the buffer */
227 /* the maximum amount to fill the buffer before flushing
228 If any write is larger than this then the buffer is flushed and
229 the full write is performed. The write is _not_ split into
234 char buffer[CBDATA_BUFSIZE];
239 call_writer(cbd, buf, size)
241 Low-level function to call the perl writer callback.
245 static ssize_t call_writer(struct cbdata *cbd, void const *buf, size_t size) {
251 if (!SvOK(cbd->writecb))
258 PUSHs(sv_2mortal(newSVpv((char *)buf, size)));
261 count = perl_call_sv(cbd->writecb, G_SCALAR);
265 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
268 success = SvTRUE(sv);
275 return success ? size : -1;
278 static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
285 if (!SvOK(cbd->readcb))
292 PUSHs(sv_2mortal(newSViv(size)));
293 PUSHs(sv_2mortal(newSViv(maxread)));
296 count = perl_call_sv(cbd->readcb, G_SCALAR);
301 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
307 char *ptr = SvPV(data, len);
309 croak("Too much data returned in reader callback");
311 memcpy(buf, ptr, len);
325 static ssize_t write_flush(struct cbdata *cbd) {
329 result = call_writer(cbd, cbd->buffer, cbd->used);
334 return 1; /* success of some sort */
338 static off_t io_seeker(void *p, off_t offset, int whence) {
339 struct cbdata *cbd = p;
344 if (!SvOK(cbd->seekcb))
348 if (cbd->used && write_flush(cbd) <= 0)
352 if (whence == SEEK_CUR && cbd->reading && cbd->where != cbd->used) {
353 offset -= cbd->where - cbd->used;
356 cbd->where = cbd->used = 0;
362 PUSHs(sv_2mortal(newSViv(offset)));
363 PUSHs(sv_2mortal(newSViv(whence)));
366 count = perl_call_sv(cbd->seekcb, G_SCALAR);
371 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
382 static ssize_t io_writer(void *p, void const *data, size_t size) {
383 struct cbdata *cbd = p;
385 /* printf("io_writer(%p, %p, %u)\n", p, data, size); */
387 if (cbd->reading && cbd->where < cbd->used) {
388 /* we read past the place where the caller expected us to be
389 so adjust our position a bit */
390 if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
395 cbd->where = cbd->used = 0;
398 if (cbd->used && cbd->used + size > cbd->maxlength) {
399 int write_res = write_flush(cbd);
400 if (write_res <= 0) {
405 if (cbd->used+size <= cbd->maxlength) {
406 memcpy(cbd->buffer + cbd->used, data, size);
410 /* it doesn't fit - just pass it up */
411 return call_writer(cbd, data, size);
415 io_reader(void *p, void *data, size_t size) {
416 struct cbdata *cbd = p;
418 char *out = data; /* so we can do pointer arithmetic */
420 /* printf("io_reader(%p, %p, %d)\n", p, data, size); */
422 if (write_flush(cbd) <= 0)
428 if (size <= cbd->used - cbd->where) {
430 memcpy(data, cbd->buffer+cbd->where, size);
435 memcpy(out, cbd->buffer + cbd->where, cbd->used - cbd->where);
436 total += cbd->used - cbd->where;
437 size -= cbd->used - cbd->where;
438 out += cbd->used - cbd->where;
439 if (size < sizeof(cbd->buffer)) {
443 && (did_read = call_reader(cbd, cbd->buffer, size,
444 sizeof(cbd->buffer))) > 0) {
446 cbd->used = did_read;
448 copy_size = i_min(size, cbd->used);
449 memcpy(out, cbd->buffer, copy_size);
450 cbd->where += copy_size;
459 /* just read the rest - too big for our buffer*/
461 while ((did_read = call_reader(cbd, out, size, size)) > 0) {
473 static int io_closer(void *p) {
474 struct cbdata *cbd = p;
476 if (cbd->writing && cbd->used > 0) {
477 if (write_flush(cbd) < 0)
482 if (SvOK(cbd->closecb)) {
490 perl_call_sv(cbd->closecb, G_VOID);
501 static void io_destroyer(void *p) {
502 struct cbdata *cbd = p;
504 SvREFCNT_dec(cbd->writecb);
505 SvREFCNT_dec(cbd->readcb);
506 SvREFCNT_dec(cbd->seekcb);
507 SvREFCNT_dec(cbd->closecb);
515 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
518 for (i = 0; i < count; ++i)
519 if (strEQ(names[i].name, name))
520 return names[i].value;
524 static struct value_name transp_names[] =
527 { "threshold", tr_threshold },
528 { "errdiff", tr_errdiff },
529 { "ordered", tr_ordered, },
532 static struct value_name make_color_names[] =
534 { "none", mc_none, },
535 { "webmap", mc_web_map, },
536 { "addi", mc_addi, },
537 { "mediancut", mc_median_cut, },
538 { "mono", mc_mono, },
539 { "monochrome", mc_mono, },
542 static struct value_name translate_names[] =
545 { "giflib", pt_giflib, },
547 { "closest", pt_closest, },
548 { "perturb", pt_perturb, },
549 { "errdiff", pt_errdiff, },
552 static struct value_name errdiff_names[] =
554 { "floyd", ed_floyd, },
555 { "jarvis", ed_jarvis, },
556 { "stucki", ed_stucki, },
557 { "custom", ed_custom, },
560 static struct value_name orddith_names[] =
562 { "random", od_random, },
563 { "dot8", od_dot8, },
564 { "dot4", od_dot4, },
565 { "hline", od_hline, },
566 { "vline", od_vline, },
567 { "/line", od_slashline, },
568 { "slashline", od_slashline, },
569 { "\\line", od_backline, },
570 { "backline", od_backline, },
571 { "tiny", od_tiny, },
572 { "custom", od_custom, },
575 /* look through the hash for quantization options */
576 static void handle_quant_opts(i_quantize *quant, HV *hv)
578 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
584 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
586 sv = hv_fetch(hv, "transp", 6, 0);
587 if (sv && *sv && (str = SvPV(*sv, len))) {
589 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
591 if (quant->transp != tr_none) {
592 quant->tr_threshold = 127;
593 sv = hv_fetch(hv, "tr_threshold", 12, 0);
595 quant->tr_threshold = SvIV(*sv);
597 if (quant->transp == tr_errdiff) {
598 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
599 if (sv && *sv && (str = SvPV(*sv, len)))
600 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
602 if (quant->transp == tr_ordered) {
603 quant->tr_orddith = od_tiny;
604 sv = hv_fetch(hv, "tr_orddith", 10, 0);
605 if (sv && *sv && (str = SvPV(*sv, len)))
606 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
608 if (quant->tr_orddith == od_custom) {
609 sv = hv_fetch(hv, "tr_map", 6, 0);
610 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
611 AV *av = (AV*)SvRV(*sv);
612 len = av_len(av) + 1;
613 if (len > sizeof(quant->tr_custom))
614 len = sizeof(quant->tr_custom);
615 for (i = 0; i < len; ++i) {
616 SV **sv2 = av_fetch(av, i, 0);
618 quant->tr_custom[i] = SvIV(*sv2);
621 while (i < sizeof(quant->tr_custom))
622 quant->tr_custom[i++] = 0;
627 quant->make_colors = mc_addi;
628 sv = hv_fetch(hv, "make_colors", 11, 0);
629 if (sv && *sv && (str = SvPV(*sv, len))) {
631 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_addi);
633 sv = hv_fetch(hv, "colors", 6, 0);
634 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
635 /* needs to be an array of Imager::Color
636 note that the caller allocates the mc_color array and sets mc_size
638 AV *av = (AV *)SvRV(*sv);
639 quant->mc_count = av_len(av)+1;
640 if (quant->mc_count > quant->mc_size)
641 quant->mc_count = quant->mc_size;
642 for (i = 0; i < quant->mc_count; ++i) {
643 SV **sv1 = av_fetch(av, i, 0);
644 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
645 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
646 quant->mc_colors[i] = *col;
650 sv = hv_fetch(hv, "max_colors", 10, 0);
653 if (i <= quant->mc_size && i >= quant->mc_count)
657 quant->translate = pt_closest;
658 sv = hv_fetch(hv, "translate", 9, 0);
659 if (sv && *sv && (str = SvPV(*sv, len))) {
660 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
662 sv = hv_fetch(hv, "errdiff", 7, 0);
663 if (sv && *sv && (str = SvPV(*sv, len))) {
664 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
666 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
667 /* get the error diffusion map */
668 sv = hv_fetch(hv, "errdiff_width", 13, 0);
670 quant->ed_width = SvIV(*sv);
671 sv = hv_fetch(hv, "errdiff_height", 14, 0);
673 quant->ed_height = SvIV(*sv);
674 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
676 quant->ed_orig = SvIV(*sv);
677 if (quant->ed_width > 0 && quant->ed_height > 0) {
679 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
680 sv = hv_fetch(hv, "errdiff_map", 11, 0);
681 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
682 AV *av = (AV*)SvRV(*sv);
683 len = av_len(av) + 1;
684 if (len > quant->ed_width * quant->ed_height)
685 len = quant->ed_width * quant->ed_height;
686 for (i = 0; i < len; ++i) {
687 SV **sv2 = av_fetch(av, i, 0);
689 quant->ed_map[i] = SvIV(*sv2);
690 sum += quant->ed_map[i];
696 myfree(quant->ed_map);
698 quant->errdiff = ed_floyd;
702 sv = hv_fetch(hv, "perturb", 7, 0);
704 quant->perturb = SvIV(*sv);
707 static void cleanup_quant_opts(i_quantize *quant) {
708 myfree(quant->mc_colors);
710 myfree(quant->ed_map);
713 /* copies the color map from the hv into the colors member of the HV */
714 static void copy_colors_back(HV *hv, i_quantize *quant) {
720 sv = hv_fetch(hv, "colors", 6, 0);
721 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
724 ref = newRV_noinc((SV*) av);
725 sv = hv_store(hv, "colors", 6, ref, 0);
728 av = (AV *)SvRV(*sv);
730 av_extend(av, quant->mc_count+1);
731 for (i = 0; i < quant->mc_count; ++i) {
732 i_color *in = quant->mc_colors+i;
733 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
734 work = sv_newmortal();
735 sv_setref_pv(work, "Imager::Color", (void *)c);
737 if (!av_store(av, i, work)) {
743 /* loads the segments of a fountain fill into an array */
744 static i_fountain_seg *
745 load_fount_segs(AV *asegs, int *count) {
746 /* Each element of segs must contain:
747 [ start, middle, end, c0, c1, segtype, colortrans ]
748 start, middle, end are doubles from 0 to 1
749 c0, c1 are Imager::Color::Float or Imager::Color objects
750 segtype, colortrans are ints
754 i_fountain_seg *segs;
758 *count = av_len(asegs)+1;
760 croak("i_fountain must have at least one segment");
761 segs = mymalloc(sizeof(i_fountain_seg) * *count);
762 for(i = 0; i < *count; i++) {
763 SV **sv1 = av_fetch(asegs, i, 0);
764 if (!sv1 || !*sv1 || !SvROK(*sv1)
765 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
767 croak("i_fountain: segs must be an arrayref of arrayrefs");
769 aseg = (AV *)SvRV(*sv1);
770 if (av_len(aseg) != 7-1) {
772 croak("i_fountain: a segment must have 7 members");
774 for (j = 0; j < 3; ++j) {
775 SV **sv2 = av_fetch(aseg, j, 0);
778 croak("i_fountain: XS error");
780 work[j] = SvNV(*sv2);
782 segs[i].start = work[0];
783 segs[i].middle = work[1];
784 segs[i].end = work[2];
785 for (j = 0; j < 2; ++j) {
786 SV **sv3 = av_fetch(aseg, 3+j, 0);
787 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
788 (!sv_derived_from(*sv3, "Imager::Color")
789 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
791 croak("i_fountain: segs must contain colors in elements 3 and 4");
793 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
794 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
797 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
799 for (ch = 0; ch < MAXCHANNELS; ++ch) {
800 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
804 for (j = 0; j < 2; ++j) {
805 SV **sv2 = av_fetch(aseg, j+5, 0);
808 croak("i_fountain: XS error");
810 worki[j] = SvIV(*sv2);
812 segs[i].type = worki[0];
813 segs[i].color = worki[1];
819 /* validates the indexes supplied to i_ppal
821 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
826 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
827 int color_count = i_colorcount(im);
830 if (color_count == -1)
831 croak("i_plin() called on direct color image");
833 for (i = 0; i < count; ++i) {
834 if (indexes[i] >= color_count) {
835 croak("i_plin() called with out of range color index %d (max %d)",
836 indexes[i], color_count-1);
842 /* I don't think ICLF_* names belong at the C interface
843 this makes the XS code think we have them, to let us avoid
844 putting function bodies in the XS code
846 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
847 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
850 /* the m_init_log() function was called init_log(), renamed to reduce
851 potential naming conflicts */
852 #define init_log m_init_log
854 #if i_int_hlines_testing()
856 typedef i_int_hlines *Imager__Internal__Hlines;
858 static i_int_hlines *
859 i_int_hlines_new(int start_y, int count_y, int start_x, int count_x) {
860 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
861 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
866 static i_int_hlines *
867 i_int_hlines_new_img(i_img *im) {
868 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
869 i_int_init_hlines_img(result, im);
875 i_int_hlines_DESTROY(i_int_hlines *hlines) {
876 i_int_hlines_destroy(hlines);
880 static int seg_compare(const void *vleft, const void *vright) {
881 const i_int_hline_seg *left = vleft;
882 const i_int_hline_seg *right = vright;
884 return left->minx - right->minx;
888 i_int_hlines_dump(i_int_hlines *hlines) {
889 SV *dump = newSVpvf("start_y: %d limit_y: %d start_x: %d limit_x: %d\n",
890 hlines->start_y, hlines->limit_y, hlines->start_x, hlines->limit_x);
893 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
894 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
897 /* sort the segments, if any */
899 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
901 sv_catpvf(dump, " %d (%d):", y, entry->count);
902 for (i = 0; i < entry->count; ++i) {
903 sv_catpvf(dump, " [%d, %d)", entry->segs[i].minx,
904 entry->segs[i].x_limit);
906 sv_catpv(dump, "\n");
916 #define i_exif_enabled() 1
918 #define i_exif_enabled() 0
921 /* trying to use more C style names, map them here */
922 #define i_io_DESTROY(ig) io_glue_destroy(ig)
924 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
927 ICL_new_internal(r,g,b,a)
939 ICL_set_internal(cl,r,g,b,a)
946 ICL_set_internal(cl, r, g, b, a);
960 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
961 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
962 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
963 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
969 RETVAL = mymalloc(sizeof(i_color));
971 i_hsv_to_rgb(RETVAL);
979 RETVAL = mymalloc(sizeof(i_color));
981 i_rgb_to_hsv(RETVAL);
987 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
990 ICLF_new_internal(r, g, b, a)
998 Imager::Color::Float cl
1002 Imager::Color::Float cl
1006 EXTEND(SP, MAXCHANNELS);
1007 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1008 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1009 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1013 ICLF_set_internal(cl,r,g,b,a)
1014 Imager::Color::Float cl
1027 Imager::Color::Float
1029 Imager::Color::Float c
1031 RETVAL = mymalloc(sizeof(i_fcolor));
1033 i_hsv_to_rgbf(RETVAL);
1037 Imager::Color::Float
1039 Imager::Color::Float c
1041 RETVAL = mymalloc(sizeof(i_fcolor));
1043 i_rgb_to_hsvf(RETVAL);
1047 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1061 MODULE = Imager PACKAGE = Imager
1080 SvPV(ST(0), length);
1081 SvREFCNT_inc(ST(0));
1082 RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0));
1087 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1096 cbd = mymalloc(sizeof(struct cbdata));
1097 SvREFCNT_inc(writecb);
1098 cbd->writecb = writecb;
1099 SvREFCNT_inc(readcb);
1100 cbd->readcb = readcb;
1101 SvREFCNT_inc(seekcb);
1102 cbd->seekcb = seekcb;
1103 SvREFCNT_inc(closecb);
1104 cbd->closecb = closecb;
1105 cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
1106 if (maxwrite > CBDATA_BUFSIZE)
1107 maxwrite = CBDATA_BUFSIZE;
1108 cbd->maxlength = maxwrite;
1109 RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
1118 unsigned char* data;
1122 tlength = io_slurp(ig, &data);
1124 PUSHs(sv_2mortal(newSVpv((char *)data,tlength)));
1129 i_set_image_file_limits(width, height, bytes)
1135 i_get_image_file_limits()
1137 int width, height, bytes;
1139 if (i_get_image_file_limits(&width, &height, &bytes)) {
1141 PUSHs(sv_2mortal(newSViv(width)));
1142 PUSHs(sv_2mortal(newSViv(height)));
1143 PUSHs(sv_2mortal(newSViv(bytes)));
1146 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1149 i_io_write(ig, data_sv)
1157 if (SvUTF8(data_sv)) {
1158 data_sv = sv_2mortal(newSVsv(data_sv));
1159 /* yes, we want this to croak() if the SV can't be downgraded */
1160 sv_utf8_downgrade(data_sv, FALSE);
1163 data = SvPV(data_sv, size);
1164 RETVAL = i_io_write(ig, data, size);
1169 i_io_read(ig, buffer_sv, size)
1178 croak("size negative in call to i_io_read()");
1179 /* prevent an undefined value warning if they supplied an
1181 Orginally conditional on !SvOK(), but this will prevent the
1182 downgrade from croaking */
1183 sv_setpvn(buffer_sv, "", 0);
1185 if (SvUTF8(buffer_sv))
1186 sv_utf8_downgrade(buffer_sv, FALSE);
1188 buffer = SvGROW(buffer_sv, size+1);
1189 result = i_io_read(ig, buffer, size);
1191 SvCUR_set(buffer_sv, result);
1192 *SvEND(buffer_sv) = '\0';
1193 SvPOK_only(buffer_sv);
1195 PUSHs(sv_2mortal(newSViv(result)));
1201 i_io_read2(ig, size)
1210 croak("size negative in call to i_io_read2()");
1211 buffer_sv = newSV(size);
1212 buffer = SvGROW(buffer_sv, size+1);
1213 result = i_io_read(ig, buffer, size);
1215 SvCUR_set(buffer_sv, result);
1216 *SvEND(buffer_sv) = '\0';
1217 SvPOK_only(buffer_sv);
1219 PUSHs(sv_2mortal(buffer_sv));
1223 SvREFCNT_dec(buffer_sv);
1227 i_io_seek(ig, position, whence)
1240 MODULE = Imager PACKAGE = Imager
1251 while( (item=i_format_list[i++]) != NULL ) {
1253 PUSHs(sv_2mortal(newSVpv(item,0)));
1270 i_img_empty_ch(im,x,y,ch)
1277 i_sametype(im, x, y)
1283 i_sametype_chans(im, x, y, channels)
1290 i_init_log(name_sv,level)
1294 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1296 i_init_log(name, level);
1299 i_log_entry(string,level)
1318 i_img_info(im,info);
1320 PUSHs(sv_2mortal(newSViv(info[0])));
1321 PUSHs(sv_2mortal(newSViv(info[1])));
1322 PUSHs(sv_2mortal(newSViv(info[2])));
1323 PUSHs(sv_2mortal(newSViv(info[3])));
1329 i_img_setmask(im,ch_mask)
1338 i_img_getchannels(im)
1347 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1351 i_img_is_monochrome(im)
1357 result = i_img_is_monochrome(im, &zero_is_white);
1359 if (GIMME_V == G_ARRAY) {
1362 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1371 i_line(im,x1,y1,x2,y2,val,endp)
1381 i_line_aa(im,x1,y1,x2,y2,val,endp)
1391 i_box(im,x1,y1,x2,y2,val)
1400 i_box_filled(im,x1,y1,x2,y2,val)
1409 i_box_cfill(im,x1,y1,x2,y2,fill)
1415 Imager::FillHandle fill
1418 i_arc(im,x,y,rad,d1,d2,val)
1428 i_arc_aa(im,x,y,rad,d1,d2,val)
1438 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1445 Imager::FillHandle fill
1448 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1455 Imager::FillHandle fill
1459 i_circle_aa(im,x,y,rad,val)
1469 i_bezier_multi(im,xc,yc,val)
1482 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1483 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1484 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1485 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1486 av1=(AV*)SvRV(ST(1));
1487 av2=(AV*)SvRV(ST(2));
1488 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1490 x=mymalloc( len*sizeof(double) );
1491 y=mymalloc( len*sizeof(double) );
1492 for(i=0;i<len;i++) {
1493 sv1=(*(av_fetch(av1,i,0)));
1494 sv2=(*(av_fetch(av2,i,0)));
1495 x[i]=(double)SvNV(sv1);
1496 y[i]=(double)SvNV(sv2);
1498 i_bezier_multi(im,len,x,y,val);
1504 i_poly_aa(im,xc,yc,val)
1517 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1518 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1519 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1520 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1521 av1=(AV*)SvRV(ST(1));
1522 av2=(AV*)SvRV(ST(2));
1523 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1525 x=mymalloc( len*sizeof(double) );
1526 y=mymalloc( len*sizeof(double) );
1527 for(i=0;i<len;i++) {
1528 sv1=(*(av_fetch(av1,i,0)));
1529 sv2=(*(av_fetch(av2,i,0)));
1530 x[i]=(double)SvNV(sv1);
1531 y[i]=(double)SvNV(sv2);
1533 i_poly_aa(im,len,x,y,val);
1538 i_poly_aa_cfill(im,xc,yc,fill)
1540 Imager::FillHandle fill
1550 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1551 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1552 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1553 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1554 av1=(AV*)SvRV(ST(1));
1555 av2=(AV*)SvRV(ST(2));
1556 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1558 x=mymalloc( len*sizeof(double) );
1559 y=mymalloc( len*sizeof(double) );
1560 for(i=0;i<len;i++) {
1561 sv1=(*(av_fetch(av1,i,0)));
1562 sv2=(*(av_fetch(av2,i,0)));
1563 x[i]=(double)SvNV(sv1);
1564 y[i]=(double)SvNV(sv2);
1566 i_poly_aa_cfill(im,len,x,y,fill);
1573 i_flood_fill(im,seedx,seedy,dcol)
1580 i_flood_cfill(im,seedx,seedy,fill)
1584 Imager::FillHandle fill
1587 i_flood_fill_border(im,seedx,seedy,dcol, border)
1592 Imager::Color border
1595 i_flood_cfill_border(im,seedx,seedy,fill, border)
1599 Imager::FillHandle fill
1600 Imager::Color border
1604 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1616 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1633 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1644 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1657 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)
1673 i_flipxy(im, direction)
1678 i_rotate90(im, degrees)
1683 i_rotate_exact(im, amount, ...)
1687 i_color *backp = NULL;
1688 i_fcolor *fbackp = NULL;
1692 /* extract the bg colors if any */
1693 /* yes, this is kind of strange */
1694 for (i = 2; i < items; ++i) {
1696 if (sv_derived_from(sv1, "Imager::Color")) {
1697 IV tmp = SvIV((SV*)SvRV(sv1));
1698 backp = INT2PTR(i_color *, tmp);
1700 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1701 IV tmp = SvIV((SV*)SvRV(sv1));
1702 fbackp = INT2PTR(i_fcolor *, tmp);
1705 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1710 i_matrix_transform(im, xsize, ysize, matrix, ...)
1720 i_color *backp = NULL;
1721 i_fcolor *fbackp = NULL;
1723 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1724 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1725 av=(AV*)SvRV(ST(3));
1729 for (i = 0; i < len; ++i) {
1730 sv1=(*(av_fetch(av,i,0)));
1731 matrix[i] = SvNV(sv1);
1735 /* extract the bg colors if any */
1736 /* yes, this is kind of strange */
1737 for (i = 4; i < items; ++i) {
1739 if (sv_derived_from(sv1, "Imager::Color")) {
1740 IV tmp = SvIV((SV*)SvRV(sv1));
1741 backp = INT2PTR(i_color *, tmp);
1743 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1744 IV tmp = SvIV((SV*)SvRV(sv1));
1745 fbackp = INT2PTR(i_fcolor *, tmp);
1748 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
1753 i_gaussian(im,stdev)
1758 i_unsharp_mask(im,stdev,scale)
1773 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1774 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1775 av=(AV*)SvRV(ST(1));
1777 coeff=mymalloc( len*sizeof(float) );
1778 for(i=0;i<len;i++) {
1779 sv1=(*(av_fetch(av,i,0)));
1780 coeff[i]=(float)SvNV(sv1);
1782 i_conv(im,coeff,len);
1786 i_convert(src, avmain)
1798 outchan = av_len(avmain)+1;
1799 /* find the biggest */
1801 for (j=0; j < outchan; ++j) {
1802 temp = av_fetch(avmain, j, 0);
1803 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1804 avsub = (AV*)SvRV(*temp);
1805 len = av_len(avsub)+1;
1810 coeff = mymalloc(sizeof(float) * outchan * inchan);
1811 for (j = 0; j < outchan; ++j) {
1812 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1813 len = av_len(avsub)+1;
1814 for (i = 0; i < len; ++i) {
1815 temp = av_fetch(avsub, i, 0);
1817 coeff[i+j*inchan] = SvNV(*temp);
1819 coeff[i+j*inchan] = 0;
1822 coeff[i++ + j*inchan] = 0;
1824 RETVAL = i_convert(src, coeff, outchan, inchan);
1834 unsigned int mask = 0;
1840 unsigned char (*maps)[256];
1842 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1843 croak("i_map: parameter 2 must be an arrayref\n");
1844 avmain = (AV*)SvRV(ST(1));
1845 len = av_len(avmain)+1;
1846 if (im->channels < len) len = im->channels;
1848 maps = mymalloc( len * sizeof(unsigned char [256]) );
1850 for (j=0; j<len ; j++) {
1851 temp = av_fetch(avmain, j, 0);
1852 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1853 avsub = (AV*)SvRV(*temp);
1854 if(av_len(avsub) != 255) continue;
1856 for (i=0; i<256 ; i++) {
1858 temp = av_fetch(avsub, i, 0);
1859 val = temp ? SvIV(*temp) : 0;
1861 if (val>255) val = 255;
1866 i_map(im, maps, mask);
1879 i_init_fonts(t1log=0)
1894 i_t1_destroy(font_id)
1899 i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
1918 str = SvPV(str_sv, len);
1919 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
1926 i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
1935 int cords[BOUNDING_BOX_COUNT];
1943 str = SvPV(str_sv, len);
1944 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
1947 for (i = 0; i < rc; ++i)
1948 PUSHs(sv_2mortal(newSViv(cords[i])));
1954 i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
1973 str = SvPV(str_sv, len);
1974 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
1980 i_t1_has_chars(handle, text_sv, utf8 = 0)
1992 if (SvUTF8(text_sv))
1995 text = SvPV(text_sv, len);
1996 work = mymalloc(len);
1997 count = i_t1_has_chars(handle, text, len, utf8, work);
1998 if (GIMME_V == G_ARRAY) {
2000 for (i = 0; i < count; ++i) {
2001 PUSHs(sv_2mortal(newSViv(work[i])));
2006 PUSHs(sv_2mortal(newSVpv(work, count)));
2011 i_t1_face_name(handle)
2017 len = i_t1_face_name(handle, name, sizeof(name));
2020 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2024 i_t1_glyph_name(handle, text_sv, utf8 = 0)
2035 if (SvUTF8(text_sv))
2038 text = SvPV(text_sv, work_len);
2043 ch = i_utf8_advance(&text, &len);
2045 i_push_error(0, "invalid UTF8 character");
2054 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
2055 PUSHs(sv_2mortal(newSVpv(name, 0)));
2058 PUSHs(&PL_sv_undef);
2072 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2074 #define TT_DESTROY(handle) i_tt_destroy(handle)
2078 Imager::Font::TT handle
2081 MODULE = Imager PACKAGE = Imager
2085 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
2086 Imager::Font::TT handle
2104 str = SvPV(str_sv, len);
2105 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2106 len, smooth, utf8, align);
2112 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
2113 Imager::Font::TT handle
2131 str = SvPV(str_sv, len);
2132 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2133 smooth, utf8, align);
2139 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
2140 Imager::Font::TT handle
2145 int cords[BOUNDING_BOX_COUNT],rc;
2154 str = SvPV(str_sv, len);
2155 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2157 for (i = 0; i < rc; ++i) {
2158 PUSHs(sv_2mortal(newSViv(cords[i])));
2163 i_tt_has_chars(handle, text_sv, utf8)
2164 Imager::Font::TT handle
2175 if (SvUTF8(text_sv))
2178 text = SvPV(text_sv, len);
2179 work = mymalloc(len);
2180 count = i_tt_has_chars(handle, text, len, utf8, work);
2181 if (GIMME_V == G_ARRAY) {
2183 for (i = 0; i < count; ++i) {
2184 PUSHs(sv_2mortal(newSViv(work[i])));
2189 PUSHs(sv_2mortal(newSVpv(work, count)));
2194 i_tt_dump_names(handle)
2195 Imager::Font::TT handle
2198 i_tt_face_name(handle)
2199 Imager::Font::TT handle
2204 len = i_tt_face_name(handle, name, sizeof(name));
2207 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2211 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2212 Imager::Font::TT handle
2223 if (SvUTF8(text_sv))
2226 text = SvPV(text_sv, work_len);
2231 ch = i_utf8_advance(&text, &len);
2233 i_push_error(0, "invalid UTF8 character");
2242 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2243 PUSHs(sv_2mortal(newSVpv(name, 0)));
2246 PUSHs(&PL_sv_undef);
2255 i_writejpeg_wiol(im, ig, qfactor)
2271 rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
2272 if (iptc_itext == NULL) {
2275 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2280 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2282 PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
2293 i_test_format_probe(ig, length)
2302 i_readtiff_wiol(ig, allow_incomplete, page=0)
2304 int allow_incomplete
2308 i_readtiff_multi_wiol(ig, length)
2316 imgs = i_readtiff_multi_wiol(ig, length, &count);
2319 for (i = 0; i < count; ++i) {
2320 SV *sv = sv_newmortal();
2321 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2329 i_writetiff_wiol(im, ig)
2334 i_writetiff_multi_wiol(ig, ...)
2342 croak("Usage: i_writetiff_multi_wiol(ig, images...)");
2343 img_count = items - 1;
2345 if (img_count < 1) {
2348 i_push_error(0, "You need to specify images to save");
2351 imgs = mymalloc(sizeof(i_img *) * img_count);
2352 for (i = 0; i < img_count; ++i) {
2355 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2356 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2360 i_push_error(0, "Only images can be saved");
2367 RETVAL = i_writetiff_multi_wiol(ig, imgs, img_count);
2375 i_writetiff_wiol_faxable(im, ig, fine)
2381 i_writetiff_multi_wiol_faxable(ig, fine, ...)
2390 croak("Usage: i_writetiff_multi_wiol_faxable(ig, fine, images...)");
2391 img_count = items - 2;
2393 if (img_count < 1) {
2396 i_push_error(0, "You need to specify images to save");
2399 imgs = mymalloc(sizeof(i_img *) * img_count);
2400 for (i = 0; i < img_count; ++i) {
2403 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2404 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2408 i_push_error(0, "Only images can be saved");
2415 RETVAL = i_writetiff_multi_wiol_faxable(ig, imgs, img_count, fine);
2426 i_tiff_has_compression(name)
2429 #endif /* HAVE_LIBTIFF */
2435 i_readpng_wiol(ig, length)
2441 i_writepng_wiol(im, ig)
2454 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
2457 i_writegif(im,fd,colors,pixdev,fixed)
2464 Imager__Color fixed;
2471 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
2472 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2473 av=(AV*)SvRV(ST(4));
2474 fixedlen=av_len(av)+1;
2475 fixed=mymalloc( fixedlen*sizeof(i_color) );
2476 for(i=0;i<fixedlen;i++) {
2477 sv1=(*(av_fetch(av,i,0)));
2478 if (sv_derived_from(sv1, "Imager::Color")) {
2479 Itmp = SvIV((SV*)SvRV(sv1));
2480 tmp = INT2PTR(i_color*, Itmp);
2481 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
2484 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
2486 ST(0) = sv_newmortal();
2487 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2488 else sv_setiv(ST(0), (IV)RETVAL);
2494 i_writegifmc(im,fd,colors)
2501 i_writegif_gen(fd, ...)
2506 i_img **imgs = NULL;
2512 croak("Usage: i_writegif_gen(fd,hashref, images...)");
2513 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2514 croak("i_writegif_gen: Second argument must be a hash ref");
2515 hv = (HV *)SvRV(ST(1));
2516 memset(&quant, 0, sizeof(quant));
2517 quant.mc_size = 256;
2518 quant.transp = tr_threshold;
2519 quant.tr_threshold = 127;
2520 handle_quant_opts(&quant, hv);
2521 img_count = items - 2;
2523 if (img_count < 1) {
2526 i_push_error(0, "You need to specify images to save");
2529 imgs = mymalloc(sizeof(i_img *) * img_count);
2530 for (i = 0; i < img_count; ++i) {
2533 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2534 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2538 i_push_error(0, "Only images can be saved");
2544 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
2548 copy_colors_back(hv, &quant);
2551 ST(0) = sv_newmortal();
2552 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2553 else sv_setiv(ST(0), (IV)RETVAL);
2554 cleanup_quant_opts(&quant);
2558 i_writegif_callback(cb, maxbuffer,...)
2562 i_img **imgs = NULL;
2569 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2570 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2571 croak("i_writegif_callback: Second argument must be a hash ref");
2572 hv = (HV *)SvRV(ST(2));
2573 memset(&quant, 0, sizeof(quant));
2574 quant.mc_size = 256;
2575 quant.transp = tr_threshold;
2576 quant.tr_threshold = 127;
2577 handle_quant_opts(&quant, hv);
2578 img_count = items - 3;
2580 if (img_count < 1) {
2584 imgs = mymalloc(sizeof(i_img *) * img_count);
2585 for (i = 0; i < img_count; ++i) {
2588 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2589 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2598 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count);
2602 copy_colors_back(hv, &quant);
2605 ST(0) = sv_newmortal();
2606 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2607 else sv_setiv(ST(0), (IV)RETVAL);
2608 cleanup_quant_opts(&quant);
2611 i_writegif_wiol(ig, opts,...)
2615 i_img **imgs = NULL;
2621 croak("Usage: i_writegif_wiol(IO,hashref, images...)");
2622 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2623 croak("i_writegif_callback: Second argument must be a hash ref");
2624 hv = (HV *)SvRV(ST(1));
2625 memset(&quant, 0, sizeof(quant));
2626 quant.mc_size = 256;
2627 quant.transp = tr_threshold;
2628 quant.tr_threshold = 127;
2629 handle_quant_opts(&quant, hv);
2630 img_count = items - 2;
2632 if (img_count < 1) {
2636 imgs = mymalloc(sizeof(i_img *) * img_count);
2637 for (i = 0; i < img_count; ++i) {
2640 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
2641 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
2649 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
2653 copy_colors_back(hv, &quant);
2656 ST(0) = sv_newmortal();
2657 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2658 else sv_setiv(ST(0), (IV)RETVAL);
2659 cleanup_quant_opts(&quant);
2672 colour_table = NULL;
2675 if(GIMME_V == G_ARRAY) {
2676 rimg = i_readgif(fd,&colour_table,&colours);
2678 /* don't waste time with colours if they aren't wanted */
2679 rimg = i_readgif(fd,NULL,NULL);
2682 if (colour_table == NULL) {
2685 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2688 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2689 /* I don't know if I have the reference counts right or not :( */
2690 /* Neither do I :-) */
2691 /* No Idea here either */
2694 av_extend(ct, colours);
2695 for(q=0; q<colours; q++) {
2697 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2698 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2700 myfree(colour_table);
2704 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2706 PUSHs(newRV_noinc((SV*)ct));
2720 colour_table = NULL;
2723 if(GIMME_V == G_ARRAY) {
2724 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2726 /* don't waste time with colours if they aren't wanted */
2727 rimg = i_readgif_wiol(ig,NULL,NULL);
2730 if (colour_table == NULL) {
2733 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2736 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2737 /* I don't know if I have the reference counts right or not :( */
2738 /* Neither do I :-) */
2739 /* No Idea here either */
2742 av_extend(ct, colours);
2743 for(q=0; q<colours; q++) {
2745 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2746 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2748 myfree(colour_table);
2752 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2754 PUSHs(newRV_noinc((SV*)ct));
2758 i_readgif_single_wiol(ig, page=0)
2763 i_readgif_scalar(...)
2775 data = (char *)SvPV(ST(0), length);
2779 if(GIMME_V == G_ARRAY) {
2780 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2782 /* don't waste time with colours if they aren't wanted */
2783 rimg=i_readgif_scalar(data,length,NULL,NULL);
2786 if (colour_table == NULL) {
2789 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2792 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2793 /* I don't know if I have the reference counts right or not :( */
2794 /* Neither do I :-) */
2796 av_extend(ct, colours);
2797 for(q=0; q<colours; q++) {
2799 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2800 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2802 myfree(colour_table);
2806 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2808 PUSHs(newRV_noinc((SV*)ct));
2812 i_readgif_callback(...)
2827 if(GIMME_V == G_ARRAY) {
2828 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2830 /* don't waste time with colours if they aren't wanted */
2831 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2834 if (colour_table == NULL) {
2837 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2840 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2841 /* I don't know if I have the reference counts right or not :( */
2842 /* Neither do I :-) */
2843 /* Neither do I - maybe I'll move this somewhere */
2845 av_extend(ct, colours);
2846 for(q=0; q<colours; q++) {
2848 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2849 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2851 myfree(colour_table);
2855 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2857 PUSHs(newRV_noinc((SV*)ct));
2868 imgs = i_readgif_multi(fd, &count);
2871 for (i = 0; i < count; ++i) {
2872 SV *sv = sv_newmortal();
2873 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2880 i_readgif_multi_scalar(data)
2888 data = (char *)SvPV(ST(0), length);
2889 imgs = i_readgif_multi_scalar(data, length, &count);
2892 for (i = 0; i < count; ++i) {
2893 SV *sv = sv_newmortal();
2894 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2901 i_readgif_multi_callback(cb)
2909 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2912 for (i = 0; i < count; ++i) {
2913 SV *sv = sv_newmortal();
2914 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2921 i_readgif_multi_wiol(ig)
2928 imgs = i_readgif_multi_wiol(ig, &count);
2931 for (i = 0; i < count; ++i) {
2932 SV *sv = sv_newmortal();
2933 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2945 i_readpnm_wiol(ig, allow_incomplete)
2947 int allow_incomplete
2951 i_writeppm_wiol(im, ig)
2957 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2966 i_writeraw_wiol(im,ig)
2971 i_writebmp_wiol(im,ig)
2976 i_readbmp_wiol(ig, allow_incomplete=0)
2978 int allow_incomplete
2982 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2991 idlen = SvCUR(ST(4));
2992 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2998 i_readtga_wiol(ig, length)
3006 i_scaleaxis(im,Value,Axis)
3012 i_scale_nn(im,scx,scy)
3018 i_scale_mixing(im, width, height)
3028 i_count_colors(im,maxc)
3033 i_get_anonymous_color_histo(im, maxc = 0x40000000)
3038 unsigned int * col_usage = NULL;
3041 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
3042 EXTEND(SP, col_cnt);
3043 for (i = 0; i < col_cnt; i++) {
3044 PUSHs(sv_2mortal(newSViv( col_usage[i])));
3051 i_transform(im,opx,opy,parm)
3064 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
3065 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
3066 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
3067 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
3068 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
3069 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
3070 av=(AV*)SvRV(ST(1));
3072 opx=mymalloc( opxl*sizeof(int) );
3073 for(i=0;i<opxl;i++) {
3074 sv1=(*(av_fetch(av,i,0)));
3075 opx[i]=(int)SvIV(sv1);
3077 av=(AV*)SvRV(ST(2));
3079 opy=mymalloc( opyl*sizeof(int) );
3080 for(i=0;i<opyl;i++) {
3081 sv1=(*(av_fetch(av,i,0)));
3082 opy[i]=(int)SvIV(sv1);
3084 av=(AV*)SvRV(ST(3));
3085 parmlen=av_len(av)+1;
3086 parm=mymalloc( parmlen*sizeof(double) );
3087 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
3088 sv1=(*(av_fetch(av,i,0)));
3089 parm[i]=(double)SvNV(sv1);
3091 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
3095 ST(0) = sv_newmortal();
3096 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3097 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3100 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
3125 in_imgs_count = av_len(av_in_imgs)+1;
3126 for (i = 0; i < in_imgs_count; ++i) {
3127 sv1 = *av_fetch(av_in_imgs, i, 0);
3128 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3129 croak("sv_in_img must contain only images");
3132 if (in_imgs_count > 0) {
3133 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
3134 for (i = 0; i < in_imgs_count; ++i) {
3135 sv1 = *av_fetch(av_in_imgs,i,0);
3136 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3137 croak("Parameter 5 must contain only images");
3139 tmp = SvIV((SV*)SvRV(sv1));
3140 in_imgs[i] = INT2PTR(i_img*, tmp);
3144 /* no input images */
3147 /* default the output size from the first input if possible */
3149 width = SvIV(sv_width);
3150 else if (in_imgs_count)
3151 width = in_imgs[0]->xsize;
3153 croak("No output image width supplied");
3155 if (SvOK(sv_height))
3156 height = SvIV(sv_height);
3157 else if (in_imgs_count)
3158 height = in_imgs[0]->ysize;
3160 croak("No output image height supplied");
3162 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
3163 if (ops_len % sizeof(struct rm_op))
3164 croak("Imager: Parameter 3 must be a bitmap of regops\n");
3165 ops_count = ops_len / sizeof(struct rm_op);
3167 n_regs_count = av_len(av_n_regs)+1;
3168 n_regs = mymalloc(n_regs_count * sizeof(double));
3169 for (i = 0; i < n_regs_count; ++i) {
3170 sv1 = *av_fetch(av_n_regs,i,0);
3172 n_regs[i] = SvNV(sv1);
3174 c_regs_count = av_len(av_c_regs)+1;
3175 c_regs = mymalloc(c_regs_count * sizeof(i_color));
3176 /* I don't bother initializing the colou?r registers */
3178 RETVAL=i_transform2(width, height, channels, ops, ops_count,
3179 n_regs, n_regs_count,
3180 c_regs, c_regs_count, in_imgs, in_imgs_count);
3185 ST(0) = sv_newmortal();
3186 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3187 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3191 i_contrast(im,intensity)
3200 i_noise(im,amount,type)
3206 i_bumpmap(im,bump,channel,light_x,light_y,strength)
3216 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
3235 i_postlevels(im,levels)
3245 i_watermark(im,wmark,tx,ty,pixdiff)
3247 Imager::ImgRaw wmark
3254 i_autolevels(im,lsat,usat,skew)
3261 i_radnoise(im,xo,yo,rscale,ascale)
3269 i_turbnoise(im, xo, yo, scale)
3292 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
3293 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3294 croak("i_gradgen: Second argument must be an array ref");
3295 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3296 croak("i_gradgen: Third argument must be an array ref");
3297 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3298 croak("i_gradgen: Fourth argument must be an array ref");
3299 axx = (AV *)SvRV(ST(1));
3300 ayy = (AV *)SvRV(ST(2));
3301 ac = (AV *)SvRV(ST(3));
3302 dmeasure = (int)SvIV(ST(4));
3304 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3305 num = num <= av_len(ac) ? num : av_len(ac);
3307 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
3308 xo = mymalloc( sizeof(int) * num );
3309 yo = mymalloc( sizeof(int) * num );
3310 ival = mymalloc( sizeof(i_color) * num );
3311 for(i = 0; i<num; i++) {
3312 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3313 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3314 sv = *av_fetch(ac, i, 0);
3315 if ( !sv_derived_from(sv, "Imager::Color") ) {
3316 free(axx); free(ayy); free(ac);
3317 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
3319 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
3321 i_gradgen(im, num, xo, yo, ival, dmeasure);
3327 i_diff_image(im, im2, mindist=0)
3333 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3343 double ssample_param
3347 i_fountain_seg *segs;
3349 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
3350 croak("i_fountain: argument 11 must be an array ref");
3352 asegs = (AV *)SvRV(ST(10));
3353 segs = load_fount_segs(asegs, &count);
3354 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
3355 super_sample, ssample_param, count, segs);
3361 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3370 double ssample_param
3374 i_fountain_seg *segs;
3376 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
3377 croak("i_fountain: argument 11 must be an array ref");
3379 asegs = (AV *)SvRV(ST(9));
3380 segs = load_fount_segs(asegs, &count);
3381 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
3382 super_sample, ssample_param, count, segs);
3395 errors = i_errors();
3397 while (errors[i].msg) {
3399 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
3400 if (!av_store(av, 0, sv)) {
3403 sv = newSViv(errors[i].code);
3404 if (!av_store(av, 1, sv)) {
3407 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
3415 i_push_error(code, msg)
3420 i_nearest_color(im, ...)
3435 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
3436 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3437 croak("i_nearest_color: Second argument must be an array ref");
3438 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3439 croak("i_nearest_color: Third argument must be an array ref");
3440 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3441 croak("i_nearest_color: Fourth argument must be an array ref");
3442 axx = (AV *)SvRV(ST(1));
3443 ayy = (AV *)SvRV(ST(2));
3444 ac = (AV *)SvRV(ST(3));
3445 dmeasure = (int)SvIV(ST(4));
3447 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3448 num = num <= av_len(ac) ? num : av_len(ac);
3450 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
3451 xo = mymalloc( sizeof(int) * num );
3452 yo = mymalloc( sizeof(int) * num );
3453 ival = mymalloc( sizeof(i_color) * num );
3454 for(i = 0; i<num; i++) {
3455 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3456 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3457 sv = *av_fetch(ac, i, 0);
3458 if ( !sv_derived_from(sv, "Imager::Color") ) {
3459 free(axx); free(ayy); free(ac);
3460 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
3462 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
3464 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
3478 rc=DSO_open(filename,&evstr);
3482 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
3483 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
3486 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
3492 DSO_close(dso_handle)
3496 DSO_funclist(dso_handle_v)
3500 DSO_handle *dso_handle;
3501 func_ptr *functions;
3503 dso_handle=(DSO_handle*)dso_handle_v;
3504 functions = DSO_funclist(dso_handle);
3506 while( functions[i].name != NULL) {
3508 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
3510 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
3514 DSO_call(handle,func_index,hv)
3520 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3521 hv=(HV*)SvRV(ST(2));
3522 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3523 DSO_call( (DSO_handle *)handle,func_index,hv);
3528 i_get_pixel(im, x, y)
3535 color = (i_color *)mymalloc(sizeof(i_color));
3536 if (i_gpix(im, x, y, color) == 0) {
3537 RETVAL = NEWSV(0, 0);
3538 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
3542 RETVAL = &PL_sv_undef;
3549 i_ppix(im, x, y, cl)
3556 i_img_pal_new(x, y, channels, maxpal)
3563 i_img_to_pal(src, quant)
3569 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3570 croak("i_img_to_pal: second argument must be a hash ref");
3571 hv = (HV *)SvRV(ST(1));
3572 memset(&quant, 0, sizeof(quant));
3573 quant.mc_size = 256;
3574 handle_quant_opts(&quant, hv);
3575 RETVAL = i_img_to_pal(src, &quant);
3577 copy_colors_back(hv, &quant);
3579 cleanup_quant_opts(&quant);
3598 work = mymalloc((r-l) * sizeof(i_palidx));
3599 count = i_gpal(im, l, r, y, work);
3600 if (GIMME_V == G_ARRAY) {
3602 for (i = 0; i < count; ++i) {
3603 PUSHs(sv_2mortal(newSViv(work[i])));
3608 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3613 if (GIMME_V != G_ARRAY) {
3615 PUSHs(&PL_sv_undef);
3620 i_ppal(im, l, y, ...)
3629 work = mymalloc(sizeof(i_palidx) * (items-3));
3630 for (i=0; i < items-3; ++i) {
3631 work[i] = SvIV(ST(i+3));
3633 validate_i_ppal(im, work, items - 3);
3634 RETVAL = i_ppal(im, l, l+items-3, y, work);
3644 i_ppal_p(im, l, y, data)
3650 i_palidx const *work;
3653 work = (i_palidx const *)SvPV(data, len);
3654 len /= sizeof(i_palidx);
3656 validate_i_ppal(im, work, len);
3657 RETVAL = i_ppal(im, l, l+len, y, work);
3666 i_addcolors(im, ...)
3674 croak("i_addcolors: no colors to add");
3675 colors = mymalloc((items-1) * sizeof(i_color));
3676 for (i=0; i < items-1; ++i) {
3677 if (sv_isobject(ST(i+1))
3678 && sv_derived_from(ST(i+1), "Imager::Color")) {
3679 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3680 colors[i] = *INT2PTR(i_color *, tmp);
3684 croak("i_addcolor: pixels must be Imager::Color objects");
3687 index = i_addcolors(im, colors, items-1);
3690 RETVAL = newSVpv("0 but true", 0);
3692 else if (index == -1) {
3693 RETVAL = &PL_sv_undef;
3696 RETVAL = newSViv(index);
3702 i_setcolors(im, index, ...)
3710 croak("i_setcolors: no colors to add");
3711 colors = mymalloc((items-2) * sizeof(i_color));
3712 for (i=0; i < items-2; ++i) {
3713 if (sv_isobject(ST(i+2))
3714 && sv_derived_from(ST(i+2), "Imager::Color")) {
3715 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3716 colors[i] = *INT2PTR(i_color *, tmp);
3720 croak("i_setcolors: pixels must be Imager::Color objects");
3723 RETVAL = i_setcolors(im, index, colors, items-2);
3729 i_getcolors(im, index, ...)
3738 croak("i_getcolors: too many arguments");
3740 count = SvIV(ST(2));
3742 croak("i_getcolors: count must be positive");
3743 colors = mymalloc(sizeof(i_color) * count);
3744 if (i_getcolors(im, index, colors, count)) {
3745 for (i = 0; i < count; ++i) {
3747 SV *sv = sv_newmortal();
3748 pv = mymalloc(sizeof(i_color));
3750 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3766 i_findcolor(im, color)
3772 if (i_findcolor(im, color, &index)) {
3773 RETVAL = newSViv(index);
3776 RETVAL = &PL_sv_undef;
3794 i_gsamp(im, l, r, y, ...)
3806 croak("No channel numbers supplied to g_samp()");
3808 chan_count = items - 4;
3809 chans = mymalloc(sizeof(int) * chan_count);
3810 for (i = 0; i < chan_count; ++i)
3811 chans[i] = SvIV(ST(i+4));
3812 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
3813 count = i_gsamp(im, l, r, y, data, chans, chan_count);
3815 if (GIMME_V == G_ARRAY) {
3817 for (i = 0; i < count; ++i)
3818 PUSHs(sv_2mortal(newSViv(data[i])));
3822 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3827 if (GIMME_V != G_ARRAY) {
3829 PUSHs(&PL_sv_undef);
3834 i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3850 croak("No channel numbers supplied to g_samp()");
3852 chan_count = items - 7;
3853 chans = mymalloc(sizeof(int) * chan_count);
3854 for (i = 0; i < chan_count; ++i)
3855 chans[i] = SvIV(ST(i+7));
3856 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3857 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3859 for (i = 0; i < count; ++i) {
3860 av_store(target, i+offset, newSVuv(data[i]));
3872 i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3890 if (SvOK(channels_sv)) {
3892 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3893 croak("channels is not an array ref");
3895 channels_av = (AV *)SvRV(channels_sv);
3896 chan_count = av_len(channels_av) + 1;
3897 if (chan_count < 1) {
3898 croak("i_psamp_bits: no channels provided");
3900 channels = mymalloc(sizeof(int) * chan_count);
3901 for (i = 0; i < chan_count; ++i)
3902 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3905 chan_count = im->channels;
3909 data_count = av_len(data_av) + 1;
3910 if (data_offset < 0) {
3911 croak("data_offset must by non-negative");
3913 if (data_offset > data_count) {
3914 croak("data_offset greater than number of samples supplied");
3916 if (pixel_count == -1 ||
3917 data_offset + pixel_count * chan_count > data_count) {
3918 pixel_count = (data_count - data_offset) / chan_count;
3921 data_used = pixel_count * chan_count;
3922 data = mymalloc(sizeof(unsigned) * data_count);
3923 for (i = 0; i < data_used; ++i)
3924 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3926 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3937 i_img_masked_new(targ, mask, x, y, w, h)
3947 if (!sv_isobject(ST(1))
3948 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3949 croak("i_img_masked_new: parameter 2 must undef or an image");
3951 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3955 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3960 i_plin(im, l, y, ...)
3971 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3972 /* supplied as a byte string */
3973 work = (i_color *)SvPV(ST(3), len);
3974 count = len / sizeof(i_color);
3975 if (count * sizeof(i_color) != len) {
3976 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3978 RETVAL = i_plin(im, l, l+count, y, work);
3981 work = mymalloc(sizeof(i_color) * (items-3));
3982 for (i=0; i < items-3; ++i) {
3983 if (sv_isobject(ST(i+3))
3984 && sv_derived_from(ST(i+3), "Imager::Color")) {
3985 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3986 work[i] = *INT2PTR(i_color *, tmp);
3990 croak("i_plin: pixels must be Imager::Color objects");
3993 RETVAL = i_plin(im, l, l+items-3, y, work);
4004 i_ppixf(im, x, y, cl)
4008 Imager::Color::Float cl
4011 i_gsampf(im, l, r, y, ...)
4023 croak("No channel numbers supplied to g_sampf()");
4025 chan_count = items - 4;
4026 chans = mymalloc(sizeof(int) * chan_count);
4027 for (i = 0; i < chan_count; ++i)
4028 chans[i] = SvIV(ST(i+4));
4029 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
4030 count = i_gsampf(im, l, r, y, data, chans, chan_count);
4032 if (GIMME_V == G_ARRAY) {
4034 for (i = 0; i < count; ++i)
4035 PUSHs(sv_2mortal(newSVnv(data[i])));
4039 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
4044 if (GIMME_V != G_ARRAY) {
4046 PUSHs(&PL_sv_undef);
4051 i_plinf(im, l, y, ...)
4062 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
4063 /* supplied as a byte string */
4064 work = (i_fcolor *)SvPV(ST(3), len);
4065 count = len / sizeof(i_fcolor);
4066 if (count * sizeof(i_fcolor) != len) {
4067 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
4069 RETVAL = i_plinf(im, l, l+count, y, work);
4072 work = mymalloc(sizeof(i_fcolor) * (items-3));
4073 for (i=0; i < items-3; ++i) {
4074 if (sv_isobject(ST(i+3))
4075 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
4076 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
4077 work[i] = *INT2PTR(i_fcolor *, tmp);
4081 croak("i_plinf: pixels must be Imager::Color::Float objects");
4085 RETVAL = i_plinf(im, l, l+items-3, y, work);
4103 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
4104 if (i_gpixf(im, x, y, color) == 0) {
4105 RETVAL = NEWSV(0,0);
4106 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
4110 RETVAL = &PL_sv_undef;
4126 vals = mymalloc((r-l) * sizeof(i_color));
4127 memset(vals, 0, (r-l) * sizeof(i_color));
4128 count = i_glin(im, l, r, y, vals);
4129 if (GIMME_V == G_ARRAY) {
4131 for (i = 0; i < count; ++i) {
4133 i_color *col = mymalloc(sizeof(i_color));
4135 sv = sv_newmortal();
4136 sv_setref_pv(sv, "Imager::Color", (void *)col);
4142 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
4148 i_glinf(im, l, r, y)
4158 for (i = 0; i < MAXCHANNELS; ++i)
4159 zero.channel[i] = 0;
4161 vals = mymalloc((r-l) * sizeof(i_fcolor));
4162 for (i = 0; i < r-l; ++i)
4164 count = i_glinf(im, l, r, y, vals);
4165 if (GIMME_V == G_ARRAY) {
4167 for (i = 0; i < count; ++i) {
4169 i_fcolor *col = mymalloc(sizeof(i_fcolor));
4171 sv = sv_newmortal();
4172 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
4178 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
4184 i_img_16_new(x, y, ch)
4194 i_img_double_new(x, y, ch)
4200 i_tags_addn(im, name, code, idata)
4209 name = SvPV(ST(1), len);
4212 RETVAL = i_tags_addn(&im->tags, name, code, idata);
4217 i_tags_add(im, name, code, data, idata)
4227 name = SvPV(ST(1), len);
4231 data = SvPV(ST(3), len);
4236 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
4241 i_tags_find(im, name, start)
4248 if (i_tags_find(&im->tags, name, start, &entry)) {
4250 RETVAL = newSVpv("0 but true", 0);
4252 RETVAL = newSViv(entry);
4254 RETVAL = &PL_sv_undef;
4260 i_tags_findn(im, code, start)
4267 if (i_tags_findn(&im->tags, code, start, &entry)) {
4269 RETVAL = newSVpv("0 but true", 0);
4271 RETVAL = newSViv(entry);
4274 RETVAL = &PL_sv_undef;
4280 i_tags_delete(im, entry)
4284 RETVAL = i_tags_delete(&im->tags, entry);
4289 i_tags_delbyname(im, name)
4293 RETVAL = i_tags_delbyname(&im->tags, name);
4298 i_tags_delbycode(im, code)
4302 RETVAL = i_tags_delbycode(&im->tags, code);
4307 i_tags_get(im, index)
4311 if (index >= 0 && index < im->tags.count) {
4312 i_img_tag *entry = im->tags.tags + index;
4316 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
4319 PUSHs(sv_2mortal(newSViv(entry->code)));
4322 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
4325 PUSHs(sv_2mortal(newSViv(entry->idata)));
4330 i_tags_get_string(im, what_sv)
4334 char const *name = NULL;
4338 if (SvIOK(what_sv)) {
4339 code = SvIV(what_sv);
4343 name = SvPV_nolen(what_sv);
4346 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
4348 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
4355 RETVAL = im->tags.count;
4362 i_wf_bbox(face, size, text_sv, utf8=0)
4368 int cords[BOUNDING_BOX_COUNT];
4373 text = SvPV(text_sv, text_len);
4375 if (SvUTF8(text_sv))
4378 if (rc = i_wf_bbox(face, size, text, text_len, cords, utf8)) {
4380 for (i = 0; i < rc; ++i)
4381 PUSHs(sv_2mortal(newSViv(cords[i])));
4385 i_wf_text(face, im, tx, ty, cl, size, text_sv, align, aa, utf8 = 0)
4400 text = SvPV(text_sv, text_len);
4402 if (SvUTF8(text_sv))
4405 RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, text_len,
4411 i_wf_cp(face, im, tx, ty, channel, size, text_sv, align, aa, utf8 = 0)
4426 text = SvPV(text_sv, text_len);
4428 if (SvUTF8(text_sv))
4431 RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, text_len,
4448 MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_
4450 #define FT2_DESTROY(font) i_ft2_destroy(font)
4454 Imager::Font::FT2 font
4456 MODULE = Imager PACKAGE = Imager::Font::FreeType2
4459 i_ft2_new(name, index)
4464 i_ft2_setdpi(font, xdpi, ydpi)
4465 Imager::Font::FT2 font
4471 Imager::Font::FT2 font
4475 if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
4477 PUSHs(sv_2mortal(newSViv(xdpi)));
4478 PUSHs(sv_2mortal(newSViv(ydpi)));
4482 i_ft2_sethinting(font, hinting)
4483 Imager::Font::FT2 font
4487 i_ft2_settransform(font, matrix)
4488 Imager::Font::FT2 font
4496 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4497 croak("i_ft2_settransform: parameter 2 must be an array ref\n");
4498 av=(AV*)SvRV(ST(1));
4502 for (i = 0; i < len; ++i) {
4503 sv1=(*(av_fetch(av,i,0)));
4504 matrix[i] = SvNV(sv1);
4508 RETVAL = i_ft2_settransform(font, matrix);
4513 i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
4514 Imager::Font::FT2 font
4520 int bbox[BOUNDING_BOX_COUNT];
4526 text = SvPV(text_sv, text_len);
4528 if (SvUTF8(text_sv))
4531 rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8);
4534 for (i = 0; i < rc; ++i)
4535 PUSHs(sv_2mortal(newSViv(bbox[i])));
4539 i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
4540 Imager::Font::FT2 font
4554 if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
4557 for (i = 0; i < 8; ++i)
4558 PUSHs(sv_2mortal(newSViv(bbox[i])));
4562 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
4563 Imager::Font::FT2 font
4579 if (SvUTF8(ST(7))) {
4583 text = SvPV(ST(7), len);
4584 RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
4585 len, align, aa, vlayout, utf8);
4590 i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text_sv, align, aa, vlayout, utf8)
4591 Imager::Font::FT2 font
4611 text = SvPV(text_sv, len);
4612 RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
4613 len, align, aa, vlayout, 1);
4618 ft2_transform_box(font, x0, x1, x2, x3)
4619 Imager::Font::FT2 font
4627 box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
4628 ft2_transform_box(font, box);
4630 PUSHs(sv_2mortal(newSViv(box[0])));
4631 PUSHs(sv_2mortal(newSViv(box[1])));
4632 PUSHs(sv_2mortal(newSViv(box[2])));
4633 PUSHs(sv_2mortal(newSViv(box[3])));
4636 i_ft2_has_chars(handle, text_sv, utf8)
4637 Imager::Font::FT2 handle
4648 if (SvUTF8(text_sv))
4651 text = SvPV(text_sv, len);
4652 work = mymalloc(len);
4653 count = i_ft2_has_chars(handle, text, len, utf8, work);
4654 if (GIMME_V == G_ARRAY) {
4656 for (i = 0; i < count; ++i) {
4657 PUSHs(sv_2mortal(newSViv(work[i])));
4662 PUSHs(sv_2mortal(newSVpv(work, count)));
4667 i_ft2_face_name(handle)
4668 Imager::Font::FT2 handle
4673 len = i_ft2_face_name(handle, name, sizeof(name));
4676 PUSHs(sv_2mortal(newSVpv(name, 0)));
4680 i_ft2_can_face_name()
4683 i_ft2_glyph_name(handle, text_sv, utf8 = 0, reliable_only = 1)
4684 Imager::Font::FT2 handle
4695 if (SvUTF8(text_sv))
4698 text = SvPV(text_sv, work_len);
4703 ch = i_utf8_advance(&text, &len);
4705 i_push_error(0, "invalid UTF8 character");
4714 if (i_ft2_glyph_name(handle, ch, name, sizeof(name),
4716 PUSHs(sv_2mortal(newSVpv(name, 0)));
4719 PUSHs(&PL_sv_undef);
4724 i_ft2_can_do_glyph_names()
4727 i_ft2_face_has_glyph_names(handle)
4728 Imager::Font::FT2 handle
4731 i_ft2_is_multiple_master(handle)
4732 Imager::Font::FT2 handle
4735 i_ft2_get_multiple_masters(handle)
4736 Imager::Font::FT2 handle
4741 if (i_ft2_get_multiple_masters(handle, &mm)) {
4742 EXTEND(SP, 2+mm.num_axis);
4743 PUSHs(sv_2mortal(newSViv(mm.num_axis)));
4744 PUSHs(sv_2mortal(newSViv(mm.num_designs)));
4745 for (i = 0; i < mm.num_axis; ++i) {
4749 sv = newSVpv(mm.axis[i].name, strlen(mm.axis[i].name));
4751 av_store(av, 0, sv);
4752 sv = newSViv(mm.axis[i].minimum);
4754 av_store(av, 1, sv);
4755 sv = newSViv(mm.axis[i].maximum);
4757 av_store(av, 2, sv);
4758 PUSHs(newRV_noinc((SV *)av));
4763 i_ft2_set_mm_coords(handle, ...)
4764 Imager::Font::FT2 handle
4770 /* T_ARRAY handling by xsubpp seems to be busted in 5.6.1, so
4771 transfer the array manually */
4772 ix_coords = items-1;
4773 coords = mymalloc(sizeof(long) * ix_coords);
4774 for (i = 0; i < ix_coords; ++i) {
4775 coords[i] = (long)SvIV(ST(1+i));
4777 RETVAL = i_ft2_set_mm_coords(handle, ix_coords, coords);
4784 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
4788 Imager::FillHandle fill
4790 MODULE = Imager PACKAGE = Imager
4793 i_new_fill_solid(cl, combine)
4798 i_new_fill_solidf(cl, combine)
4799 Imager::Color::Float cl
4803 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
4811 unsigned char *cust_hatch;
4815 cust_hatch = (unsigned char *)SvPV(ST(4), len);
4819 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
4824 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
4825 Imager::Color::Float fg
4826 Imager::Color::Float bg
4832 unsigned char *cust_hatch;
4836 cust_hatch = (unsigned char *)SvPV(ST(4), len);
4840 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
4845 i_new_fill_image(src, matrix, xoff, yoff, combine)
4862 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4863 croak("i_new_fill_image: parameter must be an arrayref");
4864 av=(AV*)SvRV(ST(1));
4868 for (i = 0; i < len; ++i) {
4869 sv1=(*(av_fetch(av,i,0)));
4870 matrix[i] = SvNV(sv1);
4876 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
4880 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
4882 # this class is only exposed for testing
4885 i_int_hlines_testing()
4887 #if i_int_hlines_testing()
4889 Imager::Internal::Hlines
4890 i_int_hlines_new(start_y, count_y, start_x, count_x)
4896 Imager::Internal::Hlines
4897 i_int_hlines_new_img(im)
4901 i_int_hlines_add(hlines, y, minx, width)
4902 Imager::Internal::Hlines hlines
4908 i_int_hlines_DESTROY(hlines)
4909 Imager::Internal::Hlines hlines
4912 i_int_hlines_dump(hlines)
4913 Imager::Internal::Hlines hlines
4918 PERL_SET_GLOBAL_CALLBACKS;