This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git.
The branch, master has been updated via 7e200feb57b68400cca6b27a5fb6d87c9692021e (commit) via 2dcfaebb1f2f7560d3b36df02066907a1fca84da (commit) via c83a0d2c773e72545e78f465ec4c2dea92272b55 (commit) via d93da078d5d3db1e457a0225a26da0cead0085cb (commit) via 147b4068a0ef11c88d116442680ad46894a7b12a (commit) from 7b640614144c242d672abe372961ef1d2e64c1fd (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- http://repo.or.cz/w/gfxprim.git/commit/7e200feb57b68400cca6b27a5fb6d87c96920...
commit 7e200feb57b68400cca6b27a5fb6d87c9692021e Author: Cyril Hrubis metan@ucw.cz Date: Thu Nov 7 00:51:50 2013 +0100
loaders: PNM: Fix aligment issues in save_ascii_rgb888
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/libs/loaders/GP_PNM.c b/libs/loaders/GP_PNM.c index 09018fe..813de81 100644 --- a/libs/loaders/GP_PNM.c +++ b/libs/loaders/GP_PNM.c @@ -974,12 +974,9 @@ static int save_ascii_rgb888(FILE *f, const GP_Context *ctx, }
for (x = 0; x < ctx->w; x++) { - GP_Pixel pix = *(addr+=3); + addr+=3;
- ret = fprintf(f, "%u %u %u ", - GP_Pixel_GET_R_RGB888(pix), - GP_Pixel_GET_G_RGB888(pix), - GP_Pixel_GET_B_RGB888(pix)); + ret = fprintf(f, "%u %u %u ", addr[2], addr[1], addr[0]);
if (ret < 0) return errno;
http://repo.or.cz/w/gfxprim.git/commit/2dcfaebb1f2f7560d3b36df02066907a1fca8...
commit 2dcfaebb1f2f7560d3b36df02066907a1fca84da Author: Cyril Hrubis metan@ucw.cz Date: Thu Nov 7 00:40:18 2013 +0100
filters: Reimplement point filters.
Point filters are now implemented using ApplyTable generic filter.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/build/syms/Filters_symbols.txt b/build/syms/Filters_symbols.txt index 970c881..1e8b74b 100644 --- a/build/syms/Filters_symbols.txt +++ b/build/syms/Filters_symbols.txt @@ -1,15 +1,23 @@ GP_CubicTable
+GP_FilterTablesApply +GP_FilterTablesAlloc +GP_FilterTablesInit +GP_FilterTablesFree + +GP_FilterInvertEx +GP_FilterInvertExAlloc + +GP_FilterBrightnessEx +GP_FilterBrightnessExAlloc + +GP_FilterContrastEx +GP_FilterContrastExAlloc + GP_FilterAddition GP_FilterAdditionAlloc GP_FilterAddition_Raw
-GP_FilterBrightness -GP_FilterBrightness_Raw - -GP_FilterContrast -GP_FilterContrast_Raw - GP_FilterConvolutionEx GP_FilterConvolutionExAlloc GP_FilterConvolutionMP_Raw @@ -46,9 +54,6 @@ GP_FilterHistogram GP_FilterHistogramAlloc GP_FilterHistogram_Raw
-GP_FilterInvert -GP_FilterInvert_Raw - GP_FilterKernelPrint_Raw
GP_FilterLaplace diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c index 7bc3071..8c798d4 100644 --- a/demos/grinder/grinder.c +++ b/demos/grinder/grinder.c @@ -273,41 +273,18 @@ static int mirror(GP_Context **c, const char *params) /* brightness filter */
static struct param bright_params[] = { - {"inc", PARAM_INT, "brightness increment", NULL, NULL}, - {"chann", PARAM_STR, "Channel name {R, G, B, A, V, ...}", NULL, NULL}, + {"inc", PARAM_FLOAT, "brightness increment", NULL, NULL}, {NULL, 0, NULL, NULL, NULL} };
static int bright(GP_Context **c, const char *params) { - int bright = 0; - char *chann = NULL; + float bright = 0;
- if (param_parse(params, bright_params, "bright", param_err, &bright, &chann)) + if (param_parse(params, bright_params, "bright", param_err, &bright)) return EINVAL;
- if (bright == 0) { - print_error("bright: bright parameter is zero or missing"); - return EINVAL; - } - - GP_FILTER_PARAMS((*c)->pixel_type, filter_params); - - if (chann == NULL) { - GP_FilterParamSetIntAll(filter_params, bright); - } else { - GP_FilterParam *param = GP_FilterParamChannel(filter_params, chann); - - if (param == NULL) { - print_error("bright: Invalid channel name"); - return EINVAL; - } - - GP_FilterParamSetIntAll(filter_params, 0); - param->val.i = bright; - } - - GP_FilterBrightness(*c, *c, filter_params, progress_callback); + GP_FilterBrightness(*c, *c, bright, progress_callback);
return 0; } @@ -316,16 +293,14 @@ static int bright(GP_Context **c, const char *params)
static struct param contrast_params[] = { {"mul", PARAM_FLOAT, "contrast (1.5 = +50%, 0.5 = -50%)", NULL, NULL}, - {"chann", PARAM_STR, "Channel name {R, G, B, A, V, ...}", NULL, NULL}, {NULL, 0, NULL, NULL, NULL} };
static int contrast(GP_Context **c, const char *params) { float mul = 0; - char *chann = NULL;
- if (param_parse(params, contrast_params, "contrast", param_err, &mul, &chann)) + if (param_parse(params, contrast_params, "contrast", param_err, &mul)) return EINVAL;
if (mul <= 0) { @@ -333,45 +308,7 @@ static int contrast(GP_Context **c, const char *params) return EINVAL; }
- GP_FILTER_PARAMS((*c)->pixel_type, filter_params); - - if (chann == NULL) { - GP_FilterParamSetFloatAll(filter_params, mul); - } else { - GP_FilterParam *param = GP_FilterParamChannel(filter_params, chann); - - if (param == NULL) { - print_error("contrast: Invalid channel name"); - return EINVAL; - } - - GP_FilterParamSetFloatAll(filter_params, 1); - param->val.f = mul; - } - - GP_FilterContrast(*c, *c, filter_params, progress_callback); - - return 0; -} - -/* noise */ -static struct param noise_params[] = { - {"ratio", PARAM_FLOAT, "noise", NULL, NULL}, - {NULL, 0, NULL, NULL, NULL} -}; - -static int noise(GP_Context **c, const char *params) -{ - float rat; - - if (param_parse(params, noise_params, "noise", param_err, &rat)) - return EINVAL; - - GP_FILTER_PARAMS((*c)->pixel_type, filter_params); - - GP_FilterParamSetFloatAll(filter_params, rat); - - GP_FilterNoise(*c, *c, filter_params, progress_callback); + GP_FilterContrast(*c, *c, mul, progress_callback);
return 0; } @@ -525,70 +462,6 @@ static int save_png(GP_Context **c, const char *params) return 0; }
-/* noise filter */ - -static struct param add_noise_params[] = { - {"percents", PARAM_FLOAT, "Percents of noise to add", NULL, NULL}, - {"chann", PARAM_STR, "Channel name {R, G, B, A, V, ...}", NULL, NULL}, - {NULL, 0, NULL, NULL, NULL} -}; - -static uint32_t add_noise_op(uint32_t val, uint8_t bits, GP_FilterParam *param) -{ - float perc; - int max = (1<<bits) - 1; - int ret; - - perc = param->val.f; - - ret = val * (1 - perc) + (random() % max) * perc; - - if (ret < 0) - ret = 0; - - if (ret > max) - ret = max; - - return ret; -} - -static uint32_t no_op(uint32_t val) -{ - return val; -} - -static int add_noise(GP_Context **c, const char *params) -{ - float percents = 0; - char *chann = NULL; - - if (param_parse(params, add_noise_params, "add_noise", param_err, &percents, &chann)) - return EINVAL; - - GP_FILTER_PARAMS((*c)->pixel_type, priv); - GP_FilterParamSetFloatAll(priv, percents/100); - GP_FILTER_PARAMS((*c)->pixel_type, op_callbacks); - - if (chann == NULL) { - GP_FilterParamSetPtrAll(op_callbacks, add_noise_op); - } else { - GP_FilterParam *param = GP_FilterParamChannel(op_callbacks, chann); - - if (param == NULL) { - print_error("add_noise: Invalid channel name"); - return EINVAL; - } - - - GP_FilterParamSetPtrAll(op_callbacks, no_op); - param->val.ptr = add_noise_op; - } - - GP_FilterPoint(*c, *c, op_callbacks, priv, progress_callback); - - return 0; -} - /* median filter */
static struct param median_params[] = { @@ -816,8 +689,6 @@ static struct filter filter_table[] = { {"bright", "alter image brightness", bright_params, bright}, {"contrast", "alter image contrast", contrast_params, contrast}, {"invert", "inverts image", invert_params, invert}, - {"add_noise", "adds noise", add_noise_params, add_noise}, - {"noise", "adds noise", noise_params, noise}, {"blur", "gaussian blur", blur_params, blur}, {"dither", "dithers bitmap", dither_params, dither}, {"arithmetic", "arithmetic operation", arithmetic_params, arithmetic}, diff --git a/demos/py_simple/invert.py b/demos/py_simple/invert.py new file mode 100755 index 0000000..84a5b6f --- /dev/null +++ b/demos/py_simple/invert.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +import sys + +import gfxprim.core as core +import gfxprim.loaders as loaders +import gfxprim.filters as filters + +def main(): + if len(sys.argv) != 2: + print("usage: invert.py image") + sys.exit(1) + + # Load Image + img = loaders.Load(sys.argv[1]) + # Invert image in-place + img.filters.Invert(img); + # Save result into grayscale png + img.loaders.SavePNG("out.png") + +if __name__ == '__main__': + main() diff --git a/libs/filters/GP_Contrast.gen.c.t b/include/filters/GP_ApplyTables.h similarity index 61% copy from libs/filters/GP_Contrast.gen.c.t copy to include/filters/GP_ApplyTables.h index c8dae6f..d2a6948 100644 --- a/libs/filters/GP_Contrast.gen.c.t +++ b/include/filters/GP_ApplyTables.h @@ -16,39 +16,50 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2011 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
-%% extends "filter.point.c.t" +/* + + Applies per-channel tables on a context pixels. Used for fast point filters + implementation.
-%% block descr -Contrast filters -- Multiply color channel(s) by a fixed float value. -%% endblock + */
-%% block body +#ifndef FILTERS_GP_APPLY_TABLES_H +#define FILTERS_GP_APPLY_TABLES_H
-{{ filter_point_include() }} +#include "GP_Filter.h" + +/* + * Per-channel lookup tables. + */ +typedef struct GP_FilterTables { + GP_Pixel *table[GP_PIXELTYPE_MAX_CHANNELS]; + int free_table:1; +} GP_FilterTables;
-%% macro filter_op(chan_name, chan_size) -{{ chan_name }} = {{ chan_name }} * {{ chan_name }}_mul + 0.5; -{{ filter_clamp_val(chan_name, chan_size) }} -%% endmacro +/* + * Generic point filter, applies corresponding table on bitmap. + */ +int GP_FilterTablesApply(const GP_FilterArea *const area, + const GP_FilterTables *const tables, + GP_ProgressCallback *callback);
/* - * Generated contrast filters for pixels with several channels. + * Aloocates and initializes tables. */ -%% call(pt) filter_point_per_channel('Contrast', 'GP_FilterParam muls[]', filter_op) -{{ filter_params(pt, 'muls', 'float ', '_mul', 'f') }} -%% endcall +int GP_FilterTablesInit(GP_FilterTables *self, const GP_Context *ctx);
/* - * Generated constrast filters for pixels with one channel. + * Allocates and initializes table structure and tables. */ -%% call(ps) filter_point_per_bpp('Contrast', 'GP_FilterParam muls[]', filter_op) -{{ filter_param(ps, 'muls', 'float ', '_mul', 'f') }} -%% endcall +GP_FilterTables *GP_FilterTablesAlloc(const GP_Context *ctx);
-{{ filter_functions('Contrast', 'GP_FilterParam muls[]', 'muls') }} +/* + * Frees point filter tables. + */ +void GP_FilterTablesFree(GP_FilterTables *self);
-%% endblock body +#endif /* FILTERS_GP_APPLY_TABLES_H */ diff --git a/include/filters/GP_Filter.h b/include/filters/GP_Filter.h index af02bd0..69254a0 100644 --- a/include/filters/GP_Filter.h +++ b/include/filters/GP_Filter.h @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2011 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
@@ -34,4 +34,29 @@
#include "GP_FilterParam.h"
+/* + * Describes filter source, destination and coordinates. + * + * For Alloc filter variants dst, dst_x and dst_y is ignored. + */ +typedef struct GP_FilterArea { + const GP_Context *src; + GP_Coord src_x, src_y; + GP_Size src_w, src_h; + + GP_Context *dst; + GP_Coord dst_x, dst_y; + + void *priv; +} GP_FilterArea; + +#define GP_FILTER_AREA_DEFAULT(srcc, dstc) + GP_FilterArea area = { + .src = srcc, + .src_x = 0, .src_y = 0, + .src_w = srcc->w, .src_h = srcc->h, + .dst = dstc, + .dst_x = 0, .dst_y = 0, + }; + #endif /* FILTERS_GP_FILTER_H */ diff --git a/include/filters/GP_Point.h b/include/filters/GP_Point.h index 42248a9..e5c7e99 100644 --- a/include/filters/GP_Point.h +++ b/include/filters/GP_Point.h @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2011 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
@@ -34,15 +34,30 @@ /* * Brightness filter. * - * Increments each pixel channel by a given value. + * Increments each pixel channel by a p * channel_max value. */ -int GP_FilterBrightness_Raw(const GP_Context *src, GP_Context *dst, - GP_FilterParam params[], - GP_ProgressCallback *callback); +int GP_FilterBrightnessEx(const GP_FilterArea *area, float p, + GP_ProgressCallback *callback); + +GP_Context *GP_FilterBrightnessExAlloc(const GP_FilterArea *area, float p, + GP_ProgressCallback *callback); + +static inline int GP_FilterBrightness(const GP_Context *src, GP_Context *dst, + float p, GP_ProgressCallback *callback) +{ + GP_FILTER_AREA_DEFAULT(src, dst);
-GP_Context *GP_FilterBrightness(const GP_Context *src, GP_Context *dst, - GP_FilterParam params[], - GP_ProgressCallback *callback); + return GP_FilterBrightnessEx(&area, p, callback); +} + +static inline GP_Context *GP_FilterBrightnessAlloc(const GP_Context *src, + float p, + GP_ProgressCallback *callback) +{ + GP_FILTER_AREA_DEFAULT(src, NULL); + + return GP_FilterBrightnessExAlloc(&area, p, callback); +}
/* * Contrast filter. @@ -52,42 +67,52 @@ GP_Context *GP_FilterBrightness(const GP_Context *src, GP_Context *dst, * The parameters should have the same pixel channels as * source pixel type and are expected to be float numbers. */ -int GP_FilterContrast_Raw(const GP_Context *src, GP_Context *dst, - GP_FilterParam params[], - GP_ProgressCallback *callback); +int GP_FilterContrastEx(const GP_FilterArea *area, float p, + GP_ProgressCallback *callback);
-GP_Context *GP_FilterContrast(const GP_Context *src, GP_Context *dst, - GP_FilterParam params[], - GP_ProgressCallback *callback); +GP_Context *GP_FilterContrastExAlloc(const GP_FilterArea *area, float p, + GP_ProgressCallback *callback);
-/* - * Invert filter. - * - * Inverts each pixel channel (eg. val = max - val) - */ -int GP_FilterInvert_Raw(const GP_Context *src, GP_Context *dst, - GP_ProgressCallback *callback); +static inline int GP_FilterContrast(const GP_Context *src, GP_Context *dst, + float p, GP_ProgressCallback *callback) +{ + GP_FILTER_AREA_DEFAULT(src, dst);
-GP_Context *GP_FilterInvert(const GP_Context *src, GP_Context *dst, - GP_ProgressCallback *callback); + return GP_FilterContrastEx(&area, p, callback); +}
-/* - * Noise filter. - */ -GP_Context *GP_FilterNoise(const GP_Context *src, GP_Context *dst, - GP_FilterParam ratio[], GP_ProgressCallback *callback); +static inline GP_Context *GP_FilterContrastAlloc(const GP_Context *src, + float p, + GP_ProgressCallback *callback) +{ + GP_FILTER_AREA_DEFAULT(src, NULL); + + return GP_FilterContrastExAlloc(&area, p, callback); +}
/* - * Generic slow point filter. - * - * The filter_callback[] is expected to be filled with pointers - * to functions of type uint32_t (*func)(uint32_t chan_val, uint8_t chan_size, GP_FilterParam *priv) - * - * The priv[] is free for your use and corresponding + * Inverts the pixel value, i.e. sets it to max - val. */ -GP_Context *GP_FilterPoint(const GP_Context *src, GP_Context *dst, - GP_FilterParam filter_callback[], - GP_FilterParam priv[], - GP_ProgressCallback *callback); +int GP_FilterInvertEx(const GP_FilterArea *area, + GP_ProgressCallback *callback); + +GP_Context *GP_FilterInvertExAlloc(const GP_FilterArea *area, + GP_ProgressCallback *callback); + +static inline int GP_FilterInvert(const GP_Context *src, GP_Context *dst, + GP_ProgressCallback *callback) +{ + GP_FILTER_AREA_DEFAULT(src, dst); + + return GP_FilterInvertEx(&area, callback); +} + +static inline GP_Context *GP_FilterInvertAlloc(const GP_Context *src, + GP_ProgressCallback *callback) +{ + GP_FILTER_AREA_DEFAULT(src, NULL); + + return GP_FilterInvertExAlloc(&area, callback); +}
#endif /* FILTERS_GP_POINT_H */ diff --git a/libs/filters/GP_ApplyTables.c b/libs/filters/GP_ApplyTables.c new file mode 100644 index 0000000..7fcb591 --- /dev/null +++ b/libs/filters/GP_ApplyTables.c @@ -0,0 +1,105 @@ +/***************************************************************************** + * 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-2013 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + +#include "core/GP_Debug.h" + +#include "filters/GP_ApplyTables.h" + +static GP_Pixel *create_table(const GP_PixelTypeChannel *chan) +{ + size_t table_size = (1 << chan->size); + GP_Pixel *table = malloc(table_size * sizeof(GP_Pixel)); + GP_Pixel i; + + if (!table) { + GP_DEBUG(1, "Malloc failed :("); + return NULL; + } + + for (i = 0; i < table_size; i++) + table[i] = i; + + return table; +} + +static void free_tables(GP_FilterTables *self) +{ + unsigned int i; + + for (i = 0; i < GP_PIXELTYPE_MAX_CHANNELS; i++) + free(self->table[i]); +} + +int GP_FilterTablesInit(GP_FilterTables *self, const GP_Context *ctx) +{ + unsigned int i; + const GP_PixelTypeDescription *desc; + + GP_DEBUG(2, "Allocating tables for pixel %s", + GP_PixelTypeName(ctx->pixel_type)); + + for (i = 0; i < GP_PIXELTYPE_MAX_CHANNELS; i++) + self->table[i] = NULL; + + desc = GP_PixelTypeDesc(ctx->pixel_type); + + for (i = 0; i < desc->numchannels; i++) { + self->table[i] = create_table(&desc->channels[i]); + if (!self->table[i]) { + free_tables(self); + return 1; + } + } + + return 0; +} + +GP_FilterTables *GP_FilterTablesAlloc(const GP_Context *ctx) +{ + GP_FilterTables *tables = malloc(sizeof(GP_FilterTables)); + + GP_DEBUG(1, "Allocating point filter (%p)", tables); + + if (!tables) { + GP_DEBUG(1, "Malloc failed :("); + return NULL; + } + + tables->free_table = 1; + + if (GP_FilterTablesInit(tables, ctx)) { + free(tables); + return NULL; + } + + return tables; +} + +void GP_FilterTablesFree(GP_FilterTables *self) +{ + GP_DEBUG(1, "Freeing point filter and tables (%p)", self); + + free_tables(self); + + if (self->free_table) + free(self); +} diff --git a/libs/filters/GP_ApplyTables.gen.c.t b/libs/filters/GP_ApplyTables.gen.c.t new file mode 100644 index 0000000..566d957 --- /dev/null +++ b/libs/filters/GP_ApplyTables.gen.c.t @@ -0,0 +1,108 @@ +/***************************************************************************** + * 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-2013 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + +%% extends "filter.c.t" + +%% block descr +Generic Point filer +%% endblock + +%% block body + +#include <errno.h> + +#include "core/GP_Context.h" +#include "core/GP_GetPutPixel.h" +#include "core/GP_Debug.h" + +#include "filters/GP_ApplyTables.h" + +%% for pt in pixeltypes +%% if not pt.is_unknown() and not pt.is_palette() +static int apply_tables_{{ pt.name }}(const GP_FilterArea *const area, + const GP_FilterTables *const tables, + GP_ProgressCallback *callback) +{ + GP_DEBUG(1, "Point filter %ux%u", area->src_w, area->src_h); + + unsigned int x, y; + const GP_Context *src = area->src; + GP_Context *dst = area->dst; + +%% for c in pt.chanslist + GP_Pixel {{ c.name }}; +%% endfor + + for (y = 0; y < area->src_h; y++) { + for (x = 0; x < area->src_w; x++) { + unsigned int src_x = area->src_x + x; + unsigned int src_y = area->src_y + y; + unsigned int dst_x = area->dst_x + x; + unsigned int dst_y = area->dst_y + y; + + GP_Pixel pix = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, src_x, src_y); + +%% for c in pt.chanslist + {{ c.name }} = GP_Pixel_GET_{{ c[0] }}_{{ pt.name }}(pix); + {{ c.name }} = tables->table[{{ c.idx }}][{{ c.name }}]; +%% endfor + + pix = GP_Pixel_CREATE_{{ pt.name }}({{ expand_chanslist(pt, "", "") }}); + GP_PutPixel_Raw_{{ pt.pixelsize.suffix }}(dst, dst_x, dst_y, pix); + } + + if (GP_ProgressCallbackReport(callback, y, area->src_h, area->src_w)) { + errno = ECANCELED; + return 1; + } + } + + GP_ProgressCallbackDone(callback); + + return 0; +} + +%% endif +%% endfor + +int GP_FilterTablesApply(const GP_FilterArea *const area, + const GP_FilterTables *const tables, + GP_ProgressCallback *callback) +{ + GP_ASSERT(area->src->pixel_type == area->dst->pixel_type); + //TODO: Assert size + + switch (area->src->pixel_type) { +%% for pt in pixeltypes +%% if not pt.is_unknown() and not pt.is_palette() + case GP_PIXEL_{{ pt.name }}: + return apply_tables_{{ pt.name }}(area, tables, callback); + break; +%% endif +%% endfor + default: + errno = EINVAL; + return -1; + } +} + +%% endblock body diff --git a/libs/filters/GP_Brightness.gen.c.t b/libs/filters/GP_Brightness.gen.c.t index 2a02268..374837d 100644 --- a/libs/filters/GP_Brightness.gen.c.t +++ b/libs/filters/GP_Brightness.gen.c.t @@ -16,39 +16,24 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2011 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
%% extends "filter.point.c.t"
%% block descr -Brightness filters -- Increments color channel(s) by a fixed value. +Brightness Point filter %% endblock
%% block body
-{{ filter_point_include() }} +#include "core/GP_Clamp.h"
-%% macro filter_op(chann_name, chann_size) -{{ chann_name }} = {{ chann_name }} + {{ chann_name }}_inc; -{{ filter_clamp_val(chann_name, chann_size) }} -%% endmacro +%% macro filter_op_brightness(val, val_max) +GP_CLAMP_GENERIC({{ val }} + (p * {{ val_max }} + 0.5), 0, {{ val_max }}) +%%- endmacro
-/* - * Generated brightness filters. - */ -%% call(pt) filter_point_per_channel('Brightness', 'GP_FilterParam incs[]', filter_op) -{{ filter_params(pt, 'incs', 'int32_t ', '_inc', 'i') }} -%% endcall - -/* - * Generated constrast filters for pixels with one channel. - */ -%% call(ps) filter_point_per_bpp('Brightness', 'GP_FilterParam incs[]', filter_op) -{{ filter_param(ps, 'incs', 'int32_t ', '_inc', 'i') }} -%% endcall - -{{ filter_functions('Brightness', 'GP_FilterParam incs[]', 'incs') }} +{{ filter_point('Brightness', filter_op_brightness, 'float p', 'p') }}
%% endblock body diff --git a/libs/filters/GP_Contrast.gen.c.t b/libs/filters/GP_Contrast.gen.c.t index c8dae6f..d00a6fc 100644 --- a/libs/filters/GP_Contrast.gen.c.t +++ b/libs/filters/GP_Contrast.gen.c.t @@ -16,39 +16,24 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2011 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
%% extends "filter.point.c.t"
%% block descr -Contrast filters -- Multiply color channel(s) by a fixed float value. +Contrast Point filter %% endblock
%% block body
-{{ filter_point_include() }} +#include "core/GP_Clamp.h"
-%% macro filter_op(chan_name, chan_size) -{{ chan_name }} = {{ chan_name }} * {{ chan_name }}_mul + 0.5; -{{ filter_clamp_val(chan_name, chan_size) }} -%% endmacro +%% macro filter_op_contrast(val, val_max) +GP_CLAMP_GENERIC({{ val }} * p + 0.5, 0, {{ val_max }}) +%%- endmacro
-/* - * Generated contrast filters for pixels with several channels. - */ -%% call(pt) filter_point_per_channel('Contrast', 'GP_FilterParam muls[]', filter_op) -{{ filter_params(pt, 'muls', 'float ', '_mul', 'f') }} -%% endcall - -/* - * Generated constrast filters for pixels with one channel. - */ -%% call(ps) filter_point_per_bpp('Contrast', 'GP_FilterParam muls[]', filter_op) -{{ filter_param(ps, 'muls', 'float ', '_mul', 'f') }} -%% endcall - -{{ filter_functions('Contrast', 'GP_FilterParam muls[]', 'muls') }} +{{ filter_point('Contrast', filter_op_contrast, 'float p', 'p') }}
%% endblock body diff --git a/libs/filters/GP_Invert.gen.c.t b/libs/filters/GP_Invert.gen.c.t index ef9598e..2f5a4fe 100644 --- a/libs/filters/GP_Invert.gen.c.t +++ b/libs/filters/GP_Invert.gen.c.t @@ -16,30 +16,22 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2011 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
%% extends "filter.point.c.t"
%% block descr -Invert filters -- Invert image +Invert Point filter -- Inverts pixel channel values %% endblock
%% block body
-{{ filter_point_include() }} +%% macro filter_op_invert(val, val_max) +{{ val_max }} - {{ val }} +%%- endmacro
-%% macro filter_op(chann_name, chann_size) -{{ chann_name }} = {{ 2 ** chann_size - 1 }} - {{ chann_name }}; -%% endmacro - -%% call(pt) filter_point_per_channel('Invert', '', filter_op) -%% endcall - -%% call(ps) filter_point_per_bpp('Invert', '', filter_op) -%% endcall - -{{ filter_functions('Invert') }} +{{ filter_point('Invert', filter_op_invert) }}
%% endblock body diff --git a/libs/filters/Makefile b/libs/filters/Makefile index 05a310e..e39d66e 100644 --- a/libs/filters/Makefile +++ b/libs/filters/Makefile @@ -3,8 +3,8 @@ include $(TOPDIR)/pre.mk
STATS_FILTERS=GP_Histogram.gen.c
-POINT_FILTERS=GP_Contrast.gen.c GP_Brightness.gen.c GP_Invert.gen.c- GP_Point.gen.c GP_Noise.gen.c GP_GaussianNoise.gen.c +POINT_FILTERS=GP_GaussianNoise.gen.c GP_ApplyTables.gen.c GP_Invert.gen.c+ GP_Brightness.gen.c GP_Contrast.gen.c
ARITHMETIC_FILTERS=GP_Difference.gen.c GP_Addition.gen.c GP_Min.gen.c GP_Max.gen.c GP_Multiply.gen.c diff --git a/pylib/gfxprim/filters/__init__.py b/pylib/gfxprim/filters/__init__.py index 67022ba..c5ef3ab 100644 --- a/pylib/gfxprim/filters/__init__.py +++ b/pylib/gfxprim/filters/__init__.py @@ -20,7 +20,10 @@ def _init(module):
_context._submodules['filters'] = FiltersSubmodule
- for name in ['Resize', 'ResizeAlloc', + for name in ['Invert', 'InvertAlloc', + 'Brightness', 'BrightnessAlloc', + 'Contrast', 'ContrastAlloc', + 'Resize', 'ResizeAlloc', 'Rotate90', 'Rotate90Alloc', 'Rotate180', 'Rotate180Alloc', 'Rotate270', 'Rotate270Alloc', diff --git a/pylib/gfxprim/filters/filters.i b/pylib/gfxprim/filters/filters.i index 7417ec4..59da75b 100644 --- a/pylib/gfxprim/filters/filters.i +++ b/pylib/gfxprim/filters/filters.i @@ -28,7 +28,10 @@ ERROR_ON_NONZERO(GP_Filter ## funcname); %newobject GP_FilterParamCreate; %include "GP_FilterParam.h"
-/* TODO: Point filters, once fixed */ +FILTER_FUNC(Invert); +FILTER_FUNC(Brightness); +FILTER_FUNC(Contrast); +%include "GP_Point.h"
/* Arithmetic filters */ FILTER_FUNC(Addition); diff --git a/pylib/templates/filter.point.c.t b/pylib/templates/filter.point.c.t index 7789bb1..bdd0679 100644 --- a/pylib/templates/filter.point.c.t +++ b/pylib/templates/filter.point.c.t @@ -1,135 +1,73 @@ %% extends "filter.c.t"
%% macro filter_point_include() -{{ filter_include() }} -#include "GP_Point.h" +#include <errno.h> + +#include "core/GP_Debug.h" + +#include "filters/GP_ApplyTables.h" +#include "filters/GP_Point.h" %% endmacro
-/* - * Filter per pixel type, used for images with more than one channel per pixel - */ -%% macro filter_point_per_channel(name, opts="", filter_op) -%% for pt in pixeltypes -%% if not pt.is_unknown() and len(pt.chanslist) > 1 -static int GP_Filter{{ name }}_{{ pt.name }}(const GP_Context *src, GP_Context *dst, - {{ maybe_opts_r(opts) }}GP_ProgressCallback *callback) +%% macro filter_point_ex(op_name, filter_op, fopts) +int GP_Filter{{ op_name }}Ex(const GP_FilterArea *const area{{ maybe_opts_l(fopts) }}, + GP_ProgressCallback *callback) { -{{ caller(pt) }} - uint32_t x, y; - - for (y = 0; y < src->h; y++) { - for (x = 0; x < src->w; x++) { - GP_Pixel pix = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, x, y); - %% for c in pt.chanslist - int32_t {{ c[0] }} = GP_Pixel_GET_{{ c[0] }}_{{ pt.name }}(pix); - %% endfor + const GP_PixelTypeDescription *desc; + GP_FilterTables tables; + unsigned int i; + GP_Pixel j; + int ret, err;
- %% for c in pt.chanslist - {{ filter_op(c[0], c[2]) }} - %% endfor + if (GP_FilterTablesInit(&tables, area->src)) + return 1;
- pix = GP_Pixel_CREATE_{{ pt.name }}({{ pt.chanslist[0][0] }}{% for c in pt.chanslist[1:] %}, {{ c[0] }}{% endfor %}); + desc = GP_PixelTypeDesc(area->src->pixel_type);
- GP_PutPixel_Raw_{{ pt.pixelsize.suffix }}(dst, x, y, pix); - } + for (i = 0; i < desc->numchannels; i++) { + GP_Pixel chan_max = (1 << desc->channels[i].size); + GP_Pixel *table = tables.table[i];
- if (GP_ProgressCallbackReport(callback, y, src->h, src->w)) - return 1; + for (j = 0; j < chan_max; j++) + table[j] = {{ filter_op('((signed)j)', '((signed)chan_max - 1)') }}; }
- GP_ProgressCallbackDone(callback); - return 0; -} - -%% endif -%% endfor -%% endmacro + ret = GP_FilterTablesApply(area, &tables, callback);
-/* - * Point filter per bpp (used for 1 channel pixels to save space). - */ -%% macro filter_point_per_bpp(name, opts="", filter_op) -%% for ps in pixelsizes -%% if ps.size > 1 -static int GP_Filter{{ name }}_{{ ps.suffix }}(const GP_Context *src, GP_Context *dst, - {{ maybe_opts_r(opts) }}GP_ProgressCallback *callback) -{ -{{ caller(ps) }} - uint32_t x, y; - - for (y = 0; y < src->h; y++) { - for (x = 0; x < src->w; x++) { - int32_t pix = GP_GetPixel_Raw_{{ ps.suffix }}(src, x, y); - {{ filter_op('pix', ps.size) }} - GP_PutPixel_Raw_{{ ps.suffix }}(dst, x, y, pix); - } - - if (GP_ProgressCallbackReport(callback, y, src->h, src->w)) - return 1; - } + err = errno; + GP_FilterTablesFree(&tables); + errno = err;
- GP_ProgressCallbackDone(callback); - return 0; + return ret; } - -%% endif -%% endfor %% endmacro
-/* - * Switch per pixel sizes or pixel types. - */ -%% macro filter_functions(name, opts="", params="", fmt="") -int GP_Filter{{ name }}_Raw(const GP_Context *src, GP_Context *dst{{ maybe_opts_l(opts) }}, - GP_ProgressCallback *callback) +%% macro filter_point_ex_alloc(op_name, fopts, opts) +GP_Context *GP_Filter{{ op_name }}ExAlloc(const GP_FilterArea *const area{{ maybe_opts_l(fopts) }}, + GP_ProgressCallback *callback) { - GP_DEBUG(1, "Running filter {{ name }}"); - - switch (src->pixel_type) { - %% for pt in pixeltypes - case GP_PIXEL_{{ pt.name }}: - %% if pt.is_unknown() or pt.pixelsize.size < 2 - return 1; - %% elif len(pt.chanslist) == 1: - //TODO: BITENDIAN - return GP_Filter{{ name }}_{{ pt.pixelsize.suffix }}(src, dst{{ maybe_opts_l(params) }}, callback); - %% else - return GP_Filter{{ name }}_{{ pt.name }}(src, dst{{ maybe_opts_l(params) }}, callback); - %% endif - %% endfor - default: - break; - } - - return 1; -} - -GP_Context *GP_Filter{{ name }}(const GP_Context *src, GP_Context *dst{{ maybe_opts_l(opts) }}, - GP_ProgressCallback *callback) -{ - GP_Context *res = dst; - - if (res == NULL) { - res = GP_ContextCopy(src, 0); - - if (res == NULL) - return NULL; - } else { - GP_ASSERT(src->pixel_type == dst->pixel_type, - "The src and dst pixel types must match"); - GP_ASSERT(src->w <= dst->w && src->h <= dst->h, - "Destination is not big enough"); - } - - if (GP_Filter{{ name }}_Raw(src, res{{ maybe_opts_l(params) }}, callback)) { - GP_DEBUG(1, "Operation aborted"); - - if (dst == NULL) - GP_ContextFree(res); - + GP_FilterArea carea = *area; + GP_Context *new = GP_ContextAlloc(area->src_w, area->src_h, + area->src->pixel_type); + + /* Clear these just to be sure */ + carea.dst_x = 0; + carea.dst_y = 0; + carea.dst = new; + + if (GP_Filter{{ op_name }}Ex(&carea, {{ maybe_opts_r(opts) }}callback)) { + int err = errno; + GP_ContextFree(new); + errno = err; return NULL; }
- return res; + return new; } %% endmacro + +%% macro filter_point(op_name, filter_op, fopts="", opts="") +{{ filter_point_include() }} +{{ filter_point_ex(op_name, filter_op, fopts) }} +{{ filter_point_ex_alloc(op_name, fopts, opts) }} +%% endmacro
http://repo.or.cz/w/gfxprim.git/commit/c83a0d2c773e72545e78f465ec4c2dea92272...
commit c83a0d2c773e72545e78f465ec4c2dea92272b55 Author: Cyril Hrubis metan@ucw.cz Date: Wed Nov 6 19:55:44 2013 +0100
doc: Cleanup loaders docs a bit.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/doc/about.txt b/doc/about.txt index fc4d176..1dc7ce5 100644 --- a/doc/about.txt +++ b/doc/about.txt @@ -61,6 +61,7 @@ printing text into the bitmap. There are two bitmap fonts compiled directly into the library and we support True Type fonts through link:http://freetype.org%5BFreeType] (so far ASCII printable characters only).
+[[Loaders]] Loaders -------
diff --git a/doc/loaders.txt b/doc/loaders.txt index 1702470..3b8e283 100644 --- a/doc/loaders.txt +++ b/doc/loaders.txt @@ -3,8 +3,10 @@ Context loaders This part of GFXprim library aims to create API to load and save images from/to common image file formats.
-Currently we support JPEG, PNG, BPM and PNM images for loading and saving and -GIF and PSP for loading. +Currently we support JPEG, PNG, BMP, TIFF and PNM images for loading and +saving and GIF, JPEG2000 and PSP for loading. + +Have a look at the link:about.html#Loaders[supported formats].
Loaders API ~~~~~~~~~~~ @@ -48,21 +50,21 @@ Image Loader GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback); -------------------------------------------------------------------------------
-Loads image from a file. +Loads an image from a file.
The image format is first guessed by the file extension. If loader for the file extension is found it's called and if it succedes the image data is returned.
-If extension based guess fails either because the extension wasn't matched or -if the loader for the extension failed; the signature based method is used. -The loader loads several bytes (currently 32) from the file and calls -signature matching functions for each format that implements signature -matching. If image signature is found particular image loader it is called -and the result is returned. +If file extension based guess fails either because the extension wasn't +matched or if the loader for the extension failed; the signature based method +is used. The loader loads several bytes (currently 32) from the file and +calls signature matching functions for each format that implements signature +matching. If image signature is found image loader it is called and the result +is returned.
-If file extension disagrees with file signature a warning is printed into the -'stderr'. +If file extension disagrees with file signature on the file format a warning +is printed into the 'stderr'.
[source,c] ------------------------------------------------------------------------------- @@ -76,11 +78,16 @@ int GP_SaveImage(GP_Context *src, const char *dst_path,
Saves a context into a file.
-The file format is matched accordingly to the file extension. If extension is -not found non-zero is returned and 'errno' is set to 'EINVAL'. If extension -was found but support for saving the image format is not implemented 'errno' -is set to 'ENOSYS'. +The file format is matched accordingly to the file extension. + +If extension is not found non-zero is returned and 'errno' is set to 'EINVAL'. + +If extension was found but support for saving the image format is not +implemented 'errno' is set to 'ENOSYS' (this may happen in case that GFXprim +wasn't compiled with support for this image type).
+If context pixel type is not supported by the format 'errno' is set to +'EINVAL'.
Advanced usage ^^^^^^^^^^^^^^
http://repo.or.cz/w/gfxprim.git/commit/d93da078d5d3db1e457a0225a26da0cead008...
commit d93da078d5d3db1e457a0225a26da0cead0085cb Author: Cyril Hrubis metan@ucw.cz Date: Wed Nov 6 19:39:21 2013 +0100
doc: Finish logo and favicon.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/doc/favicon.png b/doc/favicon.png index ad24515..e35dc42 100644 Binary files a/doc/favicon.png and b/doc/favicon.png differ diff --git a/doc/gfxprim_logo.png b/doc/gfxprim_logo.png index 5cf4f68..6857f55 100644 Binary files a/doc/gfxprim_logo.png and b/doc/gfxprim_logo.png differ
http://repo.or.cz/w/gfxprim.git/commit/147b4068a0ef11c88d116442680ad46894a7b...
commit 147b4068a0ef11c88d116442680ad46894a7b12a Author: Cyril Hrubis metan@ucw.cz Date: Sun Nov 3 20:16:00 2013 +0100
gp_codegen: Add idx to channel.
The channel.idx describes position of the channel in pixel (from left).
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/pylib/gp_codegen/pixeltype.py b/pylib/gp_codegen/pixeltype.py index bcad7fc..9887136 100644 --- a/pylib/gp_codegen/pixeltype.py +++ b/pylib/gp_codegen/pixeltype.py @@ -9,12 +9,14 @@ import re from .pixelsize import PixelSize
class PixelChannel(list): - def __init__(self, triplet): + def __init__(self, triplet, idx): (name, offset, size) = triplet # Create the list -> backward compatibility with triplets self.append(name) self.append(offset) self.append(size) + # Add index (position in pixel from left) + self.idx = idx # Add some convinience variables self.name = name self.off = offset @@ -45,8 +47,10 @@ class PixelType(object): self.name = name # Create channel list with convinience variables new_chanslist = [] + idx = 0 for i in chanslist: - new_chanslist.append(PixelChannel(i)) + new_chanslist.append(PixelChannel(i, idx)) + idx = idx + 1 self.chanslist = new_chanslist self.chans = dict() # { chan_name: (offset, size) } self.pixelsize = pixelsize
-----------------------------------------------------------------------
Summary of changes: build/syms/Filters_symbols.txt | 23 ++- demos/grinder/grinder.c | 141 +---------------- demos/py_simple/{dither.py => invert.py} | 8 +- doc/about.txt | 1 + doc/favicon.png | Bin 4929 -> 609 bytes doc/gfxprim_logo.png | Bin 8112 -> 8732 bytes doc/loaders.txt | 37 +++-- .../{GP_EdgeDetection.h => GP_ApplyTables.h} | 44 +++++- include/filters/GP_Filter.h | 27 +++- include/filters/GP_Point.h | 101 ++++++++----- .../{GP_MirrorV.gen.c.t => GP_ApplyTables.c} | 102 ++++++++----- ...{GP_ResizeNN.gen.c.t => GP_ApplyTables.gen.c.t} | 89 ++++++------ libs/filters/GP_Brightness.gen.c.t | 29 +--- libs/filters/GP_Contrast.gen.c.t | 29 +--- libs/filters/GP_Invert.gen.c.t | 20 +-- libs/filters/Makefile | 4 +- libs/loaders/GP_PNM.c | 7 +- pylib/gfxprim/filters/__init__.py | 5 +- pylib/gfxprim/filters/filters.i | 5 +- pylib/gp_codegen/pixeltype.py | 8 +- pylib/templates/filter.point.c.t | 162 ++++++-------------- 21 files changed, 370 insertions(+), 472 deletions(-) copy demos/py_simple/{dither.py => invert.py} (65%) copy include/filters/{GP_EdgeDetection.h => GP_ApplyTables.h} (66%) copy libs/filters/{GP_MirrorV.gen.c.t => GP_ApplyTables.c} (53%) copy libs/filters/{GP_ResizeNN.gen.c.t => GP_ApplyTables.gen.c.t} (56%)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos@gmail.com if you want to unsubscribe, or site admin admin@repo.or.cz if you receive no reply.