START_MY_CXT
-im_context_t fallback_context;
-
static void
start_context(pTHX) {
dMY_CXT;
MY_CXT.ctx = im_context_new();
sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
-
- /* Ideally we'd free this reference, but the error message memory
- was never released on exit, so the associated memory here is reasonable
- to keep.
- With logging enabled we always need at least one context, since
- objects may be released fairly late and attempt to get the log file.
- */
- im_context_refinc(MY_CXT.ctx, "start_context");
- fallback_context = MY_CXT.ctx;
}
static im_context_t
dTHX;
dMY_CXT;
- return MY_CXT.ctx ? MY_CXT.ctx : fallback_context;
+ return MY_CXT.ctx;
}
#else
static void
start_context(pTHX) {
perl_context = im_context_new();
- im_context_refinc(perl_context, "start_context");
+
+ /* just so it gets destroyed */
+ sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", perl_context);
}
static im_context_t
static void *
malloc_temp(pTHX_ size_t size) {
- SV *sv = sv_2mortal(newSV(size));
+ void *result;
+ Newx(result, size, char);
+ SAVEFREEPV(result);
- return SvPVX(sv);
+ return result;
}
static void *
calloc_temp(pTHX_ size_t size) {
- void *result = malloc_temp(aTHX_ size);
- memset(result, 0, size);
+ void *result;
+ Newxz(result, size, char);
+ SAVEFREEPV(result);
return result;
}
#define i_img_dimPtr(size) ((i_img_dim *)calloc_temp(aTHX_ sizeof(i_img_dim) * (size)))
#define SvI_img_dim(sv, pname) (SvIV(sv))
-#define i_colorPtr(size) ((i_color *)calloc_temp(aTHX_ sizeof(i_color *) * (size)))
+#define i_colorPtr(size) ((i_color *)calloc_temp(aTHX_ sizeof(i_color) * (size)))
#define SvI_color(sv, pname) S_sv_to_i_color(aTHX_ sv, pname)
}
struct value_name {
- char *name;
+ const char *name;
int value;
};
-static int lookup_name(const struct value_name *names, int count, char *name, int def_value)
+static int
+lookup_name(const struct value_name *names, int count, char *name, int def_value, int push_errors, const char *id, int *failed)
{
int i;
+
+ if (push_errors)
+ *failed = 0;
+
for (i = 0; i < count; ++i)
if (strEQ(names[i].name, name))
return names[i].value;
+ if (push_errors) {
+ i_push_errorf(0, "unknown value '%s' for %s", name, id);
+ *failed = 1;
+ }
+
return def_value;
}
+
static struct value_name transp_names[] =
{
{ "none", tr_none },
};
/* look through the hash for quantization options */
-static void
-ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
+static int
+ip_handle_quant_opts_low(pTHX_ i_quantize *quant, HV *hv, int push_errors)
{
- /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
SV **sv;
int i;
STRLEN len;
char *str;
+ int failed = 0;
quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
if (sv && *sv && (str = SvPV(*sv, len))) {
quant->transp =
lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
- str, tr_none);
+ str, tr_none, push_errors, "transp", &failed);
+ if (failed)
+ return 0;
if (quant->transp != tr_none) {
quant->tr_threshold = 127;
sv = hv_fetch(hv, "tr_threshold", 12, 0);
if (quant->transp == tr_errdiff) {
sv = hv_fetch(hv, "tr_errdiff", 10, 0);
if (sv && *sv && (str = SvPV(*sv, len)))
- quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
+ quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd, push_errors, "tr_errdiff", &failed);
+ if (failed)
+ return 0;
}
if (quant->transp == tr_ordered) {
quant->tr_orddith = od_tiny;
sv = hv_fetch(hv, "tr_orddith", 10, 0);
- if (sv && *sv && (str = SvPV(*sv, len)))
- quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
+ if (sv && *sv && (str = SvPV(*sv, len))) {
+ quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random, push_errors, "tr_orddith", &failed);
+ if (failed)
+ return 0;
+ }
if (quant->tr_orddith == od_custom) {
sv = hv_fetch(hv, "tr_map", 6, 0);
sv = hv_fetch(hv, "make_colors", 11, 0);
if (sv && *sv && (str = SvPV(*sv, len))) {
quant->make_colors =
- lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
+ lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut, push_errors, "make_colors", &failed);
+ if (failed)
+ return 0;
}
sv = hv_fetch(hv, "colors", 6, 0);
if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
quant->mc_colors[i] = *col;
}
+ else if (push_errors) {
+ i_push_errorf(0, "colors[%d] isn't an Imager::Color object", i);
+ return 0;
+ }
}
}
sv = hv_fetch(hv, "max_colors", 10, 0);
quant->translate = pt_closest;
sv = hv_fetch(hv, "translate", 9, 0);
if (sv && *sv && (str = SvPV(*sv, len))) {
- quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
+ quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest, push_errors, "translate", &failed);
+ if (failed)
+ return 0;
}
sv = hv_fetch(hv, "errdiff", 7, 0);
if (sv && *sv && (str = SvPV(*sv, len))) {
- quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
+ quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd, push_errors, "errdiff", &failed);
+ if (failed)
+ return 0;
}
if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
/* get the error diffusion map */
for (i = 0; i < len; ++i) {
SV **sv2 = av_fetch(av, i, 0);
if (sv2 && *sv2) {
- quant->ed_map[i] = SvIV(*sv2);
+ IV iv = SvIV(*sv2);
+ if (push_errors && iv < 0) {
+ i_push_errorf(0, "errdiff_map values must be non-negative, errdiff[%d] is negative", i);
+ return 0;
+ }
+ quant->ed_map[i] = iv;
sum += quant->ed_map[i];
}
}
myfree(quant->ed_map);
quant->ed_map = 0;
quant->errdiff = ed_floyd;
+ if (push_errors) {
+ i_push_error(0, "error diffusion map must contain some non-zero values");
+ return 0;
+ }
}
}
}
sv = hv_fetch(hv, "perturb", 7, 0);
if (sv && *sv)
quant->perturb = SvIV(*sv);
+
+ return 1;
}
static void
myfree(quant->ed_map);
}
+static int
+ip_handle_quant_opts2(pTHX_ i_quantize *quant, HV *hv) {
+ int result = ip_handle_quant_opts_low(aTHX_ quant, hv, 1);
+ if (!result) {
+ ip_cleanup_quant_opts(aTHX_ quant);
+ }
+ return result;
+}
+
+static void
+ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) {
+ (void)ip_handle_quant_opts_low(aTHX_ quant, hv, 0);
+}
+
/* copies the color map from the hv into the colors member of the HV */
static void
ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
else {
return (i_poly_fill_mode_t)lookup_name
(poly_fill_mode_names, ARRAY_COUNT(poly_fill_mode_names),
- SvPV_nolen(sv), i_pfm_evenodd);
+ SvPV_nolen(sv), i_pfm_evenodd, 0, NULL, NULL);
}
}
IMAGER_PL_API_LEVEL,
ip_handle_quant_opts,
ip_cleanup_quant_opts,
- ip_copy_colors_back
+ ip_copy_colors_back,
+ ip_handle_quant_opts2
};
#define PERL_PL_SET_GLOBAL_CALLBACKS \
unsigned char b
unsigned char a
PPCODE:
- ICL_set_internal(cl, r, g, b, a);
+ cl->rgba.r = r;
+ cl->rgba.g = g;
+ cl->rgba.b = b;
+ cl->rgba.a = a;
EXTEND(SP, 1);
PUSHs(ST(0));
Imager::Color::Float
ICLF_new_internal(r, g, b, a)
- double r
- double g
- double b
- double a
+ im_double r
+ im_double g
+ im_double b
+ im_double a
void
ICLF_DESTROY(cl)
void
ICLF_set_internal(cl,r,g,b,a)
Imager::Color::Float cl
- double r
- double g
- double b
- double a
+ im_double r
+ im_double g
+ im_double b
+ im_double a
PPCODE:
cl->rgba.r = r;
cl->rgba.g = g;
MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
Imager::ImgRaw
-IIM_new(x,y,ch)
- i_img_dim x
- i_img_dim y
+IIM_new(xsize,ysize,ch)
+ i_img_dim xsize
+ i_img_dim ysize
int ch
void
i_io_getc(ig)
Imager::IO ig
+void
+i_io_nextc(ig)
+ Imager::IO ig
+
int
i_io_putc(ig, c)
Imager::IO ig
i_img_get_height(im)
Imager::ImgRaw im
+int
+i_img_color_model(im)
+ Imager::ImgRaw im
+
+int
+i_img_color_channels(im)
+ Imager::ImgRaw im
+
+int
+i_img_alpha_channel(im)
+ Imager::ImgRaw im
+ CODE:
+ if (!i_img_alpha_channel(im, &RETVAL))
+ XSRETURN(0);
+ OUTPUT:
+ RETVAL
void
i_img_is_monochrome(im)
Imager::ImgRaw im
i_img_dim x
i_img_dim y
- double rad
- double d1
- double d2
+ im_double rad
+ im_double d1
+ im_double d2
Imager::Color val
void
i_arc_aa(im,x,y,rad,d1,d2,val)
Imager::ImgRaw im
- double x
- double y
- double rad
- double d1
- double d2
+ im_double x
+ im_double y
+ im_double rad
+ im_double d1
+ im_double d2
Imager::Color val
void
Imager::ImgRaw im
i_img_dim x
i_img_dim y
- double rad
- double d1
- double d2
+ im_double rad
+ im_double d1
+ im_double d2
Imager::FillHandle fill
void
i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
Imager::ImgRaw im
- double x
- double y
- double rad
- double d1
- double d2
+ im_double x
+ im_double y
+ im_double rad
+ im_double d1
+ im_double d2
Imager::FillHandle fill
void
i_circle_aa(im,x,y,rad,val)
Imager::ImgRaw im
- double x
- double y
- double rad
+ im_double x
+ im_double y
+ im_double rad
Imager::Color val
void
i_circle_aa_fill(im,x,y,rad,fill)
Imager::ImgRaw im
- double x
- double y
- double rad
+ im_double x
+ im_double y
+ im_double rad
Imager::FillHandle fill
int
i_img_dim x
i_img_dim y
i_img_dim rad
- double d1
- double d2
+ im_double d1
+ im_double d2
Imager::Color val
int
i_img_dim x
i_img_dim y
i_img_dim rad
- double d1
- double d2
+ im_double d1
+ im_double d2
Imager::Color val
i_img_dim width
i_img_dim height
int combine
- double opacity
+ im_double opacity
undef_int
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)
i_img_dim width
i_img_dim height
int combine
- double opacity
+ im_double opacity
Imager::ImgRaw
i_combine(src_av, channels_av = NULL)
Imager::ImgRaw
i_rotate_exact(im, amount, ...)
Imager::ImgRaw im
- double amount
+ im_double amount
PREINIT:
i_color *backp = NULL;
i_fcolor *fbackp = NULL;
undef_int
i_gaussian(im,stdev)
Imager::ImgRaw im
- double stdev
+ im_double stdev
void
i_unsharp_mask(im,stdev,scale)
Imager::ImgRaw im
- double stdev
- double scale
+ im_double stdev
+ im_double scale
int
i_conv(im,coef)
i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
Imager::ImgRaw im1
Imager::ImgRaw im2
- double epsilon
+ im_double epsilon
const char *what
double
i_img_dim xb
i_img_dim yb
Imager::Color cl
- double points
+ im_double points
SV * str_sv
int smooth
int utf8
i_img_dim xb
i_img_dim yb
int channel
- double points
+ im_double points
SV * str_sv
int smooth
int utf8
void
i_tt_bbox(handle,point,str_sv,utf8)
Imager::Font::TT handle
- double point
+ im_double point
SV* str_sv
int utf8
PREINIT:
work = mymalloc(len);
count = i_tt_has_chars(handle, text, len, utf8, work);
if (GIMME_V == G_ARRAY) {
- EXTEND(SP, count);
- for (i = 0; i < count; ++i) {
- PUSHs(boolSV(work[i]));
- }
+ if (count) {
+ EXTEND(SP, count);
+ for (i = 0; i < count; ++i) {
+ PUSHs(boolSV(work[i]));
+ }
+ }
}
else {
EXTEND(SP, 1);
size_t len;
size_t outsize;
char name[255];
- SSize_t count = 0;
PPCODE:
i_clear_error();
text = SvPV(text_sv, work_len);
ch = *text++;
--len;
}
- EXTEND(SP, count+1);
+ EXTEND(SP, 1);
if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
- ST(count) = sv_2mortal(newSVpv(name, 0));
+ PUSHs(sv_2mortal(newSVpv(name, 0)));
}
else {
- ST(count) = &PL_sv_undef;
+ PUSHs(&PL_sv_undef);
}
- ++count;
}
- XSRETURN(count);
#endif
Imager::ImgRaw
i_scaleaxis(im,Value,Axis)
Imager::ImgRaw im
- double Value
+ im_double Value
int Axis
Imager::ImgRaw
i_scale_nn(im,scx,scy)
Imager::ImgRaw im
- double scx
- double scy
+ im_double scx
+ im_double scy
Imager::ImgRaw
i_scale_mixing(im, width, height)
int col_cnt;
PPCODE:
col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
+ if (col_cnt <= 0) {
+ XSRETURN_EMPTY;
+ }
EXTEND(SP, col_cnt);
for (i = 0; i < col_cnt; i++) {
PUSHs(sv_2mortal(newSViv( col_usage[i])));
}
myfree(col_usage);
- XSRETURN(col_cnt);
void
void
i_contrast(im,intensity)
Imager::ImgRaw im
- float intensity
+ im_float intensity
void
i_hardinvert(im)
void
i_noise(im,amount,type)
Imager::ImgRaw im
- float amount
+ im_float amount
unsigned char type
void
int channel
i_img_dim tx
i_img_dim ty
- double Lx
- double Ly
- double Lz
- float cd
- float cs
- float n
+ im_double Lx
+ im_double Ly
+ im_double Lz
+ im_float cd
+ im_float cs
+ im_float n
Imager::Color Ia
Imager::Color Il
Imager::Color Is
void
i_autolevels(im,lsat,usat,skew)
Imager::ImgRaw im
- float lsat
- float usat
- float skew
+ im_float lsat
+ im_float usat
+ im_float skew
void
i_autolevels_mono(im,lsat,usat)
Imager::ImgRaw im
- float lsat
- float usat
+ im_float lsat
+ im_float usat
void
i_radnoise(im,xo,yo,rscale,ascale)
Imager::ImgRaw im
- float xo
- float yo
- float rscale
- float ascale
+ im_float xo
+ im_float yo
+ im_float rscale
+ im_float ascale
void
i_turbnoise(im, xo, yo, scale)
Imager::ImgRaw im
- float xo
- float yo
- float scale
+ im_float xo
+ im_float yo
+ im_float scale
void
i_diff_image(im, im2, mindist=0)
Imager::ImgRaw im
Imager::ImgRaw im2
- double mindist
+ im_double mindist
undef_int
i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
Imager::ImgRaw im
- double xa
- double ya
- double xb
- double yb
+ im_double xa
+ im_double ya
+ im_double xb
+ im_double yb
int type
int repeat
int combine
int super_sample
- double ssample_param
+ im_double ssample_param
PREINIT:
AV *asegs;
int count;
Imager::FillHandle
i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
- double xa
- double ya
- double xb
- double yb
+ im_double xa
+ im_double ya
+ im_double xb
+ im_double yb
int type
int repeat
int combine
int super_sample
- double ssample_param
+ im_double ssample_param
PREINIT:
AV *asegs;
int count;
Imager::FillHandle
i_new_fill_opacity(other_fill, alpha_mult)
Imager::FillHandle other_fill
- double alpha_mult
+ im_double alpha_mult
void
i_errors()
if (!av_store(av, 1, sv)) {
SvREFCNT_dec(sv);
}
- PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
+ XPUSHs(sv_2mortal(newRV_noinc((SV*)av)));
++i;
}
num = num <= av_len(ac) ? num : av_len(ac);
num++;
if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
- xo = mymalloc( sizeof(i_img_dim) * num );
- yo = mymalloc( sizeof(i_img_dim) * num );
- ival = mymalloc( sizeof(i_color) * num );
+ xo = malloc_temp(aTHX_ sizeof(i_img_dim) * num );
+ yo = malloc_temp(aTHX_ sizeof(i_img_dim) * num );
+ ival = malloc_temp(aTHX_ sizeof(i_color) * num );
for(i = 0; i<num; i++) {
xo[i] = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
yo[i] = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
i_img_dim y;
CODE:
RETVAL = (i_color *)mymalloc(sizeof(i_color));
+ memset(RETVAL, 0, sizeof(*RETVAL));
if (i_gpix(im, x, y, RETVAL) != 0) {
myfree(RETVAL);
XSRETURN_UNDEF;
int maxpal
Imager::ImgRaw
-i_img_to_pal(src, quant)
+i_img_to_pal(src, quant_hv)
Imager::ImgRaw src
+ HV *quant_hv
PREINIT:
HV *hv;
i_quantize quant;
CODE:
- if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
- croak("i_img_to_pal: second argument must be a hash ref");
- hv = (HV *)SvRV(ST(1));
memset(&quant, 0, sizeof(quant));
quant.version = 1;
quant.mc_size = 256;
- ip_handle_quant_opts(aTHX_ &quant, hv);
+ i_clear_error();
+ if (!ip_handle_quant_opts2(aTHX_ &quant, quant_hv)) {
+ XSRETURN_EMPTY;
+ }
RETVAL = i_img_to_pal(src, &quant);
if (RETVAL) {
- ip_copy_colors_back(aTHX_ hv, &quant);
+ ip_copy_colors_back(aTHX_ quant_hv, &quant);
}
ip_cleanup_quant_opts(aTHX_ &quant);
OUTPUT:
memset(&quant, 0, sizeof(quant));
quant.version = 1;
quant.mc_size = 256;
- ip_handle_quant_opts(aTHX_ &quant, quant_hv);
+ if (!ip_handle_quant_opts2(aTHX_ &quant, quant_hv)) {
+ XSRETURN_EMPTY;
+ }
i_quant_makemap(&quant, imgs, count);
EXTEND(SP, quant.mc_count);
for (i = 0; i < quant.mc_count; ++i) {
PUSHs(sv_c);
}
ip_cleanup_quant_opts(aTHX_ &quant);
+ myfree(imgs);
void
}
}
RETVAL = i_addcolors(im, colors, items-1);
+ myfree(colors);
OUTPUT:
RETVAL
i_img_dim y;
CODE:
RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
+ memset(RETVAL, 0, sizeof(*RETVAL));
if (i_gpixf(im, x, y, RETVAL) != 0) {
myfree(RETVAL);
XSRETURN_UNDEF;
}
Imager::ImgRaw
-i_img_8_new(x, y, ch)
- i_img_dim x
- i_img_dim y
- int ch
+i_img_8_new(xsize, ysize, channels)
+ i_img_dim xsize
+ i_img_dim ysize
+ int channels
Imager::ImgRaw
-i_img_16_new(x, y, ch)
- i_img_dim x
- i_img_dim y
- int ch
+i_img_16_new(xsize, ysize, channels)
+ i_img_dim xsize
+ i_img_dim ysize
+ int channels
Imager::ImgRaw
i_img_to_rgb16(im)
Imager::ImgRaw im
Imager::ImgRaw
-i_img_double_new(x, y, ch)
- i_img_dim x
- i_img_dim y
- int ch
+i_img_double_new(xsize, ysize, channels)
+ i_img_dim xsize
+ i_img_dim ysize
+ int channels
Imager::ImgRaw
i_img_to_drgb(im)
/* the following sv_setref_pv() will free this inc */
im_context_refinc(MY_CXT.ctx, "CLONE");
MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
+ if (MY_CXT.ctx == NULL) {
+ croak("Failed to clone Imager context");
+ }
sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
#endif