summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2022-11-12 16:00:55 +0200
committerOleg Oshmyan <chortos@inbox.lv>2022-11-16 16:10:37 +0200
commitdedc1594c799397c71ee45f08c5d21a2ceba6b8a (patch)
tree73cfaa554247fb109d88d45885c280e73f4a2d2a
parent830dc3a60ebf0607d90c1b158f6ccccfe4709e74 (diff)
downloadlibass-dedc1594c799397c71ee45f08c5d21a2ceba6b8a.tar.bz2
libass-dedc1594c799397c71ee45f08c5d21a2ceba6b8a.tar.xz
compare: support anamorphic scaling
The division approximation broke down for 5x7 scaling, so adjust it to be right.
-rw-r--r--compare/README.md5
-rw-r--r--compare/compare.c67
2 files changed, 43 insertions, 29 deletions
diff --git a/compare/README.md b/compare/README.md
index 2586f43..d0d7bd9 100644
--- a/compare/README.md
+++ b/compare/README.md
@@ -5,11 +5,12 @@ To build a test utility configure libass with the `--enable-compare` flag.
The utility works with `png` image files so there is external dependency of libpng.
Test program command line:
-`compare ([-i] <input-dir>)+ [-o <output-dir>] [-s <scale:1-8>] [-p <pass-level:0-3>]`
+`compare ([-i] <input-dir>)+ [-o <output-dir>] [-s <scale:1-8>[x<scale:1-8>]] [-p <pass-level:0-3>]`
* `<input-dir>` is a test input directory, can be several of them;
* `<output-dir>` if present sets directory to store the rendering results;
-* `<scale>` sets an oversampling factor (positive integer up to 8, default 1);
+* `<scale>` sets factors for horizontal and vertical oversampling (positive integers up to 8)
+ or a single factor to be used in both directions (default 1);
* `<pass-level>` corresponds to the level of image differences required to pass test:
- 0: only `SAME` level accepted, bitwise comparison mode;
- 1: `GOOD` level or less required;
diff --git a/compare/compare.c b/compare/compare.c
index 4abf512..cb6680b 100644
--- a/compare/compare.c
+++ b/compare/compare.c
@@ -171,11 +171,11 @@ static int compare1(const Image16 *target, const uint16_t *grad,
static int compare(const Image16 *target, const uint16_t *grad,
const ASS_Image *img, const char *path,
- double *result, int scale)
+ double *result, int scale_x, int scale_y)
{
- if (scale == 1)
+ if (scale_x == 1 && scale_y == 1)
return compare1(target, grad, img, path, result);
- int scale2 = scale * scale;
+ int scale_area = scale_x * scale_y;
Image16 frame;
frame.width = target->width;
@@ -186,9 +186,9 @@ static int compare(const Image16 *target, const uint16_t *grad,
return 0;
Image8 temp;
- temp.width = scale * target->width;
- temp.height = scale * target->height;
- temp.buffer = malloc(4 * scale2 * size);
+ temp.width = scale_x * target->width;
+ temp.height = scale_y * target->height;
+ temp.buffer = malloc(4 * scale_area * size);
if (!temp.buffer) {
free(frame.buffer);
return 0;
@@ -198,24 +198,24 @@ static int compare(const Image16 *target, const uint16_t *grad,
uint16_t *dst = frame.buffer;
const uint8_t *src = temp.buffer;
int32_t stride = 4 * temp.width;
- const uint32_t offs = ((uint32_t) 1 << 18) - 1;
- uint32_t mul = ((uint32_t) 257 << 19) / scale2;
+ const uint32_t offs = ((uint32_t) 1 << 19) - 1;
+ uint32_t mul = ((uint32_t) 257 << 20) / scale_area;
for (int32_t y = 0; y < frame.height; y++) {
for (int32_t x = 0; x < frame.width; x++) {
uint16_t res[4] = {0};
const uint8_t *ptr = src;
- for (int i = 0; i < scale; i++) {
- for (int j = 0; j < scale; j++)
+ for (int i = 0; i < scale_y; i++) {
+ for (int j = 0; j < scale_x; j++)
for (int k = 0; k < 4; k++)
res[k] += ptr[4 * j + k];
ptr += stride;
}
for (int k = 0; k < 4; k++)
- // equivalent to (257 * res[k] + (scale2 - 1) / 2) / scale2;
- *dst++ = (res[k] * (uint64_t) mul + offs) >> 19;
- src += 4 * scale;
+ // equivalent to (257 * res[k] + (scale_area - 1) / 2) / scale_area;
+ *dst++ = (res[k] * (uint64_t) mul + offs) >> 20;
+ src += 4 * scale_x;
}
- src += (scale - 1) * stride;
+ src += (scale_y - 1) * stride;
}
free(temp.buffer);
@@ -323,7 +323,8 @@ Result classify_result(double error)
static Result process_image(ASS_Renderer *renderer, ASS_Track *track,
const char *input, const char *output,
- const char *file, int64_t time, int scale)
+ const char *file, int64_t time,
+ int scale_x, int scale_y)
{
uint64_t tm = time;
unsigned msec = tm % 1000; tm /= 1000;
@@ -349,7 +350,7 @@ static Result process_image(ASS_Renderer *renderer, ASS_Track *track,
calc_grad(&target, grad);
ass_set_storage_size(renderer, target.width, target.height);
- ass_set_frame_size(renderer, scale * target.width, scale * target.height);
+ ass_set_frame_size(renderer, scale_x * target.width, scale_y * target.height);
ASS_Image *img = ass_render_frame(renderer, track, time, NULL);
const char *out_file = NULL;
@@ -358,7 +359,7 @@ static Result process_image(ASS_Renderer *renderer, ASS_Track *track,
out_file = path;
}
double max_err;
- int res = compare(&target, grad, img, out_file, &max_err, scale);
+ int res = compare(&target, grad, img, out_file, &max_err, scale_x, scale_y);
free(target.buffer);
free(grad);
if (!res) {
@@ -569,11 +570,26 @@ static int *parse_cmdline(int argc, char *argv[])
fail:
free(pos);
const char *fmt =
- "Usage: %s ([-i] <input-dir>)+ [-o <output-dir>] [-s <scale:1-8>] [-p <pass-level:0-3>]\n";
+ "Usage: %s ([-i] <input-dir>)+ [-o <output-dir>] [-s <scale:1-8>[x<scale:1-8>]] [-p <pass-level:0-3>]\n"
+ "\n"
+ "Scale can be a single uniform scaling factor or a pair of independent horizontal and vertical factors. -s N is equivalent to -s NxN.\n";
printf(fmt, argv[0] ? argv[0] : "compare");
return NULL;
}
+static bool parse_scale(const char *arg, int *scale_x, int *scale_y)
+{
+ if (arg[0] < '1' || arg[0] > '8')
+ return false;
+ *scale_x = *scale_y = arg[0] - '0';
+ if (!arg[1])
+ return true;
+ if (arg[1] != 'x' || arg[2] < '1' || arg[2] > '8' || arg[3])
+ return false;
+ *scale_y = arg[2] - '0';
+ return true;
+}
+
void msg_callback(int level, const char *fmt, va_list va, void *data)
{
if (level > 3)
@@ -593,14 +609,10 @@ int main(int argc, char *argv[])
ItemList list = {0};
int result = R_ERROR;
- int scale = 1;
- if (pos[SCALE]) {
- const char *arg = argv[pos[SCALE]];
- if (arg[0] < '1' || arg[0] > '8' || arg[1]) {
- printf("Invalid scale value, should be 1-8!\n");
- goto end;
- }
- scale = arg[0] - '0';
+ int scale_x = 1, scale_y = 1;
+ if (pos[SCALE] && !parse_scale(argv[pos[SCALE]], &scale_x, &scale_y)) {
+ printf("Invalid scale value, should be 1-8[x1-8]!\n");
+ goto end;
}
int level = R_BAD;
@@ -680,7 +692,8 @@ int main(int argc, char *argv[])
if (!track)
continue;
Result res = process_image(renderer, track, list.items[i].dir, output,
- name, list.items[i].time, scale);
+ name, list.items[i].time,
+ scale_x, scale_y);
result = FFMAX(result, res);
if (res <= level)
good++;