Codebase list frei0r / cc24bf4
Update upstream source from tag 'upstream/2.5.0' Update to upstream version '2.5.0' with Debian dir ada90b6647b5236b75dea93077d6b882c70515f2 IOhannes m zmölnig (Debian/GNU) 8 months ago
64 changed file(s) with 955 addition(s) and 589 deletion(s). Raw diff Collapse all Expand all
55
66 ## Developers who contributed, in alphabetic order:
77
8 Akito Iwakura, Albert Frisch, Ajrat Makhmutov, Brendan Hack, Brian Matherly, Burkhard Plaum, Carlo E. Prelz, Christoph Willing, Erik Beck, Esmane, Filippo Giunchedi, Gabriel Finch (Salsaman), Georg Seidel, Henner Zeller, Hedde Bosman, IOhannes M. Zmölnig, Janne Liljeblad, Jean-Baptiste Mardelle, Jean-François Fortin Tam , Jean-Sebastien Senecal, Jerome Blanchi (d.j.a.y), Joshua M. Doe, Luca Bigliardi, Maksim Golovkin (Максим Головкин), Marko Cebokli, Martin Bayer, Mathieu Guindon, Matthias Schnoell, Nicolas Carion, Niels Elburg, Phillip Promesberger, Raphael Graf, Richard Spindler, Richard Ling (Chungzuwalla), Robert Schweikert, Ross Lagerwall, Samuel Mimram, Simon A. Eugster, Sofian Audry, Stefano Sabatini, Steinar H. Gunderson, Thomas Coldrick, Thomas Perl, Till Theato, Vincent Pinon.
8 Akito Iwakura
9 Albert Frisch
10 Ajrat Makhmutov
11 Brendan Hack
12 Brian Matherly
13 Burkhard Plaum
14 Carlo E. Prelz
15 Christoph Willing
16 Cynthia
17 Erik Beck
18 Esmane
19 Filippo Giunchedi
20 Gabriel Finch (Salsaman)
21 Georg Seidel
22 Henner Zeller
23 Hedde Bosman
24 IOhannes m. zmölnig
25 Janne Liljeblad
26 Jean-Baptiste Mardelle
27 Jean-François Fortin Tam
28 Jean-Sebastien Senecal
29 Jerome Blanchi (d.j.a.y)
30 Johann Jeg
31 Joshua M. Doe
32 Luca Bigliardi
33 Maksim Golovkin (Максим Головкин)
34 Marko Cebokli
35 Martin Bayer
36 Mathieu Guindon
37 Matthias Schnöll
38 Nicolas Carion
39 Niels Elburg
40 Phillip Promesberger
41 Raphael Graf
42 Richard Spindler
43 Richard Ling (Chungzuwalla)
44 Robert Schweikert
45 Ross Lagerwall
46 Samuel Mimram
47 Simon A. Eugster
48 Sofian Audry
49 Stefano Sabatini
50 Steinar H. Gunderson
51 Thomas Coldrick
52 Thomas Perl
53 Till Theato
54 Vadim Druzhin
55 Vincent Pinon
195195 /**
196196 * frei0r_cairo_get_pixel_position
197197 * @norm_pos: position in range 0 - 1, either x or y
198 * @dim: dimension, either witdh or height
198 * @dim: dimension, either width or height
199199 *
200200 * Converts double range [0 -> 1] to pixel range [-2*dim -> 3*dim]. Input 0.4 gives position 0.
201201 *
206206 //convert from paked uchar RGBA to packed float RGBA
207207 //w,h are width and height of the image
208208 //tab = table used for RGB conversion
209 //atab = table used for alpha converion (usually linear)
209 //atab = table used for alpha conversion (usually linear)
210210 static inline void RGBA8_2_float(const uint32_t *in, float_rgba *out, int w, int h, float *tab, float *atab)
211211 {
212212 int i;
223223
224224 //--------------------------------------------------------
225225 //convert from paked uchar RGBA to packed float RGBA,
226 //covert RGB only, SKIP ALPHA
226 //convert RGB only, SKIP ALPHA
227227 //w,h are width and height of the image
228228 //tab = table used for RGB conversion
229229 static inline void RGB8_2_float(const uint32_t *in, float_rgba *out, int w, int h, float *tab)
258258 //----------------------------------------------------------
259259 //convert from packed float RGBA to packed uchar RGBA
260260 //tab = table used for RGB conversion
261 //atab = table used for alpha converion (usually linear)
261 //atab = table used for alpha conversion (usually linear)
262262 static inline void float_2_RGBA8(const float_rgba *in, uint32_t *out, int w, int h, uint8_t *tab, uint8_t *atab)
263263 {
264264 int i;
275275
276276 //----------------------------------------------------------
277277 //convert from packed float RGBA to packed uchar RGBA
278 //covert RGB only, SKIP ALPHA
278 //convert RGB only, SKIP ALPHA
279279 //tab = table used for RGB conversion
280280 static inline void float_2_RGB8(const float_rgba *in, uint32_t *out, int w, int h, uint8_t *tab)
281281 {
136136 * @subsection sec_icon_location Icon location
137137 *
138138 * The exact location where the application should look for the
139 * plugin is platform dependant.
139 * plugin is platform dependent.
140140 *
141141 * For Windows platforms, the icon should be at the same place as
142142 * the plugin containing the effect.
189189 * - \ref f0r_update2
190190 *
191191 * If a thread is in one of these methods its allowed for another thread to
192 * enter one of theses methods for a different effect instance. But for one
192 * enter one of these methods for a different effect instance. But for one
193193 * effect instance only one thread is allowed to execute any of these methods.
194194 */
195195
259259 * List of supported color models.
260260 *
261261 * Note: the color models are endian independent, because the
262 * color components are defined by their positon in memory, not
262 * color components are defined by their position in memory, not
263263 * by their significance in an uint32_t value.
264264 *
265265 * For effects that work on the color components,
308308
309309 /**
310310 * In PACKED32, each pixel is represented by 4 consecutive
311 * bytes, but it is not defined how the color componets are
311 * bytes, but it is not defined how the color components are
312312 * stored. The true color format could be RGBA8888,
313313 * BGRA8888, a packed 32 bit YUV format, or any other
314314 * color format that stores pixels in 32 bit.
340340 inframe3);
341341 }
342342
343 // compability for frei0r 1.0
343 // compatibility for frei0r 1.0
344344 void f0r_update(f0r_instance_t instance,
345345 double time, const uint32_t* inframe, uint32_t* outframe)
346346 {
5353 add_subdirectory (glow)
5454 add_subdirectory (glitch0r)
5555 #add_subdirectory (host_param_test)
56 add_subdirectory (heatmap0r)
5657 add_subdirectory (hueshift0r)
5758 add_subdirectory (invert0r)
5859 add_subdirectory (kaleid0sc0pe)
3131
3232 ////// TODO / IDEAS / ... //////
3333 // IDEA - directionnal echo ? (X/Y like parameter )
34 // TODO RGB gradiant by fading influence need more love (See '//Fade by color layers')!
35 // FIXME SSE2 version doesnt support RGB fading influence !
36
37 // FIXME (Veejay specifics?) on activate/desactivate/activate/..., some buffers must be cleared!
38
39 // EXPORE ME -
34 // TODO RGB gradient by fading influence need more love (See '//Fade by color layers')!
35 // FIXME SSE2 version doesn't support RGB fading influence !
36
37 // FIXME (Veejay specifics?) on activate/deactivate/activate/..., some buffers must be cleared!
38
39 // EXPLORE ME -
4040 //~ if((skip_count++)>m_skip) {
4141 //~ - skip_count = 0;
4242 //~ - m_factor += (factor * 64);
4343 //~ [...]
4444 //~ }
4545
46 // EXPLORE ME a very high m_factor value give some interresting color result ( m_factor += (factor * 64) * m_skip;)
46 // EXPLORE ME a very high m_factor value give some interesting color result ( m_factor += (factor * 64) * m_skip;)
4747
4848
4949 /* Intrinsic declarations */
128128 m_skip_count = 0;
129129
130130 register_param(factor, "Fade Factor", "Disappearance rate of the echo"); // 0 No fade, 1 No Trace
131 register_param(bright, "Direction", "Darker or Brighter echo"); // Add or Substract data
131 register_param(bright, "Direction", "Darker or Brighter echo"); // Add or Subtract data
132132 register_param(flag_r, "Keep RED", "Influence on Red channel"); // 0 Fade canal, 1 Keep canal data
133133 register_param(flag_g, "Keep GREEN", "Influence on Green channel"); // 0 Fade canal, 1 Keep canal data
134134 register_param(flag_b, "Keep BLUE", "Influence on Blue channel"); // 0 Fade canal, 1 Keep canal data
138138 //~ register_param(factor_r, "Fade R", "influence"); // 0 No fade, 1 No Trace
139139 //~ register_param(factor_g, "Fade G", "influence"); // 0 No fade, 1 No Trace
140140 //~ register_param(factor_b, "Fade B", "influence"); // 0 No fade, 1 No Trace
141 //~ register_param(flag_rgb, "Plans comparaison", "RGB");
141 //~ register_param(flag_rgb, "Plans comparison", "RGB");
142142
143143 }
144144 ~aech0r() {
5757 float sga;
5858 int inv;
5959
60 //auxilliary variables for fibe2o
60 //auxiliary variables for fibe2o
6161 float f,q,a0,a1,a2,b0,b1,b2,rd1,rd2,rs1,rs2,rc1,rc2;
6262
6363 } inst;
104104 because I did some optimizations for speed.
105105 The algorithms are so simple, that using SSE didn't bring
106106 much speedup - the limiting factor is memory bandwidth, not
107 arithmetics. Therefore I decided not to include the SSE versions.
107 arithmetic. Therefore I decided not to include the SSE versions.
108108
109109
110110
3434 CONTENTS OF FIBE.H FILE:
3535 --------------------------------
3636
37 calcab_lp1() auxilliary function to calculate lowpass
37 calcab_lp1() auxiliary function to calculate lowpass
3838 tap coefficients for FIBE-2
3939
40 young_vliet() auxilliary function to calculate tap coefs
40 young_vliet() auxiliary function to calculate tap coefs
4141 for Gauss approximation with FIBE-3
4242
43 rep() auxilliary function to calculate wraparound
43 rep() auxiliary function to calculate wraparound
4444 values for FIBE-2
4545
4646 fibe1o_8() one tap quadrilateral IIR filter
106106 {
107107 int val;
108108 case 0:
109 /* constrast */
109 /* contrast */
110110 val = (int) ((*((double*)param) - 0.5) * 512.0); /* remap to [-256, 256] */
111111 if (val != inst->brightness)
112112 {
8888 left corner x=1000, y=1000, the upper right corner x=2000, y=1000 and so on. It
8989 should also set the defaults so that the undistorted input picture is displayed.
9090 If you have no image, check that the corners specify a nonzero area at least
91 partly overlaping the output window.
91 partly overlapping the output window.
9292
9393 2. Stretch, x and y
9494
1818 */
1919
2020 /*******************************************************************
21 * The remapping functions use a map aray, which contains a pair
21 * The remapping functions use a map array, which contains a pair
2222 * of floating values fo each pixel of the output image. These
2323 * represent the location in the input image, from where the value
2424 * of the given output pixel should be interpolated.
118118 // We check all four neighbours, but in practice only one can ever overlap any given point.
119119 for (i = 0; i < 5; i++)
120120 {
121 // Find neigbouring grid point
121 // Find neighbouring grid point
122122 ttx = tx + mx[i]*gridSize;
123123 tty = ty + my[i]*gridSize;
124124 // Transform back into image space
9999 {
100100 int val;
101101 case 0:
102 /* constrast */
102 /* contrast */
103103 val = (int) ((*((double*)param) - 0.5) * 512.0); /* remap to [-256, 256] */
104104 if (val != inst->contrast)
105105 {
387387
388388 double* gaussSLESolve(size_t size, double* A) {
389389 int extSize = size + 1;
390 //direct way: tranform matrix A to triangular form
390 //direct way: transform matrix A to triangular form
391391 for(int row = 0; row < size; row++) {
392392 int col = row;
393393 int lastRowToSwap = size - 1;
545545 /*
546546 * Calculating a point on the bezier curve using the coefficients from Bernstein basis polynomial of degree 3.
547547 * Using the De Casteljau algorithm would be slightly faster when calculating a lot of values
548 * but the difference is far from noticable here since we update the spline only when the parameter changes
548 * but the difference is far from noticeable here since we update the spline only when the parameter changes
549549 */
550550 double c1 = (1-t) * (1-t) * (1-t);
551551 double c2 = 3 * t * (1-t) * (1-t);
556556 return pos;
557557 }
558558
559 #if defined(_WIN32) || defined(_WIN64)
560 # define strtok_r strtok_s
561 #endif
562
559563 /**
560564 * Splits given string into sub-strings at given delimiter.
561565 * \param string input string
568572 int count = 0;
569573 char *input = strdup(string);
570574 char *result = NULL;
571 result = strtok(input, delimiter);
575 result = strtok_r(string, delimiter, &input);
572576 while (result != NULL) {
573577 *tokens = realloc(*tokens, (count + 1) * sizeof(char *));
574578 (*tokens)[count++] = strdup(result);
575 result = strtok(NULL, delimiter);
579 result = strtok_r(NULL, delimiter, &input);
576580 }
577581 free(input);
578582 return count;
775779 curves_instance_t* inst = (curves_instance_t*)instance;
776780 unsigned int len = inst->width * inst->height;
777781
778 // test initalization c/b spline
782 // test initialization c/b spline
779783 double *splinemap = strlen(inst->bspline)>0 ? inst->bsplineMap : inst->csplineMap;
780784 if(!splinemap) {
781785 memcpy(outframe,inframe,inst->width * inst->height * 4);
221221 for (unsigned int pixel = 0; pixel < width*4; pixel++) {
222222 // Use linear interpolation on the colours
223223
224 // Use pointer arithmetics. Colour values are stored
224 // Use pointer arithmetic. Colour values are stored
225225 // as AABBGGRR in the uint32_t values.
226226 // Convert each colour separately.
227227
11 rectilinear, and vice versa. It is based on the angular mapping
22 functions actually used in fisheye lens design, to get the best
33 possible results. It can also be used to correct the slight distortion
4 of some wideangle convertors, or to bend the image beyond recognition
4 of some wideangle converters, or to bend the image beyond recognition
55 for special effects and light shows.
66
77
6363 unreasonable values the image might indeed disappear, when there are
6464 math overflows or imaginary results... (types 1 and 2 are more prone
6565 to image vanishing). Anyway, when working in the "special effect"
66 range, it is alway worth to try manual scaling.
66 range, it is always worth to try manual scaling.
6767
6868 "DeFish"
6969 If checked, the transform direction is from fisheye to rectiliear,
162162 Scaling = 1000 (manual)
163163 Manual Scale = 191
164164
165 For an effect, reminiscent of some scenes from the "2001 Spcae Odyssey" try
165 For an effect, reminiscent of some scenes from the "2001 Space Odyssey" try
166166 this:
167167 Amount = 876
168168 Defish = ON
212212 //pari,paro = pixel aspect ratio (input / output)
213213 //dx, dy offset on input (for non-cosited chroma subsampling)
214214 //lbox = letterbox
215 //stretch = dymanic stretch, convert between 4:3 and 16:9
216 //yScale = -0.5.. 0.5 change aspect ratio on y acess only
215 //stretch = dynamic stretch, convert between 4:3 and 16:9
216 //yScale = -0.5.. 0.5 change aspect ratio on y access only
217217 void defishmap(int wi, int hi, int wo, int ho, int n, float f, float scal, float pari, float paro, float dx, float dy, float *map
218218 , int lbox, float stretchFactor, float yScale)
219219 {
311311 //aspt: 0..4 aspect type square, PAL, NTSC, HDV, manual
312312 //par: pixel aspect ratio
313313 //lbox: 1=letterbox
314 //stretch 0..1 stretch video to fix superview distorsion
314 //stretch 0..1 stretch video to fix superview distortion
315315 typedef struct
316316 {
317317 int w;
512512 p->mpar=1.0;
513513 p->lbox=0; //letterbox
514514 p->stretch = 0.0f; //dynamic stretch
515 p->yScale = 1.0f; //seperate Y stretch
515 p->yScale = 1.0f; //separate Y stretch
516516
517517 p->map=(float*)calloc(1, sizeof(float)*(p->w*p->h*2+2));
518518 p->interpol=set_intp(*p);
1818 */
1919
2020 /*******************************************************************
21 * The remapping functions use a map aray, which contains a pair
22 * of floating values fo each pixel of the output image. These
21 * The remapping functions use a map array, which contains a pair
22 * of floating values of each pixel of the output image. These
2323 * represent the location in the input image, from where the value
2424 * of the given output pixel should be interpolated.
2525 * They are given in pixels of the input image.
1414 ## Description of the parameters:
1515
1616 "Scale Center":<br/>
17 Sets the horizontal center where the scaling orgins from. range: [0,1]
17 Sets the horizontal center where the scaling origins from. range: [0,1]
1818
1919
2020 "Linear Scale Area":<br/>
0 set (SOURCES heatmap0r.c)
1 set (TARGET heatmap0r)
2
3 if (MSVC)
4 set (SOURCES ${SOURCES} ${FREI0R_DEF})
5 endif (MSVC)
6
7 add_library (${TARGET} MODULE ${SOURCES})
8
9 # No «lib» prefix (name.so instead of libname.so)
10 set_target_properties (${TARGET} PROPERTIES PREFIX "")
0 /*
1 * heatmap0r.c -- feel the heat, frei0r style.
2 *
3 * Copyright (C) 2025 Cynthia (cynthia2048@proton.me)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <stdlib.h>
21 #include <assert.h>
22
23 #include "frei0r.h"
24 #include "frei0r/math.h"
25
26 typedef struct {
27 unsigned int width, height;
28 uint8_t rlut[256], glut[256], blut[256];
29
30 f0r_param_color_t black, grey, white;
31 double gp; //< Grey point
32 } heatmap0r_t;
33
34 static void gen_heatmap0r_luts(heatmap0r_t *inst)
35 {
36 double luma;
37 double L0, L1, L2;
38 double gp = inst->gp;
39 double l0 = 1.0 / gp,
40 l1 = 1.0 / (gp * (gp - 1.0)),
41 l2 = 1.0 / (1.0 - gp);
42
43 f0r_param_color_t black = inst->black,
44 grey = inst->grey,
45 white = inst->white;
46
47 for (int i = 0; i < 256; ++i)
48 {
49 luma = 1.0 / 255.0 * (double)i;
50
51 L0 = (luma - gp) * (luma - 1.0) * l0;
52 L1 = luma * (luma - 1.0) * l1;
53 L2 = luma * (luma - gp) * l2;
54
55 inst->rlut[i] = CLAMP(255.0 * (L0 * black.r + L1 * grey.r + L2 * white.r), 0, 255);
56 inst->glut[i] = CLAMP(255.0 * (L0 * black.g + L1 * grey.g + L2 * white.g), 0, 255);
57 inst->blut[i] = CLAMP(255.0 * (L0 * black.b + L1 * grey.b + L2 * white.b), 0, 255);
58 }
59 }
60
61 int f0r_init()
62 {
63 return 1;
64 }
65
66 void f0r_deinit() {}
67
68 f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
69 {
70 heatmap0r_t* inst = calloc(1, sizeof(*inst));
71
72 inst->width = width; inst->height = height;
73 inst->gp = 0.5;
74 inst->white = (f0r_param_color_t) {/* Yellow */ 1.0, 1.0, 0.0};
75 inst->grey = (f0r_param_color_t) {/* Deeppink */ 1.0, 0.0, 0.5};
76 inst->black = (f0r_param_color_t) {/* Darkviolet */ 0.27, 0.0, 0.5};
77
78 gen_heatmap0r_luts (inst);
79
80 return (f0r_instance_t)inst;
81 }
82
83 void f0r_destruct(f0r_instance_t instance)
84 {
85 free(instance);
86 }
87
88 void f0r_get_plugin_info(f0r_plugin_info_t* info)
89 {
90 info->name = "heatmap0r";
91 info->author = "Cynthia";
92 info->plugin_type = F0R_PLUGIN_TYPE_FILTER;
93 info->color_model = F0R_COLOR_MODEL_RGBA8888;
94 info->frei0r_version = FREI0R_MAJOR_VERSION;
95 info->major_version = 0;
96 info->minor_version = 1;
97 info->num_params = 4;
98 info->explanation = "Performs a continious trichromatic tinting";
99 }
100
101 void f0r_get_param_info(f0r_param_info_t* info, int param_index)
102 {
103 switch(param_index)
104 {
105 case 0:
106 info->name = "Map black to";
107 info->type = F0R_PARAM_COLOR;
108 info->explanation = "The color to map source color with zero luminance";
109 break;
110 case 1:
111 info->name = "Map grey to";
112 info->type = F0R_PARAM_COLOR;
113 info->explanation = "The color to map source color with mid luminance";
114 break;
115 case 2:
116 info->name = "Map white to";
117 info->type = F0R_PARAM_COLOR;
118 info->explanation = "The color to map source color with full luminance";
119 break;
120 case 3:
121 info->name = "Grey point";
122 info->type = F0R_PARAM_DOUBLE;
123 info->explanation = "Point in the luminance axis grey color is located";
124 break;
125 }
126 }
127
128 void f0r_set_param_value(f0r_instance_t instance,
129 f0r_param_t param, int param_index)
130 {
131 assert(instance);
132 heatmap0r_t* inst = (heatmap0r_t*)instance;
133
134 switch(param_index)
135 {
136 case 0:
137 inst->black = *((f0r_param_color_t *)param);
138 break;
139 case 1:
140 inst->grey = *((f0r_param_color_t *)param);
141 break;
142 case 2:
143 inst->white = *((f0r_param_color_t *)param);
144 break;
145 case 3:
146 inst->gp = *((double *)param);
147 break;
148 }
149
150 gen_heatmap0r_luts (inst);
151 }
152
153 void f0r_get_param_value(f0r_instance_t instance,
154 f0r_param_t param, int param_index)
155 {
156 assert(instance);
157 heatmap0r_t* inst = (heatmap0r_t*)instance;
158
159 switch(param_index)
160 {
161 case 0:
162 *((f0r_param_color_t*)param) = inst->black;
163 break;
164 case 1:
165 *((f0r_param_color_t*)param) = inst->grey;
166 break;
167 case 2:
168 *((f0r_param_color_t*)param) = inst->white;
169 break;
170 case 3:
171 *((double *)param) = inst->gp;
172 break;
173 }
174 }
175
176 void f0r_update(f0r_instance_t instance, double time,
177 const uint32_t* inframe, uint32_t* outframe)
178 {
179 assert(instance);
180 heatmap0r_t* inst = (heatmap0r_t*)instance;
181 unsigned int len = inst->width * inst->height;
182
183 const unsigned char* src = (void*)inframe;
184 unsigned char* dst = (void*)outframe;
185
186 unsigned char luma, r, g, b;
187 while (len--)
188 {
189 r = *src++;
190 g = *src++;
191 b = *src++;
192
193 luma = 0.299 * r + 0.587 * g + 0.114 * b;
194
195 *dst++ = inst->rlut[luma];
196 *dst++ = inst->glut[luma];
197 *dst++ = inst->blut[luma];
198 *dst++ = *src++;
199 }
200 }
100100 {
101101 int val;
102102 case 0:
103 /* constrast */
103 /* contrast */
104104 val = (int) (*((double*)param) * 360.0); /* remap to [0, 360] */
105105 if (val != inst->hueshift)
106106 {
00 /*
11 * matrix -
2 * Use 4x4 matricies to process color images.
2 * Use 4x4 matrices to process color images.
33 *
44 * To compile:
55 cc matrix.c -o matrix -lgutil -limage -lgl -lm
7272
7373 /*
7474 * matrixmult -
75 * multiply two matricies
75 * multiply two matrices
7676 */
7777 void
7878 matrixmult(float a[4][4],float b[4][4],float c[4][4])
131131
132132 /*
133133 * cscalemat -
134 * make a color scale marix
134 * make a color scale matrix
135135 */
136136 void
137137 cscalemat(float mat[4][4],float rscale,float gscale,float bscale)
163163
164164 /*
165165 * lummat -
166 * make a luminance marix
166 * make a luminance matrix
167167 */
168168 void
169169 lummat(float mat[4][4])
198198
199199 /*
200200 * saturatemat -
201 * make a saturation marix
201 * make a saturation matrix
202202 */
203203 void
204204 saturatemat(float mat[4][4],float sat)
2727 3. `segmentation` `(float=16/128)` - The kaleid0sc0pe effect is broken into `segmentation * 128` segments. Segmentations of 1, 2 or multiples of 4 work best. Range `[0, 1]`.
2828 4. `specify_source` `(bool=false)` - If `true` then the source segment for the mirror is specified by `source_segment`. Otherwise the furthest corner from the origin is used as the source segment and the segment's orientation is defined by `segmentation_direction`. When multiple corners are the same distance the tie is broken according to the `preferred_corner` and `corner_search` parameters.
2929 5. `source_segment` `(float=0)` - Normalized angle that specifies the centre of the source segment if `specify_source` is `true`. `0` is in `+x` and rotates counter clockwise. Range `[0, 1]`.
30 6. `segmentation_direction` `(float=1)` - When `source_segment` is `false` the source segement is either centred on the corner (< `1/3`), extends counter clockwise from the corner (< `2/3`) or clockwise from the corner (>= `2/3` the default). Range `[0, 1]`.
30 6. `segmentation_direction` `(float=1)` - When `source_segment` is `false` the source segment is either centred on the corner (< `1/3`), extends counter clockwise from the corner (< `2/3`) or clockwise from the corner (>= `2/3` the default). Range `[0, 1]`.
3131 7. `reflect_edges` `(bool=true)` - If `true` then reflections that end up outside the frame reflect back into it, otherwise the colour specified in `bg_color` is used.
3232 8. `edge_threshold` `(float=0)` - if `reflect_edges` is `false` then reflections outside the frame but within `edge_threshold * 4` pixels of the frame clamp to the edge value rather than use the background color. Range `[0, 1]`.
3333 9. `preferred_corner` `(float=0)` - The preferred corner when breaking ties when searching for the furthest corner. Searching starts in this corner and proceeds in the direction given in `corner_search`. The first and furthest corner found wins. Supported values are `0`: top right (default), `0.25`: top left, `0.5`: bottom left, `0.75`: bottom right.
3535 {
3636
3737 // default delete for IKaleid0sc0pe
38 // this isn't going to work across an actaul shared object boundary but
38 // this isn't going to work across an actual shared object boundary but
3939 // not particular worried about that at the moment
4040 template<>
4141 class default_delete<libkaleid0sc0pe::IKaleid0sc0pe>
256256 /**
257257 * Sets the number of threads to use when processing.
258258 * Default to 0.
259 * @param threading the nubmer of threads to use. \c 0, calculate automatically,
259 * @param threading the number of threads to use. \c 0, calculate automatically,
260260 * otherwise the explicit thread count.
261261 * @return
262262 * - 0: Success
142142 /// <tt>source_x,source_y</tt>
143143 /// @param x x coordinate to start rotate from
144144 /// @param y y coordinate to rotate
145 /// @param source_x receives the x coordiante results
145 /// @param source_x receives the x coordinate results
146146 /// @param source_y receives the y coordinate results
147147 inline void rotate(int x, int y, __m128 *source_x, __m128 *source_y);
148148 #else
163163 Reflect_info calculate_reflect_info(std::uint32_t x, std::uint32_t y);
164164
165165 /// Converts coordinates to screen space
166 /// @param x recieves x coordinate
167 /// @param y recieves y coordinate
166 /// @param x receives x coordinate
167 /// @param y receives y coordinate
168168 /// @param sx source x coordinate
169169 /// @param sy source y coordinate
170170 void to_screen(float *x, float *y, std::uint32_t sx, std::uint32_t sy);
300300 _PS_CONST(cephes_FOPI, 1.27323954473516); // 4 / M_PI
301301
302302
303 /* evaluation of 4 sines at onces, using only SSE1+MMX intrinsics so
303 /* evaluation of 4 sines at once, using only SSE1+MMX intrinsics so
304304 it runs also on old athlons XPs and the pentium III of your grand
305305 mother.
306306
6767 This plugin can be cascaded, but it is not possible to get the same
6868 color based mask in the second instance, because the colors will be
6969 changed by the first instance. To enable two operations with the
70 same mask, each plugin instance can do two opertions.
70 same mask, each plugin instance can do two operations.
7171 With transparency and edge masks, cascading is a bit easier.
7272 If the hue gate and saturation threshold are not used, transparency
7373 and edge masks can be exactly the same in cascaded plugins.
121121
122122 Show mask:
123123 This will show the selected mask as a greyscale image, to help with
124 fine tuning of the masks. Shoud be OFF for the final render.
124 fine tuning of the masks. Should be OFF for the final render.
125125
126126 Mask to Alpha:
127127 Copies the active mask to the alpha channel.
128128 For all normal spill cleaning operations, this should be OFF.
129 By seting it ON, the keyspillm0pup itself can be used as a keyer,
129 By setting it ON, the keyspillm0pup itself can be used as a keyer,
130130 or to generate some special effects.
851851 fb = m_rgbLightMask[pixel].b;
852852
853853 if (lowerOverexposure > 0) {
854 // Comparisation of plots with octave:
854 // Comparison of plots with octave:
855855 // clf;hold on;plot([0 1],[0 1],'k');plot(range,ones(length(range),1),'k');plot(range,sqrt(range));plot(range,log(1+range),'k');plot(range,log(1+range),'g');plot(range,(log(1+range)/3).^.5,'r');axis equal
856856 fr = pow( log(1+fr)/lowerOverexposure, .5 );
857857 fg = pow( log(1+fg)/lowerOverexposure, .5 );
3737 double PI=3.14159265358979;
3838
3939 //---------------------------------------------------------------
40 void draw_rectangle(float_rgba *s, int w, int h, float x, float y, float wr, float hr, float_rgba c)
40 static inline void draw_rectangle(float_rgba *s, int w, int h, float x, float y, float wr, float hr, float_rgba c)
4141 {
4242 int i,j;
4343 int zx,kx,zy,ky;
138138 //justified
139139 //p=0 one decimal place p=1 three decimal places
140140 //m=1 always show sign
141 void forstr(float a, int p, int m, char *s)
141 inline static void forstr(float a, int p, int m, char *s)
142142 {
143143 float b;
144144 char *p3=" %5.3f";
191191 forstr(s.rms,1-u,0,rs);
192192 forstr(s.min,1-u,m,ns);
193193 forstr(s.max,1-u,m,xs);
194 sprintf(fs,"%s%s%s %s%s", lab, as, rs, ns, xs);
194 snprintf(fs,255,"%s%s%s %s%s", lab, as, rs, ns, xs);
195195 sprintf(str,fs,s.avg,s.rms,s.min,s.max);
196196 }
197197 else
198198 {
199199 forstr(s.avg,1-u,m,as);
200200 forstr(s.rms,1-u,0,rs);
201 sprintf(fs,"%s%s%s", lab, as, rs);
201 snprintf(fs,255,"%s%s%s", lab, as, rs);
202202 sprintf(str,fs,s.avg,s.rms);
203203 }
204204 }
205205
206206 //-----------------------------------------------------------
207 //probe size markers in the magnifier diaplay
207 //probe size markers in the magnifier display
208208 void sxmarkers(float_rgba *s, int w, int h, int x0, int y0, int np, int sx, int sy, int vp)
209209 {
210210 int np2,x,y,i,j;
250250 s[w*y+x]=white;
251251 x=x0+(np+2)*vp-i-1;
252252 s[w*y+x]=white;
253 }
253 }
254254 }
255255 if (sy>np)
256256 {
262262 s[w*y+x]=white;
263263 y=y0+(np+2)*vp-i-1;
264264 s[w*y+x]=white;
265 }
265 }
266266 }
267267
268268 }
300300 if (bw==1) //big window
301301 {
302302 vx=240;
303 vy = (m<=2) ? 320 : 300;
303 vy = (m<=2) ? 320 : 300;
304304 x0 = (*poz==0) ? h/20 : w-h/20-vx;
305305 np=25; //size of magnifier
306306 xn = (m<=2) ? x0+8 : x0+70;
744744
745745 floatrgba2color(in->sl, outframe, in->w , in->h);
746746 }
747
113113 //justified
114114 //p=0 one decimal place p=1 three decimal places
115115 //m=1 always show sign
116 void forstr(float a, int p, int m, char *s)
116 inline static void forstr(float a, int p, int m, char *s)
117117 {
118118 float b;
119119 char *p3=" %5.3f";
319319 if (m1>0)
320320 {
321321 forstr(data[0],1-u,0,frs);
322 sprintf(fs,"%%s Mk1=%s", frs);
322 snprintf(fs,255,"%%s Mk1=%s", frs);
323323 sprintf(str,fs,str,data[0]);
324324 }
325325 else
330330 if (m2>0)
331331 {
332332 forstr(data[1],1-u,0,frs);
333 sprintf(fs,"%%s Mk2=%s", frs);
333 snprintf(fs,255,"%%s Mk2=%s", frs);
334334 sprintf(str,fs,str,data[1]);
335335 }
336336 else
341341 if ((m2>0)&&(m1>0))
342342 {
343343 forstr(data[2],1-u,0,frs);
344 sprintf(fs,"%%s D=%s", frs);
344 snprintf(fs,255,"%%s D=%s", frs);
345345 sprintf(str,fs,str,data[2]);
346346 }
347347 else
350350 if ((dit&0x00000020)!=0) //average of profile
351351 {
352352 forstr(data[3],1-u,0,frs);
353 sprintf(fs,"%%s Avg=%s", frs);
353 snprintf(fs,255,"%%s Avg=%s", frs);
354354 sprintf(str,fs,str,data[3]);
355355 }
356356 if ((dit&0x00000040)!=0) //RMS of profile
357357 {
358358 forstr(data[4],1-u,0,frs);
359 sprintf(fs,"%%s RMS=%s", frs);
359 snprintf(fs,255,"%%s RMS=%s", frs);
360360 sprintf(str,fs,str,data[4]);
361361 }
362362 if ((dit&0x00000080)!=0) //MIN of profile
363363 {
364364 forstr(data[5],1-u,0,frs);
365 sprintf(fs,"%%s Min=%s", frs);
365 snprintf(fs,255,"%%s Min=%s", frs);
366366 sprintf(str,fs,str,data[5]);
367367 }
368368 if ((dit&0x00000100)!=0) //MAX of profile
369369 {
370370 forstr(data[6],1-u,0,frs);
371 sprintf(fs,"%%s Max=%s", frs);
371 snprintf(fs,255,"%%s Max=%s", frs);
372372 sprintf(str,fs,str,data[6]);
373373 }
374374 }
407407 if (y>h/2+20) *poz=0; //top
408408 x0=h/20;
409409 vx=w*15/16;
410 vy = h*6/16;
410 vy = h*6/16;
411411 y0 = (*poz==0) ? h/20 : h-h/20-vy;
412412
413413 //end points of profile
10341034
10351035 floatrgba2color(in->sl, outframe, in->w , in->h);
10361036 }
1037
335335 * odd dimensions. Images of arbitrary size may be processed.
336336 *
337337 * To process multi-channel images, you must call this function multiple times,
338 * changing the source and destination adresses and steps such that each channel
338 * changing the source and destination addresses and steps such that each channel
339339 * is processed as an independent single-channel image.
340340 *
341341 * Processing images of arbitrary bit depth is not supported.
6767 ML3DEX: multilevel spatio-temporal, see [1]
6868
6969
70 [1] Anil Christopher Kokaram: Motion Picure Restoration
71 phd disertation
70 [1] Anil Christopher Kokaram: Motion Picture Restoration
71 phd dissertation
7272
7373 ****************************************** */
7474
113113 http://nomis80.org/ctmf.pdf
114114 http://nomis80.org/ctmf.html
115115
116 [3] Anil Christopher Kokaram: Motion Picure Restoration
117 phd disertation
116 [3] Anil Christopher Kokaram: Motion Picture Restoration
117 phd dissertation
33 *
44 * 2002/2/9
55 * Original code copied same frame twice, and did not use memcpy().
6 * I modifed those point.
6 * I modified those point.
77 * -Kentarou Fukuchi
88 *
99 * 2009/8/26
5656 if (n > ((T14_2PI >> 1) - 1)) {
5757 *c = -*c;
5858 *s = -*s;
59 }
60 }
61
62 extern int
63 crt_bpp4fmt(int format)
64 {
65 switch (format) {
66 case CRT_PIX_FORMAT_RGB:
67 case CRT_PIX_FORMAT_BGR:
68 return 3;
69 case CRT_PIX_FORMAT_ARGB:
70 case CRT_PIX_FORMAT_RGBA:
71 case CRT_PIX_FORMAT_ABGR:
72 case CRT_PIX_FORMAT_BGRA:
73 return 4;
74 default:
75 return 0;
5976 }
6077 }
6178
221238 /*****************************************************************************/
222239
223240 extern void
224 crt_resize(struct CRT *v, int w, int h, unsigned char *out)
241 crt_resize(struct CRT *v, int w, int h, int f, unsigned char *out)
225242 {
226243 v->outw = w;
227244 v->outh = h;
245 v->out_format = f;
228246 v->out = out;
229247 }
230248
238256 v->black_point = 0;
239257 v->white_point = 100;
240258 v->hsync = 0;
241 v->vsync = 0;
242
243 v->scanlines = 0; /* leave gaps between lines if necessary */
244 v->blend = 0; /* blend new field onto previous image */
245
246 // these options were previously #defined in crt_core.h
247 v->crt_do_vsync = 1;
248 v->crt_do_hsync = 1;
249 v->do_vhs_noise = 0;
259 v->vsync = 0;
250260 }
251261
252262 extern void
253 crt_init(struct CRT *v, int w, int h, unsigned char *out)
263 crt_init(struct CRT *v, int w, int h, int f, unsigned char *out)
254264 {
255265 memset(v, 0, sizeof(struct CRT));
256 crt_resize(v, w, h, out);
266 crt_resize(v, w, h, f, out);
257267 crt_reset(v);
258268 v->rn = 194;
259269
292302 int huesn, huecs;
293303 int xnudge = -3, ynudge = 3;
294304 int bright = v->brightness - (BLACK_LEVEL + v->black_point);
295 int pitch;
296
297 pitch = v->outw * BPP;
305 int bpp, pitch;
306 #if CRT_DO_BLOOM
307 int prev_e; /* filtered beam energy per scan line */
308 int max_e; /* approx maximum energy in a scan line */
309 #endif
310
311 bpp = crt_bpp4fmt(v->out_format);
312 if (bpp == 0) {
313 return;
314 }
315 pitch = v->outw * bpp;
298316
299317 crt_sincos14(&huesn, &huecs, ((v->hue % 360) + 33) * 8192 / 180);
300318 huesn >>= 11; /* make 4-bit */
301319 huecs >>= 11;
302320
303321 rn = v->rn;
304 if(!v->crt_do_vsync)
305 {
306 /* determine field before we add noise,
307 * otherwise it's not reliably recoverable
308 */
309 for (i = -CRT_VSYNC_WINDOW; i < CRT_VSYNC_WINDOW; i++) {
310 line = POSMOD(v->vsync + i, CRT_VRES);
311 sig = v->analog + line * CRT_HRES;
312 s = 0;
313 for (j = 0; j < CRT_HRES; j++) {
314 s += sig[j];
315 if (s <= (CRT_VSYNC_THRESH * SYNC_LEVEL)) {
316 goto found_field;
317 }
322 #if !CRT_DO_VSYNC
323 /* determine field before we add noise,
324 * otherwise it's not reliably recoverable
325 */
326 for (i = -CRT_VSYNC_WINDOW; i < CRT_VSYNC_WINDOW; i++) {
327 line = POSMOD(v->vsync + i, CRT_VRES);
328 sig = v->analog + line * CRT_HRES;
329 s = 0;
330 for (j = 0; j < CRT_HRES; j++) {
331 s += sig[j];
332 if (s <= (CRT_VSYNC_THRESH * SYNC_LEVEL)) {
333 goto found_field;
318334 }
319335 }
320 found_field:
321 /* if vsync signal was in second half of line, odd field */
322 field = (j > (CRT_HRES / 2));
323 v->vsync = -3;
324 }
325 if(v->do_vhs_noise)
326 {
327 line = ((rand() % 8) - 4) + 14;
328 }
336 }
337 found_field:
338 /* if vsync signal was in second half of line, odd field */
339 field = (j > (CRT_HRES / 2));
340 v->vsync = -3;
341 #endif
342 #if ((CRT_SYSTEM == CRT_SYSTEM_NTSCVHS) && CRT_VHS_NOISE)
343 line = ((rand() % 8) - 4) + 14;
344 #endif
329345 for (i = 0; i < CRT_INPUT_SIZE; i++) {
330346 int nn = noise;
331 if(v->do_vhs_noise)
332 {
333 rn = rand();
334 if (i > (CRT_INPUT_SIZE - CRT_HRES * (16 + ((rand() % 20) - 10))) &&
335 i < (CRT_INPUT_SIZE - CRT_HRES * (5 + ((rand() % 8) - 4)))) {
336 int ln, sn, cs;
337
338 ln = (i * line) / CRT_HRES;
339 crt_sincos14(&sn, &cs, ln * 8192 / 180);
340 nn = cs >> 8;
341 }
342 }
343 else
344 {
345 rn = (214019 * rn + 140327895);
346 }
347 #if ((CRT_SYSTEM == CRT_SYSTEM_NTSCVHS) && CRT_VHS_NOISE)
348 rn = rand();
349 if (i > (CRT_INPUT_SIZE - CRT_HRES * (16 + ((rand() % 20) - 10))) &&
350 i < (CRT_INPUT_SIZE - CRT_HRES * (5 + ((rand() % 8) - 4)))) {
351 int ln, sn, cs;
352
353 ln = (i * line) / CRT_HRES;
354 crt_sincos14(&sn, &cs, ln * 8192 / 180);
355 nn = cs >> 8;
356 }
357 #else
358 rn = (214019 * rn + 140327895);
359 #endif
347360 /* signal + noise */
348361 s = v->analog[i] + (((((rn >> 16) & 0xff) - 0x7f) * nn) >> 8);
349362 if (s > 127) { s = 127; }
352365 }
353366 v->rn = rn;
354367
355 if(v->crt_do_vsync)
356 {
357 /* Look for vertical sync.
358 *
359 * This is done by integrating the signal and
360 * seeing if it exceeds a threshold. The threshold of
361 * the vertical sync pulse is much higher because the
362 * vsync pulse is a lot longer than the hsync pulse.
363 * The signal needs to be integrated to lessen
364 * the noise in the signal.
365 */
366 for (i = -CRT_VSYNC_WINDOW; i < CRT_VSYNC_WINDOW; i++) {
367 line = POSMOD(v->vsync + i, CRT_VRES);
368 sig = v->inp + line * CRT_HRES;
369 s = 0;
370 for (j = 0; j < CRT_HRES; j++) {
371 s += sig[j];
372 /* increase the multiplier to make the vsync
373 * more stable when there is a lot of noise
374 */
375 if (s <= (CRT_VSYNC_THRESH * SYNC_LEVEL)) {
376 goto vsync_found;
377 }
368 #if CRT_DO_VSYNC
369 /* Look for vertical sync.
370 *
371 * This is done by integrating the signal and
372 * seeing if it exceeds a threshold. The threshold of
373 * the vertical sync pulse is much higher because the
374 * vsync pulse is a lot longer than the hsync pulse.
375 * The signal needs to be integrated to lessen
376 * the noise in the signal.
377 */
378 for (i = -CRT_VSYNC_WINDOW; i < CRT_VSYNC_WINDOW; i++) {
379 line = POSMOD(v->vsync + i, CRT_VRES);
380 sig = v->inp + line * CRT_HRES;
381 s = 0;
382 for (j = 0; j < CRT_HRES; j++) {
383 s += sig[j];
384 /* increase the multiplier to make the vsync
385 * more stable when there is a lot of noise
386 */
387 if (s <= (CRT_VSYNC_THRESH * SYNC_LEVEL)) {
388 goto vsync_found;
378389 }
379390 }
380 vsync_found:
381 v->vsync = line; /* vsync found (or gave up) at this line */
382 /* if vsync signal was in second half of line, odd field */
383 field = (j > (CRT_HRES / 2));
384 }
385
391 }
392 vsync_found:
393 v->vsync = line; /* vsync found (or gave up) at this line */
394 /* if vsync signal was in second half of line, odd field */
395 field = (j > (CRT_HRES / 2));
396 #endif
397
398 #if CRT_DO_BLOOM
399 max_e = (128 + (noise / 2)) * AV_LEN;
400 prev_e = (16384 / 8);
401 #endif
386402 /* ratio of output height to active video lines in the signal */
387403 ratio = (v->outh << 16) / CRT_LINES;
388404 ratio = (ratio + 32768) >> 16;
404420 int xpos, ypos;
405421 int beg, end;
406422 int phasealign;
423 #if CRT_DO_BLOOM
424 int line_w;
425 #endif
407426
408427 beg = (line - CRT_TOP + 0) * (v->outh + v->v_fac) / CRT_LINES + field;
409428 end = (line - CRT_TOP + 1) * (v->outh + v->v_fac) / CRT_LINES + field;
423442 break;
424443 }
425444 }
426 if(v->crt_do_hsync)
427 {
428 v->hsync = POSMOD(i + v->hsync, CRT_HRES);
429 }
430 else
431 {
432 v->hsync = 0;
433 }
445 #if CRT_DO_HSYNC
446 v->hsync = POSMOD(i + v->hsync, CRT_HRES);
447 #else
448 v->hsync = 0;
449 #endif
434450
435451 xpos = POSMOD(AV_BEG + v->hsync + xnudge, CRT_HRES);
436452 ypos = POSMOD(line + v->vsync + ynudge, CRT_VRES);
492508 }
493509 #endif
494510 sig = v->inp + pos;
495
511 #if CRT_DO_BLOOM
512 s = 0;
513 for (i = 0; i < AV_LEN; i++) {
514 s += sig[i]; /* sum up the scan line */
515 }
516 /* bloom emulation */
517 prev_e = (prev_e * 123 / 128) + ((((max_e >> 1) - s) << 10) / max_e);
518 line_w = (AV_LEN * 112 / 128) + (prev_e >> 9);
519
520 dx = (line_w << 12) / v->outw;
521 scanL = ((AV_LEN / 2) - (line_w >> 1) + 8) << 12;
522 scanR = (AV_LEN - 1) << 12;
523
524 L = (scanL >> 12);
525 R = (scanR >> 12);
526 #else
496527 dx = ((AV_LEN - 1) << 12) / v->outw;
497528 scanL = 0;
498529 scanR = (AV_LEN - 1) << 12;
499530 L = 0;
500 R = AV_LEN;
501
531 R = AV_LEN;
532 #endif
502533 reset_eq(&eqY);
503534 reset_eq(&eqI);
504535 reset_eq(&eqQ);
551582
552583 if (v->blend) {
553584 aa = (r << 16 | g << 8 | b);
554 bb = cL[0] << 16 | cL[1] << 8 | cL[2];
555
585
586 switch (v->out_format) {
587 case CRT_PIX_FORMAT_RGB:
588 case CRT_PIX_FORMAT_RGBA:
589 bb = cL[0] << 16 | cL[1] << 8 | cL[2];
590 break;
591 case CRT_PIX_FORMAT_BGR:
592 case CRT_PIX_FORMAT_BGRA:
593 bb = cL[2] << 16 | cL[1] << 8 | cL[0];
594 break;
595 case CRT_PIX_FORMAT_ARGB:
596 bb = cL[1] << 16 | cL[2] << 8 | cL[3];
597 break;
598 case CRT_PIX_FORMAT_ABGR:
599 bb = cL[3] << 16 | cL[2] << 8 | cL[1];
600 break;
601 default:
602 bb = 0;
603 break;
604 }
556605
557606 /* blend with previous color there */
558607 bb = (((aa & 0xfefeff) >> 1) + ((bb & 0xfefeff) >> 1));
560609 bb = (r << 16 | g << 8 | b);
561610 }
562611
563 cL[0] = bb >> 16 & 0xff;
564 cL[1] = bb >> 8 & 0xff;
565 cL[2] = bb >> 0 & 0xff;
566 cL[3] = 0xff;
567
568 cL += BPP;
612 switch (v->out_format) {
613 case CRT_PIX_FORMAT_RGB:
614 cL[0] = bb >> 16 & 0xff;
615 cL[1] = bb >> 8 & 0xff;
616 cL[2] = bb >> 0 & 0xff;
617 break;
618
619 case CRT_PIX_FORMAT_RGBA:
620 cL[0] = bb >> 16 & 0xff;
621 cL[1] = bb >> 8 & 0xff;
622 cL[2] = bb >> 0 & 0xff;
623 cL[3] = 0xff;
624 break;
625
626 case CRT_PIX_FORMAT_BGR:
627 cL[0] = bb >> 0 & 0xff;
628 cL[1] = bb >> 8 & 0xff;
629 cL[2] = bb >> 16 & 0xff;
630 break;
631
632 case CRT_PIX_FORMAT_BGRA:
633 cL[0] = bb >> 0 & 0xff;
634 cL[1] = bb >> 8 & 0xff;
635 cL[2] = bb >> 16 & 0xff;
636 cL[3] = 0xff;
637 break;
638
639 case CRT_PIX_FORMAT_ARGB:
640 cL[0] = 0xff;
641 cL[1] = bb >> 16 & 0xff;
642 cL[2] = bb >> 8 & 0xff;
643 cL[3] = bb >> 0 & 0xff;
644 break;
645
646 case CRT_PIX_FORMAT_ABGR:
647 cL[0] = 0xff;
648 cL[1] = bb >> 0 & 0xff;
649 cL[2] = bb >> 8 & 0xff;
650 cL[3] = bb >> 16 & 0xff;
651 break;
652
653 default:
654 break;
655 }
656
657 cL += bpp;
569658 }
570659
571660 /* duplicate extra lines */
1717 /* crt_core.h
1818 *
1919 * The demodulator. This is also where you can define which system to emulate.
20 *
20 *
2121 */
22
22
2323 /* library version */
2424 #define CRT_MAJOR 2
2525 #define CRT_MINOR 3
2626 #define CRT_PATCH 2
2727
28 #include "crt_ntsc.h"
29
30 // frei0r always uses 4 bits per pixel so it is pointless for there to be any other possibilities
31 #define BPP 4
28
29 #define CRT_SYSTEM_NTSC 0 /* standard NTSC */
30 #define CRT_SYSTEM_NES 1 /* decode 6 or 9-bit NES pixels */
31 #define CRT_SYSTEM_PV1K 2 /* Casio PV-1000 */
32 #define CRT_SYSTEM_SNES 3 /* SNES - uses RGB */
33 #define CRT_SYSTEM_TEMP 4 /* template implementation */
34 #define CRT_SYSTEM_NTSCVHS 5 /* standard NTSC VHS */
35 #define CRT_SYSTEM_NESRGB 6 /* encode RGB image with NES artifacts */
36
37 /* the system to be compiled */
38 #ifndef CRT_SYSTEM
39 #define CRT_SYSTEM CRT_SYSTEM_NTSC
40 #endif
41
42 #if (CRT_SYSTEM == CRT_SYSTEM_NES)
43 #include "crt_nes.h"
44 #elif (CRT_SYSTEM == CRT_SYSTEM_SNES)
45 #include "crt_snes.h"
46 #elif (CRT_SYSTEM == CRT_SYSTEM_NTSC)
47 #include "crt_ntsc.h"
48 #elif (CRT_SYSTEM == CRT_SYSTEM_PV1K)
49 #include "crt_pv1k.h"
50 #elif (CRT_SYSTEM == CRT_SYSTEM_TEMP)
51 #include "crt_template.h"
52 #elif (CRT_SYSTEM == CRT_SYSTEM_NTSCVHS)
53 #include "crt_ntscvhs.h"
54 #elif (CRT_SYSTEM == CRT_SYSTEM_NESRGB)
55 #include "crt_nesrgb.h"
56 #else
57 #error No system defined
58 #endif
59
60 /* NOTE: this library does not use the alpha channel at all */
61 #define CRT_PIX_FORMAT_RGB 0 /* 3 bytes per pixel [R,G,B,R,G,B,R,G,B...] */
62 #define CRT_PIX_FORMAT_BGR 1 /* 3 bytes per pixel [B,G,R,B,G,R,B,G,R...] */
63 #define CRT_PIX_FORMAT_ARGB 2 /* 4 bytes per pixel [A,R,G,B,A,R,G,B...] */
64 #define CRT_PIX_FORMAT_RGBA 3 /* 4 bytes per pixel [R,G,B,A,R,G,B,A...] */
65 #define CRT_PIX_FORMAT_ABGR 4 /* 4 bytes per pixel [A,B,G,R,A,B,G,R...] */
66 #define CRT_PIX_FORMAT_BGRA 5 /* 4 bytes per pixel [B,G,R,A,B,G,R,A...] */
67
68 /* do bloom emulation (side effect: makes screen have black borders) */
69 #define CRT_DO_BLOOM 0 /* does not work for NES */
70 #define CRT_DO_VSYNC 1 /* look for VSYNC */
71 #define CRT_DO_HSYNC 1 /* look for HSYNC */
3272
3373 struct CRT {
3474 signed char analog[CRT_INPUT_SIZE];
3575 signed char inp[CRT_INPUT_SIZE]; /* CRT input, can be noisy */
3676
3777 int outw, outh; /* output width/height */
78 int out_format; /* output pixel format (one of the CRT_PIX_FORMATs) */
3879 unsigned char *out; /* output image */
3980
4081 int hue, brightness, contrast, saturation; /* common monitor settings */
4182 int black_point, white_point; /* user-adjustable */
4283 int scanlines; /* leave gaps between lines if necessary */
4384 int blend; /* blend new field onto previous image */
44 unsigned v_fac; /* factor to stretch img vertically onto the output img */
45
46 // these options were previously #defined in crt_core.h
47 int crt_do_vsync;
48 int crt_do_hsync;
49 int do_vhs_noise; /* 0 = no additional vhs noise, 1 = with additional vhs noise */
85 unsigned v_fac; /* factor to stretch img vertically onto the output img */
5086
5187 /* internal data */
5288 int ccf[CRT_CC_VPER][CRT_CC_SAMPLES]; /* faster color carrier convergence */
6096 * f - format of the output image
6197 * out - pointer to output image data
6298 */
63 extern void crt_init(struct CRT *v, int w, int h, unsigned char *out);
99 extern void crt_init(struct CRT *v, int w, int h, int f, unsigned char *out);
64100
65101 /* Updates the output image parameters
66102 * w - width of the output image
68104 * f - format of the output image
69105 * out - pointer to output image data
70106 */
71 extern void crt_resize(struct CRT *v, int w, int h, unsigned char *out);
107 extern void crt_resize(struct CRT *v, int w, int h, int f, unsigned char *out);
72108
73109 /* Resets the CRT settings back to their defaults */
74110 extern void crt_reset(struct CRT *v);
77113 * s - struct containing settings to apply to this field
78114 */
79115 extern void crt_modulate(struct CRT *v, struct NTSC_SETTINGS *s);
80
116
81117 /* Demodulates the NTSC signal generated by crt_modulate()
82118 * noise - the amount of noise added to the signal (0 - inf)
83119 */
84120 extern void crt_demodulate(struct CRT *v, int noise);
121
122 /* Get the bytes per pixel for a certain CRT_PIX_FORMAT_
123 *
124 * format - the format to get the bytes per pixel for
125 *
126 * returns 0 if the specified format does not exist
127 */
128 extern int crt_bpp4fmt(int format);
85129
86130 /*****************************************************************************/
87131 /*************************** FIXED POINT SIN/COS *****************************/
00 /*****************************************************************************/
11 /*
22 * NTSC/CRT - integer-only NTSC video signal encoding / decoding emulation
3 *
3 *
44 * by EMMIR 2018-2023
5 *
5 *
66 * YouTube: https://www.youtube.com/@EMMIR_KC/videos
77 * Discord: https://discord.com/invite/hdYctSmyQJ
88 */
1010
1111 #include "crt_core.h"
1212
13 #if (CRT_SYSTEM == CRT_SYSTEM_NTSCVHS)
13 #if (CRT_SYSTEM == CRT_SYSTEM_NTSC)
1414 #include <stdlib.h>
1515 #include <string.h>
1616
3434 15133, /* e^2 */
3535 41135, /* e^3 */
3636 111817 /* e^4 */
37 };
37 };
3838
3939 /* fixed point e^x */
4040 static int
6060 if (idx > 0) {
6161 res = EXP_MUL(res, e11[idx]);
6262 }
63
63
6464 n &= EXP_MASK;
6565 nxt = EXP_ONE;
6666 acc = 0;
9898 init_iir(struct IIRLP *f, int freq, int limit)
9999 {
100100 int rate; /* cycles/pixel rate */
101
101
102102 memset(f, 0, sizeof(struct IIRLP));
103103 rate = (freq << 9) / limit;
104104 f->c = EXP_ONE - expx(-((EXP_PI << 9) / rate));
136136 int ccburst[CRT_CC_SAMPLES]; /* color phase for burst */
137137 int sn, cs, n, ph;
138138 int inv_phase = 0;
139 int aberration = 0;
139 int bpp;
140140
141141 if (!s->iirs_initialized) {
142 int y_freq = Y_FREQ_OFF;
143 int i_freq = I_FREQ_OFF;
144 int q_freq = Q_FREQ_OFF;
145
146 switch(s->vhs_mode)
147 {
148 case VHS_OFF:
149 break;
150 case VHS_SP:
151 y_freq = Y_FREQ_SP;
152 i_freq = I_FREQ_SP;
153 q_freq = Q_FREQ_SP;
154 break;
155 case VHS_LP:
156 y_freq = Y_FREQ_LP;
157 i_freq = I_FREQ_LP;
158 q_freq = Q_FREQ_LP;
159 break;
160 case VHS_EP:
161 y_freq = Y_FREQ_EP;
162 i_freq = I_FREQ_EP;
163 q_freq = Q_FREQ_EP;
164 break;
165 default:
166 break;
167 }
168
169 init_iir(&iirY, L_FREQ, y_freq);
170 init_iir(&iirI, L_FREQ, i_freq);
171 init_iir(&iirQ, L_FREQ, q_freq);
142 init_iir(&iirY, L_FREQ, Y_FREQ);
143 init_iir(&iirI, L_FREQ, I_FREQ);
144 init_iir(&iirQ, L_FREQ, Q_FREQ);
172145 s->iirs_initialized = 1;
173146 }
147 #if CRT_DO_BLOOM
148 if (s->raw) {
149 destw = s->w;
150 desth = s->h;
151 if (destw > ((AV_LEN * 55500) >> 16)) {
152 destw = ((AV_LEN * 55500) >> 16);
153 }
154 if (desth > ((CRT_LINES * 63500) >> 16)) {
155 desth = ((CRT_LINES * 63500) >> 16);
156 }
157 } else {
158 destw = (AV_LEN * 55500) >> 16;
159 desth = (CRT_LINES * 63500) >> 16;
160 }
161 #else
174162 if (s->raw) {
175163 destw = s->w;
176164 desth = s->h;
181169 desth = ((CRT_LINES * 64500) >> 16);
182170 }
183171 }
184
172 #endif
185173 if (s->as_color) {
186174 for (x = 0; x < CRT_CC_SAMPLES; x++) {
187175 n = s->hue + x * (360 / CRT_CC_SAMPLES);
197185 memset(ccmodI, 0, sizeof(ccmodI));
198186 memset(ccmodQ, 0, sizeof(ccmodQ));
199187 }
200
188
189 bpp = crt_bpp4fmt(s->format);
190 if (bpp == 0) {
191 return; /* just to be safe */
192 }
201193 xo = AV_BEG + s->xoffset + (AV_LEN - destw) / 2;
202194 yo = CRT_TOP + s->yoffset + (CRT_LINES - desth) / 2;
203
195
204196 s->field &= 1;
205197 s->frame &= 1;
206198 inv_phase = (s->field == s->frame);
208200
209201 /* align signal */
210202 xo = (xo & ~3);
211 if (s->do_aberration) {
212 aberration = ((rand() % 12) - 8) + 14;
213 }
203
214204 for (n = 0; n < CRT_VRES; n++) {
215205 int t; /* time */
216206 signed char *line = &v->analog[n * CRT_HRES];
217
207
218208 t = LINE_BEG;
219209
220210 if (n <= 3 || (n >= 7 && n <= 9)) {
237227 while (t < (offs[3] * CRT_HRES / 100)) line[t++] = BLANK_LEVEL;
238228 } else {
239229 int cb;
240 if (n < (CRT_VRES - aberration)) {
241 /* video line */
242 while (t < SYNC_BEG) line[t++] = BLANK_LEVEL; /* FP */
243 while (t < BW_BEG) line[t++] = SYNC_LEVEL; /* SYNC */
244 }
230
231 /* video line */
232 while (t < SYNC_BEG) line[t++] = BLANK_LEVEL; /* FP */
233 while (t < BW_BEG) line[t++] = SYNC_LEVEL; /* SYNC */
245234 while (t < AV_BEG) line[t++] = BLANK_LEVEL; /* BW + CB + BP */
246
247235 if (n < CRT_TOP) {
248236 while (t < CRT_HRES) line[t++] = BLANK_LEVEL;
249237 }
260248 iccf[t % CRT_CC_SAMPLES] = line[t];
261249 }
262250 }
263 }
264
265 if(s->vhs_mode != VHS_OFF)
266 {
267 /* reset hsync every frame so only the bottom part is warped */
268 v->hsync = 0;
269251 }
270252
271253 for (y = 0; y < desth; y++) {
272254 int field_offset;
273255 int sy;
274
256
275257 field_offset = (s->field * s->h + desth) / desth / 2;
276258 sy = (y * s->h) / desth;
277
259
278260 sy += field_offset;
279261
280262 if (sy >= s->h) sy = s->h;
281
263
282264 sy *= s->w;
283
265
284266 reset_iir(&iirY);
285267 reset_iir(&iirI);
286268 reset_iir(&iirQ);
287
269
288270 for (x = 0; x < destw; x++) {
289271 int fy, fi, fq;
290272 int rA, gA, bA;
291273 const unsigned char *pix;
292274 int ire; /* composite signal */
293275 int xoff;
294
295 pix = s->data + ((((x * s->w) / destw) + sy) * BPP);
296 rA = pix[0];
297 gA = pix[1];
298 bA = pix[2];
299
276
277 pix = s->data + ((((x * s->w) / destw) + sy) * bpp);
278 switch (s->format) {
279 case CRT_PIX_FORMAT_RGB:
280 case CRT_PIX_FORMAT_RGBA:
281 rA = pix[0];
282 gA = pix[1];
283 bA = pix[2];
284 break;
285 case CRT_PIX_FORMAT_BGR:
286 case CRT_PIX_FORMAT_BGRA:
287 rA = pix[2];
288 gA = pix[1];
289 bA = pix[0];
290 break;
291 case CRT_PIX_FORMAT_ARGB:
292 rA = pix[1];
293 gA = pix[2];
294 bA = pix[3];
295 break;
296 case CRT_PIX_FORMAT_ABGR:
297 rA = pix[3];
298 gA = pix[2];
299 bA = pix[1];
300 break;
301 default:
302 rA = gA = bA = 0;
303 break;
304 }
300305
301306 /* RGB to YIQ */
302307 fy = (19595 * rA + 38470 * gA + 7471 * bA) >> 14;
303308 fi = (39059 * rA - 18022 * gA - 21103 * bA) >> 14;
304309 fq = (13894 * rA - 34275 * gA + 20382 * bA) >> 14;
305310 ire = BLACK_LEVEL + v->black_point;
306
311
307312 xoff = (x + xo) % CRT_CC_SAMPLES;
308313 /* bandlimit Y,I,Q */
309314 fy = iirf(&iirY, fy);
318323 }
319324 for (n = 0; n < CRT_CC_VPER; n++) {
320325 for (x = 0; x < CRT_CC_SAMPLES; x++) {
321 if(s->vhs_mode != VHS_OFF)
322 {
323 v->ccf[n][x] = 0;
324 }
325 else
326 {
327 v->ccf[n][x] = iccf[x] << 7;
328 }
329 }
330 }
331 }
332 #endif
326 v->ccf[n][x] = iccf[x] << 7;
327 }
328 }
329 }
330 #endif
77 * Discord: https://discord.com/invite/hdYctSmyQJ
88 */
99 /*****************************************************************************/
10 #ifndef _CRT_NTSC_VHS_H_
11 #define _CRT_NTSC_VHS_H_
10 #ifndef _CRT_NTSC_H_
11 #define _CRT_NTSC_H_
1212
1313 #ifdef __cplusplus
1414 extern "C" {
1515 #endif
1616
17 /* crt_ntscvhs.h
17 /* crt_ntsc.h
1818 *
19 * An interface to convert a digital image to an analog NTSC signal with VHS
20 * quality and some optional signal aberration at the bottom.
21 *
19 * An interface to convert a digital image to an analog NTSC signal.
20 *
2221 */
2322 /* 0 = vertical chroma (228 chroma clocks per line) */
2423 /* 1 = checkered chroma (227.5 chroma clocks per line) */
4140 #define CRT_TOP 21 /* first line with active video */
4241 #define CRT_BOT 261 /* final line with active video */
4342 #define CRT_LINES (CRT_BOT - CRT_TOP) /* number of active video lines */
44
43
4544 #define CRT_CC_SAMPLES 4 /* samples per chroma period (samples per 360 deg) */
4645 #define CRT_CC_VPER 1 /* vertical period in which the artifacts repeat */
4746
6160 * |---------------------------------------------------------------------------|
6261 * HBLANK (~10900 ns) ACTIVE VIDEO (~52600 ns)
6362 * |-------------------||------------------------------------------------------|
64 *
65 *
63 *
64 *
6665 * WITHIN HBLANK PERIOD:
67 *
66 *
6867 * FP (~1500 ns) SYNC (~4700 ns) BW (~600 ns) CB (~2500 ns) BP (~1600 ns)
6968 * |--------------||---------------||------------||-------------||-------------|
7069 * BLANK SYNC BLANK BLANK BLANK
71 *
70 *
7271 */
7372 #define LINE_BEG 0
7473 #define FP_ns 1500 /* front porch */
9493
9594 /* somewhere between 7 and 12 cycles */
9695 #define CB_CYCLES 10
97
98 #define VHS_OFF 0
99 #define VHS_SP 1
100 #define VHS_LP 2
101 #define VHS_EP 3
10296
103 #define VHS_MODE VHS_OFF
104
105 /* frequencies for bandlimiting */
106 #define L_FREQ 1431818 /* full line */
107
108 #define Y_FREQ_OFF 420000 /* Luma (Y) 4.2 MHz of the 14.31818 MHz */
109 #define I_FREQ_OFF 150000 /* Chroma (I) 1.5 MHz of the 14.31818 MHz */
110 #define Q_FREQ_OFF 55000 /* Chroma (Q) 0.55 MHz of the 14.31818 MHz */
111
112 #define Y_FREQ_SP 300000 /* Luma (Y) 3.0 MHz of the 14.31818 MHz */
113 #define I_FREQ_SP 62700 /* Chroma (I) 627 kHz of the 14.31818 MHz */
114 #define Q_FREQ_SP 62700 /* Chroma (Q) 627 kHz of the 14.31818 MHz */
115
116 #define Y_FREQ_LP 240000 /* Luma (Y) 2.4 MHz of the 14.31818 MHz */
117 #define I_FREQ_LP 40000 /* Chroma (I) 400 kHz of the 14.31818 MHz */
118 #define Q_FREQ_LP 40000 /* Chroma (Q) 400 kHz of the 14.31818 MHz */
119
120 #define Y_FREQ_EP 200000 /* Luma (Y) 2.0 MHz of the 14.31818 MHz */
121 #define I_FREQ_EP 37000 /* Chroma (I) 370 kHz of the 14.31818 MHz */
122 #define Q_FREQ_EP 37000 /* Chroma (Q) 370 kHz of the 14.31818 MHz */
123
97 /* frequencies for bandlimiting */
98 #define L_FREQ 1431818 /* full line */
99 #define Y_FREQ 420000 /* Luma (Y) 4.2 MHz of the 14.31818 MHz */
100 #define I_FREQ 150000 /* Chroma (I) 1.5 MHz of the 14.31818 MHz */
101 #define Q_FREQ 55000 /* Chroma (Q) 0.55 MHz of the 14.31818 MHz */
124102
125103 /* IRE units (100 = 1.0V, -40 = 0.0V) */
126104 #define WHITE_LEVEL 100
131109
132110 struct NTSC_SETTINGS {
133111 const unsigned char *data; /* image data */
112 int format; /* pix format (one of the CRT_PIX_FORMATs in crt_core.h) */
134113 int w, h; /* width and height of image */
135114 int raw; /* 0 = scale image to fit monitor, 1 = don't scale */
136115 int as_color; /* 0 = monochrome, 1 = full color */
139118 int hue; /* 0-359 */
140119 int xoffset; /* x offset in sample space. 0 is minimum value */
141120 int yoffset; /* y offset in # of lines. 0 is minimum value */
142 int do_aberration; /* 0 = no aberration, 1 = with aberration */
143
144 // these are changed by the vhs mode
145 int vhs_mode;
146 int y_freq;
147 int i_freq;
148 int q_freq;
149
150121 /* make sure your NTSC_SETTINGS struct is zeroed out before you do anything */
151122 int iirs_initialized; /* internal state */
152123 };
00 #include <stdlib.h>
1 #include <string.h>
12
23 #include "frei0r.h"
34 #include "frei0r/math.h"
45
56 #include "crt_core.h"
67
7 // the actual NTSC emulation code is modified from here: https://github.com/LMP88959/NTSC-CRT
8 // the actual NTSC emulation code is from here: https://github.com/LMP88959/NTSC-CRT
9
810
911 typedef struct ntsc_instance
1012 {
1416
1517 // parameters
1618 struct CRT crt;
17 struct NTSC_SETTINGS ntsc_settings;
19 struct NTSC_SETTINGS ntsc;
1820
1921 int noise;
20 double vhs_speed;
21
2222 int field;
2323 int progressive;
2424
2525 } ntsc_instance_t;
26
2627
2728 // these functions are for frei0r
2829 // mostly copy/paste/slightly modified from the other frei0r effects
4344 info->color_model = F0R_COLOR_MODEL_RGBA8888;
4445 info->frei0r_version = FREI0R_MAJOR_VERSION;
4546 info->major_version = 0;
46 info->minor_version = 1;
47 info->num_params = 8;
47 info->minor_version = 2;
48 info->num_params = 3;
4849 }
4950
5051 void f0r_get_param_info(f0r_param_info_t* info, int param_index)
5657 info->explanation = "Amount of noise introduced into the NTSC signal.";
5758 info->type = F0R_PARAM_DOUBLE;
5859 break;
59
60
6061 case 1:
61 info->name = "VHS Speed";
62 info->explanation = "Simulates VHS. 0 = off, 1 = SP, 2 = LP, 3 = EP";
63 info->type = F0R_PARAM_DOUBLE;
64 break;
65
66 case 2:
67 info->name = "VHS Noise";
68 info->explanation = "Toggles VHS noise at the bottom of the screen";
69 info->type = F0R_PARAM_BOOL;
70 break;
71
72 case 3:
73 info->name = "Aberration";
74 info->explanation = "Toggles VHS aberration at the bottom of the screen. Not visible if V-sync is on.";
75 info->type = F0R_PARAM_BOOL;
76 break;
77
78 case 4:
79 info->name = "Force V-sync";
80 info->explanation = "Forces V-sync even when the signal is really noisy.";
81 info->type = F0R_PARAM_BOOL;
82 break;
83
84 case 5:
85 info->name = "Force H-sync";
86 info->explanation = "Forces V-sync even when the signal is really noisy.";
87 info->type = F0R_PARAM_BOOL;
88 break;
89
90 case 6:
9162 info->name = "Progressive Scan";
9263 info->explanation = "Toggles progressive scan (Interlaced if off).";
9364 info->type = F0R_PARAM_BOOL;
9465 break;
9566
96 case 7:
97 info->name = "Blend";
98 info->explanation = "Blends frames.";
67 case 2:
68 info->name = "Scanlines";
69 info->explanation = "Draw borders between scanlines.";
9970 info->type = F0R_PARAM_BOOL;
10071 break;
10172 }
10273 }
74
10375
10476 f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
10577 {
10880 inst->width = width;
10981 inst->height = height;
11082
111 inst->vhs_speed = 0.0;
83 inst->ntsc.format = CRT_PIX_FORMAT_RGBA;
84 inst->ntsc.w = width;
85 inst->ntsc.h = height;
86 inst->ntsc.raw = 0;
87 inst->ntsc.field = 0;
88 inst->ntsc.frame = 0;
89 inst->ntsc.as_color = 1;
90 inst->ntsc.hue = 0;
91 inst->ntsc.xoffset = 0;
92 inst->ntsc.yoffset = 0;
93 inst->ntsc.iirs_initialized = 0;
94
95 inst->noise = 0;
96 inst->progressive = 0;
11297 inst->field = 0;
113 inst->progressive = 1;
11498
115 crt_init(&(inst->crt), width, height, NULL);
99 crt_init(&(inst->crt), width, height, CRT_PIX_FORMAT_RGBA, NULL);
100 inst->crt.blend = 0;
101 inst->crt.scanlines = 0;
102
116103
117 // init NTSC_SETTINGS
118 inst->ntsc_settings.data = NULL;
119 inst->ntsc_settings.w = width;
120 inst->ntsc_settings.h = height;
121 inst->ntsc_settings.raw = 0;
122 inst->ntsc_settings.as_color = 1;
123 inst->ntsc_settings.field = 0;
124 inst->ntsc_settings.frame = 0;
125 inst->ntsc_settings.hue = 0;
126 inst->ntsc_settings.xoffset = 0;
127 inst->ntsc_settings.yoffset = 0;
128 inst->ntsc_settings.do_aberration = 0;
129
130 // these are changed by the vhs mode
131 inst->ntsc_settings.vhs_mode = 0;
132 inst->ntsc_settings.y_freq = 0;
133 inst->ntsc_settings.i_freq = 0;
134 inst->ntsc_settings.q_freq = 0;
135
136 /* make sure your NTSC_SETTINGS struct is zeroed out before you do anything */
137 inst->ntsc_settings.iirs_initialized = 0;
138
139 inst->noise = 0;
140
104
141105 return (f0r_instance_t)inst;
142106 }
143107
154118 switch(param_index)
155119 {
156120 case 0:
157 inst->noise = *((double*)param) * 100;
121 inst->noise = *((double*)param) * 200;
158122 break;
159123 case 1:
160 inst->ntsc_settings.vhs_mode = (int)CLAMP(*((double*)param) * 4, 0, 4);
161 inst->ntsc_settings.iirs_initialized = 0;
124 inst->progressive = (*((double*)param) >= 0.5);
162125 break;
163126 case 2:
164 inst->crt.do_vhs_noise = (*((double*)param) >= 0.5);
165 break;
166 case 3:
167 inst->ntsc_settings.do_aberration = (*((double*)param) >= 0.5);
168 break;
169 case 4:
170 inst->crt.crt_do_vsync = !(*((double*)param) >= 0.5);
171 break;
172 case 5:
173 inst->crt.crt_do_hsync = !(*((double*)param) >= 0.5);
174 break;
175 case 6:
176 inst->progressive = (*((double*)param) >= 0.5);
177 break;
178 case 7:
179 inst->crt.blend = (*((double*)param) >= 0.5);
127 inst->crt.scanlines = (*((double*)param) >= 0.5);
180128 break;
181129 }
182130 }
187135 switch(param_index)
188136 {
189137 case 0:
190 *((double*)param) = (inst->noise / 100);
138 *((double*)param) = (inst->noise / 200);
191139 break;
192140 case 1:
193 *((double*)param) = (inst->ntsc_settings.vhs_mode / 4);
141 *((double*)param) = (inst->progressive ? 1.0 : 0.0);
194142 break;
195143 case 2:
196 *((double*)param) = (inst->crt.do_vhs_noise ? 1.0 : 0.0);
197 break;
198 case 3:
199 *((double*)param) = (inst->ntsc_settings.do_aberration ? 1.0 : 0.0);
200 break;
201 case 4:
202 *((double*)param) = !(inst->crt.crt_do_vsync ? 1.0 : 0.0);
203 break;
204 case 5:
205 *((double*)param) = !(inst->crt.crt_do_hsync ? 1.0 : 0.0);
206 break;
207 case 6:
208 *((double*)param) = (inst->progressive ? 1.0 : 0.0);
209 break;
210 case 7:
211 *((double*)param) = (inst->crt.blend ? 1.0 : 0.0);
144 *((double*)param) = (inst->crt.scanlines ? 1.0 : 0.0);
212145 break;
213146 }
214147 }
215148
216149
217150 void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, uint32_t* outframe)
218 {
151 {
219152 ntsc_instance_t* inst = (ntsc_instance_t*)instance;
153
154 // clear the output frame
155 memset(outframe, 0, inst->width * inst->height * sizeof(uint32_t));
156 inst->crt.blend = 0;
157
158 // set everything up for the simulation
159 inst->crt.out = (char*)outframe;
160 inst->ntsc.data = (const char*)inframe;
220161
221 inst->crt.out = (char*)outframe;
222 inst->ntsc_settings.data = (const char*)inframe;
162 _render_field:
163 inst->ntsc.field = inst->field & 1;
223164
224 inst->ntsc_settings.field = inst->field & 1;
225 if (inst->ntsc_settings.field == 0) {
165 if (inst->ntsc.field == 0) {
226166 /* a frame is two fields */
227 inst->ntsc_settings.frame ^= 1;
167 inst->ntsc.frame ^= 1;
228168 }
229169
230 crt_modulate(&(inst->crt), &(inst->ntsc_settings));
170 // encode and decode ntsc signal
171 crt_modulate(&(inst->crt), &(inst->ntsc));
231172 crt_demodulate(&(inst->crt), inst->noise);
232 if(!inst->progressive)
173
174 inst->field ^= 1;
175 // if we are in progressive mode, we render both fields onto the frame.
176 // in interlaced mode, we will hit the opposite field on the next frame.
177 if(inst->field && inst->progressive)
233178 {
234 inst->field ^= 1;
179 // if we are not leaving scanlines blank, we will want to blend the frames in progressive mode
180 if(!inst->crt.scanlines)
181 {
182 inst->crt.blend = 1;
183 }
184 goto _render_field;
235185 }
236186 }
127127 case 0:
128128 info->name = "shift_intensity";
129129 info->type = F0R_PARAM_DOUBLE;
130 info->explanation = "Agressiveness of row/column-shifting";
130 info->explanation = "Aggressiveness of row/column-shifting";
131131 break;
132132
133133 case 1:
3737 Invert selection:
3838 When ON, the selected color will be transparent, as normally used
3939 with keying. When OFF (default) the selected color will be opaque,
40 for exmaple for alpha controlled adjustment of that color only.
40 for example for alpha controlled adjustment of that color only.
4141
4242 Delta XXXX:
4343 These three parameters determine the size of the color subspace
00 /*
1 * This file is contains sigmoidal transfer function from file plug-ins/common/softglow.c in gimp.
1 * This file used to contain sigmoidal transfer function from file plug-ins/common/softglow.c in gimp.
2 * However, it is now modified to match ImageMagick; i.e. whereas only the steepness of the sigmoidal
3 * curves was tunable earlier, now the midpoint of the curve is adjustable as well -- both to a degree.
24 *
35 * sigmoidaltransfer.c
4 * Copyright 2012 Janne Liljeblad
6 * Copyright 2012 Janne Liljeblad, 2025 Cynthia
57 *
68 * This file is a Frei0r plugin.
79 *
2729 #include "frei0r.h"
2830 #include "frei0r/math.h"
2931
30 #define SIGMOIDAL_BASE 2
31 #define SIGMOIDAL_RANGE 20
32
3332 typedef struct sigmoidal_instance
3433 {
3534 unsigned int width;
3635 unsigned int height;
37 double brightness;
36 double base;
3837 double sharpness;
38
39 /* Precomputed values of the (scaled and shifted) sigmoid function
40 is stored in this lookup table. */
41 uint8_t lut[256];
3942 } sigmoidal_instance_t;
4043
41 static inline int gimp_rgb_to_l_int (int red,
42 int green,
43 int blue)
44 void gen_sigmoid_lut (uint8_t *const lut, const float base, const float sharpness)
4445 {
45 int min, max;
46 float k = expf(sharpness * 5.0) / 255.0;
47 float b = (base - 0.5) * 63.0;
4648
47 if (red > green)
48 {
49 max = MAX (red, blue);
50 min = MIN (green, blue);
51 }
52 else
53 {
54 max = MAX (green, blue);
55 min = MIN (red, blue);
56 }
57
58 return ROUND ((max + min) / 2.0);
49 for (int i = 0; i < 256; ++i)
50 lut[i] = CLAMP (255.0 / (1.0 + expf(-k * (i - b - 127.0))), 0, 255.0);
5951 }
6052
6153 void sigmoidal_transfer(f0r_instance_t instance, double time,
6456 assert(instance);
6557 sigmoidal_instance_t* inst = (sigmoidal_instance_t*)instance;
6658 unsigned int len = inst->width * inst->height;
67
68 double brightness = inst->brightness;
69 double sharpness = inst->sharpness;
7059
7160 const unsigned char* src = (unsigned char*)inframe;
7261 unsigned char* dst = (unsigned char*)outframe;
8069 b = *src++;
8170
8271 //desaturate
83 luma = (unsigned char) gimp_rgb_to_l_int (r, g, b);
84
72 luma = (unsigned char)(0.299 * r + 0.587 * g + 0.114 * b);
8573 //compute sigmoidal transfer
86 val = luma / 255.0;
87 val = 255.0 / (1 + exp (-(SIGMOIDAL_BASE + (sharpness * SIGMOIDAL_RANGE)) * (val - 0.5)));
88 val = val * brightness;
89 luma = (unsigned char) CLAMP (val, 0, 255);
74 luma = inst->lut[luma];
9075
9176 *dst++ = luma;
9277 *dst++ = luma;
10792 void f0r_get_plugin_info(f0r_plugin_info_t* sigmoidalInfo)
10893 {
10994 sigmoidalInfo->name = "sigmoidaltransfer";
110 sigmoidalInfo->author = "Janne Liljeblad";
95 sigmoidalInfo->author = "Janne Liljeblad & Cynthia";
11196 sigmoidalInfo->plugin_type = F0R_PLUGIN_TYPE_FILTER;
11297 sigmoidalInfo->color_model = F0R_COLOR_MODEL_RGBA8888;
11398 sigmoidalInfo->frei0r_version = FREI0R_MAJOR_VERSION;
114 sigmoidalInfo->major_version = 0;
115 sigmoidalInfo->minor_version = 9;
99 sigmoidalInfo->major_version = 1;
100 sigmoidalInfo->minor_version = 0;
116101 sigmoidalInfo->num_params = 2;
117102 sigmoidalInfo->explanation = "Desaturates image and creates a particular look that could be called Stamp, Newspaper or Photocopy";
118103 }
121106 {
122107 switch ( param_index ) {
123108 case 0:
124 info->name = "brightness";
109 info->name = "base";
125110 info->type = F0R_PARAM_DOUBLE;
126 info->explanation = "Brightnesss of image";
111 info->explanation = "Brightness of image. Midpoint of sigmoidal curve";
127112 break;
128 case 1:
129 info->name = "sharpness";
130 info->type = F0R_PARAM_DOUBLE;
131 info->explanation = "Sharpness of transfer";
132 break;
113 case 1:
114 info->name = "sharpness";
115 info->type = F0R_PARAM_DOUBLE;
116 info->explanation = "Sharpness of transfer";
117 break;
133118 }
134119 }
135120
138123 sigmoidal_instance_t* inst = (sigmoidal_instance_t*)calloc(1, sizeof(*inst));
139124 inst->width = width;
140125 inst->height = height;
141 inst->brightness = 0.75;
142 inst->sharpness = 0.85;
126 inst->base = 0.5;
127 inst->sharpness = 3.0 / 5.0;
128
129 gen_sigmoid_lut (inst->lut, inst->base, inst->sharpness);
143130 return (f0r_instance_t)inst;
144131 }
145132
155142 switch (param_index)
156143 {
157144 case 0:
158 inst->brightness = *((double*)param);
145 inst->base = *((double*)param);
159146 break;
160147 case 1:
161148 inst->sharpness = *((double*)param);
162149 break;
163150 }
151
152 gen_sigmoid_lut (inst->lut, inst->base, inst->sharpness);
164153 }
165154
166155 void f0r_get_param_value(f0r_instance_t instance,
170159 switch (param_index)
171160 {
172161 case 0:
173 *((double*)param) = inst->brightness;
162 *((double*)param) = inst->base;
174163 break;
175164 case 1:
176165 *((double*)param) = inst->sharpness;
131131 uint32_t* out,
132132 const uint32_t* in)
133133 {
134 // Rebuild the lookup table in case the prarameters have changed.
134 // Rebuild the lookup table in case the parameters have changed.
135135 updateLUT();
136136
137137 unsigned char *pixel = (unsigned char *) in;
9090 {
9191 unsigned int width;
9292 unsigned int height;
93 double supress_type; /* type of spill supression applied to image
94 <= 0.5, green supress
95 > 0.5, blue supress */
93 double supress_type; /* type of spill suppression applied to image
94 <= 0.5, green suppress
95 > 0.5, blue suppress */
9696 } spillsupress_instance_t;
9797
9898 int f0r_init()
133133 spillsupress_instance_t* inst = (spillsupress_instance_t*)calloc(1, sizeof(*inst));
134134 inst->width = width;
135135 inst->height = height;
136 inst->supress_type = 0.0; // default supress type is green supress
136 inst->supress_type = 0.0; // default suppress type is green suppress
137137 return (f0r_instance_t)inst;
138138 }
139139
166166
167167 double* gaussSLESolve(size_t size, double* A) {
168168 int extSize = size + 1;
169 //direct way: tranform matrix A to triangular form
169 //direct way: transform matrix A to triangular form
170170 for(int row = 0; row < size; row++) {
171171 int col = row;
172172 int lastRowToSwap = size - 1;
00 /* tint0r.c
1 * Copyright (C) 2009 Maksim Golovkin (m4ks1k@gmail.com)
1 * Copyright (C) 2009 Maksim Golovkin (m4ks1k@gmail.com),
2 * 2025 Cynthia (cynthia2048@proton.me)
23 * This file is a Frei0r plugin.
34 *
45 * This program is free software; you can redistribute it and/or modify
1617 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1718 */
1819
20 #include <stdint.h>
1921 #include <stdlib.h>
2022 #include <assert.h>
2123
22 #include "frei0r.h"
23 #include "frei0r/math.h"
24 #ifdef __SSE4_1__
25 #include <smmintrin.h>
26 #endif
27
28 #include <frei0r.h>
29 #include <frei0r/math.h>
2430
2531 typedef struct tint0r_instance
2632 {
4248 void f0r_get_plugin_info(f0r_plugin_info_t* tint0r_instance_t)
4349 {
4450 tint0r_instance_t->name = "Tint0r";
45 tint0r_instance_t->author = "Maksim Golovkin";
51 tint0r_instance_t->author = "Maksim Golovkin & Cynthia";
4652 tint0r_instance_t->plugin_type = F0R_PLUGIN_TYPE_FILTER;
47 tint0r_instance_t->color_model = F0R_COLOR_MODEL_RGBA8888;
53 tint0r_instance_t->color_model = F0R_COLOR_MODEL_BGRA8888;
4854 tint0r_instance_t->frei0r_version = FREI0R_MAJOR_VERSION;
49 tint0r_instance_t->major_version = 0;
50 tint0r_instance_t->minor_version = 1;
51 tint0r_instance_t->num_params = 3;
52 tint0r_instance_t->explanation = "Tint a source image with specified color";
55 tint0r_instance_t->major_version = 0;
56 tint0r_instance_t->minor_version = 1;
57 tint0r_instance_t->num_params = 3;
58 tint0r_instance_t->explanation = "Tint a source image with specified colors";
5359 }
5460
5561 void f0r_get_param_info(f0r_param_info_t* info, int param_index)
5662 {
5763 switch(param_index)
5864 {
59 case 0:
60 info->name = "Map black to";
61 info->type = F0R_PARAM_COLOR;
62 info->explanation = "The color to map source color with null luminance";
63 break;
64 case 1:
65 info->name = "Map white to";
66 info->type = F0R_PARAM_COLOR;
67 info->explanation = "The color to map source color with full luminance";
68 break;
69 case 2:
70 info->name = "Tint amount";
71 info->type = F0R_PARAM_DOUBLE;
72 info->explanation = "Amount of color";
73 break;
65 case 0:
66 info->name = "Map black to";
67 info->type = F0R_PARAM_COLOR;
68 info->explanation = "The color to map source color with null luminance";
69 break;
70 case 1:
71 info->name = "Map white to";
72 info->type = F0R_PARAM_COLOR;
73 info->explanation = "The color to map source color with full luminance";
74 break;
75 case 2:
76 info->name = "Tint amount";
77 info->type = F0R_PARAM_DOUBLE;
78 info->explanation = "Amount of color";
79 break;
7480 }
7581 }
7682
7884 {
7985 tint0r_instance_t* inst = (tint0r_instance_t*)calloc(1, sizeof(*inst));
8086 inst->width = width; inst->height = height;
81 inst->amount = .25;
82 inst->whiteColor.r = .5;
87 inst->amount = 0.25;
88 inst->whiteColor.r = 0.5;
8389 inst->whiteColor.g = 1.0;
84 inst->whiteColor.b = .5;
90 inst->whiteColor.b = 0.5;
8591 inst->blackColor.r = 0.0;
8692 inst->blackColor.g = 0.0;
8793 inst->blackColor.b = 0.0;
9399 free(instance);
94100 }
95101
96 void f0r_set_param_value(f0r_instance_t instance,
102 void f0r_set_param_value(f0r_instance_t instance,
97103 f0r_param_t param, int param_index)
98104 {
99105 assert(instance);
101107
102108 switch(param_index)
103109 {
104 case 0:
105 /* black color */
106 inst->blackColor = *((f0r_param_color_t *)param);
107 break;
108 case 1:
109 /* white color */
110 inst->whiteColor = *((f0r_param_color_t *)param);
111 break;
112 case 2:
113 /* amount */
114 inst->amount = *((double *)param);
115 break;
110 case 0:
111 /* black color */
112 inst->blackColor = *((f0r_param_color_t *)param);
113 break;
114 case 1:
115 /* white color */
116 inst->whiteColor = *((f0r_param_color_t *)param);
117 break;
118 case 2:
119 /* amount */
120 inst->amount = *((double *)param);
121 break;
116122 }
117123 }
118124
121127 {
122128 assert(instance);
123129 tint0r_instance_t* inst = (tint0r_instance_t*)instance;
124
130
125131 switch(param_index)
126132 {
127 case 0:
128 *((f0r_param_color_t*)param) = inst->blackColor;
129 break;
130 case 1:
131 *((f0r_param_color_t*)param) = inst->whiteColor;
132 break;
133 case 2:
134 *((double *)param) = inst->amount;
135 break;
136 }
137 }
138
139 unsigned char map_color(double amount, double comp_amount, float color, float luma, float minColor, float maxColor) {
133 case 0:
134 *((f0r_param_color_t*)param) = inst->blackColor;
135 break;
136 case 1:
137 *((f0r_param_color_t*)param) = inst->whiteColor;
138 break;
139 case 2:
140 *((double *)param) = inst->amount;
141 break;
142 }
143 }
144
145 #ifndef __SSE4_1__
146 static inline unsigned char map_color(double amount, double comp_amount, float color, float luma, float minColor, float maxColor)
147 {
140148 double val = (comp_amount * color) + amount * (luma * (maxColor - minColor) + minColor);
141149 return (unsigned char)(255*CLAMP(val, 0, 1));
142150 }
151 #endif
143152
144153 void f0r_update(f0r_instance_t instance, double time,
145154 const uint32_t* inframe, uint32_t* outframe)
146155 {
147156 assert(instance);
148157 tint0r_instance_t* inst = (tint0r_instance_t*)instance;
158
159 #ifdef __SSE4_1__
160 size_t len = (inst->width * inst->height) / 4;
161
162 const __m128 weights = _mm_set_ps(0.0, 0.299, 0.587, 0.114),
163 amount = _mm_set1_ps(inst->amount),
164 /* Pass the alpha channel */
165 comp_amount = _mm_set_ps(1.0,
166 1.0 - inst->amount,
167 1.0 - inst->amount,
168 1.0 - inst->amount);
169
170 f0r_param_color_t black = inst->blackColor,
171 white = inst->whiteColor;
172
173 /* Zero the alpha component to exclude it from calculations. */
174 const __m128 cmin = _mm_set_ps(0.0, black.r, black.g, black.b),
175 cdelta = _mm_sub_ps(_mm_set_ps(0.0, white.r, white.g, white.b), cmin),
176 tmp0 = _mm_mul_ps(cdelta, amount),
177 tmp1 = _mm_mul_ps(_mm_mul_ps(amount, _mm_set1_ps(255.0)), cmin);
178
179 __m128 p, p0, p1, p2, p3, luma;
180 #else
149181 unsigned int len = inst->width * inst->height;
150182 double amount = inst->amount;
151183 double comp_amount = 1.0 - inst->amount;
152
184
153185 unsigned char* dst = (unsigned char*)outframe;
154186 const unsigned char* src = (unsigned char*)inframe;
155187 float b, g, r;
156188 float luma;
189 #endif
157190
158191 while (len--)
159192 {
160 r = *src++ / 255.;
161 g = *src++ / 255.;
162 b = *src++ / 255.;
163
164 luma = (b * .114 + g * .587 + r * .299);
165
166 *dst++ = map_color(amount, comp_amount, r, luma, inst->blackColor.r, inst->whiteColor.r);
167 *dst++ = map_color(amount, comp_amount, g, luma, inst->blackColor.g, inst->whiteColor.g);
168 *dst++ = map_color(amount, comp_amount, b, luma, inst->blackColor.b, inst->whiteColor.b);
169
170 *dst++ = *src++; // copy alpha
171 }
172 }
173
193 #ifdef __SSE4_1__
194 /* Load four pixels at once. */
195 p = _mm_loadu_si128((__m128i*)inframe);
196
197 /* Extract four pixels into separate XMM registers and convert them to float. */
198 p0 = _mm_cvtepi32_ps(_mm_cvtepu8_epi32(p));
199 p1 = _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_srli_si128(p, 4)));
200 p2 = _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_srli_si128(p, 8)));
201 p3 = _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_srli_si128(p, 12)));
202 #else
203 b = *src++ / 255.;
204 g = *src++ / 255.;
205 r = *src++ / 255.;
206 #endif
207
208 #ifdef __SSE4_1__
209 #define tint(v) \
210 luma = _mm_dp_ps((v), weights, 0x7F); \
211 v = _mm_add_ps(_mm_mul_ps(comp_amount, (v)), \
212 _mm_add_ps(_mm_mul_ps(luma, tmp0), tmp1)); \
213 v = _mm_cvtps_epi32(v)
214
215 tint(p0); tint(p1); tint(p2); tint(p3);
216
217 /* Gather the processed pixels */
218 p = _mm_packus_epi16(_mm_packus_epi32(p0, p1),
219 _mm_packus_epi32(p2, p3));
220
221 _mm_storeu_si128((__m128i*)outframe, p);
222
223 /* Stride of 128 bits; i.e. 16 bytes */
224 inframe += 4;
225 outframe += 4;
226 #else
227 luma = (b * .114 + g * .587 + r * .299);
228
229 *dst++ = map_color(amount, comp_amount, b, luma, inst->blackColor.b, inst->whiteColor.b);
230 *dst++ = map_color(amount, comp_amount, g, luma, inst->blackColor.g, inst->whiteColor.g);
231 *dst++ = map_color(amount, comp_amount, r, luma, inst->blackColor.r, inst->whiteColor.r);
232 *dst++ = *src++;
233 #endif
234 }
235 }
236
107107 const uint32_t* in)
108108 {
109109 // Just copy input to output.
110 // This is useful if ony few changes are made to the output.
110 // This is useful if only few changes are made to the output.
111111 // If the whole image is processed, this makes no sense!
112112 std::copy(in, in + width*height, out);
113113
124124
125125 // This parameter allows one to do simple benchmarking: Rendering a
126126 // video with uint8_t pointers and with uint32_t pointers.
127 // (Don't forget to substract the rendering time without this effect applied to avoid counting
127 // (Don't forget to subtract the rendering time without this effect applied to avoid counting
128128 // encoding and decoding as well!)
129129 if (m_pointerMethod == 0) {
130130 uint8_t *in_pointer = (uint8_t *) in;
141141 for (int y = 0; y < m_height; y++) {
142142 for (int x = 0; x < m_width; x++) {
143143
144 // Euclidian distance to the center, normalized to [0,1]
144 // Euclidean distance to the center, normalized to [0,1]
145145 r = std::sqrt(std::pow(scaleX*(x-cx), 2) + std::pow(scaleY*(y-cy), 2))/rmax;
146146
147147 // Subtract the clear center
209209 double zx, zy;
210210
211211 /* here place a formula that draws on the screen
212 the surface being drawed at this point is always blank */
212 the surface being drawn at this point is always blank */
213213 for( a=0.0 ; a<pi2; a+=0.005 ) {
214214 zx = blossom_m*a;
215215 zy = blossom_n*a;
162162 NOTE: the numbers tell which two axes are represented in the 2D plane,
163163 (the first two numbers), and which axis is controlled by the "third
164164 axis value" slider (the third number in parentheses). For example,
165 23(1) in RGB menas that G will change along the horizontal axis, B
165 23(1) in RGB means that G will change along the horizontal axis, B
166166 along vertical, and R will be set by the "third axis value" slider.
167167
168168 Third axis value:
169 sets the value along the "third" axis, which cannot be accomodated
169 sets the value along the "third" axis, which cannot be accommodated
170170 on a 2D display.
171171
172172 Fullscreen:
379379 smooth phase sinewaves.
380380
381381 NOTE: These patterns are very sensitive to scaling and interpolation,
382 any warts there will be revealed in a very drastical manner! Monitor
382 any warts there will be revealed in a drastic manner! Monitor
383383 windows in video software are often done in a "fast" way, so it may
384384 be necessary to do a final rendering, to see a fair result.
385385
421421 }
422422
423423 //----------------------------------------------------------
424 //draws a transparent mesurement grid
424 //draws a transparent measurement grid
425425 //*a = alpha channel
426426 void grid(unsigned char *sl, int w, int h, unsigned char *a)
427427 {
657657 case 4: //contrast bands
658658 trakovi(inst->sl, inst->w, inst->h);
659659 break;
660 case 5: //gama ckecking chart
660 case 5: //gama checking chart
661661 gamatest(inst->sl, inst->w, inst->h);
662662 break;
663663 case 6: //for testing orthicon simulator
512512 }
513513
514514 //----------------------------------------------------------
515 //fills frame with constand 2D spatial frequency
515 //fills frame with constant 2D spatial frequency
516516 //ar = pixel aspect ratio (not used currently)
517517 void diags(float *sl, int w, int h, float a, float ar, float fh, float fv)
518518 {
5050
5151 uint32_t b;
5252
53 /* FIXME: Is the burn effect supposed to be dependant on the sign of this
53 /* FIXME: Is the burn effect supposed to be dependent on the sign of this
5454 * temporary variable? */
5555 int tmp;
5656
7474 case 0:
7575 info->name = "x";
7676 info->type = F0R_PARAM_DOUBLE;
77 info->explanation = "X position of second input, value interperted as range -2*width - 3*width";
77 info->explanation = "X position of second input, value interpreted as range -2*width - 3*width";
7878 break;
7979 case 1:
8080 info->name = "y";
8181 info->type = F0R_PARAM_DOUBLE;
82 info->explanation = "Y position of second input, value interperted as range -2*height - 3*height";
82 info->explanation = "Y position of second input, value interpreted as range -2*height - 3*height";
8383 break;
8484 case 2:
8585 info->name = "x scale";
8686 info->type = F0R_PARAM_DOUBLE;
87 info->explanation = "X scale of second input, value interperted as range 0 - 5";
87 info->explanation = "X scale of second input, value interpreted as range 0 - 5";
8888 break;
8989 case 3:
9090 info->name = "y scale";
9191 info->type = F0R_PARAM_DOUBLE;
92 info->explanation = "Y scale of second input, value interperted as range 0 - 5";
92 info->explanation = "Y scale of second input, value interpreted as range 0 - 5";
9393 break;
9494 case 4:
9595 info->name = "rotation";
9696 info->type = F0R_PARAM_DOUBLE;
97 info->explanation = "Rotation of second input, value interperted as range 0 - 360";
97 info->explanation = "Rotation of second input, value interpreted as range 0 - 360";
9898 break;
9999 case 5:
100100 info->name = "opacity";
6363 r1 = r2;
6464 g1 = g2;
6565
66 /* set the dstination */
66 /* set the destination */
6767 hsl_to_rgb_int(&r1, &g1, &b1);
6868
6969 dst[0] = r1;
111111 };
112112
113113 frei0r::construct<euclid_eraser> plugin("euclid_eraser",
114 "Erasing backgrounds with euclidian distance",
114 "Erasing backgrounds with euclidean distance",
115115 "Erik H. Beck",
116116 0,1,
117117 F0R_COLOR_MODEL_RGBA8888);
2020 background, and removes it from every frame in the video stream of the
2121 second input.
2222
23 The alpha channel on the output is based on the euclidian distance of
23 The alpha channel on the output is based on the euclidean distance of
2424 the two input coordinates in 3-d RGB space. If the calculated distance
25 betwen the two inputs for a given pixel is less than a provided
25 between the two inputs for a given pixel is less than a provided
2626 (variable) threshold amount, that indicates the pixel in the
2727 background (reference) image is the same or similar enough to the
2828 operational (second) input that is part of the background to be
2929 removed, and the transparency is set to fully transparent via the
3030 alpha channel (set to 0).
3131
32 If the calcuated distance exceeds the threshold, then that pixel is
32 If the calculated distance exceeds the threshold, then that pixel is
3333 part of the foreground image to be retained, and the transparency
3434 of it is set to be fully opaque (alpha channel for that pixel set
3535 to 255).
6767 if (g2)
6868 r1 = r2;
6969
70 /* set the dstination */
70 /* set the destination */
7171 hsv_to_rgb_int (&r1, &g1, &b1);
7272
7373 dst[0] = r1;
6262
6363 g1 = g2;
6464
65 /* set the dstination */
65 /* set the destination */
6666 hsv_to_rgb_int(&r1, &g1, &b1);
6767
6868 dst[0] = r1;
6363
6464 b1 = b2;
6565
66 /* set the dstination */
66 /* set the destination */
6767 hsv_to_rgb_int(&r1, &g1, &b1);
6868
6969 dst[0] = r1;