From d4c258f6b3bd05560a400bb20a9d428782262eb9 Mon Sep 17 00:00:00 2001 From: Cyril Hrubis Date: Sun, 17 Jun 2012 23:28:33 +0200 Subject: [PATCH] filters: Add fixed point, table based, cubic curve aproximation. --- libs/filters/GP_Cubic.gen.c.t | 27 +++++++++++++++++ libs/filters/GP_Cubic.h | 69 +++++++++++++++++++++++++++++++++++++++++++ libs/filters/GP_Resize.c | 39 +++++++++++++----------- libs/filters/Makefile | 2 +- 4 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 libs/filters/GP_Cubic.gen.c.t create mode 100644 libs/filters/GP_Cubic.h diff --git a/libs/filters/GP_Cubic.gen.c.t b/libs/filters/GP_Cubic.gen.c.t new file mode 100644 index 00000000..4d66517e --- /dev/null +++ b/libs/filters/GP_Cubic.gen.c.t @@ -0,0 +1,27 @@ +%% extends "base.c.t" + +{% block descr %}Table for fixed point cubic coeficients for A=0.5{% endblock %} + +%% block body + +/* + * Fixed point cubic coeficients. + * + * Copyright (c) 2012 Cyril Hrubis + */ + +#include + +int16_t GP_CubicTable[2047] = { +%% set A=0.5 +%% for i in range(0, 1023) +%% set x = i/1024 + {{ round(((2 - A)*x*x*x + (A - 3)*x*x + 1) * 1024) }}, /* {{ i }} {{ x }} */ +%% endfor +%% for i in range(1024, 2047) +%% set x = i/1024 + {{ round((-A*x*x*x + 5*A*x*x - 8*A*x + 4*A) * 1024) }}, /* {{ i }} {{ x }} */ +%% endfor +}; + +%% endblock body diff --git a/libs/filters/GP_Cubic.h b/libs/filters/GP_Cubic.h new file mode 100644 index 00000000..3e7dbefd --- /dev/null +++ b/libs/filters/GP_Cubic.h @@ -0,0 +1,69 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2012 Cyril Hrubis * + * * + *****************************************************************************/ + + /* + + This header contains cubic resampling function aproximation. + + */ + +#ifndef FILTERS_GP_CUBIC_H +#define FILTERS_GP_CUBIC_H + +#define A 0.5 + +static inline float cubic_float(float x) +{ + if (x < 0) + x = -x; + + if (x < 1) + return (2 - A)*x*x*x + (A - 3)*x*x + 1; + + if (x < 2) + return -A*x*x*x + 5*A*x*x - 8*A*x + 4*A; + + return 0; +} + +#include + +/* Defined in GP_Cubic.gen.c */ +extern int16_t GP_CubicTable[]; + +/* + * Fixed point version of above. + * + * Both input and output value are multiplied by MUL. + */ +static inline int cubic_int(int x) +{ + if (x < 0) + x = -x; + + if (x >= 2048) + return 0; + + return GP_CubicTable[x]; +} + +#endif /* FILTERS_GP_CUBIC_H */ diff --git a/libs/filters/GP_Resize.c b/libs/filters/GP_Resize.c index b7182f9b..79362ef6 100644 --- a/libs/filters/GP_Resize.c +++ b/libs/filters/GP_Resize.c @@ -252,6 +252,8 @@ int GP_FilterInterpolate_Cubic(const GP_Context *src, GP_Context *dst, return 0; } +#include "GP_Cubic.h" + #define MUL 1024 #define MUL_I(a, b) ({ \ @@ -299,23 +301,24 @@ int GP_FilterInterpolate_CubicInt(const GP_Context *src, GP_Context *dst, int32_t xmap_c[dst->w][4]; for (i = 0; i < dst->w; i++) { - float x = (1.00 * i / (dst->w - 1)) * (src->w - 1); - - xmap[i][0] = floor(x - 1); - xmap[i][1] = x; - xmap[i][2] = x + 1; - xmap[i][3] = x + 2; + float x = (1.00 * i / (dst->w - 1)) * (src->w - 1); + + xmap[i][0] = floor(x - 1); + xmap[i][1] = x; + xmap[i][2] = x + 1; + xmap[i][3] = x + 2; + - xmap_c[i][0] = cubic(xmap[i][0] - x) * MUL + 0.5; - xmap_c[i][1] = cubic(xmap[i][1] - x) * MUL + 0.5; - xmap_c[i][2] = cubic(xmap[i][2] - x) * MUL + 0.5; - xmap_c[i][3] = cubic(xmap[i][3] - x) * MUL + 0.5; + xmap_c[i][0] = cubic_int((xmap[i][0] - x) * MUL + 0.5); + xmap_c[i][1] = cubic_int((xmap[i][1] - x) * MUL + 0.5); + xmap_c[i][2] = cubic_int((xmap[i][2] - x) * MUL + 0.5); + xmap_c[i][3] = cubic_int((xmap[i][3] - x) * MUL + 0.5); - if (xmap[i][0] < 0) - xmap[i][0] = 0; + if (xmap[i][0] < 0) + xmap[i][0] = 0; - if (xmap[i][3] >= (int32_t)src->w) - xmap[i][3] = src->w - 1; + if (xmap[i][3] >= (int32_t)src->w) + xmap[i][3] = src->w - 1; } /* cubic resampling */ @@ -329,10 +332,10 @@ int GP_FilterInterpolate_CubicInt(const GP_Context *src, GP_Context *dst, yi[2] = y + 1; yi[3] = y + 2; - cvy[0] = cubic(yi[0] - y) * MUL + 0.5; - cvy[1] = cubic(yi[1] - y) * MUL + 0.5; - cvy[2] = cubic(yi[2] - y) * MUL + 0.5; - cvy[3] = cubic(yi[3] - y) * MUL + 0.5; + cvy[0] = cubic_int((yi[0] - y) * MUL + 0.5); + cvy[1] = cubic_int((yi[1] - y) * MUL + 0.5); + cvy[2] = cubic_int((yi[2] - y) * MUL + 0.5); + cvy[3] = cubic_int((yi[3] - y) * MUL + 0.5); if (yi[0] < 0) yi[0] = 0; diff --git a/libs/filters/Makefile b/libs/filters/Makefile index 1470e55c..e07d92aa 100644 --- a/libs/filters/Makefile +++ b/libs/filters/Makefile @@ -8,7 +8,7 @@ POINT_FILTERS=GP_Contrast.gen.c GP_Brightness.gen.c GP_Invert.gen.c\ ARITHMETIC_FILTERS=GP_Difference.gen.c GP_Addition.gen.c GP_Min.gen.c\ GP_Max.gen.c GP_Multiply.gen.c -RESAMPLING_FILTERS=GP_ResizeNN.gen.c +RESAMPLING_FILTERS=GP_ResizeNN.gen.c GP_Cubic.gen.c GENSOURCES=GP_MirrorV.gen.c GP_Rotate.gen.c GP_FloydSteinberg.gen.c GP_HilbertPeano.gen.c\ $(POINT_FILTERS) $(ARITHMETIC_FILTERS) $(STATS_FILTERS) $(RESAMPLING_FILTERS) -- 2.11.4.GIT