Skip to content

Commit e9c5a31

Browse files
authored
Use alpha range of 0.0 - 1.0 for scRGB (libvips#3627)
1 parent a9f6793 commit e9c5a31

File tree

14 files changed

+272
-62
lines changed

14 files changed

+272
-62
lines changed

ChangeLog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
- swap built-in profiles with ICC v4 variants [kleisauke]
2323
- remove libgsf dependency in favor of libarchive [kleisauke]
2424
- better chunking for small shrinks [jcupitt]
25+
- use alpha range of 0.0 - 1.0 for scRGB images [DarthSim]
2526

2627
18/9/23 8.14.5
2728

libvips/colour/XYZ2scRGB.c

Lines changed: 115 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,20 @@
4747

4848
#include "pcolour.h"
4949

50-
typedef VipsColourTransform VipsXYZ2scRGB;
51-
typedef VipsColourTransformClass VipsXYZ2scRGBClass;
50+
/* We can't use VipsColourCode as our parent class. We want to handle
51+
* alpha ourselves.
52+
*/
53+
54+
typedef struct _VipsXYZ2scRGB {
55+
VipsOperation parent_instance;
56+
57+
VipsImage *in;
58+
VipsImage *out;
59+
} VipsXYZ2scRGB;
5260

53-
G_DEFINE_TYPE(VipsXYZ2scRGB, vips_XYZ2scRGB, VIPS_TYPE_COLOUR_TRANSFORM);
61+
typedef VipsOperationClass VipsXYZ2scRGBClass;
62+
63+
G_DEFINE_TYPE(VipsXYZ2scRGB, vips_XYZ2scRGB, VIPS_TYPE_OPERATION);
5464

5565
/* We used to have the comment:
5666
@@ -69,17 +79,15 @@ G_DEFINE_TYPE(VipsXYZ2scRGB, vips_XYZ2scRGB, VIPS_TYPE_COLOUR_TRANSFORM);
6979
*/
7080

7181
static void
72-
vips_XYZ2scRGB_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width)
82+
vips_XYZ2scRGB_line(float *restrict q, float *restrict p,
83+
int extra_bands, int width)
7384
{
74-
float *restrict p = (float *) in[0];
75-
float *restrict q = (float *) out;
76-
77-
int i;
85+
int i, j;
7886

7987
for (i = 0; i < width; i++) {
80-
float X = p[0];
81-
float Y = p[1];
82-
float Z = p[2];
88+
const float X = p[0];
89+
const float Y = p[1];
90+
const float Z = p[2];
8391

8492
float R, G, B;
8593

@@ -92,27 +100,118 @@ vips_XYZ2scRGB_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width)
92100
q[2] = B;
93101

94102
q += 3;
103+
104+
for (j = 0; j < extra_bands; j++)
105+
q[j] = VIPS_CLIP(0, p[j] / 255.0, 1.0);
106+
p += extra_bands;
107+
q += extra_bands;
108+
}
109+
}
110+
111+
static int
112+
vips_XYZ2scRGB_gen(VipsRegion *out_region,
113+
void *seq, void *a, void *b, gboolean *stop)
114+
{
115+
VipsRegion *ir = (VipsRegion *) seq;
116+
VipsRect *r = &out_region->valid;
117+
VipsImage *in = ir->im;
118+
119+
int y;
120+
121+
if (vips_region_prepare(ir, r))
122+
return -1;
123+
124+
VIPS_GATE_START("vips_XYZ2scRGB: work");
125+
126+
for (y = 0; y < r->height; y++) {
127+
float *p = (float *)
128+
VIPS_REGION_ADDR(ir, r->left, r->top + y);
129+
float *q = (float *)
130+
VIPS_REGION_ADDR(out_region, r->left, r->top + y);
131+
132+
vips_XYZ2scRGB_line(q, p, in->Bands - 3, r->width);
133+
}
134+
135+
VIPS_GATE_STOP("vips_XYZ2scRGB: work");
136+
137+
return 0;
138+
}
139+
140+
static int
141+
vips_XYZ2scRGB_build(VipsObject *object)
142+
{
143+
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object);
144+
VipsXYZ2scRGB *XYZ2scRGB = (VipsXYZ2scRGB *) object;
145+
146+
VipsImage **t = (VipsImage **) vips_object_local_array(object, 2);
147+
148+
VipsImage *in;
149+
VipsImage *out;
150+
151+
if (VIPS_OBJECT_CLASS(vips_XYZ2scRGB_parent_class)->build(object))
152+
return -1;
153+
154+
in = XYZ2scRGB->in;
155+
if (vips_check_bands_atleast(class->nickname, in, 3))
156+
return -1;
157+
158+
if (vips_cast_float(in, &t[0], NULL))
159+
return -1;
160+
in = t[0];
161+
162+
out = vips_image_new();
163+
if (vips_image_pipelinev(out,
164+
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL)) {
165+
g_object_unref(out);
166+
return -1;
167+
}
168+
out->Type = VIPS_INTERPRETATION_scRGB;
169+
out->BandFmt = VIPS_FORMAT_FLOAT;
170+
171+
if (vips_image_generate(out,
172+
vips_start_one, vips_XYZ2scRGB_gen, vips_stop_one,
173+
in, XYZ2scRGB)) {
174+
g_object_unref(out);
175+
return -1;
95176
}
177+
178+
g_object_set(object, "out", out, NULL);
179+
180+
return 0;
96181
}
97182

98183
static void
99184
vips_XYZ2scRGB_class_init(VipsXYZ2scRGBClass *class)
100185
{
186+
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
101187
VipsObjectClass *object_class = (VipsObjectClass *) class;
102-
VipsColourClass *colour_class = VIPS_COLOUR_CLASS(class);
188+
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(class);
189+
190+
gobject_class->set_property = vips_object_set_property;
191+
gobject_class->get_property = vips_object_get_property;
103192

104193
object_class->nickname = "XYZ2scRGB";
105194
object_class->description = _("transform XYZ to scRGB");
195+
object_class->build = vips_XYZ2scRGB_build;
196+
197+
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
106198

107-
colour_class->process_line = vips_XYZ2scRGB_line;
199+
VIPS_ARG_IMAGE(class, "in", 1,
200+
_("Input"),
201+
_("Input image"),
202+
VIPS_ARGUMENT_REQUIRED_INPUT,
203+
G_STRUCT_OFFSET(VipsXYZ2scRGB, in));
204+
205+
VIPS_ARG_IMAGE(class, "out", 100,
206+
_("Output"),
207+
_("Output image"),
208+
VIPS_ARGUMENT_REQUIRED_OUTPUT,
209+
G_STRUCT_OFFSET(VipsXYZ2scRGB, out));
108210
}
109211

110212
static void
111213
vips_XYZ2scRGB_init(VipsXYZ2scRGB *XYZ2scRGB)
112214
{
113-
VipsColour *colour = VIPS_COLOUR(XYZ2scRGB);
114-
115-
colour->interpretation = VIPS_INTERPRETATION_scRGB;
116215
}
117216

118217
/**

libvips/colour/sRGB2scRGB.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ vips_sRGB2scRGB_line_8(float *restrict q, VipsPel *restrict p,
9898
q[0] = vips_v2Y_8[p[0]];
9999
q[1] = vips_v2Y_8[p[1]];
100100
q[2] = vips_v2Y_8[p[2]];
101-
q[3] = p[3];
101+
q[3] = p[3] / 255.0;
102102

103103
p += 4;
104104
q += 4;
@@ -114,7 +114,7 @@ vips_sRGB2scRGB_line_8(float *restrict q, VipsPel *restrict p,
114114
q += 3;
115115

116116
for (j = 0; j < extra_bands; j++)
117-
q[j] = p[j];
117+
q[j] = p[j] / 255.0;
118118
p += extra_bands;
119119
q += extra_bands;
120120
}
@@ -144,7 +144,7 @@ vips_sRGB2scRGB_line_16(float *restrict q, unsigned short *restrict p,
144144
q[0] = vips_v2Y_16[p[0]];
145145
q[1] = vips_v2Y_16[p[1]];
146146
q[2] = vips_v2Y_16[p[2]];
147-
q[3] = p[3] / 256.0;
147+
q[3] = p[3] / 65535.0;
148148

149149
p += 4;
150150
q += 4;
@@ -160,7 +160,7 @@ vips_sRGB2scRGB_line_16(float *restrict q, unsigned short *restrict p,
160160
q += 3;
161161

162162
for (j = 0; j < extra_bands; j++)
163-
q[j] = p[j] / 256.0;
163+
q[j] = p[j] / 65535.0;
164164
p += extra_bands;
165165
q += extra_bands;
166166
}

libvips/colour/scRGB2BW.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ vips_scRGB2BW_line_8(VipsPel *restrict q, float *restrict p,
8484
q += 1;
8585

8686
for (j = 0; j < extra_bands; j++)
87-
q[j] = VIPS_CLIP(0, p[j], UCHAR_MAX);
87+
q[j] = VIPS_CLIP(0, (int) (p[j] * 255.0), UCHAR_MAX);
8888
p += extra_bands;
8989
q += extra_bands;
9090
}
@@ -113,7 +113,7 @@ vips_scRGB2BW_line_16(unsigned short *restrict q, float *restrict p,
113113
q += 1;
114114

115115
for (j = 0; j < extra_bands; j++)
116-
q[j] = VIPS_CLIP(0, (int) (p[j] * 256.0), USHRT_MAX);
116+
q[j] = VIPS_CLIP(0, (int) (p[j] * 65535.0), USHRT_MAX);
117117
p += extra_bands;
118118
q += extra_bands;
119119
}

0 commit comments

Comments
 (0)