mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 06:08:21 +01:00
Merge "libsharpyuv: add colorspace utilities" into main
This commit is contained in:
commit
40e8aa57f8
@ -35,6 +35,7 @@ endif
|
|||||||
|
|
||||||
sharpyuv_srcs := \
|
sharpyuv_srcs := \
|
||||||
sharpyuv/sharpyuv.c \
|
sharpyuv/sharpyuv.c \
|
||||||
|
sharpyuv/sharpyuv_csp.c \
|
||||||
sharpyuv/sharpyuv_dsp.c \
|
sharpyuv/sharpyuv_dsp.c \
|
||||||
sharpyuv/sharpyuv_neon.$(NEON) \
|
sharpyuv/sharpyuv_neon.$(NEON) \
|
||||||
sharpyuv/sharpyuv_sse2.c \
|
sharpyuv/sharpyuv_sse2.c \
|
||||||
|
@ -220,6 +220,7 @@ target_include_directories(sharpyuv
|
|||||||
set_target_properties(
|
set_target_properties(
|
||||||
sharpyuv
|
sharpyuv
|
||||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv.h;\
|
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv.h;\
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv_csp.h;\
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
@ -107,6 +107,7 @@ model {
|
|||||||
source {
|
source {
|
||||||
srcDir "sharpyuv"
|
srcDir "sharpyuv"
|
||||||
include "sharpyuv.c"
|
include "sharpyuv.c"
|
||||||
|
include "sharpyuv_csp.c"
|
||||||
include "sharpyuv_dsp.c"
|
include "sharpyuv_dsp.c"
|
||||||
include "sharpyuv_neon.c"
|
include "sharpyuv_neon.c"
|
||||||
include "sharpyuv_sse2.c"
|
include "sharpyuv_sse2.c"
|
||||||
|
@ -127,6 +127,7 @@ ANIM_UTIL_OBJS = \
|
|||||||
|
|
||||||
SHARPYUV_OBJS = \
|
SHARPYUV_OBJS = \
|
||||||
sharpyuv/sharpyuv.o \
|
sharpyuv/sharpyuv.o \
|
||||||
|
sharpyuv/sharpyuv_csp.o \
|
||||||
sharpyuv/sharpyuv_dsp.o \
|
sharpyuv/sharpyuv_dsp.o \
|
||||||
sharpyuv/sharpyuv_neon.o \
|
sharpyuv/sharpyuv_neon.o \
|
||||||
sharpyuv/sharpyuv_sse2.o \
|
sharpyuv/sharpyuv_sse2.o \
|
||||||
|
@ -20,6 +20,7 @@ libsharpyuv_neon_la_CPPFLAGS = $(libsharpyuv_la_CPPFLAGS)
|
|||||||
libsharpyuv_neon_la_CFLAGS = $(AM_CFLAGS) $(NEON_FLAGS)
|
libsharpyuv_neon_la_CFLAGS = $(AM_CFLAGS) $(NEON_FLAGS)
|
||||||
|
|
||||||
libsharpyuv_la_SOURCES =
|
libsharpyuv_la_SOURCES =
|
||||||
|
libsharpyuv_la_SOURCES += sharpyuv_csp.c sharpyuv_csp.h
|
||||||
libsharpyuv_la_SOURCES += sharpyuv_dsp.c sharpyuv_dsp.h
|
libsharpyuv_la_SOURCES += sharpyuv_dsp.c sharpyuv_dsp.h
|
||||||
libsharpyuv_la_SOURCES += sharpyuv.c sharpyuv.h
|
libsharpyuv_la_SOURCES += sharpyuv.c sharpyuv.h
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
//
|
//
|
||||||
// Author: Skal (pascal.massimino@gmail.com)
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
#include "./sharpyuv.h"
|
#include "sharpyuv/sharpyuv.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -455,17 +455,6 @@ void SharpYuvInit(VP8CPUInfo cpu_info_func) {
|
|||||||
sharpyuv_last_cpuinfo_used = cpu_info_func;
|
sharpyuv_last_cpuinfo_used = cpu_info_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In YUV_FIX fixed point precision.
|
|
||||||
static const SharpYuvConversionMatrix kWebpYuvMatrix = {
|
|
||||||
{16839, 33059, 6420, 16 << 16},
|
|
||||||
{-9719, -19081, 28800, 128 << 16},
|
|
||||||
{28800, -24116, -4684, 128 << 16},
|
|
||||||
};
|
|
||||||
|
|
||||||
const SharpYuvConversionMatrix* SharpYuvGetWebpMatrix(void) {
|
|
||||||
return &kWebpYuvMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SharpYuvConvert(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
int SharpYuvConvert(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
||||||
const uint8_t* b_ptr, int step, int rgb_stride,
|
const uint8_t* b_ptr, int step, int rgb_stride,
|
||||||
uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u,
|
uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u,
|
||||||
|
@ -29,18 +29,15 @@ typedef struct {
|
|||||||
int rgb_to_v[4];
|
int rgb_to_v[4];
|
||||||
} SharpYuvConversionMatrix;
|
} SharpYuvConversionMatrix;
|
||||||
|
|
||||||
// Returns the RGB to YUV matrix used by WebP.
|
|
||||||
const SharpYuvConversionMatrix* SharpYuvGetWebpMatrix(void);
|
|
||||||
|
|
||||||
// Converts RGB to YUV420 using a downsampling algorithm that minimizes
|
// Converts RGB to YUV420 using a downsampling algorithm that minimizes
|
||||||
// artefacts caused by chroma subsampling.
|
// artefacts caused by chroma subsampling.
|
||||||
// This is slower than standard downsampling (averaging of 4 UV values).
|
// This is slower than standard downsampling (averaging of 4 UV values).
|
||||||
// Assumes that the image will be upsampled using a bilinear filter. If nearest
|
// Assumes that the image will be upsampled using a bilinear filter. If nearest
|
||||||
// neighbor is used instead, the upsampled image might look worse than with
|
// neighbor is used instead, the upsampled image might look worse than with
|
||||||
// standard downsampling.
|
// standard downsampling.
|
||||||
// TODO(maryla): add 10 bits and handling of various colorspaces. Add YUV444 to
|
// TODO(maryla): add 10 bits support. Add YUV444 to YUV420 conversion.
|
||||||
// YUV420 conversion. Maybe also add 422 support (it's rarely used in practice,
|
// Maybe also add 422 support (it's rarely used in practice, especially for
|
||||||
// especially for images).
|
// images).
|
||||||
int SharpYuvConvert(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
int SharpYuvConvert(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
||||||
const uint8_t* b_ptr, int step, int rgb_stride,
|
const uint8_t* b_ptr, int step, int rgb_stride,
|
||||||
uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u,
|
uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u,
|
||||||
|
111
sharpyuv/sharpyuv_csp.c
Normal file
111
sharpyuv/sharpyuv_csp.c
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the COPYING file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Colorspace utilities.
|
||||||
|
|
||||||
|
#include "sharpyuv/sharpyuv_csp.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static int ToFixed16(float f) { return (int)round(f * (1 << 16)); }
|
||||||
|
|
||||||
|
void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space,
|
||||||
|
SharpYuvConversionMatrix* matrix) {
|
||||||
|
const float kr = yuv_color_space->kr;
|
||||||
|
const float kb = yuv_color_space->kb;
|
||||||
|
const float kg = 1.0f - kr - kb;
|
||||||
|
const float cr = 0.5f / (1.0f - kb);
|
||||||
|
const float cb = 0.5f / (1.0f - kr);
|
||||||
|
|
||||||
|
const int shift = yuv_color_space->bits - 8;
|
||||||
|
|
||||||
|
const float denom = (float)((1 << yuv_color_space->bits) - 1);
|
||||||
|
float scaleY = 1.0f;
|
||||||
|
float addY = 0.0f;
|
||||||
|
float scaleU = cr;
|
||||||
|
float scaleV = cb;
|
||||||
|
float addUV = (128 << shift);
|
||||||
|
|
||||||
|
assert(yuv_color_space->bits >= 8);
|
||||||
|
|
||||||
|
if (yuv_color_space->range == kSharpYuvRangeLimited) {
|
||||||
|
scaleY *= (219 << shift) / denom;
|
||||||
|
scaleU *= (224 << shift) / denom;
|
||||||
|
scaleV *= (224 << shift) / denom;
|
||||||
|
addY = (16 << shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix->rgb_to_y[0] = ToFixed16(kr * scaleY);
|
||||||
|
matrix->rgb_to_y[1] = ToFixed16(kg * scaleY);
|
||||||
|
matrix->rgb_to_y[2] = ToFixed16(kb * scaleY);
|
||||||
|
matrix->rgb_to_y[3] = ToFixed16(addY);
|
||||||
|
|
||||||
|
matrix->rgb_to_u[0] = ToFixed16(-kr * scaleU);
|
||||||
|
matrix->rgb_to_u[1] = ToFixed16(-kg * scaleU);
|
||||||
|
matrix->rgb_to_u[2] = ToFixed16((1 - kb) * scaleU);
|
||||||
|
matrix->rgb_to_u[3] = ToFixed16(addUV);
|
||||||
|
|
||||||
|
matrix->rgb_to_v[0] = ToFixed16((1 - kr) * scaleV);
|
||||||
|
matrix->rgb_to_v[1] = ToFixed16(-kg * scaleV);
|
||||||
|
matrix->rgb_to_v[2] = ToFixed16(-kb * scaleV);
|
||||||
|
matrix->rgb_to_v[3] = ToFixed16(addUV);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matrices are in YUV_FIX fixed point precision.
|
||||||
|
// WebP's matrix, similar but not identical to kRec601LimitedMatrix.
|
||||||
|
static const SharpYuvConversionMatrix kWebpMatrix = {
|
||||||
|
{16839, 33059, 6420, 16 << 16},
|
||||||
|
{-9719, -19081, 28800, 128 << 16},
|
||||||
|
{28800, -24116, -4684, 128 << 16},
|
||||||
|
};
|
||||||
|
// Kr=0.2990f Kb=0.1140f btits=8 range=kLimited
|
||||||
|
static const SharpYuvConversionMatrix kRec601LimitedMatrix = {
|
||||||
|
{16829, 33039, 6416, 16 << 16},
|
||||||
|
{-9714, -19071, 28784, 128 << 16},
|
||||||
|
{28784, -24103, -4681, 128 << 16},
|
||||||
|
};
|
||||||
|
// Kr=0.2990f Kb=0.1140f btits=8 range=kFull
|
||||||
|
static const SharpYuvConversionMatrix kRec601FullMatrix = {
|
||||||
|
{19595, 38470, 7471, 0},
|
||||||
|
{-11058, -21710, 32768, 128 << 16},
|
||||||
|
{32768, -27439, -5329, 128 << 16},
|
||||||
|
};
|
||||||
|
// Kr=0.2126f Kb=0.0722f bits=8 range=kLimited
|
||||||
|
static const SharpYuvConversionMatrix kRec709LimitedMatrix = {
|
||||||
|
{11966, 40254, 4064, 16 << 16},
|
||||||
|
{-6596, -22189, 28784, 128 << 16},
|
||||||
|
{28784, -26145, -2639, 128 << 16},
|
||||||
|
};
|
||||||
|
// Kr=0.2126f Kb=0.0722f bits=8 range=kFull
|
||||||
|
static const SharpYuvConversionMatrix kRec709FullMatrix = {
|
||||||
|
{13933, 46871, 4732, 0},
|
||||||
|
{-7509, -25259, 32768, 128 << 16},
|
||||||
|
{32768, -29763, -3005, 128 << 16},
|
||||||
|
};
|
||||||
|
|
||||||
|
const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(
|
||||||
|
SharpYuvMatrixType matrix_type) {
|
||||||
|
switch (matrix_type) {
|
||||||
|
case kSharpYuvMatrixWebp:
|
||||||
|
return &kWebpMatrix;
|
||||||
|
case kSharpYuvMarixRec601Limited:
|
||||||
|
return &kRec601LimitedMatrix;
|
||||||
|
case kSharpYuvMarixRec601Full:
|
||||||
|
return &kRec601FullMatrix;
|
||||||
|
case kSharpYuvMarixRec709Limited:
|
||||||
|
return &kRec709LimitedMatrix;
|
||||||
|
case kSharpYuvMarixRec709Full:
|
||||||
|
return &kRec709FullMatrix;
|
||||||
|
case kSharpYuvMarixNum:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
59
sharpyuv/sharpyuv_csp.h
Normal file
59
sharpyuv/sharpyuv_csp.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the COPYING file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Colorspace utilities.
|
||||||
|
|
||||||
|
#ifndef WEBP_SHARPYUV_SHARPYUV_CSP_H_
|
||||||
|
#define WEBP_SHARPYUV_SHARPYUV_CSP_H_
|
||||||
|
|
||||||
|
#include "sharpyuv/sharpyuv.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Range of YUV values.
|
||||||
|
typedef enum {
|
||||||
|
kSharpYuvRangeFull, // YUV values between [0;255] (for 8 bit)
|
||||||
|
kSharpYuvRangeLimited // Y in [16;235], YUV in [16;240] (for 8 bit)
|
||||||
|
} SharpYuvRange;
|
||||||
|
|
||||||
|
// Constants that define a YUV color space.
|
||||||
|
typedef struct {
|
||||||
|
// Kr and Kb are defined such that:
|
||||||
|
// Y = Kr * r + Kg * g + Kb * b where Kg = 1 - Kr - Kb.
|
||||||
|
float kr;
|
||||||
|
float kb;
|
||||||
|
int bits; // Only 8 bit is supported by SharpYuvConvert.
|
||||||
|
SharpYuvRange range;
|
||||||
|
} SharpYuvColorSpace;
|
||||||
|
|
||||||
|
// Fills in 'matrix' for the given YUVColorSpace.
|
||||||
|
void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space,
|
||||||
|
SharpYuvConversionMatrix* matrix);
|
||||||
|
|
||||||
|
// Enums for precomputed conversion matrices.
|
||||||
|
typedef enum {
|
||||||
|
kSharpYuvMatrixWebp = 0,
|
||||||
|
kSharpYuvMarixRec601Limited,
|
||||||
|
kSharpYuvMarixRec601Full,
|
||||||
|
kSharpYuvMarixRec709Limited,
|
||||||
|
kSharpYuvMarixRec709Full,
|
||||||
|
kSharpYuvMarixNum
|
||||||
|
} SharpYuvMatrixType;
|
||||||
|
|
||||||
|
// Returns a pointer to a matrix for one of the predefined colorspaces.
|
||||||
|
const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(
|
||||||
|
SharpYuvMatrixType matrix_type);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // WEBP_SHARPYUV_SHARPYUV_CSP_H_
|
@ -9,8 +9,8 @@
|
|||||||
//
|
//
|
||||||
// Speed-critical functions for Sharp YUV.
|
// Speed-critical functions for Sharp YUV.
|
||||||
|
|
||||||
#ifndef WEBP_SHARPYUV_DSP_H_
|
#ifndef WEBP_SHARPYUV_SHARPYUV_DSP_H_
|
||||||
#define WEBP_SHARPYUV_DSP_H_
|
#define WEBP_SHARPYUV_SHARPYUV_DSP_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -25,4 +25,4 @@ extern void (*SharpYUVFilterRow)(const int16_t* A, const int16_t* B, int len,
|
|||||||
|
|
||||||
void SharpYuvInitDsp(VP8CPUInfo cpu_info_func);
|
void SharpYuvInitDsp(VP8CPUInfo cpu_info_func);
|
||||||
|
|
||||||
#endif // WEBP_SHARPYUV_DSP_H_
|
#endif // WEBP_SHARPYUV_SHARPYUV_DSP_H_
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "sharpyuv/sharpyuv.h"
|
#include "sharpyuv/sharpyuv.h"
|
||||||
|
#include "sharpyuv/sharpyuv_csp.h"
|
||||||
#include "src/enc/vp8i_enc.h"
|
#include "src/enc/vp8i_enc.h"
|
||||||
#include "src/utils/random_utils.h"
|
#include "src/utils/random_utils.h"
|
||||||
#include "src/utils/utils.h"
|
#include "src/utils/utils.h"
|
||||||
@ -202,7 +203,8 @@ static int PreprocessARGB(const uint8_t* r_ptr,
|
|||||||
const int ok = SharpYuvConvert(
|
const int ok = SharpYuvConvert(
|
||||||
r_ptr, g_ptr, b_ptr, step, rgb_stride, picture->y, picture->y_stride,
|
r_ptr, g_ptr, b_ptr, step, rgb_stride, picture->y, picture->y_stride,
|
||||||
picture->u, picture->uv_stride, picture->v, picture->uv_stride,
|
picture->u, picture->uv_stride, picture->v, picture->uv_stride,
|
||||||
picture->width, picture->height, SharpYuvGetWebpMatrix());
|
picture->width, picture->height,
|
||||||
|
SharpYuvGetConversionMatrix(kSharpYuvMatrixWebp));
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
|
return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user