mirror of
https://github.com/webmproject/libwebp.git
synced 2025-02-13 07:22:52 +01:00
Merge "fix TIFF encoder regarding rgbA/RGBA"
This commit is contained in:
commit
18f0dfac82
@ -332,9 +332,8 @@ int main(int argc, const char *argv[]) {
|
|||||||
case BMP:
|
case BMP:
|
||||||
output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
|
output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
|
||||||
break;
|
break;
|
||||||
case TIFF: // note: force pre-multiplied alpha
|
case TIFF:
|
||||||
output_buffer->colorspace =
|
output_buffer->colorspace = bitstream->has_alpha ? MODE_RGBA : MODE_RGB;
|
||||||
bitstream->has_alpha ? MODE_rgbA : MODE_RGB;
|
|
||||||
break;
|
break;
|
||||||
case PGM:
|
case PGM:
|
||||||
case RAW_YUV:
|
case RAW_YUV:
|
||||||
|
@ -361,6 +361,7 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
|
|||||||
const uint8_t* rgba = buffer->u.RGBA.rgba;
|
const uint8_t* rgba = buffer->u.RGBA.rgba;
|
||||||
const int stride = buffer->u.RGBA.stride;
|
const int stride = buffer->u.RGBA.stride;
|
||||||
const uint8_t bytes_per_px = has_alpha ? 4 : 3;
|
const uint8_t bytes_per_px = has_alpha ? 4 : 3;
|
||||||
|
const int assoc_alpha = WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2;
|
||||||
// For non-alpha case, we omit tag 0x152 (ExtraSamples).
|
// For non-alpha case, we omit tag 0x152 (ExtraSamples).
|
||||||
const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES
|
const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES
|
||||||
: NUM_IFD_ENTRIES - 1;
|
: NUM_IFD_ENTRIES - 1;
|
||||||
@ -388,7 +389,8 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
|
|||||||
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
|
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
|
||||||
0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 154: PlanarConfiguration
|
0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 154: PlanarConfiguration
|
||||||
0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch)
|
0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch)
|
||||||
0x52, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 178: ExtraSamples: rgbA
|
0x52, 0x01, 3, 0, 1, 0, 0, 0,
|
||||||
|
assoc_alpha, 0, 0, 0, // 178: ExtraSamples: rgbA/RGBA
|
||||||
0, 0, 0, 0, // 190: IFD terminator
|
0, 0, 0, 0, // 190: IFD terminator
|
||||||
// EXTRA_DATA_OFFSET:
|
// EXTRA_DATA_OFFSET:
|
||||||
8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample
|
8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample
|
||||||
|
@ -116,13 +116,48 @@ static tsize_t MyRead(thandle_t opaque, void* dst, tsize_t size) {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unmultiply Argb data. Taken from dsp/alpha_processing
|
||||||
|
// (we don't want to force a dependency to a libdspdec library).
|
||||||
|
#define MFIX 24 // 24bit fixed-point arithmetic
|
||||||
|
#define HALF ((1u << MFIX) >> 1)
|
||||||
|
#define KINV_255 ((1u << MFIX) / 255u)
|
||||||
|
|
||||||
|
static uint32_t Unmult(uint8_t x, uint32_t mult) {
|
||||||
|
const uint32_t v = (x * mult + HALF) >> MFIX;
|
||||||
|
return (v > 255u) ? 255u : v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE uint32_t GetScale(uint32_t a) {
|
||||||
|
return (255u << MFIX) / a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MultARGBRow(uint8_t* ptr, int width) {
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < width; ++x, ptr += 4) {
|
||||||
|
const uint32_t alpha = ptr[3];
|
||||||
|
if (alpha < 255) {
|
||||||
|
if (alpha == 0) { // alpha == 0
|
||||||
|
ptr[0] = ptr[1] = ptr[2] = 0;
|
||||||
|
} else {
|
||||||
|
const uint32_t scale = GetScale(alpha);
|
||||||
|
ptr[0] = Unmult(ptr[0], scale);
|
||||||
|
ptr[1] = Unmult(ptr[1], scale);
|
||||||
|
ptr[2] = Unmult(ptr[2], scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ReadTIFF(const uint8_t* const data, size_t data_size,
|
int ReadTIFF(const uint8_t* const data, size_t data_size,
|
||||||
WebPPicture* const pic, int keep_alpha,
|
WebPPicture* const pic, int keep_alpha,
|
||||||
Metadata* const metadata) {
|
Metadata* const metadata) {
|
||||||
MyData my_data = { data, (toff_t)data_size, 0 };
|
MyData my_data = { data, (toff_t)data_size, 0 };
|
||||||
TIFF* tif;
|
TIFF* tif;
|
||||||
uint32 width, height;
|
uint32_t width, height;
|
||||||
uint32* raster;
|
uint16_t samples_per_px = 0;
|
||||||
|
uint16_t extra_samples = 0;
|
||||||
|
uint16_t* extra_samples_ptr = NULL;
|
||||||
|
uint32_t* raster;
|
||||||
int64_t alloc_size;
|
int64_t alloc_size;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
tdir_t dircount;
|
tdir_t dircount;
|
||||||
@ -143,17 +178,27 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
"Only the first will be used, %d will be ignored.\n",
|
"Only the first will be used, %d will be ignored.\n",
|
||||||
dircount - 1);
|
dircount - 1);
|
||||||
}
|
}
|
||||||
|
if (!TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_px)) {
|
||||||
|
fprintf(stderr, "Error! Cannot retrieve TIFF samples-per-pixel info.\n");
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
if (samples_per_px < 3 || samples_per_px > 4) goto End; // not supported
|
||||||
|
|
||||||
if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) &&
|
if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) &&
|
||||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))) {
|
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))) {
|
||||||
fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n");
|
fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n");
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ImgIoUtilCheckSizeArgumentsOverflow((uint64_t)width * height,
|
if (!ImgIoUtilCheckSizeArgumentsOverflow((uint64_t)width * height,
|
||||||
sizeof(*raster))) {
|
sizeof(*raster))) {
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
if (!TIFFGetField(tif, TIFFTAG_EXTRASAMPLES,
|
||||||
|
&extra_samples, &extra_samples_ptr)) {
|
||||||
|
fprintf(stderr, "Error! Cannot retrieve TIFF ExtraSamples info.\n");
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
// _Tiffmalloc uses a signed type for size.
|
// _Tiffmalloc uses a signed type for size.
|
||||||
alloc_size = (int64_t)((uint64_t)width * height * sizeof(*raster));
|
alloc_size = (int64_t)((uint64_t)width * height * sizeof(*raster));
|
||||||
if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End;
|
if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End;
|
||||||
@ -169,6 +214,15 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
TIFFSwabArrayOfLong(raster, width * height);
|
TIFFSwabArrayOfLong(raster, width * height);
|
||||||
#endif
|
#endif
|
||||||
|
// if we have an alpha channel, we must un-multiply from rgbA to RGBA
|
||||||
|
if (samples_per_px > 3 && extra_samples == 1) {
|
||||||
|
uint32_t y;
|
||||||
|
uint8_t* tmp = (uint8_t*)raster;
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
MultARGBRow(tmp, width);
|
||||||
|
tmp += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
ok = keep_alpha
|
ok = keep_alpha
|
||||||
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride)
|
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride)
|
||||||
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride);
|
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user