mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 22:28:22 +01:00
reorder the YUVA->ARGB and ARGB->YUVA functions correctly
+ rework few loops + consolidate few error-checks / error-reporting + don't modify picture->colorspace in Import() for ARGB output Change-Id: Iae6da9b50acc738c59b85c3ee64efbaf6af8bffc
This commit is contained in:
parent
c6461bfda2
commit
1549d62067
@ -176,18 +176,19 @@ static int ImportYUVAFromRGBA(const uint8_t* const r_ptr,
|
|||||||
int rgb_stride, // bytes per scanline
|
int rgb_stride, // bytes per scanline
|
||||||
float dithering,
|
float dithering,
|
||||||
WebPPicture* const picture) {
|
WebPPicture* const picture) {
|
||||||
const WebPEncCSP uv_csp = picture->colorspace & WEBP_CSP_UV_MASK;
|
|
||||||
int x, y;
|
int x, y;
|
||||||
const int width = picture->width;
|
const int width = picture->width;
|
||||||
const int height = picture->height;
|
const int height = picture->height;
|
||||||
const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride);
|
const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride);
|
||||||
VP8Random rg;
|
VP8Random rg;
|
||||||
|
|
||||||
picture->colorspace = uv_csp;
|
|
||||||
picture->use_argb = 0;
|
|
||||||
if (has_alpha) {
|
if (has_alpha) {
|
||||||
picture->colorspace |= WEBP_CSP_ALPHA_BIT;
|
picture->colorspace |= WEBP_CSP_ALPHA_BIT;
|
||||||
|
} else {
|
||||||
|
picture->colorspace &= WEBP_CSP_UV_MASK;
|
||||||
}
|
}
|
||||||
|
picture->use_argb = 0;
|
||||||
|
|
||||||
if (!WebPPictureAllocYUVA(picture, width, height)) return 0;
|
if (!WebPPictureAllocYUVA(picture, width, height)) return 0;
|
||||||
|
|
||||||
VP8InitRandom(&rg, dithering);
|
VP8InitRandom(&rg, dithering);
|
||||||
@ -195,10 +196,10 @@ static int ImportYUVAFromRGBA(const uint8_t* const r_ptr,
|
|||||||
|
|
||||||
// Import luma plane
|
// Import luma plane
|
||||||
for (y = 0; y < height; ++y) {
|
for (y = 0; y < height; ++y) {
|
||||||
|
uint8_t* const dst = &picture->y[y * picture->y_stride];
|
||||||
for (x = 0; x < width; ++x) {
|
for (x = 0; x < width; ++x) {
|
||||||
const int offset = step * x + y * rgb_stride;
|
const int offset = step * x + y * rgb_stride;
|
||||||
picture->y[x + y * picture->y_stride] =
|
dst[x] = RGBToY(r_ptr[offset], g_ptr[offset], b_ptr[offset], &rg);
|
||||||
RGBToY(r_ptr[offset], g_ptr[offset], b_ptr[offset], &rg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,53 +234,6 @@ static int ImportYUVAFromRGBA(const uint8_t* const r_ptr,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Import(WebPPicture* const picture,
|
|
||||||
const uint8_t* const rgb, int rgb_stride,
|
|
||||||
int step, int swap_rb, int import_alpha) {
|
|
||||||
const uint8_t* const r_ptr = rgb + (swap_rb ? 2 : 0);
|
|
||||||
const uint8_t* const g_ptr = rgb + 1;
|
|
||||||
const uint8_t* const b_ptr = rgb + (swap_rb ? 0 : 2);
|
|
||||||
const uint8_t* const a_ptr = import_alpha ? rgb + 3 : NULL;
|
|
||||||
const int width = picture->width;
|
|
||||||
const int height = picture->height;
|
|
||||||
|
|
||||||
if (!picture->use_argb) {
|
|
||||||
return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride,
|
|
||||||
0.f /* no dithering */, picture);
|
|
||||||
}
|
|
||||||
if (import_alpha) {
|
|
||||||
picture->colorspace |= WEBP_CSP_ALPHA_BIT;
|
|
||||||
} else {
|
|
||||||
picture->colorspace &= ~WEBP_CSP_ALPHA_BIT;
|
|
||||||
}
|
|
||||||
if (!WebPPictureAlloc(picture)) return 0;
|
|
||||||
|
|
||||||
if (!import_alpha) {
|
|
||||||
int x, y;
|
|
||||||
for (y = 0; y < height; ++y) {
|
|
||||||
for (x = 0; x < width; ++x) {
|
|
||||||
const int offset = step * x + y * rgb_stride;
|
|
||||||
const uint32_t argb =
|
|
||||||
MakeARGB32(r_ptr[offset], g_ptr[offset], b_ptr[offset]);
|
|
||||||
picture->argb[x + y * picture->argb_stride] = argb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int x, y;
|
|
||||||
assert(step >= 4);
|
|
||||||
for (y = 0; y < height; ++y) {
|
|
||||||
for (x = 0; x < width; ++x) {
|
|
||||||
const int offset = step * x + y * rgb_stride;
|
|
||||||
const uint32_t argb = ((uint32_t)a_ptr[offset] << 24) |
|
|
||||||
(r_ptr[offset] << 16) |
|
|
||||||
(g_ptr[offset] << 8) |
|
|
||||||
(b_ptr[offset]);
|
|
||||||
picture->argb[x + y * picture->argb_stride] = argb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#undef SUM4
|
#undef SUM4
|
||||||
#undef SUM2V
|
#undef SUM2V
|
||||||
#undef SUM2H
|
#undef SUM2H
|
||||||
@ -287,39 +241,32 @@ static int Import(WebPPicture* const picture,
|
|||||||
#undef RGB_TO_UV
|
#undef RGB_TO_UV
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
// call for ARGB->YUVA conversion
|
||||||
|
|
||||||
int WebPPictureImportRGB(WebPPicture* picture,
|
int WebPPictureARGBToYUVADithered(WebPPicture* picture, WebPEncCSP colorspace,
|
||||||
const uint8_t* rgb, int rgb_stride) {
|
float dithering) {
|
||||||
return Import(picture, rgb, rgb_stride, 3, 0, 0);
|
if (picture == NULL) return 0;
|
||||||
|
if (picture->argb == NULL) {
|
||||||
|
return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
|
||||||
|
} else {
|
||||||
|
const uint8_t* const argb = (const uint8_t*)picture->argb;
|
||||||
|
const uint8_t* const r = ALPHA_IS_LAST ? argb + 2 : argb + 1;
|
||||||
|
const uint8_t* const g = ALPHA_IS_LAST ? argb + 1 : argb + 2;
|
||||||
|
const uint8_t* const b = ALPHA_IS_LAST ? argb + 0 : argb + 3;
|
||||||
|
const uint8_t* const a = ALPHA_IS_LAST ? argb + 3 : argb + 0;
|
||||||
|
|
||||||
|
picture->colorspace = colorspace;
|
||||||
|
return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride,
|
||||||
|
dithering, picture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebPPictureImportBGR(WebPPicture* picture,
|
int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) {
|
||||||
const uint8_t* rgb, int rgb_stride) {
|
return WebPPictureARGBToYUVADithered(picture, colorspace, 0.f);
|
||||||
return Import(picture, rgb, rgb_stride, 3, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int WebPPictureImportRGBA(WebPPicture* picture,
|
|
||||||
const uint8_t* rgba, int rgba_stride) {
|
|
||||||
return Import(picture, rgba, rgba_stride, 4, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int WebPPictureImportBGRA(WebPPicture* picture,
|
|
||||||
const uint8_t* rgba, int rgba_stride) {
|
|
||||||
return Import(picture, rgba, rgba_stride, 4, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int WebPPictureImportRGBX(WebPPicture* picture,
|
|
||||||
const uint8_t* rgba, int rgba_stride) {
|
|
||||||
return Import(picture, rgba, rgba_stride, 4, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int WebPPictureImportBGRX(WebPPicture* picture,
|
|
||||||
const uint8_t* rgba, int rgba_stride) {
|
|
||||||
return Import(picture, rgba, rgba_stride, 4, 1, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Automatic YUV <-> ARGB conversions.
|
// call for YUVA -> ARGB conversion
|
||||||
|
|
||||||
int WebPPictureYUVAToARGB(WebPPicture* picture) {
|
int WebPPictureYUVAToARGB(WebPPicture* picture) {
|
||||||
if (picture == NULL) return 0;
|
if (picture == NULL) return 0;
|
||||||
@ -380,29 +327,75 @@ int WebPPictureYUVAToARGB(WebPPicture* picture) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebPPictureARGBToYUVADithered(WebPPicture* picture, WebPEncCSP colorspace,
|
//------------------------------------------------------------------------------
|
||||||
float dithering) {
|
// automatic import / conversion
|
||||||
if (picture == NULL) return 0;
|
|
||||||
if (picture->argb == NULL) {
|
|
||||||
return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
|
|
||||||
} else {
|
|
||||||
const uint8_t* const argb = (const uint8_t*)picture->argb;
|
|
||||||
const uint8_t* const r = ALPHA_IS_LAST ? argb + 2 : argb + 1;
|
|
||||||
const uint8_t* const g = ALPHA_IS_LAST ? argb + 1 : argb + 2;
|
|
||||||
const uint8_t* const b = ALPHA_IS_LAST ? argb + 0 : argb + 3;
|
|
||||||
const uint8_t* const a = ALPHA_IS_LAST ? argb + 3 : argb + 0;
|
|
||||||
|
|
||||||
picture->colorspace = colorspace;
|
static int Import(WebPPicture* const picture,
|
||||||
if (!ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride, dithering,
|
const uint8_t* const rgb, int rgb_stride,
|
||||||
picture)) {
|
int step, int swap_rb, int import_alpha) {
|
||||||
return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
|
int y;
|
||||||
|
const uint8_t* const r_ptr = rgb + (swap_rb ? 2 : 0);
|
||||||
|
const uint8_t* const g_ptr = rgb + 1;
|
||||||
|
const uint8_t* const b_ptr = rgb + (swap_rb ? 0 : 2);
|
||||||
|
const uint8_t* const a_ptr = import_alpha ? rgb + 3 : NULL;
|
||||||
|
const int width = picture->width;
|
||||||
|
const int height = picture->height;
|
||||||
|
|
||||||
|
if (!picture->use_argb) {
|
||||||
|
return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride,
|
||||||
|
0.f /* no dithering */, picture);
|
||||||
|
}
|
||||||
|
if (!WebPPictureAlloc(picture)) return 0;
|
||||||
|
|
||||||
|
assert(step >= (import_alpha ? 4 : 3));
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
uint32_t* const dst = &picture->argb[y * picture->argb_stride];
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < width; ++x) {
|
||||||
|
const int offset = step * x + y * rgb_stride;
|
||||||
|
if (!import_alpha) {
|
||||||
|
dst[x] = MakeARGB32(r_ptr[offset], g_ptr[offset], b_ptr[offset]);
|
||||||
|
} else {
|
||||||
|
dst[x] = ((uint32_t)a_ptr[offset] << 24) |
|
||||||
|
(r_ptr[offset] << 16) |
|
||||||
|
(g_ptr[offset] << 8) |
|
||||||
|
(b_ptr[offset]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) {
|
// Public API
|
||||||
return WebPPictureARGBToYUVADithered(picture, colorspace, 0.f);
|
|
||||||
|
int WebPPictureImportRGB(WebPPicture* picture,
|
||||||
|
const uint8_t* rgb, int rgb_stride) {
|
||||||
|
return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 0, 0) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebPPictureImportBGR(WebPPicture* picture,
|
||||||
|
const uint8_t* rgb, int rgb_stride) {
|
||||||
|
return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 1, 0) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebPPictureImportRGBA(WebPPicture* picture,
|
||||||
|
const uint8_t* rgba, int rgba_stride) {
|
||||||
|
return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebPPictureImportBGRA(WebPPicture* picture,
|
||||||
|
const uint8_t* rgba, int rgba_stride) {
|
||||||
|
return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebPPictureImportRGBX(WebPPicture* picture,
|
||||||
|
const uint8_t* rgba, int rgba_stride) {
|
||||||
|
return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 0) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebPPictureImportBGRX(WebPPicture* picture,
|
||||||
|
const uint8_t* rgba, int rgba_stride) {
|
||||||
|
return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 0) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user