Ahora le toca el turno a la creación de filtros, y de paso presento algunas utilidades más para frei0r de mi cosecha (con alguna que otra función copiada de algún lado).
Esta vez, entre otras cosas, aunque habrá mucho código sin documentar por aquí, vamos a ver cómo podemos dar para cada canal de la imagen, la porción de rojo, verde y azul que queramos, sólo para practicar la creación de un filtro sencillo. Para ello, lo primero que debíamos hacer es completar las frei0r_utils, para ello, he subido el archivo en otra web.
El desarrollo del efecto, está muy ligado a las frei0r_utils (version 0.2, tal vez una versión futura no funcione), que espero documentar pronto, por lo que es recomendable descargar ese archivo antes de empezar.
Para el resto del efecto, seguiremos el orden de elementos que se marcaron en el anterior artículo, y las funciones que se llamarán desde frei0r para generar la imagen resultante:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | /* Version 0.3 may 2013 Copyright (C) 2013 Gaspar Fernández https://poesiabinaria.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ //******************************************************************* #include <stdio.h> #include <frei0r.h> #include <stdlib.h> //#include <math.h> #include <assert.h> #include <math.h> #include "config_play.h" #include <frei0r.h> #include "frei0r_utils.h" /* version 0.2 */ typedef struct { videosize_t size; double r_amount_for_r; double g_amount_for_r; double b_amount_for_r; double r_amount_for_g; double g_amount_for_g; double b_amount_for_g; double r_amount_for_b; double g_amount_for_b; double b_amount_for_b; } inst_t; param0r_def parameters[9]; int f0r_init() { parameters[0] = f0ut_set_double_param("redred", "Amount of red in the red channel", 1, 0, 1); parameters[1] = f0ut_set_double_param("greenred", "Amount of green in the red channel", 0, 0, 1); parameters[2] = f0ut_set_double_param("bluered", "Amount of blue in the red channel", 0, 0, 1); parameters[3] = f0ut_set_double_param("redgreen", "Amount of red in the green channel", 0, 0, 1); parameters[4] = f0ut_set_double_param("greengreen", "Amount of green in the green channel", 1, 0, 1); parameters[5] = f0ut_set_double_param("bluegreen", "Amount of blue in the green channel", 0, 0, 1); parameters[6] = f0ut_set_double_param("redblue", "Amount of red in the blue channel", 0, 0, 1); parameters[7] = f0ut_set_double_param("greenblue", "Amount of green in the blue channel", 0, 0, 1); parameters[8] = f0ut_set_double_param("blueblue", "Amount of blue in the blue channel", 1, 0, 1); return 1; } //------------------------------------------------ void f0r_deinit() { } //----------------------------------------------- void f0r_get_plugin_info(f0r_plugin_info_t* info) { f0ut_set_plugin_info(info, FREI0R_PLUGIN_NAME, FREI0R_PLUGIN_AUTHOR, FREI0R_PLUGIN_DESCRIPTION, F0R_PLUGIN_TYPE_FILTER, F0R_COLOR_MODEL_RGBA8888, FREI0R_PLUGIN_VERSION_MA, FREI0R_PLUGIN_VERSION_MI, 9); } //-------------------------------------------------- void f0r_get_param_info(f0r_param_info_t* info, int param_index) { f0ut_get_param_info(info, ¶meters[param_index]); } //---------------------------------------------- f0r_instance_t f0r_construct(unsigned int width, unsigned int height) { inst_t *in; in=calloc(1,sizeof(inst_t)); f0ut_set_videosize(&in->size, width, height); f0ut_set_default_value(&in->r_amount_for_r, ¶meters[0], &in->size); f0ut_set_default_value(&in->g_amount_for_r, ¶meters[1], &in->size); f0ut_set_default_value(&in->b_amount_for_r, ¶meters[2], &in->size); f0ut_set_default_value(&in->r_amount_for_g, ¶meters[3], &in->size); f0ut_set_default_value(&in->g_amount_for_g, ¶meters[4], &in->size); f0ut_set_default_value(&in->b_amount_for_g, ¶meters[5], &in->size); f0ut_set_default_value(&in->r_amount_for_b, ¶meters[6], &in->size); f0ut_set_default_value(&in->g_amount_for_b, ¶meters[7], &in->size); f0ut_set_default_value(&in->b_amount_for_b, ¶meters[8], &in->size); /* define parameters */ return (f0r_instance_t)in; } //--------------------------------------------------- void f0r_destruct(f0r_instance_t instance) { inst_t *in; in=(inst_t*)instance; free(instance); } //----------------------------------------------------- void f0r_set_param_value(f0r_instance_t instance, f0r_param_t param, int param_index) { inst_t *in; in=(inst_t*)instance; if (param_index==0) f0ut_set_param_value(&in->size, ¶meters[0], param, (void*)&in->r_amount_for_r); else if (param_index==1) f0ut_set_param_value(&in->size, ¶meters[1], param, (void*)&in->g_amount_for_r); else if (param_index==2) f0ut_set_param_value(&in->size, ¶meters[2], param, (void*)&in->b_amount_for_r); else if (param_index==3) f0ut_set_param_value(&in->size, ¶meters[3], param, (void*)&in->r_amount_for_g); else if (param_index==4) f0ut_set_param_value(&in->size, ¶meters[4], param, (void*)&in->g_amount_for_g); else if (param_index==5) f0ut_set_param_value(&in->size, ¶meters[5], param, (void*)&in->b_amount_for_g); else if (param_index==6) f0ut_set_param_value(&in->size, ¶meters[6], param, (void*)&in->r_amount_for_b); else if (param_index==7) f0ut_set_param_value(&in->size, ¶meters[7], param, (void*)&in->g_amount_for_b); else if (param_index==8) f0ut_set_param_value(&in->size, ¶meters[8], param, (void*)&in->b_amount_for_b); } //-------------------------------------------------- void f0r_get_param_value(f0r_instance_t instance, f0r_param_t param, int param_index) { inst_t *in; in=(inst_t*)instance; if (param_index==0) f0ut_get_param_value(&in->size, ¶meters[0], param, (void*)&in->r_amount_for_r); else if (param_index==1) f0ut_get_param_value(&in->size, ¶meters[1], param, (void*)&in->g_amount_for_r); else if (param_index==2) f0ut_get_param_value(&in->size, ¶meters[2], param, (void*)&in->b_amount_for_r); else if (param_index==3) f0ut_get_param_value(&in->size, ¶meters[3], param, (void*)&in->r_amount_for_g); else if (param_index==4) f0ut_get_param_value(&in->size, ¶meters[4], param, (void*)&in->g_amount_for_g); else if (param_index==5) f0ut_get_param_value(&in->size, ¶meters[5], param, (void*)&in->b_amount_for_g); else if (param_index==6) f0ut_get_param_value(&in->size, ¶meters[6], param, (void*)&in->r_amount_for_b); else if (param_index==7) f0ut_get_param_value(&in->size, ¶meters[7], param, (void*)&in->g_amount_for_b); else if (param_index==8) f0ut_get_param_value(&in->size, ¶meters[8], param, (void*)&in->b_amount_for_b); } //============================================================== void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, uint32_t* outframe) { inst_t *in; int r, g, b, a; in=(inst_t*)instance; unsigned int len = in->size.width * in->size.height; unsigned char* dst = (unsigned char*)outframe; const unsigned char* src = (unsigned char*)inframe; while (len--) { r = (int)*src++; g = (int)*src++; b = (int)*src++; a = (int)*src++; *dst++ = (unsigned char) MIN2( ( r*in->r_amount_for_r + g*in->g_amount_for_r + b*in->b_amount_for_r ), 255) ; *dst++ = (unsigned char) MIN2( ( r*in->r_amount_for_g + g*in->g_amount_for_g + b*in->b_amount_for_g ), 255) ; *dst++ = (unsigned char) MIN2( ( r*in->r_amount_for_b + g*in->g_amount_for_b + b*in->b_amount_for_b ), 255) ; // a *dst++ = (unsigned char) a; } } |
Lo más pesado es la configuración de parámetros, aunque lo arreglaré para la siguiente versión de frei0r_utils, por lo demás, una vez tenemos los parámetros en nuestra variable instancia, podemos hacer la multiplicación de cada componente por el factor que le hemos dado de manera interactiva (usando melt, o usando kdenlive, por poner un ejemplo)
Por último, para compilar:
$ gcc -c -fPIC channel-play.c -o channel-play.o ; gcc -g -shared -o channel-play.so channel-play.o frei0r_utils.o
tenemos que compilar y linkar la biblioteca dinámica. Y como siempre, si queremos utilizarla sin tener que ser root:
$ cp channel-play.so ~/.frei0r-1/lib/
Pingback: Bitacoras.com /
Pingback: Edición de vídeo en GNU/Linux con software libre, ¿Qué características necesito para editar vídeo? – Poesía Binaria /