Last active
July 8, 2020 13:33
-
-
Save dwbuiten/2a9b37cb64842b88d507f45d4b08d17c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use strict; | |
use warnings; | |
use utf8; | |
use bignum; | |
use Statistics::Basic qw(mean stddev); | |
use List::Util qw(max); | |
my @id; | |
my @yuv; | |
my @ycgco; | |
my @haar; | |
my $list = shift; | |
for (`cat $list`) { # lazy | |
chomp; | |
open(my $f, "<", "$_") or die("cant open $_"); | |
my $i = 0; | |
while (<$f>) { | |
chomp; | |
if ($i == 0) { | |
$i++; | |
next; | |
} | |
my @vals = split(','); | |
if (scalar(@vals) != 5) { | |
die("invalid number of vals"); | |
} | |
push(@id, ($vals[1] / $vals[0]) * 100); | |
push(@yuv, ($vals[2] / $vals[0]) * 100); | |
push(@ycgco, ($vals[3] / $vals[0]) * 100); | |
push(@haar, ($vals[4] / $vals[0]) * 100); | |
$i++; | |
} | |
if ($i != 2) { | |
die("$_ is invalid"); | |
} | |
close($f); | |
} | |
my $name = (split(/\./, $list))[0]; | |
printf("|-----------------------------------------------------------|\n"); | |
printf("| $name".(" " x (58 - length($name)))."|\n"); | |
printf("|-----------------------------------------------------------|\n"); | |
printf("| Identity (GBR) | Mean: %6.2f%% | StdDev: %6.02f%% |\n", mean(\@id), stddev(\@id)); | |
printf("| YCbCr 10-bit | Mean: %6.2f%% | StdDev: %6.02f%% |\n", mean(\@yuv), stddev(\@yuv)); | |
printf("| YCgCo 9-bit (as 10-bit) | Mean: %6.2f%% | StdDev: %6.02f%% |\n", mean(\@ycgco), stddev(\@ycgco)); | |
printf("| PLHaar N-bit to N-bit | Mean: %6.2f%% | StdDev: %6.02f%% |\n", mean(\@haar), stddev(\@haar)); | |
printf("|-----------------------------------------------------------|\n"); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <assert.h> | |
static void plhaar_int(int *l, int *h, int a, int b, int c) | |
{ | |
const int s = (a < c), t = (b < c); | |
a += s; b += t; | |
if (s == t) { | |
a -= b - c; | |
if ((a < c) == s) | |
b += a - c; | |
} else { | |
b += a - c; | |
if ((b < c) == t) | |
a -= b - c; | |
} | |
a -= s; b -= t; | |
*l = b; *h = a; | |
} | |
static void haar_conv(uint8_t *dst, uint8_t *src, int w, int h) | |
{ | |
uint8_t *g = src; | |
uint8_t *b = g + w * h; | |
uint8_t *r = b + w * h; | |
uint8_t *yp = dst; | |
uint8_t *u = yp + w * h; | |
uint8_t *v = u + w * h; | |
int x, y; | |
for (y = 0; y < h; y++) { | |
for (x = 0; x < w; x++) { | |
int ri = (int) r[y * w + x]; | |
int gi = (int) g[y * w + x]; | |
int bi = (int) b[y * w + x]; | |
int sum, diff; | |
plhaar_int(&sum, &diff, ri, bi, 128); | |
int ui = diff; | |
int tmp = sum; | |
plhaar_int(&sum, &diff, gi, tmp, 128); | |
int vi = diff; | |
int ypi = sum; | |
assert(ypi <= 255 && ypi >= 0); | |
assert(ui <= 255 && ui >= 0); | |
assert(vi <= 255 && vi >= 0); | |
yp[y * w + x] = (uint8_t) ypi; | |
u[y * w + x] = (uint8_t) ui; | |
v[y * w + x] = (uint8_t) vi; | |
/* Everything below here is non-functional paranoid checks. */ | |
plhaar_int(&sum, &diff, ypi, vi, 128); | |
int gicheck = sum; | |
tmp = diff; | |
plhaar_int(&sum, &diff, tmp, ui, 128); | |
int richeck = sum; | |
int bicheck = diff; | |
assert(ri == richeck); | |
assert(gi == gicheck); | |
assert(bi == bicheck); | |
} | |
} | |
} | |
static void ycgco_r_conv(uint8_t *dst, uint8_t *src, int w, int h) | |
{ | |
uint8_t *g = src; | |
uint8_t *b = g + w * h; | |
uint8_t *r = b + w * h; | |
uint8_t *yp = dst; | |
uint8_t *cg = yp + w * h * 2; | |
uint8_t *co = cg + w * h * 2; | |
int x, y; | |
for (y = 0; y < h; y++) { | |
int ox; | |
for (x = 0, ox = 0; x < w; x++, ox += 2) { | |
int16_t g16 = g[y * w + x]; | |
int16_t b16 = b[y * w + x]; | |
int16_t r16 = r[y * w + x]; | |
int16_t co16 = r16 - b16; | |
int16_t tmp16 = b16 + (co16 / 2); | |
int16_t cg16 = g16 - tmp16; | |
int16_t y16 = tmp16 + (cg16 / 2); | |
co16 += 256; | |
cg16 += 256; | |
/* Little endian. */ | |
yp[y * (w * 2) + ox + 0] = (uint8_t) (((uint16_t) y16) & 0xFF); | |
yp[y * (w * 2) + ox + 1] = (uint8_t) ((((uint16_t) y16) & 0xFF00) >> 8); | |
cg[y * (w * 2) + ox + 0] = (uint8_t) (((uint16_t) cg16) & 0xFF); | |
cg[y * (w * 2) + ox + 1] = (uint8_t) ((((uint16_t) cg16) & 0xFF00) >> 8); | |
co[y * (w * 2) + ox + 0] = (uint8_t) (((uint16_t) co16) & 0xFF); | |
co[y * (w * 2) + ox + 1] = (uint8_t) ((((uint16_t) co16) & 0xFF00) >> 8); | |
/* Everything below here is non-functional paranoid checks. */ | |
assert(y16 <= 255 && y16 >= 0); | |
assert(cg16 <= 511 && y16 >= 0); | |
assert(co16 <= 511 && y16 >= 0); | |
co16 -= 256; | |
cg16 -= 256; | |
tmp16 = y16 - (cg16 / 2); | |
int16_t g16check = cg16 + tmp16; | |
int16_t b16check = tmp16 - (co16 / 2); | |
int16_t r16check = b16check + co16; | |
assert(g16check == g16); | |
assert(b16check == b16); | |
assert(r16check == r16); | |
} | |
} | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int ret = 0; | |
uint8_t *inbuf = NULL, *ycgcobuf = NULL, *haarbuf = NULL; | |
FILE *in = NULL, *yout = NULL, *hout = NULL; | |
int width, height; | |
size_t fret; | |
if (argc < 6) { | |
printf("Usage: conv file.gbrp width height ycgco-r.out haar.out\n"); | |
return 1; | |
} | |
width = atoi(argv[2]); | |
height = atoi(argv[3]); | |
if (width <= 0 || height <= 0) { | |
printf("Invalid width/height (%dx%d).\n", width, height); | |
return 1; | |
} | |
in = fopen(argv[1], "rb"); | |
if (in == NULL) { | |
printf("Failed to open %s\n", argv[1]); | |
return 1; | |
} | |
inbuf = malloc(width * height * 3); | |
if (inbuf == NULL) { | |
printf("Failed to allocate input buffer.\n"); | |
ret = 1; | |
goto end; | |
} | |
fret = fread(inbuf, 1, width * height * 3, in); | |
if (fret != (size_t) width * height * 3) { | |
printf("Failed to read enough input bytes (wanted %zu got %d).\n", fret, width * height * 3); | |
ret = 1; | |
goto end; | |
} | |
fclose(in); | |
in = NULL; | |
ycgcobuf = malloc(width * height * 3 * 2); | |
if (ycgcobuf == NULL) { | |
printf("Failed to allocate YCgCo buffer.\n"); | |
ret = 1; | |
goto end; | |
} | |
ycgco_r_conv(ycgcobuf, inbuf, width, height); | |
yout = fopen(argv[4], "wb"); | |
if (yout == NULL) { | |
printf("Failed to open out.ycgco\n"); | |
ret = 1; | |
goto end; | |
} | |
fret = fwrite(ycgcobuf, 1, width * height * 3 * 2, yout); | |
if (fret != (size_t) width * height * 3 * 2) { | |
printf("Failed to write enough bytes (wanted %zu got %d).\n", fret, width * height * 3 * 2); | |
ret = 1; | |
goto end; | |
} | |
fclose(yout); | |
yout = NULL; | |
free(ycgcobuf); | |
ycgcobuf = NULL; | |
haarbuf = malloc(width * height * 3); | |
if (haarbuf == NULL) { | |
printf("Failed to allocate Haar buffer.\n"); | |
ret = 1; | |
goto end; | |
} | |
haar_conv(haarbuf, inbuf, width, height); | |
free(inbuf); | |
inbuf = NULL; | |
hout = fopen(argv[5], "wb"); | |
if (hout == NULL) { | |
printf("Failed to open out.haar.\n"); | |
ret = 1; | |
goto end; | |
} | |
fret = fwrite(haarbuf, 1, width * height * 3, hout); | |
if (fret != (size_t) width * height * 3) { | |
printf("Failed to write enough bytes (wanted %zu got %d).\n", fret, width * height * 3); | |
ret = 1; | |
goto end; | |
} | |
fclose(hout); | |
hout = NULL; | |
free(haarbuf); | |
haarbuf = NULL; | |
end: | |
if (inbuf != NULL) | |
free(inbuf); | |
if (ycgcobuf != NULL) | |
free(ycgcobuf); | |
if (haarbuf != NULL) | |
free(haarbuf); | |
if (in != NULL) | |
fclose(in); | |
if (yout != NULL) | |
fclose(yout); | |
if (hout != NULL) | |
fclose(hout); | |
return ret; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh -e | |
FILE=$1 | |
DIR=$(dirname ${FILE}) | |
TMP=$(ffprobe -show_streams "${FILE}" 2>/dev/null | egrep "^width=|^height=" | tr '\n' ' ') | |
WIDTH=$(echo ${TMP} | sed -e 's/width=\(.\+\) height=.\+/\1/') | |
HEIGHT=$(echo ${TMP} | sed -e 's/width=.\+ height=\(.\+\)/\1/') | |
ffmpeg -i "${FILE}" -pix_fmt gbrp -f rawvideo -y "${FILE}.gbrp" 2>/dev/null | |
conv "${FILE}".gbrp ${WIDTH} ${HEIGHT} "${FILE}.ycgco" "${FILE}.haar" | |
ffmpeg -f rawvideo -s ${WIDTH}x${HEIGHT} -pix_fmt gbrp -i "${FILE}.gbrp" -y "${FILE}.png" 2>/dev/null | |
pngcrush -brute "${FILE}.png" "${FILE}.crush.png" 2>/dev/null | |
avifenc --lossless --range full --yuv 444 --depth 10 "${FILE}.png" -s 0 "${FILE}.ycbcr.avif" >/dev/null | |
ffmpeg -f rawvideo -s ${WIDTH}x${HEIGHT} -color_range pc -pix_fmt yuv444p -i "${FILE}.gbrp" -color_range pc -strict -1 -y "${FILE}.identity.y4m" 2>/dev/null | |
avifenc --lossless "${FILE}.identity.y4m" -s 0 "${FILE}.identity.avif" >/dev/null | |
ffmpeg -f rawvideo -s ${WIDTH}x${HEIGHT} -color_range pc -pix_fmt yuv444p10le -i "${FILE}.ycgco" -color_range pc -strict -1 -y "${FILE}.ycgco.y4m" 2>/dev/null | |
avifenc --lossless "${FILE}.ycgco.y4m" -s 0 "${FILE}.ycgco.avif" >/dev/null | |
ffmpeg -f rawvideo -s ${WIDTH}x${HEIGHT} -color_range pc -pix_fmt yuv444p -i "${FILE}.haar" -color_range pc -strict -1 -y "${FILE}.haar.y4m" 2>/dev/null | |
avifenc --lossless "${FILE}.haar.y4m" -s 0 "${FILE}.haar.avif" >/dev/null | |
PNGSIZE=$(stat -c '%s' "${FILE}.crush.png") | |
IDSIZE=$(stat -c '%s' "${FILE}.identity.avif") | |
YUVSIZE=$(stat -c '%s' "${FILE}.ycbcr.avif") | |
YCGCOSIZE=$(stat -c '%s' "${FILE}.ycgco.avif") | |
HAARSIZE=$(stat -c '%s' "${FILE}.haar.avif") | |
rm "${FILE}.png" | |
rm "${FILE}.crush.png" | |
rm "${FILE}.ycbcr.avif" | |
rm "${FILE}.gbrp" | |
rm "${FILE}.identity.y4m" | |
rm "${FILE}.identity.avif" | |
rm "${FILE}.ycgco" | |
rm "${FILE}.ycgco.y4m" | |
rm "${FILE}.ycgco.avif" | |
rm "${FILE}.haar" | |
rm "${FILE}.haar.y4m" | |
rm "${FILE}.haar.avif" | |
echo "PNG,IDENTITY,YCBCR,YCGCO,HAAR" > ${FILE}.csv | |
echo "${PNGSIZE},${IDSIZE},${YUVSIZE},${YCGCOSIZE},${HAARSIZE}" >> ${FILE}.csv |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment