Skip to content

Commit 9203c29

Browse files
committed
tiffload: add 16-bit float support
1 parent 8ae3e5e commit 9203c29

File tree

1 file changed

+94
-8
lines changed

1 file changed

+94
-8
lines changed

libvips/foreign/tiff2vips.c

Lines changed: 94 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,28 @@ typedef struct _Rtiff {
425425
int y_pos;
426426
} Rtiff;
427427

428+
/* Convert IEEE 754-2008 16-bit float to 32-bit float
429+
*/
430+
static inline float
431+
half_2_float(gushort h)
432+
{
433+
const float sign = (h >> 15) * -2 + 1;
434+
const int exp = ((h & 0x7C00) >> 10) - 15;
435+
const float prec = (h & 0x03FF);
436+
437+
switch (exp)
438+
{
439+
case 16:
440+
return INFINITY * sign;
441+
case -15:
442+
return sign / (float)(1 << 14) * (prec / 1024.0);
443+
default:
444+
return exp > 0 ?
445+
sign * (float)(1 << exp) * (1.0 + prec / 1024.0) :
446+
sign / (float)(1 << -exp) * (1.0 + prec / 1024.0);
447+
}
448+
}
449+
428450
/* Test for field exists.
429451
*/
430452
static int
@@ -869,6 +891,8 @@ rtiff_guess_format(Rtiff *rtiff)
869891
return VIPS_FORMAT_SHORT;
870892
if (sample_format == SAMPLEFORMAT_UINT)
871893
return VIPS_FORMAT_USHORT;
894+
if(sample_format == SAMPLEFORMAT_IEEEFP)
895+
return VIPS_FORMAT_FLOAT;
872896
break;
873897

874898
case 32:
@@ -1229,13 +1253,37 @@ rtiff_parse_fourbit(Rtiff *rtiff, VipsImage *out)
12291253
} \
12301254
}
12311255

1256+
/* GREY_LOOP implementation for 16-bit float
1257+
*/
1258+
#define GREY_LOOP_F16 \
1259+
{ \
1260+
gushort *p1; \
1261+
float *q1; \
1262+
\
1263+
p1 = (gushort *) p; \
1264+
q1 = (float *) q; \
1265+
for (x = 0; x < n; x++) { \
1266+
if (invert) \
1267+
q1[0] = 1.0 - half_2_float(p1[0]); \
1268+
else \
1269+
q1[0] = half_2_float(p1[0]); \
1270+
\
1271+
for (i = 1; i < samples_per_pixel; i++) \
1272+
q1[i] = half_2_float(p1[i]); \
1273+
\
1274+
q1 += samples_per_pixel; \
1275+
p1 += samples_per_pixel; \
1276+
} \
1277+
}
1278+
12321279
/* Per-scanline process function for greyscale images.
12331280
*/
12341281
static void
12351282
rtiff_greyscale_line(Rtiff *rtiff,
12361283
VipsPel *q, VipsPel *p, int n, void *client)
12371284
{
12381285
int samples_per_pixel = rtiff->header.samples_per_pixel;
1286+
int bits_per_sample = rtiff->header.bits_per_sample;
12391287
int photometric_interpretation =
12401288
rtiff->header.photometric_interpretation;
12411289
VipsBandFormat format = rtiff_guess_format(rtiff);
@@ -1274,7 +1322,12 @@ rtiff_greyscale_line(Rtiff *rtiff,
12741322
break;
12751323

12761324
case VIPS_FORMAT_FLOAT:
1277-
GREY_LOOP(float, 1.0);
1325+
if (bits_per_sample == 16) {
1326+
GREY_LOOP_F16;
1327+
}
1328+
else {
1329+
GREY_LOOP(float, 1.0);
1330+
}
12781331
break;
12791332

12801333
case VIPS_FORMAT_DOUBLE:
@@ -1565,6 +1618,28 @@ rtiff_memcpy_line(Rtiff *rtiff, VipsPel *q, VipsPel *p, int n, void *client)
15651618
memcpy(q, p, len);
15661619
}
15671620

1621+
/* Per-scanline process function when we just need to copy.
1622+
*/
1623+
static void
1624+
rtiff_memcpy_f16_line( Rtiff *rtiff, VipsPel *q, VipsPel *p, int n, void *client )
1625+
{
1626+
VipsImage *im = (VipsImage *) client;
1627+
size_t len = n * im->Bands;
1628+
1629+
if( im->BandFmt == VIPS_FORMAT_COMPLEX ||
1630+
im->BandFmt == VIPS_FORMAT_DPCOMPLEX )
1631+
len *= 2;
1632+
1633+
int i;
1634+
1635+
gushort * restrict hp = (gushort *) p;
1636+
float * restrict fq = (float *) q;
1637+
1638+
for( i = 0; i < len; i++) {
1639+
fq[i] = half_2_float(hp[i]);
1640+
}
1641+
}
1642+
15681643
/* Read a regular multiband image where we can just copy pixels from the tiff
15691644
* buffer.
15701645
*/
@@ -1574,6 +1649,8 @@ rtiff_parse_copy(Rtiff *rtiff, VipsImage *out)
15741649
int samples_per_pixel = rtiff->header.samples_per_pixel;
15751650
int photometric_interpretation =
15761651
rtiff->header.photometric_interpretation;
1652+
int bits_per_sample = rtiff->header.bits_per_sample;
1653+
int sample_format = rtiff->header.sample_format;
15771654
int inkset = rtiff->header.inkset;
15781655

15791656
if (rtiff_non_fractional(rtiff))
@@ -1608,16 +1685,21 @@ rtiff_parse_copy(Rtiff *rtiff, VipsImage *out)
16081685
else
16091686
out->Type = VIPS_INTERPRETATION_MULTIBAND;
16101687

1611-
rtiff->sfn = rtiff_memcpy_line;
16121688
rtiff->client = out;
16131689

1614-
/* We expand YCBCR images to RGB using JPEGCOLORMODE_RGB, and this
1615-
* means we need a slightly larger read buffer for the edge pixels. In
1616-
* turn, this means we can't just memcpy to libvips regions.
1617-
*/
1618-
rtiff->memcpy = photometric_interpretation != PHOTOMETRIC_YCBCR;
1690+
if( bits_per_sample == 16 && sample_format == SAMPLEFORMAT_IEEEFP ) {
1691+
rtiff->sfn = rtiff_memcpy_f16_line;
1692+
}
1693+
else {
1694+
rtiff->sfn = rtiff_memcpy_line;
16191695

1620-
return 0;
1696+
/* We expand YCBCR images to RGB using JPEGCOLORMODE_RGB, and this
1697+
* means we need a slightly larger read buffer for the edge pixels. In
1698+
* turn, this means we can't just memcpy to libvips regions.
1699+
*/
1700+
rtiff->memcpy = photometric_interpretation != PHOTOMETRIC_YCBCR;
1701+
}
1702+
return( 0 );
16211703
}
16221704

16231705
typedef int (*reader_fn)(Rtiff *rtiff, VipsImage *out);
@@ -2695,6 +2777,10 @@ rtiff_read_stripwise(Rtiff *rtiff, VipsImage *out)
26952777
else
26962778
vips_line_size = VIPS_IMAGE_SIZEOF_LINE(t[0]);
26972779

2780+
if (rtiff->header.bits_per_sample == 16 &&
2781+
rtiff->header.sample_format == SAMPLEFORMAT_IEEEFP)
2782+
vips_line_size /= 2;
2783+
26982784
if (vips_line_size != rtiff->header.scanline_size) {
26992785
vips_error("tiff2vips",
27002786
"%s", _("unsupported tiff image type"));

0 commit comments

Comments
 (0)