Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[RT #68508] do error diffusion on gray scale if the supplied palette …

…is all gray
  • Loading branch information...
commit 6d068d36c4215152210275bc15f866b1cdc988fe 1 parent a2f9a61
@tonycoz authored
View
5 Changes
@@ -22,6 +22,11 @@ Bug fixes:
- Imager no longer exports anything by default
https://rt.cpan.org/Ticket/Display.html?id=65228
+ - convert colors to grayscale if the supplied (or generated) palette
+ contains only grays when performing error diffusion color
+ translation.
+ https://rt.cpan.org/Ticket/Display.html?id=68508
+
Imager 0.83 - 21 May 2011
===========
View
2  imageri.h
@@ -114,4 +114,6 @@ i_img_dim i_maxx(i_img_dim x, i_img_dim y);
#define i_min(a, b) i_minx((a), (b))
#define i_max(a, b) i_maxx((a), (b))
+#define color_to_grey(col) ((col)->rgb.r * 0.222 + (col)->rgb.g * 0.707 + (col)->rgb.b * 0.071)
+
#endif
View
7 lib/Imager/ImageTypes.pod
@@ -1047,7 +1047,8 @@ Possible values are:
=item *
-C<giflib> - the C<giflib> native quantization function is used.
+C<giflib> - this is a historical equivalent for C<closest> that also
+forces C<make_colors> to C<mediancut>.
=item *
@@ -1060,7 +1061,9 @@ closest color is chosen.
=item *
-C<errdiff> - an error diffusion dither is performed.
+C<errdiff> - an error diffusion dither is performed. If the supplied
+(or generated) palette contains only grays the source colors are
+converted to gray before error diffusion is performed.
=back
View
3  paste.im
@@ -1,4 +1,5 @@
#include "imager.h"
+#include "imageri.h"
/*
=item i_copyto(C<dest>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>)
@@ -59,8 +60,6 @@ i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty)
#/code
}
-#define color_to_grey(col) ((col)->rgb.r * 0.222 + (col)->rgb.g * 0.707 + (col)->rgb.b * 0.071)
-
#code
void
#ifdef IM_EIGHT_BIT
View
31 quant.c
@@ -223,9 +223,12 @@ eucl_d_ch(cvec* cv,i_sample_t *chans) {
+ PWR2(cv->b - chans[2]);
}
-static
-int
-ceucl_d(i_color *c1, i_color *c2) { return PWR2(c1->channel[0]-c2->channel[0])+PWR2(c1->channel[1]-c2->channel[1])+PWR2(c1->channel[2]-c2->channel[2]); }
+static int
+ceucl_d(i_color *c1, i_color *c2) {
+return PWR2(c1->channel[0]-c2->channel[0])
+ +PWR2(c1->channel[1]-c2->channel[1])
+ +PWR2(c1->channel[2]-c2->channel[2]);
+}
static const int
gray_samples[] = { 0, 0, 0 };
@@ -755,6 +758,23 @@ makemap_mono(i_quantize *quant) {
/*#define IM_CFRAND2DIST*/
#endif
+/* return true if the color map contains only grays */
+static int
+is_gray_map(const i_quantize *quant) {
+ int i;
+
+ for (i = 0; i < quant->mc_count; ++i) {
+ if (quant->mc_colors[i].rgb.r != quant->mc_colors[i].rgb.g
+ || quant->mc_colors[i].rgb.r != quant->mc_colors[i].rgb.b) {
+ mm_log((1, " not a gray map\n"));
+ return 0;
+ }
+ }
+
+ mm_log((1, " is a gray map\n"));
+ return 1;
+}
+
#ifdef IM_CFHASHBOX
/* The original version I wrote for this used the sort.
@@ -1205,6 +1225,7 @@ translate_errdiff(i_quantize *quant, i_img *img, i_palidx *out) {
int difftotal;
int x, y, dx, dy;
int bst_idx = 0;
+ int is_gray = is_gray_map(quant);
CF_VARS;
if ((quant->errdiff & ed_mask) == ed_custom) {
@@ -1249,6 +1270,10 @@ translate_errdiff(i_quantize *quant, i_img *img, i_palidx *out) {
if (img->channels < 3) {
val.channel[1] = val.channel[2] = val.channel[0];
}
+ else if (is_gray) {
+ int gray = 0.5 + color_to_grey(&val);
+ val.channel[0] = val.channel[1] = val.channel[2] = gray;
+ }
perr = err[x+mapo];
perr.r = perr.r < 0 ? -((-perr.r)/difftotal) : perr.r/difftotal;
perr.g = perr.g < 0 ? -((-perr.g)/difftotal) : perr.g/difftotal;
View
13 t/t023palette.t
@@ -1,10 +1,10 @@
#!perl -w
# some of this is tested in t01introvert.t too
use strict;
-use Test::More tests => 126;
+use Test::More tests => 128;
BEGIN { use_ok("Imager"); }
-use Imager::Test qw(image_bounds_checks test_image is_color3);
+use Imager::Test qw(image_bounds_checks test_image is_color3 isnt_image);
Imager->open_log(log => "testout/t023palette.log");
@@ -345,6 +345,15 @@ cmp_ok(Imager->errstr, '=~', qr/Channels must be positive and <= 4/,
is_color3($colors[8], 0, 0x33, 0x66, "9th should be 003366");
}
+{ # RT 68508
+ my $im = Imager->new(xsize => 10, ysize => 10);
+ $im->box(filled => 1, color => Imager::Color->new(255, 0, 0));
+ my $palim = $im->to_paletted(make_colors => "mono", translate => "errdiff");
+ ok($palim, "convert to mono with error diffusion");
+ my $blank = Imager->new(xsize => 10, ysize => 10);
+ isnt_image($palim, $blank, "make sure paletted isn't all black");
+}
+
Imager->close_log;
unless ($ENV{IMAGER_KEEP_FILES}) {
Please sign in to comment.
Something went wrong with that request. Please try again.