mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
improved XYB conversion
This commit is contained in:
@@ -684,7 +684,6 @@ DCT-based compression, motion compensation, and efficient temporal coding.
|
||||
* Enables bitrate-constrained encoding alongside quality modes
|
||||
* All video frames now include 4-byte rate control factor after payload size
|
||||
- Version 3.0: Additional support of XYB Colour space
|
||||
* Increased encoding efficiency, decreased decoding performance
|
||||
|
||||
# File Structure
|
||||
\x1F T S V M T E V
|
||||
|
||||
@@ -1656,10 +1656,13 @@ class GraphicsJSR223Delegate(private val vm: VM) {
|
||||
val x = xBlock[xbIdx]
|
||||
val b = bBlock[xbIdx]
|
||||
|
||||
// Dequantize from integer ranges
|
||||
val yVal = (y - 128.0) / 255.0
|
||||
val xVal = x / 255.0
|
||||
val bVal = b / 255.0
|
||||
// Optimal range-based dequantization (exact inverse of improved quantization)
|
||||
val X_MIN = -0.016; val X_MAX = 0.030
|
||||
val xVal = (x / 255.0) * (X_MAX - X_MIN) + X_MIN // X: inverse of range mapping
|
||||
val Y_MAX = 0.85
|
||||
val yVal = (y / 255.0) * Y_MAX // Y: inverse of improved scale
|
||||
val B_MAX = 0.85
|
||||
val bVal = (((b - 1.0) + 128.0) / 255.0) * B_MAX // B: inverse of ((val/B_MAX*255)-128+1)
|
||||
|
||||
// XYB to LMS gamma
|
||||
val lgamma = xVal + yVal
|
||||
@@ -1723,10 +1726,16 @@ class GraphicsJSR223Delegate(private val vm: VM) {
|
||||
val yVal = (lgamma + mgamma) / 2.0
|
||||
val bVal = sgamma
|
||||
|
||||
// Quantize to integer ranges suitable for TEV
|
||||
val yQuant = (yVal * 255.0 + 128.0).toInt().coerceIn(0, 255) // Y: 0-255 (like YCoCg Y)
|
||||
val xQuant = (xVal * 255.0).toInt().coerceIn(-128, 127) // X: -128 to +127 (like Co)
|
||||
val bQuant = (bVal * 255.0).toInt().coerceIn(-128, 127) // B: -128 to +127 (like Cg, aggressively quantized)
|
||||
// Optimal range-based quantization for XYB values (improved precision)
|
||||
// X: actual range -0.016 to +0.030, map to full 0-255 precision
|
||||
val X_MIN = -0.016; val X_MAX = 0.030
|
||||
val xQuant = (((xVal - X_MIN) / (X_MAX - X_MIN)) * 255.0).toInt().coerceIn(0, 255)
|
||||
// Y: range 0 to 0.85, map to 0 to 255 (improved scale)
|
||||
val Y_MAX = 0.85
|
||||
val yQuant = ((yVal / Y_MAX) * 255.0).toInt().coerceIn(0, 255)
|
||||
// B: range 0 to 0.85, map to -128 to +127 (improved precision with +1 offset for yellow-green)
|
||||
val B_MAX = 0.85
|
||||
val bQuant = (((bVal / B_MAX) * 255.0) - 128.0 + 1.0).toInt().coerceIn(-128, 127)
|
||||
|
||||
// Store XYB values
|
||||
val yIdx = py * 16 + px
|
||||
|
||||
@@ -232,18 +232,32 @@ static void rgb_to_xyb(uint8_t r, uint8_t g, uint8_t b, int *y, int *x, int *xyb
|
||||
double y_val = (lgamma + mgamma) / 2.0;
|
||||
double b_val = sgamma;
|
||||
|
||||
// Quantize to integer ranges suitable for TEV
|
||||
*y = CLAMP((int)(y_val * 255.0 + 128.0), 0, 255); // Y: 0-255 (like YCoCg Y)
|
||||
*x = CLAMP((int)(x_val * 255.0), -128, 127); // X: -128 to +127 (like Co)
|
||||
*xyb_b = CLAMP((int)(b_val * 255.0), -128, 127); // B: -128 to +127 (like Cg, aggressively quantized)
|
||||
// Optimal range-based quantization for XYB values (improved precision)
|
||||
// X: actual range -0.016 to +0.030, map to full 0-255 precision
|
||||
const double X_MIN = -0.016, X_MAX = 0.030;
|
||||
*x = CLAMP((int)(((x_val - X_MIN) / (X_MAX - X_MIN)) * 255.0), 0, 255);
|
||||
// Y: range 0 to 0.85, map to 0 to 255 (improved scale)
|
||||
const double Y_MAX = 0.85;
|
||||
*y = CLAMP((int)((y_val / Y_MAX) * 255.0), 0, 255);
|
||||
// B: range 0 to 0.85, map to -128 to +127 (improved precision with +1 offset for yellow-green)
|
||||
const double B_MAX = 0.85;
|
||||
*xyb_b = CLAMP((int)(((b_val / B_MAX) * 255.0) - 128.0 + 1.0), -128, 127);
|
||||
}
|
||||
|
||||
// XYB to RGB transform (for verification)
|
||||
static void xyb_to_rgb(int y, int x, int xyb_b, uint8_t *r, uint8_t *g, uint8_t *b) {
|
||||
// Dequantize from integer ranges
|
||||
double y_val = (y - 128.0) / 255.0;
|
||||
double x_val = x / 255.0;
|
||||
double b_val = xyb_b / 255.0;
|
||||
// Optimal range-based dequantization (exact inverse of improved quantization)
|
||||
const double X_MIN = -0.016, X_MAX = 0.030;
|
||||
double x_val = (x / 255.0) * (X_MAX - X_MIN) + X_MIN; // X: inverse of range mapping
|
||||
const double Y_MAX = 0.85;
|
||||
double y_val = (y / 255.0) * Y_MAX; // Y: inverse of improved scale
|
||||
const double B_MAX = 0.85;
|
||||
double b_val = (((xyb_b - 1.0) + 128.0) / 255.0) * B_MAX; // B: inverse of ((val/B_MAX*255)-128+1)
|
||||
|
||||
// Debug print for red color
|
||||
if (x == 127 && y == 147 && xyb_b == 28) {
|
||||
printf("DEBUG: Red conversion - Dequantized XYB: X=%.6f Y=%.6f B=%.6f\n", x_val, y_val, b_val);
|
||||
}
|
||||
|
||||
// XYB to LMS gamma
|
||||
double lgamma = x_val + y_val;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
// XYB conversion constants from JPEG XL specification
|
||||
static const double XYB_BIAS = 0.00379307325527544933;
|
||||
static const double CBRT_BIAS = 0.01558; // cbrt(XYB_BIAS)
|
||||
static const double CBRT_BIAS = 0.155954200549248620; // cbrt(XYB_BIAS)
|
||||
|
||||
// RGB to LMS mixing coefficients
|
||||
static const double RGB_TO_LMS[3][3] = {
|
||||
|
||||
Reference in New Issue
Block a user