diff --git a/AUTHORS.md b/AUTHORS.md
index 650e026..68728a7 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -6,4 +6,51 @@
## Developers who contributed, in alphabetic order:
-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.
+Akito Iwakura
+Albert Frisch
+Ajrat Makhmutov
+Brendan Hack
+Brian Matherly
+Burkhard Plaum
+Carlo E. Prelz
+Christoph Willing
+Cynthia
+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)
+Johann Jeg
+Joshua M. Doe
+Luca Bigliardi
+Maksim Golovkin (Максим Головкин)
+Marko Cebokli
+Martin Bayer
+Mathieu Guindon
+Matthias Schnöll
+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
+Vadim Druzhin
+Vincent Pinon
diff --git a/include/frei0r/cairo.h b/include/frei0r/cairo.h
index c7b3330..8aa2d88 100644
--- a/include/frei0r/cairo.h
+++ b/include/frei0r/cairo.h
@@ -196,7 +196,7 @@
/**
* frei0r_cairo_get_pixel_position
* @norm_pos: position in range 0 - 1, either x or y
-* @dim: dimension, either witdh or height
+* @dim: dimension, either width or height
*
* Converts double range [0 -> 1] to pixel range [-2*dim -> 3*dim]. Input 0.4 gives position 0.
*
diff --git a/include/frei0r/cfc.h b/include/frei0r/cfc.h
index 14cca12..010f147 100644
--- a/include/frei0r/cfc.h
+++ b/include/frei0r/cfc.h
@@ -207,7 +207,7 @@
//convert from paked uchar RGBA to packed float RGBA
//w,h are width and height of the image
//tab = table used for RGB conversion
-//atab = table used for alpha converion (usually linear)
+//atab = table used for alpha conversion (usually linear)
static inline void RGBA8_2_float(const uint32_t *in, float_rgba *out, int w, int h, float *tab, float *atab)
{
int i;
@@ -224,7 +224,7 @@
//--------------------------------------------------------
//convert from paked uchar RGBA to packed float RGBA,
-//covert RGB only, SKIP ALPHA
+//convert RGB only, SKIP ALPHA
//w,h are width and height of the image
//tab = table used for RGB conversion
static inline void RGB8_2_float(const uint32_t *in, float_rgba *out, int w, int h, float *tab)
@@ -259,7 +259,7 @@
//----------------------------------------------------------
//convert from packed float RGBA to packed uchar RGBA
//tab = table used for RGB conversion
-//atab = table used for alpha converion (usually linear)
+//atab = table used for alpha conversion (usually linear)
static inline void float_2_RGBA8(const float_rgba *in, uint32_t *out, int w, int h, uint8_t *tab, uint8_t *atab)
{
int i;
@@ -276,7 +276,7 @@
//----------------------------------------------------------
//convert from packed float RGBA to packed uchar RGBA
-//covert RGB only, SKIP ALPHA
+//convert RGB only, SKIP ALPHA
//tab = table used for RGB conversion
static inline void float_2_RGB8(const float_rgba *in, uint32_t *out, int w, int h, uint8_t *tab)
{
diff --git a/include/frei0r.h b/include/frei0r.h
index 09b6e31..88b814e 100644
--- a/include/frei0r.h
+++ b/include/frei0r.h
@@ -137,7 +137,7 @@
* @subsection sec_icon_location Icon location
*
* The exact location where the application should look for the
- * plugin is platform dependant.
+ * plugin is platform dependent.
*
* For Windows platforms, the icon should be at the same place as
* the plugin containing the effect.
@@ -190,7 +190,7 @@
* - \ref f0r_update2
*
* If a thread is in one of these methods its allowed for another thread to
- * enter one of theses methods for a different effect instance. But for one
+ * enter one of these methods for a different effect instance. But for one
* effect instance only one thread is allowed to execute any of these methods.
*/
@@ -260,7 +260,7 @@
* List of supported color models.
*
* Note: the color models are endian independent, because the
- * color components are defined by their positon in memory, not
+ * color components are defined by their position in memory, not
* by their significance in an uint32_t value.
*
* For effects that work on the color components,
@@ -309,7 +309,7 @@
/**
* In PACKED32, each pixel is represented by 4 consecutive
- * bytes, but it is not defined how the color componets are
+ * bytes, but it is not defined how the color components are
* stored. The true color format could be RGBA8888,
* BGRA8888, a packed 32 bit YUV format, or any other
* color format that stores pixels in 32 bit.
diff --git a/include/frei0r.hpp b/include/frei0r.hpp
index ef12be4..a340bae 100644
--- a/include/frei0r.hpp
+++ b/include/frei0r.hpp
@@ -341,7 +341,7 @@
inframe3);
}
-// compability for frei0r 1.0
+// compatibility for frei0r 1.0
void f0r_update(f0r_instance_t instance,
double time, const uint32_t* inframe, uint32_t* outframe)
{
diff --git a/src/filter/CMakeLists.txt b/src/filter/CMakeLists.txt
index 804fcda..ee19ac6 100644
--- a/src/filter/CMakeLists.txt
+++ b/src/filter/CMakeLists.txt
@@ -54,6 +54,7 @@
add_subdirectory (glow)
add_subdirectory (glitch0r)
#add_subdirectory (host_param_test)
+add_subdirectory (heatmap0r)
add_subdirectory (hueshift0r)
add_subdirectory (invert0r)
add_subdirectory (kaleid0sc0pe)
diff --git a/src/filter/aech0r/aech0r.cpp b/src/filter/aech0r/aech0r.cpp
index 7aa005a..4c2380f 100644
--- a/src/filter/aech0r/aech0r.cpp
+++ b/src/filter/aech0r/aech0r.cpp
@@ -32,19 +32,19 @@
////// TODO / IDEAS / ... //////
// IDEA - directionnal echo ? (X/Y like parameter )
-// TODO RGB gradiant by fading influence need more love (See '//Fade by color layers')!
-// FIXME SSE2 version doesnt support RGB fading influence !
-
-// FIXME (Veejay specifics?) on activate/desactivate/activate/..., some buffers must be cleared!
-
-// EXPORE ME -
+// TODO RGB gradient by fading influence need more love (See '//Fade by color layers')!
+// FIXME SSE2 version doesn't support RGB fading influence !
+
+// FIXME (Veejay specifics?) on activate/deactivate/activate/..., some buffers must be cleared!
+
+// EXPLORE ME -
//~ if((skip_count++)>m_skip) {
//~ - skip_count = 0;
//~ - m_factor += (factor * 64);
//~ [...]
//~ }
-// EXPLORE ME a very high m_factor value give some interresting color result ( m_factor += (factor * 64) * m_skip;)
+// EXPLORE ME a very high m_factor value give some interesting color result ( m_factor += (factor * 64) * m_skip;)
/* Intrinsic declarations */
@@ -129,7 +129,7 @@
m_skip_count = 0;
register_param(factor, "Fade Factor", "Disappearance rate of the echo"); // 0 No fade, 1 No Trace
- register_param(bright, "Direction", "Darker or Brighter echo"); // Add or Substract data
+ register_param(bright, "Direction", "Darker or Brighter echo"); // Add or Subtract data
register_param(flag_r, "Keep RED", "Influence on Red channel"); // 0 Fade canal, 1 Keep canal data
register_param(flag_g, "Keep GREEN", "Influence on Green channel"); // 0 Fade canal, 1 Keep canal data
register_param(flag_b, "Keep BLUE", "Influence on Blue channel"); // 0 Fade canal, 1 Keep canal data
@@ -139,7 +139,7 @@
//~ register_param(factor_r, "Fade R", "influence"); // 0 No fade, 1 No Trace
//~ register_param(factor_g, "Fade G", "influence"); // 0 No fade, 1 No Trace
//~ register_param(factor_b, "Fade B", "influence"); // 0 No fade, 1 No Trace
- //~ register_param(flag_rgb, "Plans comparaison", "RGB");
+ //~ register_param(flag_rgb, "Plans comparison", "RGB");
}
~aech0r() {
diff --git a/src/filter/alpha0ps/alpha0ps_alpha0ps.c b/src/filter/alpha0ps/alpha0ps_alpha0ps.c
index e4ac4e6..6eb662e 100644
--- a/src/filter/alpha0ps/alpha0ps_alpha0ps.c
+++ b/src/filter/alpha0ps/alpha0ps_alpha0ps.c
@@ -58,7 +58,7 @@
float sga;
int inv;
- //auxilliary variables for fibe2o
+ //auxiliary variables for fibe2o
float f,q,a0,a1,a2,b0,b1,b2,rd1,rd2,rs1,rs2,rc1,rc2;
} inst;
diff --git a/src/filter/blur/README b/src/filter/blur/README
index 284d008..af1d14e 100755
--- a/src/filter/blur/README
+++ b/src/filter/blur/README
@@ -105,7 +105,7 @@
because I did some optimizations for speed.
The algorithms are so simple, that using SSE didn't bring
much speedup - the limiting factor is memory bandwidth, not
-arithmetics. Therefore I decided not to include the SSE versions.
+arithmetic. Therefore I decided not to include the SSE versions.
diff --git a/src/filter/blur/fibe.h b/src/filter/blur/fibe.h
index 5c317c3..fe39c13 100755
--- a/src/filter/blur/fibe.h
+++ b/src/filter/blur/fibe.h
@@ -35,13 +35,13 @@
CONTENTS OF FIBE.H FILE:
--------------------------------
-calcab_lp1() auxilliary function to calculate lowpass
+calcab_lp1() auxiliary function to calculate lowpass
tap coefficients for FIBE-2
-young_vliet() auxilliary function to calculate tap coefs
+young_vliet() auxiliary function to calculate tap coefs
for Gauss approximation with FIBE-3
-rep() auxilliary function to calculate wraparound
+rep() auxiliary function to calculate wraparound
values for FIBE-2
fibe1o_8() one tap quadrilateral IIR filter
diff --git a/src/filter/brightness/brightness.c b/src/filter/brightness/brightness.c
index 1738a4d..8f0732c 100644
--- a/src/filter/brightness/brightness.c
+++ b/src/filter/brightness/brightness.c
@@ -107,7 +107,7 @@
{
int val;
case 0:
- /* constrast */
+ /* contrast */
val = (int) ((*((double*)param) - 0.5) * 512.0); /* remap to [-256, 256] */
if (val != inst->brightness)
{
diff --git a/src/filter/c0rners/README b/src/filter/c0rners/README
index a686b54..aba4caf 100644
--- a/src/filter/c0rners/README
+++ b/src/filter/c0rners/README
@@ -89,7 +89,7 @@
left corner x=1000, y=1000, the upper right corner x=2000, y=1000 and so on. It
should also set the defaults so that the undistorted input picture is displayed.
If you have no image, check that the corners specify a nonzero area at least
-partly overlaping the output window.
+partly overlapping the output window.
2. Stretch, x and y
diff --git a/src/filter/c0rners/interp.h b/src/filter/c0rners/interp.h
index 3777ddc..18af283 100644
--- a/src/filter/c0rners/interp.h
+++ b/src/filter/c0rners/interp.h
@@ -19,7 +19,7 @@
*/
/*******************************************************************
- * The remapping functions use a map aray, which contains a pair
+ * The remapping functions use a map array, which contains a pair
* of floating values fo each pixel of the output image. These
* represent the location in the input image, from where the value
* of the given output pixel should be interpolated.
diff --git a/src/filter/colorhalftone/colorhalftone.c b/src/filter/colorhalftone/colorhalftone.c
index 9bc0dde..d2d74ba 100644
--- a/src/filter/colorhalftone/colorhalftone.c
+++ b/src/filter/colorhalftone/colorhalftone.c
@@ -119,7 +119,7 @@
// We check all four neighbours, but in practice only one can ever overlap any given point.
for (i = 0; i < 5; i++)
{
- // Find neigbouring grid point
+ // Find neighbouring grid point
ttx = tx + mx[i]*gridSize;
tty = ty + my[i]*gridSize;
// Transform back into image space
diff --git a/src/filter/contrast0r/contrast0r.c b/src/filter/contrast0r/contrast0r.c
index 22efb05..5b906c1 100644
--- a/src/filter/contrast0r/contrast0r.c
+++ b/src/filter/contrast0r/contrast0r.c
@@ -100,7 +100,7 @@
{
int val;
case 0:
- /* constrast */
+ /* contrast */
val = (int) ((*((double*)param) - 0.5) * 512.0); /* remap to [-256, 256] */
if (val != inst->contrast)
{
diff --git a/src/filter/curves/curves.c b/src/filter/curves/curves.c
index fc8d060..f30181f 100644
--- a/src/filter/curves/curves.c
+++ b/src/filter/curves/curves.c
@@ -388,7 +388,7 @@
double* gaussSLESolve(size_t size, double* A) {
int extSize = size + 1;
- //direct way: tranform matrix A to triangular form
+ //direct way: transform matrix A to triangular form
for(int row = 0; row < size; row++) {
int col = row;
int lastRowToSwap = size - 1;
@@ -546,7 +546,7 @@
/*
* Calculating a point on the bezier curve using the coefficients from Bernstein basis polynomial of degree 3.
* Using the De Casteljau algorithm would be slightly faster when calculating a lot of values
- * but the difference is far from noticable here since we update the spline only when the parameter changes
+ * but the difference is far from noticeable here since we update the spline only when the parameter changes
*/
double c1 = (1-t) * (1-t) * (1-t);
double c2 = 3 * t * (1-t) * (1-t);
@@ -557,6 +557,10 @@
return pos;
}
+#if defined(_WIN32) || defined(_WIN64)
+# define strtok_r strtok_s
+#endif
+
/**
* Splits given string into sub-strings at given delimiter.
* \param string input string
@@ -569,11 +573,11 @@
int count = 0;
char *input = strdup(string);
char *result = NULL;
- result = strtok(input, delimiter);
+ result = strtok_r(string, delimiter, &input);
while (result != NULL) {
*tokens = realloc(*tokens, (count + 1) * sizeof(char *));
(*tokens)[count++] = strdup(result);
- result = strtok(NULL, delimiter);
+ result = strtok_r(NULL, delimiter, &input);
}
free(input);
return count;
@@ -776,7 +780,7 @@
curves_instance_t* inst = (curves_instance_t*)instance;
unsigned int len = inst->width * inst->height;
- // test initalization c/b spline
+ // test initialization c/b spline
double *splinemap = strlen(inst->bspline)>0 ? inst->bsplineMap : inst->csplineMap;
if(!splinemap) {
memcpy(outframe,inframe,inst->width * inst->height * 4);
diff --git a/src/filter/d90stairsteppingfix/d90stairsteppingfix.cpp b/src/filter/d90stairsteppingfix/d90stairsteppingfix.cpp
index 1b44136..e2b8817 100644
--- a/src/filter/d90stairsteppingfix/d90stairsteppingfix.cpp
+++ b/src/filter/d90stairsteppingfix/d90stairsteppingfix.cpp
@@ -222,7 +222,7 @@
for (unsigned int pixel = 0; pixel < width*4; pixel++) {
// Use linear interpolation on the colours
- // Use pointer arithmetics. Colour values are stored
+ // Use pointer arithmetic. Colour values are stored
// as AABBGGRR in the uint32_t values.
// Convert each colour separately.
diff --git a/src/filter/defish0r/README b/src/filter/defish0r/README
index 017ea26..8940fe9 100644
--- a/src/filter/defish0r/README
+++ b/src/filter/defish0r/README
@@ -2,7 +2,7 @@
rectilinear, and vice versa. It is based on the angular mapping
functions actually used in fisheye lens design, to get the best
possible results. It can also be used to correct the slight distortion
-of some wideangle convertors, or to bend the image beyond recognition
+of some wideangle converters, or to bend the image beyond recognition
for special effects and light shows.
@@ -64,7 +64,7 @@
unreasonable values the image might indeed disappear, when there are
math overflows or imaginary results... (types 1 and 2 are more prone
to image vanishing). Anyway, when working in the "special effect"
- range, it is alway worth to try manual scaling.
+ range, it is always worth to try manual scaling.
"DeFish"
If checked, the transform direction is from fisheye to rectiliear,
@@ -163,7 +163,7 @@
Scaling = 1000 (manual)
Manual Scale = 191
-For an effect, reminiscent of some scenes from the "2001 Spcae Odyssey" try
+For an effect, reminiscent of some scenes from the "2001 Space Odyssey" try
this:
Amount = 876
Defish = ON
diff --git a/src/filter/defish0r/defish0r.c b/src/filter/defish0r/defish0r.c
index e3060f3..944c09f 100644
--- a/src/filter/defish0r/defish0r.c
+++ b/src/filter/defish0r/defish0r.c
@@ -213,8 +213,8 @@
//pari,paro = pixel aspect ratio (input / output)
//dx, dy offset on input (for non-cosited chroma subsampling)
//lbox = letterbox
-//stretch = dymanic stretch, convert between 4:3 and 16:9
-//yScale = -0.5.. 0.5 change aspect ratio on y acess only
+//stretch = dynamic stretch, convert between 4:3 and 16:9
+//yScale = -0.5.. 0.5 change aspect ratio on y access only
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
, int lbox, float stretchFactor, float yScale)
{
@@ -312,7 +312,7 @@
//aspt: 0..4 aspect type square, PAL, NTSC, HDV, manual
//par: pixel aspect ratio
//lbox: 1=letterbox
-//stretch 0..1 stretch video to fix superview distorsion
+//stretch 0..1 stretch video to fix superview distortion
typedef struct
{
int w;
@@ -513,7 +513,7 @@
p->mpar=1.0;
p->lbox=0; //letterbox
p->stretch = 0.0f; //dynamic stretch
- p->yScale = 1.0f; //seperate Y stretch
+ p->yScale = 1.0f; //separate Y stretch
p->map=(float*)calloc(1, sizeof(float)*(p->w*p->h*2+2));
p->interpol=set_intp(*p);
diff --git a/src/filter/defish0r/interp.h b/src/filter/defish0r/interp.h
index b1234d0..4c3fa6f 100644
--- a/src/filter/defish0r/interp.h
+++ b/src/filter/defish0r/interp.h
@@ -19,8 +19,8 @@
*/
/*******************************************************************
- * The remapping functions use a map aray, which contains a pair
- * of floating values fo each pixel of the output image. These
+ * The remapping functions use a map array, which contains a pair
+ * of floating values of each pixel of the output image. These
* represent the location in the input image, from where the value
* of the given output pixel should be interpolated.
* They are given in pixels of the input image.
diff --git a/src/filter/elastic_scale/README.md b/src/filter/elastic_scale/README.md
index f419a0a..8fc2591 100755
--- a/src/filter/elastic_scale/README.md
+++ b/src/filter/elastic_scale/README.md
@@ -15,7 +15,7 @@
## Description of the parameters:
"Scale Center":
-Sets the horizontal center where the scaling orgins from. range: [0,1]
+Sets the horizontal center where the scaling origins from. range: [0,1]
"Linear Scale Area":
diff --git a/src/filter/heatmap0r/CMakeLists.txt b/src/filter/heatmap0r/CMakeLists.txt
new file mode 100644
index 0000000..8e62b3a
--- /dev/null
+++ b/src/filter/heatmap0r/CMakeLists.txt
@@ -0,0 +1,11 @@
+set (SOURCES heatmap0r.c)
+set (TARGET heatmap0r)
+
+if (MSVC)
+ set (SOURCES ${SOURCES} ${FREI0R_DEF})
+endif (MSVC)
+
+add_library (${TARGET} MODULE ${SOURCES})
+
+# No «lib» prefix (name.so instead of libname.so)
+set_target_properties (${TARGET} PROPERTIES PREFIX "")
diff --git a/src/filter/heatmap0r/heatmap0r.c b/src/filter/heatmap0r/heatmap0r.c
new file mode 100644
index 0000000..6e360cd
--- /dev/null
+++ b/src/filter/heatmap0r/heatmap0r.c
@@ -0,0 +1,201 @@
+/*
+ * heatmap0r.c -- feel the heat, frei0r style.
+ *
+ * Copyright (C) 2025 Cynthia (cynthia2048@proton.me)
+ *
+ * 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
+#include
+
+#include "frei0r.h"
+#include "frei0r/math.h"
+
+typedef struct {
+ unsigned int width, height;
+ uint8_t rlut[256], glut[256], blut[256];
+
+ f0r_param_color_t black, grey, white;
+ double gp; //< Grey point
+} heatmap0r_t;
+
+static void gen_heatmap0r_luts(heatmap0r_t *inst)
+{
+ double luma;
+ double L0, L1, L2;
+ double gp = inst->gp;
+ double l0 = 1.0 / gp,
+ l1 = 1.0 / (gp * (gp - 1.0)),
+ l2 = 1.0 / (1.0 - gp);
+
+ f0r_param_color_t black = inst->black,
+ grey = inst->grey,
+ white = inst->white;
+
+ for (int i = 0; i < 256; ++i)
+ {
+ luma = 1.0 / 255.0 * (double)i;
+
+ L0 = (luma - gp) * (luma - 1.0) * l0;
+ L1 = luma * (luma - 1.0) * l1;
+ L2 = luma * (luma - gp) * l2;
+
+ inst->rlut[i] = CLAMP(255.0 * (L0 * black.r + L1 * grey.r + L2 * white.r), 0, 255);
+ inst->glut[i] = CLAMP(255.0 * (L0 * black.g + L1 * grey.g + L2 * white.g), 0, 255);
+ inst->blut[i] = CLAMP(255.0 * (L0 * black.b + L1 * grey.b + L2 * white.b), 0, 255);
+ }
+}
+
+int f0r_init()
+{
+ return 1;
+}
+
+void f0r_deinit() {}
+
+f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
+{
+ heatmap0r_t* inst = calloc(1, sizeof(*inst));
+
+ inst->width = width; inst->height = height;
+ inst->gp = 0.5;
+ inst->white = (f0r_param_color_t) {/* Yellow */ 1.0, 1.0, 0.0};
+ inst->grey = (f0r_param_color_t) {/* Deeppink */ 1.0, 0.0, 0.5};
+ inst->black = (f0r_param_color_t) {/* Darkviolet */ 0.27, 0.0, 0.5};
+
+ gen_heatmap0r_luts (inst);
+
+ return (f0r_instance_t)inst;
+}
+
+void f0r_destruct(f0r_instance_t instance)
+{
+ free(instance);
+}
+
+void f0r_get_plugin_info(f0r_plugin_info_t* info)
+{
+ info->name = "heatmap0r";
+ info->author = "Cynthia";
+ info->plugin_type = F0R_PLUGIN_TYPE_FILTER;
+ info->color_model = F0R_COLOR_MODEL_RGBA8888;
+ info->frei0r_version = FREI0R_MAJOR_VERSION;
+ info->major_version = 0;
+ info->minor_version = 1;
+ info->num_params = 4;
+ info->explanation = "Performs a continious trichromatic tinting";
+}
+
+void f0r_get_param_info(f0r_param_info_t* info, int param_index)
+{
+ switch(param_index)
+ {
+ case 0:
+ info->name = "Map black to";
+ info->type = F0R_PARAM_COLOR;
+ info->explanation = "The color to map source color with zero luminance";
+ break;
+ case 1:
+ info->name = "Map grey to";
+ info->type = F0R_PARAM_COLOR;
+ info->explanation = "The color to map source color with mid luminance";
+ break;
+ case 2:
+ info->name = "Map white to";
+ info->type = F0R_PARAM_COLOR;
+ info->explanation = "The color to map source color with full luminance";
+ break;
+ case 3:
+ info->name = "Grey point";
+ info->type = F0R_PARAM_DOUBLE;
+ info->explanation = "Point in the luminance axis grey color is located";
+ break;
+ }
+}
+
+void f0r_set_param_value(f0r_instance_t instance,
+ f0r_param_t param, int param_index)
+{
+ assert(instance);
+ heatmap0r_t* inst = (heatmap0r_t*)instance;
+
+ switch(param_index)
+ {
+ case 0:
+ inst->black = *((f0r_param_color_t *)param);
+ break;
+ case 1:
+ inst->grey = *((f0r_param_color_t *)param);
+ break;
+ case 2:
+ inst->white = *((f0r_param_color_t *)param);
+ break;
+ case 3:
+ inst->gp = *((double *)param);
+ break;
+ }
+
+ gen_heatmap0r_luts (inst);
+}
+
+void f0r_get_param_value(f0r_instance_t instance,
+ f0r_param_t param, int param_index)
+{
+ assert(instance);
+ heatmap0r_t* inst = (heatmap0r_t*)instance;
+
+ switch(param_index)
+ {
+ case 0:
+ *((f0r_param_color_t*)param) = inst->black;
+ break;
+ case 1:
+ *((f0r_param_color_t*)param) = inst->grey;
+ break;
+ case 2:
+ *((f0r_param_color_t*)param) = inst->white;
+ break;
+ case 3:
+ *((double *)param) = inst->gp;
+ break;
+ }
+}
+
+void f0r_update(f0r_instance_t instance, double time,
+ const uint32_t* inframe, uint32_t* outframe)
+{
+ assert(instance);
+ heatmap0r_t* inst = (heatmap0r_t*)instance;
+ unsigned int len = inst->width * inst->height;
+
+ const unsigned char* src = (void*)inframe;
+ unsigned char* dst = (void*)outframe;
+
+ unsigned char luma, r, g, b;
+ while (len--)
+ {
+ r = *src++;
+ g = *src++;
+ b = *src++;
+
+ luma = 0.299 * r + 0.587 * g + 0.114 * b;
+
+ *dst++ = inst->rlut[luma];
+ *dst++ = inst->glut[luma];
+ *dst++ = inst->blut[luma];
+ *dst++ = *src++;
+ }
+}
diff --git a/src/filter/hueshift0r/hueshift0r.c b/src/filter/hueshift0r/hueshift0r.c
index e3a88ba..4cf5000 100644
--- a/src/filter/hueshift0r/hueshift0r.c
+++ b/src/filter/hueshift0r/hueshift0r.c
@@ -101,7 +101,7 @@
{
int val;
case 0:
- /* constrast */
+ /* contrast */
val = (int) (*((double*)param) * 360.0); /* remap to [0, 360] */
if (val != inst->hueshift)
{
diff --git a/src/filter/hueshift0r/matrix.h b/src/filter/hueshift0r/matrix.h
index 2331ef6..9016438 100644
--- a/src/filter/hueshift0r/matrix.h
+++ b/src/filter/hueshift0r/matrix.h
@@ -1,6 +1,6 @@
/*
* matrix -
- * Use 4x4 matricies to process color images.
+ * Use 4x4 matrices to process color images.
*
* To compile:
cc matrix.c -o matrix -lgutil -limage -lgl -lm
@@ -73,7 +73,7 @@
/*
* matrixmult -
- * multiply two matricies
+ * multiply two matrices
*/
void
matrixmult(float a[4][4],float b[4][4],float c[4][4])
@@ -132,7 +132,7 @@
/*
* cscalemat -
- * make a color scale marix
+ * make a color scale matrix
*/
void
cscalemat(float mat[4][4],float rscale,float gscale,float bscale)
@@ -164,7 +164,7 @@
/*
* lummat -
- * make a luminance marix
+ * make a luminance matrix
*/
void
lummat(float mat[4][4])
@@ -199,7 +199,7 @@
/*
* saturatemat -
- * make a saturation marix
+ * make a saturation matrix
*/
void
saturatemat(float mat[4][4],float sat)
diff --git a/src/filter/kaleid0sc0pe/README.md b/src/filter/kaleid0sc0pe/README.md
index d13375e..459667a 100644
--- a/src/filter/kaleid0sc0pe/README.md
+++ b/src/filter/kaleid0sc0pe/README.md
@@ -28,7 +28,7 @@
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]`.
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.
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]`.
-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]`.
+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]`.
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.
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]`.
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.
diff --git a/src/filter/kaleid0sc0pe/ikaleid0sc0pe.h b/src/filter/kaleid0sc0pe/ikaleid0sc0pe.h
index 4a35e89..56c0510 100644
--- a/src/filter/kaleid0sc0pe/ikaleid0sc0pe.h
+++ b/src/filter/kaleid0sc0pe/ikaleid0sc0pe.h
@@ -36,7 +36,7 @@
{
// default delete for IKaleid0sc0pe
-// this isn't going to work across an actaul shared object boundary but
+// this isn't going to work across an actual shared object boundary but
// not particular worried about that at the moment
template<>
class default_delete
@@ -257,7 +257,7 @@
/**
* Sets the number of threads to use when processing.
* Default to 0.
- * @param threading the nubmer of threads to use. \c 0, calculate automatically,
+ * @param threading the number of threads to use. \c 0, calculate automatically,
* otherwise the explicit thread count.
* @return
* - 0: Success
diff --git a/src/filter/kaleid0sc0pe/kaleid0sc0pe.h b/src/filter/kaleid0sc0pe/kaleid0sc0pe.h
index 699cde7..c14d05d 100644
--- a/src/filter/kaleid0sc0pe/kaleid0sc0pe.h
+++ b/src/filter/kaleid0sc0pe/kaleid0sc0pe.h
@@ -143,7 +143,7 @@
/// source_x,source_y
/// @param x x coordinate to start rotate from
/// @param y y coordinate to rotate
- /// @param source_x receives the x coordiante results
+ /// @param source_x receives the x coordinate results
/// @param source_y receives the y coordinate results
inline void rotate(int x, int y, __m128 *source_x, __m128 *source_y);
#else
@@ -164,8 +164,8 @@
Reflect_info calculate_reflect_info(std::uint32_t x, std::uint32_t y);
/// Converts coordinates to screen space
- /// @param x recieves x coordinate
- /// @param y recieves y coordinate
+ /// @param x receives x coordinate
+ /// @param y receives y coordinate
/// @param sx source x coordinate
/// @param sy source y coordinate
void to_screen(float *x, float *y, std::uint32_t sx, std::uint32_t sy);
diff --git a/src/filter/kaleid0sc0pe/sse_mathfun.h b/src/filter/kaleid0sc0pe/sse_mathfun.h
index fd0570f..b3e8e77 100644
--- a/src/filter/kaleid0sc0pe/sse_mathfun.h
+++ b/src/filter/kaleid0sc0pe/sse_mathfun.h
@@ -301,7 +301,7 @@
_PS_CONST(cephes_FOPI, 1.27323954473516); // 4 / M_PI
-/* evaluation of 4 sines at onces, using only SSE1+MMX intrinsics so
+/* evaluation of 4 sines at once, using only SSE1+MMX intrinsics so
it runs also on old athlons XPs and the pentium III of your grand
mother.
diff --git a/src/filter/keyspillm0pup/readme b/src/filter/keyspillm0pup/readme
index 8ac3ea2..43bd9f0 100755
--- a/src/filter/keyspillm0pup/readme
+++ b/src/filter/keyspillm0pup/readme
@@ -68,7 +68,7 @@
This plugin can be cascaded, but it is not possible to get the same
color based mask in the second instance, because the colors will be
changed by the first instance. To enable two operations with the
-same mask, each plugin instance can do two opertions.
+same mask, each plugin instance can do two operations.
With transparency and edge masks, cascading is a bit easier.
If the hue gate and saturation threshold are not used, transparency
and edge masks can be exactly the same in cascaded plugins.
@@ -122,10 +122,10 @@
Show mask:
This will show the selected mask as a greyscale image, to help with
-fine tuning of the masks. Shoud be OFF for the final render.
+fine tuning of the masks. Should be OFF for the final render.
Mask to Alpha:
Copies the active mask to the alpha channel.
For all normal spill cleaning operations, this should be OFF.
-By seting it ON, the keyspillm0pup itself can be used as a keyer,
+By setting it ON, the keyspillm0pup itself can be used as a keyer,
or to generate some special effects.
diff --git a/src/filter/lightgraffiti/lightgraffiti.cpp b/src/filter/lightgraffiti/lightgraffiti.cpp
index 9f9ae77..b96a0f9 100644
--- a/src/filter/lightgraffiti/lightgraffiti.cpp
+++ b/src/filter/lightgraffiti/lightgraffiti.cpp
@@ -852,7 +852,7 @@
fb = m_rgbLightMask[pixel].b;
if (lowerOverexposure > 0) {
- // Comparisation of plots with octave:
+ // Comparison of plots with octave:
// 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
fr = pow( log(1+fr)/lowerOverexposure, .5 );
fg = pow( log(1+fg)/lowerOverexposure, .5 );
diff --git a/src/filter/measure/measure_pr0be.c b/src/filter/measure/measure_pr0be.c
index d9d7e17..11527ad 100644
--- a/src/filter/measure/measure_pr0be.c
+++ b/src/filter/measure/measure_pr0be.c
@@ -38,7 +38,7 @@
double PI=3.14159265358979;
//---------------------------------------------------------------
-void draw_rectangle(float_rgba *s, int w, int h, float x, float y, float wr, float hr, float_rgba c)
+static inline void draw_rectangle(float_rgba *s, int w, int h, float x, float y, float wr, float hr, float_rgba c)
{
int i,j;
int zx,kx,zy,ky;
@@ -139,7 +139,7 @@
//justified
//p=0 one decimal place p=1 three decimal places
//m=1 always show sign
-void forstr(float a, int p, int m, char *s)
+inline static void forstr(float a, int p, int m, char *s)
{
float b;
char *p3=" %5.3f";
@@ -192,20 +192,20 @@
forstr(s.rms,1-u,0,rs);
forstr(s.min,1-u,m,ns);
forstr(s.max,1-u,m,xs);
- sprintf(fs,"%s%s%s %s%s", lab, as, rs, ns, xs);
+ snprintf(fs,255,"%s%s%s %s%s", lab, as, rs, ns, xs);
sprintf(str,fs,s.avg,s.rms,s.min,s.max);
}
else
{
forstr(s.avg,1-u,m,as);
forstr(s.rms,1-u,0,rs);
- sprintf(fs,"%s%s%s", lab, as, rs);
+ snprintf(fs,255,"%s%s%s", lab, as, rs);
sprintf(str,fs,s.avg,s.rms);
}
}
//-----------------------------------------------------------
-//probe size markers in the magnifier diaplay
+//probe size markers in the magnifier display
void sxmarkers(float_rgba *s, int w, int h, int x0, int y0, int np, int sx, int sy, int vp)
{
int np2,x,y,i,j;
@@ -251,7 +251,7 @@
s[w*y+x]=white;
x=x0+(np+2)*vp-i-1;
s[w*y+x]=white;
- }
+ }
}
if (sy>np)
{
@@ -263,7 +263,7 @@
s[w*y+x]=white;
y=y0+(np+2)*vp-i-1;
s[w*y+x]=white;
- }
+ }
}
}
@@ -301,7 +301,7 @@
if (bw==1) //big window
{
vx=240;
- vy = (m<=2) ? 320 : 300;
+ vy = (m<=2) ? 320 : 300;
x0 = (*poz==0) ? h/20 : w-h/20-vx;
np=25; //size of magnifier
xn = (m<=2) ? x0+8 : x0+70;
@@ -745,4 +745,3 @@
floatrgba2color(in->sl, outframe, in->w , in->h);
}
-
diff --git a/src/filter/measure/measure_pr0file.c b/src/filter/measure/measure_pr0file.c
index 83c5ef6..72335b1 100644
--- a/src/filter/measure/measure_pr0file.c
+++ b/src/filter/measure/measure_pr0file.c
@@ -114,7 +114,7 @@
//justified
//p=0 one decimal place p=1 three decimal places
//m=1 always show sign
-void forstr(float a, int p, int m, char *s)
+inline static void forstr(float a, int p, int m, char *s)
{
float b;
char *p3=" %5.3f";
@@ -320,7 +320,7 @@
if (m1>0)
{
forstr(data[0],1-u,0,frs);
- sprintf(fs,"%%s Mk1=%s", frs);
+ snprintf(fs,255,"%%s Mk1=%s", frs);
sprintf(str,fs,str,data[0]);
}
else
@@ -331,7 +331,7 @@
if (m2>0)
{
forstr(data[1],1-u,0,frs);
- sprintf(fs,"%%s Mk2=%s", frs);
+ snprintf(fs,255,"%%s Mk2=%s", frs);
sprintf(str,fs,str,data[1]);
}
else
@@ -342,7 +342,7 @@
if ((m2>0)&&(m1>0))
{
forstr(data[2],1-u,0,frs);
- sprintf(fs,"%%s D=%s", frs);
+ snprintf(fs,255,"%%s D=%s", frs);
sprintf(str,fs,str,data[2]);
}
else
@@ -351,25 +351,25 @@
if ((dit&0x00000020)!=0) //average of profile
{
forstr(data[3],1-u,0,frs);
- sprintf(fs,"%%s Avg=%s", frs);
+ snprintf(fs,255,"%%s Avg=%s", frs);
sprintf(str,fs,str,data[3]);
}
if ((dit&0x00000040)!=0) //RMS of profile
{
forstr(data[4],1-u,0,frs);
- sprintf(fs,"%%s RMS=%s", frs);
+ snprintf(fs,255,"%%s RMS=%s", frs);
sprintf(str,fs,str,data[4]);
}
if ((dit&0x00000080)!=0) //MIN of profile
{
forstr(data[5],1-u,0,frs);
- sprintf(fs,"%%s Min=%s", frs);
+ snprintf(fs,255,"%%s Min=%s", frs);
sprintf(str,fs,str,data[5]);
}
if ((dit&0x00000100)!=0) //MAX of profile
{
forstr(data[6],1-u,0,frs);
- sprintf(fs,"%%s Max=%s", frs);
+ snprintf(fs,255,"%%s Max=%s", frs);
sprintf(str,fs,str,data[6]);
}
}
@@ -408,7 +408,7 @@
if (y>h/2+20) *poz=0; //top
x0=h/20;
vx=w*15/16;
-vy = h*6/16;
+vy = h*6/16;
y0 = (*poz==0) ? h/20 : h-h/20-vy;
//end points of profile
@@ -1035,4 +1035,3 @@
floatrgba2color(in->sl, outframe, in->w , in->h);
}
-
diff --git a/src/filter/medians/ctmf.h b/src/filter/medians/ctmf.h
index f956aa6..317d04f 100644
--- a/src/filter/medians/ctmf.h
+++ b/src/filter/medians/ctmf.h
@@ -336,7 +336,7 @@
* odd dimensions. Images of arbitrary size may be processed.
*
* To process multi-channel images, you must call this function multiple times,
- * changing the source and destination adresses and steps such that each channel
+ * changing the source and destination addresses and steps such that each channel
* is processed as an independent single-channel image.
*
* Processing images of arbitrary bit depth is not supported.
diff --git a/src/filter/medians/medians.c b/src/filter/medians/medians.c
index 48293c4..2b1c73a 100644
--- a/src/filter/medians/medians.c
+++ b/src/filter/medians/medians.c
@@ -68,8 +68,8 @@
ML3DEX: multilevel spatio-temporal, see [1]
-[1] Anil Christopher Kokaram: Motion Picure Restoration
- phd disertation
+[1] Anil Christopher Kokaram: Motion Picture Restoration
+ phd dissertation
****************************************** */
diff --git a/src/filter/medians/readme b/src/filter/medians/readme
index 64a434b..754ee7f 100755
--- a/src/filter/medians/readme
+++ b/src/filter/medians/readme
@@ -114,5 +114,5 @@
http://nomis80.org/ctmf.pdf
http://nomis80.org/ctmf.html
-[3] Anil Christopher Kokaram: Motion Picure Restoration
- phd disertation
+[3] Anil Christopher Kokaram: Motion Picture Restoration
+ phd dissertation
diff --git a/src/filter/nervous/nervous.cpp b/src/filter/nervous/nervous.cpp
index 1a2d8d7..7d79f7f 100644
--- a/src/filter/nervous/nervous.cpp
+++ b/src/filter/nervous/nervous.cpp
@@ -4,7 +4,7 @@
*
* 2002/2/9
* Original code copied same frame twice, and did not use memcpy().
- * I modifed those point.
+ * I modified those point.
* -Kentarou Fukuchi
*
* 2009/8/26
diff --git a/src/filter/ntsc/crt_core.c b/src/filter/ntsc/crt_core.c
index 1202d38..3dfed0c 100644
--- a/src/filter/ntsc/crt_core.c
+++ b/src/filter/ntsc/crt_core.c
@@ -57,6 +57,23 @@
if (n > ((T14_2PI >> 1) - 1)) {
*c = -*c;
*s = -*s;
+ }
+}
+
+extern int
+crt_bpp4fmt(int format)
+{
+ switch (format) {
+ case CRT_PIX_FORMAT_RGB:
+ case CRT_PIX_FORMAT_BGR:
+ return 3;
+ case CRT_PIX_FORMAT_ARGB:
+ case CRT_PIX_FORMAT_RGBA:
+ case CRT_PIX_FORMAT_ABGR:
+ case CRT_PIX_FORMAT_BGRA:
+ return 4;
+ default:
+ return 0;
}
}
@@ -222,10 +239,11 @@
/*****************************************************************************/
extern void
-crt_resize(struct CRT *v, int w, int h, unsigned char *out)
+crt_resize(struct CRT *v, int w, int h, int f, unsigned char *out)
{
v->outw = w;
v->outh = h;
+ v->out_format = f;
v->out = out;
}
@@ -239,22 +257,14 @@
v->black_point = 0;
v->white_point = 100;
v->hsync = 0;
- v->vsync = 0;
-
- v->scanlines = 0; /* leave gaps between lines if necessary */
- v->blend = 0; /* blend new field onto previous image */
-
- // these options were previously #defined in crt_core.h
- v->crt_do_vsync = 1;
- v->crt_do_hsync = 1;
- v->do_vhs_noise = 0;
+ v->vsync = 0;
}
extern void
-crt_init(struct CRT *v, int w, int h, unsigned char *out)
+crt_init(struct CRT *v, int w, int h, int f, unsigned char *out)
{
memset(v, 0, sizeof(struct CRT));
- crt_resize(v, w, h, out);
+ crt_resize(v, w, h, f, out);
crt_reset(v);
v->rn = 194;
@@ -293,58 +303,61 @@
int huesn, huecs;
int xnudge = -3, ynudge = 3;
int bright = v->brightness - (BLACK_LEVEL + v->black_point);
- int pitch;
-
- pitch = v->outw * BPP;
+ int bpp, pitch;
+#if CRT_DO_BLOOM
+ int prev_e; /* filtered beam energy per scan line */
+ int max_e; /* approx maximum energy in a scan line */
+#endif
+
+ bpp = crt_bpp4fmt(v->out_format);
+ if (bpp == 0) {
+ return;
+ }
+ pitch = v->outw * bpp;
crt_sincos14(&huesn, &huecs, ((v->hue % 360) + 33) * 8192 / 180);
huesn >>= 11; /* make 4-bit */
huecs >>= 11;
rn = v->rn;
- if(!v->crt_do_vsync)
- {
- /* determine field before we add noise,
- * otherwise it's not reliably recoverable
- */
- for (i = -CRT_VSYNC_WINDOW; i < CRT_VSYNC_WINDOW; i++) {
- line = POSMOD(v->vsync + i, CRT_VRES);
- sig = v->analog + line * CRT_HRES;
- s = 0;
- for (j = 0; j < CRT_HRES; j++) {
- s += sig[j];
- if (s <= (CRT_VSYNC_THRESH * SYNC_LEVEL)) {
- goto found_field;
- }
+#if !CRT_DO_VSYNC
+ /* determine field before we add noise,
+ * otherwise it's not reliably recoverable
+ */
+ for (i = -CRT_VSYNC_WINDOW; i < CRT_VSYNC_WINDOW; i++) {
+ line = POSMOD(v->vsync + i, CRT_VRES);
+ sig = v->analog + line * CRT_HRES;
+ s = 0;
+ for (j = 0; j < CRT_HRES; j++) {
+ s += sig[j];
+ if (s <= (CRT_VSYNC_THRESH * SYNC_LEVEL)) {
+ goto found_field;
}
}
- found_field:
- /* if vsync signal was in second half of line, odd field */
- field = (j > (CRT_HRES / 2));
- v->vsync = -3;
- }
- if(v->do_vhs_noise)
- {
- line = ((rand() % 8) - 4) + 14;
- }
+ }
+found_field:
+ /* if vsync signal was in second half of line, odd field */
+ field = (j > (CRT_HRES / 2));
+ v->vsync = -3;
+#endif
+#if ((CRT_SYSTEM == CRT_SYSTEM_NTSCVHS) && CRT_VHS_NOISE)
+ line = ((rand() % 8) - 4) + 14;
+#endif
for (i = 0; i < CRT_INPUT_SIZE; i++) {
int nn = noise;
- if(v->do_vhs_noise)
- {
- rn = rand();
- if (i > (CRT_INPUT_SIZE - CRT_HRES * (16 + ((rand() % 20) - 10))) &&
- i < (CRT_INPUT_SIZE - CRT_HRES * (5 + ((rand() % 8) - 4)))) {
- int ln, sn, cs;
-
- ln = (i * line) / CRT_HRES;
- crt_sincos14(&sn, &cs, ln * 8192 / 180);
- nn = cs >> 8;
- }
- }
- else
- {
- rn = (214019 * rn + 140327895);
- }
+#if ((CRT_SYSTEM == CRT_SYSTEM_NTSCVHS) && CRT_VHS_NOISE)
+ rn = rand();
+ if (i > (CRT_INPUT_SIZE - CRT_HRES * (16 + ((rand() % 20) - 10))) &&
+ i < (CRT_INPUT_SIZE - CRT_HRES * (5 + ((rand() % 8) - 4)))) {
+ int ln, sn, cs;
+
+ ln = (i * line) / CRT_HRES;
+ crt_sincos14(&sn, &cs, ln * 8192 / 180);
+ nn = cs >> 8;
+ }
+#else
+ rn = (214019 * rn + 140327895);
+#endif
/* signal + noise */
s = v->analog[i] + (((((rn >> 16) & 0xff) - 0x7f) * nn) >> 8);
if (s > 127) { s = 127; }
@@ -353,37 +366,40 @@
}
v->rn = rn;
- if(v->crt_do_vsync)
- {
- /* Look for vertical sync.
- *
- * This is done by integrating the signal and
- * seeing if it exceeds a threshold. The threshold of
- * the vertical sync pulse is much higher because the
- * vsync pulse is a lot longer than the hsync pulse.
- * The signal needs to be integrated to lessen
- * the noise in the signal.
- */
- for (i = -CRT_VSYNC_WINDOW; i < CRT_VSYNC_WINDOW; i++) {
- line = POSMOD(v->vsync + i, CRT_VRES);
- sig = v->inp + line * CRT_HRES;
- s = 0;
- for (j = 0; j < CRT_HRES; j++) {
- s += sig[j];
- /* increase the multiplier to make the vsync
- * more stable when there is a lot of noise
- */
- if (s <= (CRT_VSYNC_THRESH * SYNC_LEVEL)) {
- goto vsync_found;
- }
+#if CRT_DO_VSYNC
+ /* Look for vertical sync.
+ *
+ * This is done by integrating the signal and
+ * seeing if it exceeds a threshold. The threshold of
+ * the vertical sync pulse is much higher because the
+ * vsync pulse is a lot longer than the hsync pulse.
+ * The signal needs to be integrated to lessen
+ * the noise in the signal.
+ */
+ for (i = -CRT_VSYNC_WINDOW; i < CRT_VSYNC_WINDOW; i++) {
+ line = POSMOD(v->vsync + i, CRT_VRES);
+ sig = v->inp + line * CRT_HRES;
+ s = 0;
+ for (j = 0; j < CRT_HRES; j++) {
+ s += sig[j];
+ /* increase the multiplier to make the vsync
+ * more stable when there is a lot of noise
+ */
+ if (s <= (CRT_VSYNC_THRESH * SYNC_LEVEL)) {
+ goto vsync_found;
}
}
- vsync_found:
- v->vsync = line; /* vsync found (or gave up) at this line */
- /* if vsync signal was in second half of line, odd field */
- field = (j > (CRT_HRES / 2));
- }
-
+ }
+vsync_found:
+ v->vsync = line; /* vsync found (or gave up) at this line */
+ /* if vsync signal was in second half of line, odd field */
+ field = (j > (CRT_HRES / 2));
+#endif
+
+#if CRT_DO_BLOOM
+ max_e = (128 + (noise / 2)) * AV_LEN;
+ prev_e = (16384 / 8);
+#endif
/* ratio of output height to active video lines in the signal */
ratio = (v->outh << 16) / CRT_LINES;
ratio = (ratio + 32768) >> 16;
@@ -405,6 +421,9 @@
int xpos, ypos;
int beg, end;
int phasealign;
+#if CRT_DO_BLOOM
+ int line_w;
+#endif
beg = (line - CRT_TOP + 0) * (v->outh + v->v_fac) / CRT_LINES + field;
end = (line - CRT_TOP + 1) * (v->outh + v->v_fac) / CRT_LINES + field;
@@ -424,14 +443,11 @@
break;
}
}
- if(v->crt_do_hsync)
- {
- v->hsync = POSMOD(i + v->hsync, CRT_HRES);
- }
- else
- {
- v->hsync = 0;
- }
+#if CRT_DO_HSYNC
+ v->hsync = POSMOD(i + v->hsync, CRT_HRES);
+#else
+ v->hsync = 0;
+#endif
xpos = POSMOD(AV_BEG + v->hsync + xnudge, CRT_HRES);
ypos = POSMOD(line + v->vsync + ynudge, CRT_VRES);
@@ -493,13 +509,28 @@
}
#endif
sig = v->inp + pos;
-
+#if CRT_DO_BLOOM
+ s = 0;
+ for (i = 0; i < AV_LEN; i++) {
+ s += sig[i]; /* sum up the scan line */
+ }
+ /* bloom emulation */
+ prev_e = (prev_e * 123 / 128) + ((((max_e >> 1) - s) << 10) / max_e);
+ line_w = (AV_LEN * 112 / 128) + (prev_e >> 9);
+
+ dx = (line_w << 12) / v->outw;
+ scanL = ((AV_LEN / 2) - (line_w >> 1) + 8) << 12;
+ scanR = (AV_LEN - 1) << 12;
+
+ L = (scanL >> 12);
+ R = (scanR >> 12);
+#else
dx = ((AV_LEN - 1) << 12) / v->outw;
scanL = 0;
scanR = (AV_LEN - 1) << 12;
L = 0;
- R = AV_LEN;
-
+ R = AV_LEN;
+#endif
reset_eq(&eqY);
reset_eq(&eqI);
reset_eq(&eqQ);
@@ -552,8 +583,26 @@
if (v->blend) {
aa = (r << 16 | g << 8 | b);
- bb = cL[0] << 16 | cL[1] << 8 | cL[2];
-
+
+ switch (v->out_format) {
+ case CRT_PIX_FORMAT_RGB:
+ case CRT_PIX_FORMAT_RGBA:
+ bb = cL[0] << 16 | cL[1] << 8 | cL[2];
+ break;
+ case CRT_PIX_FORMAT_BGR:
+ case CRT_PIX_FORMAT_BGRA:
+ bb = cL[2] << 16 | cL[1] << 8 | cL[0];
+ break;
+ case CRT_PIX_FORMAT_ARGB:
+ bb = cL[1] << 16 | cL[2] << 8 | cL[3];
+ break;
+ case CRT_PIX_FORMAT_ABGR:
+ bb = cL[3] << 16 | cL[2] << 8 | cL[1];
+ break;
+ default:
+ bb = 0;
+ break;
+ }
/* blend with previous color there */
bb = (((aa & 0xfefeff) >> 1) + ((bb & 0xfefeff) >> 1));
@@ -561,12 +610,52 @@
bb = (r << 16 | g << 8 | b);
}
- cL[0] = bb >> 16 & 0xff;
- cL[1] = bb >> 8 & 0xff;
- cL[2] = bb >> 0 & 0xff;
- cL[3] = 0xff;
-
- cL += BPP;
+ switch (v->out_format) {
+ case CRT_PIX_FORMAT_RGB:
+ cL[0] = bb >> 16 & 0xff;
+ cL[1] = bb >> 8 & 0xff;
+ cL[2] = bb >> 0 & 0xff;
+ break;
+
+ case CRT_PIX_FORMAT_RGBA:
+ cL[0] = bb >> 16 & 0xff;
+ cL[1] = bb >> 8 & 0xff;
+ cL[2] = bb >> 0 & 0xff;
+ cL[3] = 0xff;
+ break;
+
+ case CRT_PIX_FORMAT_BGR:
+ cL[0] = bb >> 0 & 0xff;
+ cL[1] = bb >> 8 & 0xff;
+ cL[2] = bb >> 16 & 0xff;
+ break;
+
+ case CRT_PIX_FORMAT_BGRA:
+ cL[0] = bb >> 0 & 0xff;
+ cL[1] = bb >> 8 & 0xff;
+ cL[2] = bb >> 16 & 0xff;
+ cL[3] = 0xff;
+ break;
+
+ case CRT_PIX_FORMAT_ARGB:
+ cL[0] = 0xff;
+ cL[1] = bb >> 16 & 0xff;
+ cL[2] = bb >> 8 & 0xff;
+ cL[3] = bb >> 0 & 0xff;
+ break;
+
+ case CRT_PIX_FORMAT_ABGR:
+ cL[0] = 0xff;
+ cL[1] = bb >> 0 & 0xff;
+ cL[2] = bb >> 8 & 0xff;
+ cL[3] = bb >> 16 & 0xff;
+ break;
+
+ default:
+ break;
+ }
+
+ cL += bpp;
}
/* duplicate extra lines */
diff --git a/src/filter/ntsc/crt_core.h b/src/filter/ntsc/crt_core.h
index eed9332..456191b 100644
--- a/src/filter/ntsc/crt_core.h
+++ b/src/filter/ntsc/crt_core.h
@@ -18,36 +18,72 @@
/* crt_core.h
*
* The demodulator. This is also where you can define which system to emulate.
- *
+ *
*/
-
+
/* library version */
#define CRT_MAJOR 2
#define CRT_MINOR 3
#define CRT_PATCH 2
-#include "crt_ntsc.h"
-
-// frei0r always uses 4 bits per pixel so it is pointless for there to be any other possibilities
-#define BPP 4
+
+#define CRT_SYSTEM_NTSC 0 /* standard NTSC */
+#define CRT_SYSTEM_NES 1 /* decode 6 or 9-bit NES pixels */
+#define CRT_SYSTEM_PV1K 2 /* Casio PV-1000 */
+#define CRT_SYSTEM_SNES 3 /* SNES - uses RGB */
+#define CRT_SYSTEM_TEMP 4 /* template implementation */
+#define CRT_SYSTEM_NTSCVHS 5 /* standard NTSC VHS */
+#define CRT_SYSTEM_NESRGB 6 /* encode RGB image with NES artifacts */
+
+/* the system to be compiled */
+#ifndef CRT_SYSTEM
+#define CRT_SYSTEM CRT_SYSTEM_NTSC
+#endif
+
+#if (CRT_SYSTEM == CRT_SYSTEM_NES)
+#include "crt_nes.h"
+#elif (CRT_SYSTEM == CRT_SYSTEM_SNES)
+#include "crt_snes.h"
+#elif (CRT_SYSTEM == CRT_SYSTEM_NTSC)
+#include "crt_ntsc.h"
+#elif (CRT_SYSTEM == CRT_SYSTEM_PV1K)
+#include "crt_pv1k.h"
+#elif (CRT_SYSTEM == CRT_SYSTEM_TEMP)
+#include "crt_template.h"
+#elif (CRT_SYSTEM == CRT_SYSTEM_NTSCVHS)
+#include "crt_ntscvhs.h"
+#elif (CRT_SYSTEM == CRT_SYSTEM_NESRGB)
+#include "crt_nesrgb.h"
+#else
+#error No system defined
+#endif
+
+/* NOTE: this library does not use the alpha channel at all */
+#define CRT_PIX_FORMAT_RGB 0 /* 3 bytes per pixel [R,G,B,R,G,B,R,G,B...] */
+#define CRT_PIX_FORMAT_BGR 1 /* 3 bytes per pixel [B,G,R,B,G,R,B,G,R...] */
+#define CRT_PIX_FORMAT_ARGB 2 /* 4 bytes per pixel [A,R,G,B,A,R,G,B...] */
+#define CRT_PIX_FORMAT_RGBA 3 /* 4 bytes per pixel [R,G,B,A,R,G,B,A...] */
+#define CRT_PIX_FORMAT_ABGR 4 /* 4 bytes per pixel [A,B,G,R,A,B,G,R...] */
+#define CRT_PIX_FORMAT_BGRA 5 /* 4 bytes per pixel [B,G,R,A,B,G,R,A...] */
+
+/* do bloom emulation (side effect: makes screen have black borders) */
+#define CRT_DO_BLOOM 0 /* does not work for NES */
+#define CRT_DO_VSYNC 1 /* look for VSYNC */
+#define CRT_DO_HSYNC 1 /* look for HSYNC */
struct CRT {
signed char analog[CRT_INPUT_SIZE];
signed char inp[CRT_INPUT_SIZE]; /* CRT input, can be noisy */
int outw, outh; /* output width/height */
+ int out_format; /* output pixel format (one of the CRT_PIX_FORMATs) */
unsigned char *out; /* output image */
int hue, brightness, contrast, saturation; /* common monitor settings */
int black_point, white_point; /* user-adjustable */
int scanlines; /* leave gaps between lines if necessary */
int blend; /* blend new field onto previous image */
- unsigned v_fac; /* factor to stretch img vertically onto the output img */
-
- // these options were previously #defined in crt_core.h
- int crt_do_vsync;
- int crt_do_hsync;
- int do_vhs_noise; /* 0 = no additional vhs noise, 1 = with additional vhs noise */
+ unsigned v_fac; /* factor to stretch img vertically onto the output img */
/* internal data */
int ccf[CRT_CC_VPER][CRT_CC_SAMPLES]; /* faster color carrier convergence */
@@ -61,7 +97,7 @@
* f - format of the output image
* out - pointer to output image data
*/
-extern void crt_init(struct CRT *v, int w, int h, unsigned char *out);
+extern void crt_init(struct CRT *v, int w, int h, int f, unsigned char *out);
/* Updates the output image parameters
* w - width of the output image
@@ -69,7 +105,7 @@
* f - format of the output image
* out - pointer to output image data
*/
-extern void crt_resize(struct CRT *v, int w, int h, unsigned char *out);
+extern void crt_resize(struct CRT *v, int w, int h, int f, unsigned char *out);
/* Resets the CRT settings back to their defaults */
extern void crt_reset(struct CRT *v);
@@ -78,11 +114,19 @@
* s - struct containing settings to apply to this field
*/
extern void crt_modulate(struct CRT *v, struct NTSC_SETTINGS *s);
-
+
/* Demodulates the NTSC signal generated by crt_modulate()
* noise - the amount of noise added to the signal (0 - inf)
*/
extern void crt_demodulate(struct CRT *v, int noise);
+
+/* Get the bytes per pixel for a certain CRT_PIX_FORMAT_
+ *
+ * format - the format to get the bytes per pixel for
+ *
+ * returns 0 if the specified format does not exist
+ */
+extern int crt_bpp4fmt(int format);
/*****************************************************************************/
/*************************** FIXED POINT SIN/COS *****************************/
diff --git a/src/filter/ntsc/crt_ntsc.c b/src/filter/ntsc/crt_ntsc.c
index 7933b73..107a2ea 100644
--- a/src/filter/ntsc/crt_ntsc.c
+++ b/src/filter/ntsc/crt_ntsc.c
@@ -1,9 +1,9 @@
/*****************************************************************************/
/*
* NTSC/CRT - integer-only NTSC video signal encoding / decoding emulation
- *
+ *
* by EMMIR 2018-2023
- *
+ *
* YouTube: https://www.youtube.com/@EMMIR_KC/videos
* Discord: https://discord.com/invite/hdYctSmyQJ
*/
@@ -11,7 +11,7 @@
#include "crt_core.h"
-#if (CRT_SYSTEM == CRT_SYSTEM_NTSCVHS)
+#if (CRT_SYSTEM == CRT_SYSTEM_NTSC)
#include
#include
@@ -35,7 +35,7 @@
15133, /* e^2 */
41135, /* e^3 */
111817 /* e^4 */
-};
+};
/* fixed point e^x */
static int
@@ -61,7 +61,7 @@
if (idx > 0) {
res = EXP_MUL(res, e11[idx]);
}
-
+
n &= EXP_MASK;
nxt = EXP_ONE;
acc = 0;
@@ -99,7 +99,7 @@
init_iir(struct IIRLP *f, int freq, int limit)
{
int rate; /* cycles/pixel rate */
-
+
memset(f, 0, sizeof(struct IIRLP));
rate = (freq << 9) / limit;
f->c = EXP_ONE - expx(-((EXP_PI << 9) / rate));
@@ -137,41 +137,29 @@
int ccburst[CRT_CC_SAMPLES]; /* color phase for burst */
int sn, cs, n, ph;
int inv_phase = 0;
- int aberration = 0;
+ int bpp;
if (!s->iirs_initialized) {
- int y_freq = Y_FREQ_OFF;
- int i_freq = I_FREQ_OFF;
- int q_freq = Q_FREQ_OFF;
-
- switch(s->vhs_mode)
- {
- case VHS_OFF:
- break;
- case VHS_SP:
- y_freq = Y_FREQ_SP;
- i_freq = I_FREQ_SP;
- q_freq = Q_FREQ_SP;
- break;
- case VHS_LP:
- y_freq = Y_FREQ_LP;
- i_freq = I_FREQ_LP;
- q_freq = Q_FREQ_LP;
- break;
- case VHS_EP:
- y_freq = Y_FREQ_EP;
- i_freq = I_FREQ_EP;
- q_freq = Q_FREQ_EP;
- break;
- default:
- break;
- }
-
- init_iir(&iirY, L_FREQ, y_freq);
- init_iir(&iirI, L_FREQ, i_freq);
- init_iir(&iirQ, L_FREQ, q_freq);
+ init_iir(&iirY, L_FREQ, Y_FREQ);
+ init_iir(&iirI, L_FREQ, I_FREQ);
+ init_iir(&iirQ, L_FREQ, Q_FREQ);
s->iirs_initialized = 1;
}
+#if CRT_DO_BLOOM
+ if (s->raw) {
+ destw = s->w;
+ desth = s->h;
+ if (destw > ((AV_LEN * 55500) >> 16)) {
+ destw = ((AV_LEN * 55500) >> 16);
+ }
+ if (desth > ((CRT_LINES * 63500) >> 16)) {
+ desth = ((CRT_LINES * 63500) >> 16);
+ }
+ } else {
+ destw = (AV_LEN * 55500) >> 16;
+ desth = (CRT_LINES * 63500) >> 16;
+ }
+#else
if (s->raw) {
destw = s->w;
desth = s->h;
@@ -182,7 +170,7 @@
desth = ((CRT_LINES * 64500) >> 16);
}
}
-
+#endif
if (s->as_color) {
for (x = 0; x < CRT_CC_SAMPLES; x++) {
n = s->hue + x * (360 / CRT_CC_SAMPLES);
@@ -198,10 +186,14 @@
memset(ccmodI, 0, sizeof(ccmodI));
memset(ccmodQ, 0, sizeof(ccmodQ));
}
-
+
+ bpp = crt_bpp4fmt(s->format);
+ if (bpp == 0) {
+ return; /* just to be safe */
+ }
xo = AV_BEG + s->xoffset + (AV_LEN - destw) / 2;
yo = CRT_TOP + s->yoffset + (CRT_LINES - desth) / 2;
-
+
s->field &= 1;
s->frame &= 1;
inv_phase = (s->field == s->frame);
@@ -209,13 +201,11 @@
/* align signal */
xo = (xo & ~3);
- if (s->do_aberration) {
- aberration = ((rand() % 12) - 8) + 14;
- }
+
for (n = 0; n < CRT_VRES; n++) {
int t; /* time */
signed char *line = &v->analog[n * CRT_HRES];
-
+
t = LINE_BEG;
if (n <= 3 || (n >= 7 && n <= 9)) {
@@ -238,13 +228,11 @@
while (t < (offs[3] * CRT_HRES / 100)) line[t++] = BLANK_LEVEL;
} else {
int cb;
- if (n < (CRT_VRES - aberration)) {
- /* video line */
- while (t < SYNC_BEG) line[t++] = BLANK_LEVEL; /* FP */
- while (t < BW_BEG) line[t++] = SYNC_LEVEL; /* SYNC */
- }
+
+ /* video line */
+ while (t < SYNC_BEG) line[t++] = BLANK_LEVEL; /* FP */
+ while (t < BW_BEG) line[t++] = SYNC_LEVEL; /* SYNC */
while (t < AV_BEG) line[t++] = BLANK_LEVEL; /* BW + CB + BP */
-
if (n < CRT_TOP) {
while (t < CRT_HRES) line[t++] = BLANK_LEVEL;
}
@@ -261,50 +249,67 @@
iccf[t % CRT_CC_SAMPLES] = line[t];
}
}
- }
-
- if(s->vhs_mode != VHS_OFF)
- {
- /* reset hsync every frame so only the bottom part is warped */
- v->hsync = 0;
}
for (y = 0; y < desth; y++) {
int field_offset;
int sy;
-
+
field_offset = (s->field * s->h + desth) / desth / 2;
sy = (y * s->h) / desth;
-
+
sy += field_offset;
if (sy >= s->h) sy = s->h;
-
+
sy *= s->w;
-
+
reset_iir(&iirY);
reset_iir(&iirI);
reset_iir(&iirQ);
-
+
for (x = 0; x < destw; x++) {
int fy, fi, fq;
int rA, gA, bA;
const unsigned char *pix;
int ire; /* composite signal */
int xoff;
-
- pix = s->data + ((((x * s->w) / destw) + sy) * BPP);
- rA = pix[0];
- gA = pix[1];
- bA = pix[2];
-
+
+ pix = s->data + ((((x * s->w) / destw) + sy) * bpp);
+ switch (s->format) {
+ case CRT_PIX_FORMAT_RGB:
+ case CRT_PIX_FORMAT_RGBA:
+ rA = pix[0];
+ gA = pix[1];
+ bA = pix[2];
+ break;
+ case CRT_PIX_FORMAT_BGR:
+ case CRT_PIX_FORMAT_BGRA:
+ rA = pix[2];
+ gA = pix[1];
+ bA = pix[0];
+ break;
+ case CRT_PIX_FORMAT_ARGB:
+ rA = pix[1];
+ gA = pix[2];
+ bA = pix[3];
+ break;
+ case CRT_PIX_FORMAT_ABGR:
+ rA = pix[3];
+ gA = pix[2];
+ bA = pix[1];
+ break;
+ default:
+ rA = gA = bA = 0;
+ break;
+ }
/* RGB to YIQ */
fy = (19595 * rA + 38470 * gA + 7471 * bA) >> 14;
fi = (39059 * rA - 18022 * gA - 21103 * bA) >> 14;
fq = (13894 * rA - 34275 * gA + 20382 * bA) >> 14;
ire = BLACK_LEVEL + v->black_point;
-
+
xoff = (x + xo) % CRT_CC_SAMPLES;
/* bandlimit Y,I,Q */
fy = iirf(&iirY, fy);
@@ -319,15 +324,8 @@
}
for (n = 0; n < CRT_CC_VPER; n++) {
for (x = 0; x < CRT_CC_SAMPLES; x++) {
- if(s->vhs_mode != VHS_OFF)
- {
- v->ccf[n][x] = 0;
- }
- else
- {
- v->ccf[n][x] = iccf[x] << 7;
- }
- }
- }
-}
-#endif
+ v->ccf[n][x] = iccf[x] << 7;
+ }
+ }
+}
+#endif
diff --git a/src/filter/ntsc/crt_ntsc.h b/src/filter/ntsc/crt_ntsc.h
index a979ff9..2a6f0e9 100644
--- a/src/filter/ntsc/crt_ntsc.h
+++ b/src/filter/ntsc/crt_ntsc.h
@@ -8,18 +8,17 @@
* Discord: https://discord.com/invite/hdYctSmyQJ
*/
/*****************************************************************************/
-#ifndef _CRT_NTSC_VHS_H_
-#define _CRT_NTSC_VHS_H_
+#ifndef _CRT_NTSC_H_
+#define _CRT_NTSC_H_
#ifdef __cplusplus
extern "C" {
#endif
-/* crt_ntscvhs.h
+/* crt_ntsc.h
*
- * An interface to convert a digital image to an analog NTSC signal with VHS
- * quality and some optional signal aberration at the bottom.
- *
+ * An interface to convert a digital image to an analog NTSC signal.
+ *
*/
/* 0 = vertical chroma (228 chroma clocks per line) */
/* 1 = checkered chroma (227.5 chroma clocks per line) */
@@ -42,7 +41,7 @@
#define CRT_TOP 21 /* first line with active video */
#define CRT_BOT 261 /* final line with active video */
#define CRT_LINES (CRT_BOT - CRT_TOP) /* number of active video lines */
-
+
#define CRT_CC_SAMPLES 4 /* samples per chroma period (samples per 360 deg) */
#define CRT_CC_VPER 1 /* vertical period in which the artifacts repeat */
@@ -62,14 +61,14 @@
* |---------------------------------------------------------------------------|
* HBLANK (~10900 ns) ACTIVE VIDEO (~52600 ns)
* |-------------------||------------------------------------------------------|
- *
- *
+ *
+ *
* WITHIN HBLANK PERIOD:
- *
+ *
* FP (~1500 ns) SYNC (~4700 ns) BW (~600 ns) CB (~2500 ns) BP (~1600 ns)
* |--------------||---------------||------------||-------------||-------------|
* BLANK SYNC BLANK BLANK BLANK
- *
+ *
*/
#define LINE_BEG 0
#define FP_ns 1500 /* front porch */
@@ -95,33 +94,12 @@
/* somewhere between 7 and 12 cycles */
#define CB_CYCLES 10
-
-#define VHS_OFF 0
-#define VHS_SP 1
-#define VHS_LP 2
-#define VHS_EP 3
-#define VHS_MODE VHS_OFF
-
-/* frequencies for bandlimiting */
-#define L_FREQ 1431818 /* full line */
-
-#define Y_FREQ_OFF 420000 /* Luma (Y) 4.2 MHz of the 14.31818 MHz */
-#define I_FREQ_OFF 150000 /* Chroma (I) 1.5 MHz of the 14.31818 MHz */
-#define Q_FREQ_OFF 55000 /* Chroma (Q) 0.55 MHz of the 14.31818 MHz */
-
-#define Y_FREQ_SP 300000 /* Luma (Y) 3.0 MHz of the 14.31818 MHz */
-#define I_FREQ_SP 62700 /* Chroma (I) 627 kHz of the 14.31818 MHz */
-#define Q_FREQ_SP 62700 /* Chroma (Q) 627 kHz of the 14.31818 MHz */
-
-#define Y_FREQ_LP 240000 /* Luma (Y) 2.4 MHz of the 14.31818 MHz */
-#define I_FREQ_LP 40000 /* Chroma (I) 400 kHz of the 14.31818 MHz */
-#define Q_FREQ_LP 40000 /* Chroma (Q) 400 kHz of the 14.31818 MHz */
-
-#define Y_FREQ_EP 200000 /* Luma (Y) 2.0 MHz of the 14.31818 MHz */
-#define I_FREQ_EP 37000 /* Chroma (I) 370 kHz of the 14.31818 MHz */
-#define Q_FREQ_EP 37000 /* Chroma (Q) 370 kHz of the 14.31818 MHz */
-
+/* frequencies for bandlimiting */
+#define L_FREQ 1431818 /* full line */
+#define Y_FREQ 420000 /* Luma (Y) 4.2 MHz of the 14.31818 MHz */
+#define I_FREQ 150000 /* Chroma (I) 1.5 MHz of the 14.31818 MHz */
+#define Q_FREQ 55000 /* Chroma (Q) 0.55 MHz of the 14.31818 MHz */
/* IRE units (100 = 1.0V, -40 = 0.0V) */
#define WHITE_LEVEL 100
@@ -132,6 +110,7 @@
struct NTSC_SETTINGS {
const unsigned char *data; /* image data */
+ int format; /* pix format (one of the CRT_PIX_FORMATs in crt_core.h) */
int w, h; /* width and height of image */
int raw; /* 0 = scale image to fit monitor, 1 = don't scale */
int as_color; /* 0 = monochrome, 1 = full color */
@@ -140,14 +119,6 @@
int hue; /* 0-359 */
int xoffset; /* x offset in sample space. 0 is minimum value */
int yoffset; /* y offset in # of lines. 0 is minimum value */
- int do_aberration; /* 0 = no aberration, 1 = with aberration */
-
- // these are changed by the vhs mode
- int vhs_mode;
- int y_freq;
- int i_freq;
- int q_freq;
-
/* make sure your NTSC_SETTINGS struct is zeroed out before you do anything */
int iirs_initialized; /* internal state */
};
diff --git a/src/filter/ntsc/ntsc-effect.c b/src/filter/ntsc/ntsc-effect.c
index e2b0c3b..d0df0c1 100644
--- a/src/filter/ntsc/ntsc-effect.c
+++ b/src/filter/ntsc/ntsc-effect.c
@@ -1,11 +1,13 @@
#include
+#include
#include "frei0r.h"
#include "frei0r/math.h"
#include "crt_core.h"
-// the actual NTSC emulation code is modified from here: https://github.com/LMP88959/NTSC-CRT
+// the actual NTSC emulation code is from here: https://github.com/LMP88959/NTSC-CRT
+
typedef struct ntsc_instance
{
@@ -15,15 +17,14 @@
// parameters
struct CRT crt;
- struct NTSC_SETTINGS ntsc_settings;
+ struct NTSC_SETTINGS ntsc;
int noise;
- double vhs_speed;
-
int field;
int progressive;
} ntsc_instance_t;
+
// these functions are for frei0r
// mostly copy/paste/slightly modified from the other frei0r effects
@@ -44,8 +45,8 @@
info->color_model = F0R_COLOR_MODEL_RGBA8888;
info->frei0r_version = FREI0R_MAJOR_VERSION;
info->major_version = 0;
- info->minor_version = 1;
- info->num_params = 8;
+ info->minor_version = 2;
+ info->num_params = 3;
}
void f0r_get_param_info(f0r_param_info_t* info, int param_index)
@@ -57,50 +58,21 @@
info->explanation = "Amount of noise introduced into the NTSC signal.";
info->type = F0R_PARAM_DOUBLE;
break;
-
+
case 1:
- info->name = "VHS Speed";
- info->explanation = "Simulates VHS. 0 = off, 1 = SP, 2 = LP, 3 = EP";
- info->type = F0R_PARAM_DOUBLE;
- break;
-
- case 2:
- info->name = "VHS Noise";
- info->explanation = "Toggles VHS noise at the bottom of the screen";
- info->type = F0R_PARAM_BOOL;
- break;
-
- case 3:
- info->name = "Aberration";
- info->explanation = "Toggles VHS aberration at the bottom of the screen. Not visible if V-sync is on.";
- info->type = F0R_PARAM_BOOL;
- break;
-
- case 4:
- info->name = "Force V-sync";
- info->explanation = "Forces V-sync even when the signal is really noisy.";
- info->type = F0R_PARAM_BOOL;
- break;
-
- case 5:
- info->name = "Force H-sync";
- info->explanation = "Forces V-sync even when the signal is really noisy.";
- info->type = F0R_PARAM_BOOL;
- break;
-
- case 6:
info->name = "Progressive Scan";
info->explanation = "Toggles progressive scan (Interlaced if off).";
info->type = F0R_PARAM_BOOL;
break;
- case 7:
- info->name = "Blend";
- info->explanation = "Blends frames.";
+ case 2:
+ info->name = "Scanlines";
+ info->explanation = "Draw borders between scanlines.";
info->type = F0R_PARAM_BOOL;
break;
}
}
+
f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
{
@@ -109,36 +81,28 @@
inst->width = width;
inst->height = height;
- inst->vhs_speed = 0.0;
+ inst->ntsc.format = CRT_PIX_FORMAT_RGBA;
+ inst->ntsc.w = width;
+ inst->ntsc.h = height;
+ inst->ntsc.raw = 0;
+ inst->ntsc.field = 0;
+ inst->ntsc.frame = 0;
+ inst->ntsc.as_color = 1;
+ inst->ntsc.hue = 0;
+ inst->ntsc.xoffset = 0;
+ inst->ntsc.yoffset = 0;
+ inst->ntsc.iirs_initialized = 0;
+
+ inst->noise = 0;
+ inst->progressive = 0;
inst->field = 0;
- inst->progressive = 1;
- crt_init(&(inst->crt), width, height, NULL);
+ crt_init(&(inst->crt), width, height, CRT_PIX_FORMAT_RGBA, NULL);
+ inst->crt.blend = 0;
+ inst->crt.scanlines = 0;
+
- // init NTSC_SETTINGS
- inst->ntsc_settings.data = NULL;
- inst->ntsc_settings.w = width;
- inst->ntsc_settings.h = height;
- inst->ntsc_settings.raw = 0;
- inst->ntsc_settings.as_color = 1;
- inst->ntsc_settings.field = 0;
- inst->ntsc_settings.frame = 0;
- inst->ntsc_settings.hue = 0;
- inst->ntsc_settings.xoffset = 0;
- inst->ntsc_settings.yoffset = 0;
- inst->ntsc_settings.do_aberration = 0;
-
- // these are changed by the vhs mode
- inst->ntsc_settings.vhs_mode = 0;
- inst->ntsc_settings.y_freq = 0;
- inst->ntsc_settings.i_freq = 0;
- inst->ntsc_settings.q_freq = 0;
-
- /* make sure your NTSC_SETTINGS struct is zeroed out before you do anything */
- inst->ntsc_settings.iirs_initialized = 0;
-
- inst->noise = 0;
-
+
return (f0r_instance_t)inst;
}
@@ -155,29 +119,13 @@
switch(param_index)
{
case 0:
- inst->noise = *((double*)param) * 100;
+ inst->noise = *((double*)param) * 200;
break;
case 1:
- inst->ntsc_settings.vhs_mode = (int)CLAMP(*((double*)param) * 4, 0, 4);
- inst->ntsc_settings.iirs_initialized = 0;
+ inst->progressive = (*((double*)param) >= 0.5);
break;
case 2:
- inst->crt.do_vhs_noise = (*((double*)param) >= 0.5);
- break;
- case 3:
- inst->ntsc_settings.do_aberration = (*((double*)param) >= 0.5);
- break;
- case 4:
- inst->crt.crt_do_vsync = !(*((double*)param) >= 0.5);
- break;
- case 5:
- inst->crt.crt_do_hsync = !(*((double*)param) >= 0.5);
- break;
- case 6:
- inst->progressive = (*((double*)param) >= 0.5);
- break;
- case 7:
- inst->crt.blend = (*((double*)param) >= 0.5);
+ inst->crt.scanlines = (*((double*)param) >= 0.5);
break;
}
}
@@ -188,50 +136,52 @@
switch(param_index)
{
case 0:
- *((double*)param) = (inst->noise / 100);
+ *((double*)param) = (inst->noise / 200);
break;
case 1:
- *((double*)param) = (inst->ntsc_settings.vhs_mode / 4);
+ *((double*)param) = (inst->progressive ? 1.0 : 0.0);
break;
case 2:
- *((double*)param) = (inst->crt.do_vhs_noise ? 1.0 : 0.0);
- break;
- case 3:
- *((double*)param) = (inst->ntsc_settings.do_aberration ? 1.0 : 0.0);
- break;
- case 4:
- *((double*)param) = !(inst->crt.crt_do_vsync ? 1.0 : 0.0);
- break;
- case 5:
- *((double*)param) = !(inst->crt.crt_do_hsync ? 1.0 : 0.0);
- break;
- case 6:
- *((double*)param) = (inst->progressive ? 1.0 : 0.0);
- break;
- case 7:
- *((double*)param) = (inst->crt.blend ? 1.0 : 0.0);
+ *((double*)param) = (inst->crt.scanlines ? 1.0 : 0.0);
break;
}
}
void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, uint32_t* outframe)
-{
+{
ntsc_instance_t* inst = (ntsc_instance_t*)instance;
+
+ // clear the output frame
+ memset(outframe, 0, inst->width * inst->height * sizeof(uint32_t));
+ inst->crt.blend = 0;
+
+ // set everything up for the simulation
+ inst->crt.out = (char*)outframe;
+ inst->ntsc.data = (const char*)inframe;
- inst->crt.out = (char*)outframe;
- inst->ntsc_settings.data = (const char*)inframe;
+_render_field:
+ inst->ntsc.field = inst->field & 1;
- inst->ntsc_settings.field = inst->field & 1;
- if (inst->ntsc_settings.field == 0) {
+ if (inst->ntsc.field == 0) {
/* a frame is two fields */
- inst->ntsc_settings.frame ^= 1;
+ inst->ntsc.frame ^= 1;
}
- crt_modulate(&(inst->crt), &(inst->ntsc_settings));
+ // encode and decode ntsc signal
+ crt_modulate(&(inst->crt), &(inst->ntsc));
crt_demodulate(&(inst->crt), inst->noise);
- if(!inst->progressive)
+
+ inst->field ^= 1;
+ // if we are in progressive mode, we render both fields onto the frame.
+ // in interlaced mode, we will hit the opposite field on the next frame.
+ if(inst->field && inst->progressive)
{
- inst->field ^= 1;
+ // if we are not leaving scanlines blank, we will want to blend the frames in progressive mode
+ if(!inst->crt.scanlines)
+ {
+ inst->crt.blend = 1;
+ }
+ goto _render_field;
}
}
diff --git a/src/filter/pixs0r/pixs0r.cc b/src/filter/pixs0r/pixs0r.cc
index 3c72b41..66a5fff 100644
--- a/src/filter/pixs0r/pixs0r.cc
+++ b/src/filter/pixs0r/pixs0r.cc
@@ -128,7 +128,7 @@
case 0:
info->name = "shift_intensity";
info->type = F0R_PARAM_DOUBLE;
- info->explanation = "Agressiveness of row/column-shifting";
+ info->explanation = "Aggressiveness of row/column-shifting";
break;
case 1:
diff --git a/src/filter/select0r/readme b/src/filter/select0r/readme
index d31b520..fe01805 100755
--- a/src/filter/select0r/readme
+++ b/src/filter/select0r/readme
@@ -38,7 +38,7 @@
Invert selection:
When ON, the selected color will be transparent, as normally used
with keying. When OFF (default) the selected color will be opaque,
-for exmaple for alpha controlled adjustment of that color only.
+for example for alpha controlled adjustment of that color only.
Delta XXXX:
These three parameters determine the size of the color subspace
diff --git a/src/filter/sigmoidaltransfer/sigmoidaltransfer.c b/src/filter/sigmoidaltransfer/sigmoidaltransfer.c
index 0ad141f..2f0079b 100644
--- a/src/filter/sigmoidaltransfer/sigmoidaltransfer.c
+++ b/src/filter/sigmoidaltransfer/sigmoidaltransfer.c
@@ -1,8 +1,10 @@
/*
- * This file is contains sigmoidal transfer function from file plug-ins/common/softglow.c in gimp.
+ * This file used to contain sigmoidal transfer function from file plug-ins/common/softglow.c in gimp.
+ * However, it is now modified to match ImageMagick; i.e. whereas only the steepness of the sigmoidal
+ * curves was tunable earlier, now the midpoint of the curve is adjustable as well -- both to a degree.
*
* sigmoidaltransfer.c
- * Copyright 2012 Janne Liljeblad
+ * Copyright 2012 Janne Liljeblad, 2025 Cynthia
*
* This file is a Frei0r plugin.
*
@@ -28,35 +30,25 @@
#include "frei0r.h"
#include "frei0r/math.h"
-#define SIGMOIDAL_BASE 2
-#define SIGMOIDAL_RANGE 20
-
typedef struct sigmoidal_instance
{
unsigned int width;
unsigned int height;
- double brightness;
+ double base;
double sharpness;
+
+ /* Precomputed values of the (scaled and shifted) sigmoid function
+ is stored in this lookup table. */
+ uint8_t lut[256];
} sigmoidal_instance_t;
-static inline int gimp_rgb_to_l_int (int red,
- int green,
- int blue)
+void gen_sigmoid_lut (uint8_t *const lut, const float base, const float sharpness)
{
- int min, max;
+ float k = expf(sharpness * 5.0) / 255.0;
+ float b = (base - 0.5) * 63.0;
- if (red > green)
- {
- max = MAX (red, blue);
- min = MIN (green, blue);
- }
- else
- {
- max = MAX (green, blue);
- min = MIN (red, blue);
- }
-
- return ROUND ((max + min) / 2.0);
+ for (int i = 0; i < 256; ++i)
+ lut[i] = CLAMP (255.0 / (1.0 + expf(-k * (i - b - 127.0))), 0, 255.0);
}
void sigmoidal_transfer(f0r_instance_t instance, double time,
@@ -65,9 +57,6 @@
assert(instance);
sigmoidal_instance_t* inst = (sigmoidal_instance_t*)instance;
unsigned int len = inst->width * inst->height;
-
- double brightness = inst->brightness;
- double sharpness = inst->sharpness;
const unsigned char* src = (unsigned char*)inframe;
unsigned char* dst = (unsigned char*)outframe;
@@ -81,13 +70,9 @@
b = *src++;
//desaturate
- luma = (unsigned char) gimp_rgb_to_l_int (r, g, b);
-
+ luma = (unsigned char)(0.299 * r + 0.587 * g + 0.114 * b);
//compute sigmoidal transfer
- val = luma / 255.0;
- val = 255.0 / (1 + exp (-(SIGMOIDAL_BASE + (sharpness * SIGMOIDAL_RANGE)) * (val - 0.5)));
- val = val * brightness;
- luma = (unsigned char) CLAMP (val, 0, 255);
+ luma = inst->lut[luma];
*dst++ = luma;
*dst++ = luma;
@@ -108,12 +93,12 @@
void f0r_get_plugin_info(f0r_plugin_info_t* sigmoidalInfo)
{
sigmoidalInfo->name = "sigmoidaltransfer";
- sigmoidalInfo->author = "Janne Liljeblad";
+ sigmoidalInfo->author = "Janne Liljeblad & Cynthia";
sigmoidalInfo->plugin_type = F0R_PLUGIN_TYPE_FILTER;
sigmoidalInfo->color_model = F0R_COLOR_MODEL_RGBA8888;
sigmoidalInfo->frei0r_version = FREI0R_MAJOR_VERSION;
- sigmoidalInfo->major_version = 0;
- sigmoidalInfo->minor_version = 9;
+ sigmoidalInfo->major_version = 1;
+ sigmoidalInfo->minor_version = 0;
sigmoidalInfo->num_params = 2;
sigmoidalInfo->explanation = "Desaturates image and creates a particular look that could be called Stamp, Newspaper or Photocopy";
}
@@ -122,15 +107,15 @@
{
switch ( param_index ) {
case 0:
- info->name = "brightness";
+ info->name = "base";
info->type = F0R_PARAM_DOUBLE;
- info->explanation = "Brightnesss of image";
+ info->explanation = "Brightness of image. Midpoint of sigmoidal curve";
break;
- case 1:
- info->name = "sharpness";
- info->type = F0R_PARAM_DOUBLE;
- info->explanation = "Sharpness of transfer";
- break;
+ case 1:
+ info->name = "sharpness";
+ info->type = F0R_PARAM_DOUBLE;
+ info->explanation = "Sharpness of transfer";
+ break;
}
}
@@ -139,8 +124,10 @@
sigmoidal_instance_t* inst = (sigmoidal_instance_t*)calloc(1, sizeof(*inst));
inst->width = width;
inst->height = height;
- inst->brightness = 0.75;
- inst->sharpness = 0.85;
+ inst->base = 0.5;
+ inst->sharpness = 3.0 / 5.0;
+
+ gen_sigmoid_lut (inst->lut, inst->base, inst->sharpness);
return (f0r_instance_t)inst;
}
@@ -156,12 +143,14 @@
switch (param_index)
{
case 0:
- inst->brightness = *((double*)param);
+ inst->base = *((double*)param);
break;
case 1:
inst->sharpness = *((double*)param);
break;
}
+
+ gen_sigmoid_lut (inst->lut, inst->base, inst->sharpness);
}
void f0r_get_param_value(f0r_instance_t instance,
@@ -171,7 +160,7 @@
switch (param_index)
{
case 0:
- *((double*)param) = inst->brightness;
+ *((double*)param) = inst->base;
break;
case 1:
*((double*)param) = inst->sharpness;
diff --git a/src/filter/sopsat/sopsat.cpp b/src/filter/sopsat/sopsat.cpp
index 7d28603..65fda2f 100644
--- a/src/filter/sopsat/sopsat.cpp
+++ b/src/filter/sopsat/sopsat.cpp
@@ -132,7 +132,7 @@
uint32_t* out,
const uint32_t* in)
{
- // Rebuild the lookup table in case the prarameters have changed.
+ // Rebuild the lookup table in case the parameters have changed.
updateLUT();
unsigned char *pixel = (unsigned char *) in;
diff --git a/src/filter/spillsupress/spillsupress.c b/src/filter/spillsupress/spillsupress.c
index 213f405..bef9e13 100644
--- a/src/filter/spillsupress/spillsupress.c
+++ b/src/filter/spillsupress/spillsupress.c
@@ -91,9 +91,9 @@
{
unsigned int width;
unsigned int height;
- double supress_type; /* type of spill supression applied to image
- <= 0.5, green supress
- > 0.5, blue supress */
+ double supress_type; /* type of spill suppression applied to image
+ <= 0.5, green suppress
+ > 0.5, blue suppress */
} spillsupress_instance_t;
int f0r_init()
@@ -134,7 +134,7 @@
spillsupress_instance_t* inst = (spillsupress_instance_t*)calloc(1, sizeof(*inst));
inst->width = width;
inst->height = height;
- inst->supress_type = 0.0; // default supress type is green supress
+ inst->supress_type = 0.0; // default suppress type is green suppress
return (f0r_instance_t)inst;
}
diff --git a/src/filter/three_point_balance/three_point_balance.c b/src/filter/three_point_balance/three_point_balance.c
index 7a3a0df..2270293 100644
--- a/src/filter/three_point_balance/three_point_balance.c
+++ b/src/filter/three_point_balance/three_point_balance.c
@@ -167,7 +167,7 @@
double* gaussSLESolve(size_t size, double* A) {
int extSize = size + 1;
- //direct way: tranform matrix A to triangular form
+ //direct way: transform matrix A to triangular form
for(int row = 0; row < size; row++) {
int col = row;
int lastRowToSwap = size - 1;
diff --git a/src/filter/tint0r/tint0r.c b/src/filter/tint0r/tint0r.c
index 2b96599..103bc3f 100644
--- a/src/filter/tint0r/tint0r.c
+++ b/src/filter/tint0r/tint0r.c
@@ -1,5 +1,6 @@
/* tint0r.c
- * Copyright (C) 2009 Maksim Golovkin (m4ks1k@gmail.com)
+ * Copyright (C) 2009 Maksim Golovkin (m4ks1k@gmail.com),
+ * 2025 Cynthia (cynthia2048@proton.me)
* This file is a Frei0r plugin.
*
* This program is free software; you can redistribute it and/or modify
@@ -17,11 +18,16 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include
#include
#include
-#include "frei0r.h"
-#include "frei0r/math.h"
+#ifdef __SSE4_1__
+#include
+#endif
+
+#include
+#include
typedef struct tint0r_instance
{
@@ -43,35 +49,35 @@
void f0r_get_plugin_info(f0r_plugin_info_t* tint0r_instance_t)
{
tint0r_instance_t->name = "Tint0r";
- tint0r_instance_t->author = "Maksim Golovkin";
+ tint0r_instance_t->author = "Maksim Golovkin & Cynthia";
tint0r_instance_t->plugin_type = F0R_PLUGIN_TYPE_FILTER;
- tint0r_instance_t->color_model = F0R_COLOR_MODEL_RGBA8888;
+ tint0r_instance_t->color_model = F0R_COLOR_MODEL_BGRA8888;
tint0r_instance_t->frei0r_version = FREI0R_MAJOR_VERSION;
- tint0r_instance_t->major_version = 0;
- tint0r_instance_t->minor_version = 1;
- tint0r_instance_t->num_params = 3;
- tint0r_instance_t->explanation = "Tint a source image with specified color";
+ tint0r_instance_t->major_version = 0;
+ tint0r_instance_t->minor_version = 1;
+ tint0r_instance_t->num_params = 3;
+ tint0r_instance_t->explanation = "Tint a source image with specified colors";
}
void f0r_get_param_info(f0r_param_info_t* info, int param_index)
{
switch(param_index)
{
- case 0:
- info->name = "Map black to";
- info->type = F0R_PARAM_COLOR;
- info->explanation = "The color to map source color with null luminance";
- break;
- case 1:
- info->name = "Map white to";
- info->type = F0R_PARAM_COLOR;
- info->explanation = "The color to map source color with full luminance";
- break;
- case 2:
- info->name = "Tint amount";
- info->type = F0R_PARAM_DOUBLE;
- info->explanation = "Amount of color";
- break;
+ case 0:
+ info->name = "Map black to";
+ info->type = F0R_PARAM_COLOR;
+ info->explanation = "The color to map source color with null luminance";
+ break;
+ case 1:
+ info->name = "Map white to";
+ info->type = F0R_PARAM_COLOR;
+ info->explanation = "The color to map source color with full luminance";
+ break;
+ case 2:
+ info->name = "Tint amount";
+ info->type = F0R_PARAM_DOUBLE;
+ info->explanation = "Amount of color";
+ break;
}
}
@@ -79,10 +85,10 @@
{
tint0r_instance_t* inst = (tint0r_instance_t*)calloc(1, sizeof(*inst));
inst->width = width; inst->height = height;
- inst->amount = .25;
- inst->whiteColor.r = .5;
+ inst->amount = 0.25;
+ inst->whiteColor.r = 0.5;
inst->whiteColor.g = 1.0;
- inst->whiteColor.b = .5;
+ inst->whiteColor.b = 0.5;
inst->blackColor.r = 0.0;
inst->blackColor.g = 0.0;
inst->blackColor.b = 0.0;
@@ -94,7 +100,7 @@
free(instance);
}
-void f0r_set_param_value(f0r_instance_t instance,
+void f0r_set_param_value(f0r_instance_t instance,
f0r_param_t param, int param_index)
{
assert(instance);
@@ -102,18 +108,18 @@
switch(param_index)
{
- case 0:
- /* black color */
- inst->blackColor = *((f0r_param_color_t *)param);
- break;
- case 1:
- /* white color */
- inst->whiteColor = *((f0r_param_color_t *)param);
- break;
- case 2:
- /* amount */
- inst->amount = *((double *)param);
- break;
+ case 0:
+ /* black color */
+ inst->blackColor = *((f0r_param_color_t *)param);
+ break;
+ case 1:
+ /* white color */
+ inst->whiteColor = *((f0r_param_color_t *)param);
+ break;
+ case 2:
+ /* amount */
+ inst->amount = *((double *)param);
+ break;
}
}
@@ -122,53 +128,110 @@
{
assert(instance);
tint0r_instance_t* inst = (tint0r_instance_t*)instance;
-
+
switch(param_index)
{
- case 0:
- *((f0r_param_color_t*)param) = inst->blackColor;
- break;
- case 1:
- *((f0r_param_color_t*)param) = inst->whiteColor;
- break;
- case 2:
- *((double *)param) = inst->amount;
- break;
- }
-}
-
-unsigned char map_color(double amount, double comp_amount, float color, float luma, float minColor, float maxColor) {
+ case 0:
+ *((f0r_param_color_t*)param) = inst->blackColor;
+ break;
+ case 1:
+ *((f0r_param_color_t*)param) = inst->whiteColor;
+ break;
+ case 2:
+ *((double *)param) = inst->amount;
+ break;
+ }
+}
+
+#ifndef __SSE4_1__
+static inline unsigned char map_color(double amount, double comp_amount, float color, float luma, float minColor, float maxColor)
+{
double val = (comp_amount * color) + amount * (luma * (maxColor - minColor) + minColor);
return (unsigned char)(255*CLAMP(val, 0, 1));
}
+#endif
void f0r_update(f0r_instance_t instance, double time,
const uint32_t* inframe, uint32_t* outframe)
{
assert(instance);
tint0r_instance_t* inst = (tint0r_instance_t*)instance;
+
+ #ifdef __SSE4_1__
+ size_t len = (inst->width * inst->height) / 4;
+
+ const __m128 weights = _mm_set_ps(0.0, 0.299, 0.587, 0.114),
+ amount = _mm_set1_ps(inst->amount),
+ /* Pass the alpha channel */
+ comp_amount = _mm_set_ps(1.0,
+ 1.0 - inst->amount,
+ 1.0 - inst->amount,
+ 1.0 - inst->amount);
+
+ f0r_param_color_t black = inst->blackColor,
+ white = inst->whiteColor;
+
+ /* Zero the alpha component to exclude it from calculations. */
+ const __m128 cmin = _mm_set_ps(0.0, black.r, black.g, black.b),
+ cdelta = _mm_sub_ps(_mm_set_ps(0.0, white.r, white.g, white.b), cmin),
+ tmp0 = _mm_mul_ps(cdelta, amount),
+ tmp1 = _mm_mul_ps(_mm_mul_ps(amount, _mm_set1_ps(255.0)), cmin);
+
+ __m128 p, p0, p1, p2, p3, luma;
+ #else
unsigned int len = inst->width * inst->height;
double amount = inst->amount;
double comp_amount = 1.0 - inst->amount;
-
+
unsigned char* dst = (unsigned char*)outframe;
const unsigned char* src = (unsigned char*)inframe;
float b, g, r;
float luma;
+ #endif
while (len--)
{
- r = *src++ / 255.;
- g = *src++ / 255.;
- b = *src++ / 255.;
-
- luma = (b * .114 + g * .587 + r * .299);
-
- *dst++ = map_color(amount, comp_amount, r, luma, inst->blackColor.r, inst->whiteColor.r);
- *dst++ = map_color(amount, comp_amount, g, luma, inst->blackColor.g, inst->whiteColor.g);
- *dst++ = map_color(amount, comp_amount, b, luma, inst->blackColor.b, inst->whiteColor.b);
-
- *dst++ = *src++; // copy alpha
- }
-}
-
+ #ifdef __SSE4_1__
+ /* Load four pixels at once. */
+ p = _mm_loadu_si128((__m128i*)inframe);
+
+ /* Extract four pixels into separate XMM registers and convert them to float. */
+ p0 = _mm_cvtepi32_ps(_mm_cvtepu8_epi32(p));
+ p1 = _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_srli_si128(p, 4)));
+ p2 = _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_srli_si128(p, 8)));
+ p3 = _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_srli_si128(p, 12)));
+ #else
+ b = *src++ / 255.;
+ g = *src++ / 255.;
+ r = *src++ / 255.;
+ #endif
+
+ #ifdef __SSE4_1__
+ #define tint(v) \
+ luma = _mm_dp_ps((v), weights, 0x7F); \
+ v = _mm_add_ps(_mm_mul_ps(comp_amount, (v)), \
+ _mm_add_ps(_mm_mul_ps(luma, tmp0), tmp1)); \
+ v = _mm_cvtps_epi32(v)
+
+ tint(p0); tint(p1); tint(p2); tint(p3);
+
+ /* Gather the processed pixels */
+ p = _mm_packus_epi16(_mm_packus_epi32(p0, p1),
+ _mm_packus_epi32(p2, p3));
+
+ _mm_storeu_si128((__m128i*)outframe, p);
+
+ /* Stride of 128 bits; i.e. 16 bytes */
+ inframe += 4;
+ outframe += 4;
+ #else
+ luma = (b * .114 + g * .587 + r * .299);
+
+ *dst++ = map_color(amount, comp_amount, b, luma, inst->blackColor.b, inst->whiteColor.b);
+ *dst++ = map_color(amount, comp_amount, g, luma, inst->blackColor.g, inst->whiteColor.g);
+ *dst++ = map_color(amount, comp_amount, r, luma, inst->blackColor.r, inst->whiteColor.r);
+ *dst++ = *src++;
+ #endif
+ }
+}
+
diff --git a/src/filter/tutorial/tutorial.cpp b/src/filter/tutorial/tutorial.cpp
index e291546..06b633c 100644
--- a/src/filter/tutorial/tutorial.cpp
+++ b/src/filter/tutorial/tutorial.cpp
@@ -108,7 +108,7 @@
const uint32_t* in)
{
// Just copy input to output.
- // This is useful if ony few changes are made to the output.
+ // This is useful if only few changes are made to the output.
// If the whole image is processed, this makes no sense!
std::copy(in, in + width*height, out);
@@ -125,7 +125,7 @@
// This parameter allows one to do simple benchmarking: Rendering a
// video with uint8_t pointers and with uint32_t pointers.
- // (Don't forget to substract the rendering time without this effect applied to avoid counting
+ // (Don't forget to subtract the rendering time without this effect applied to avoid counting
// encoding and decoding as well!)
if (m_pointerMethod == 0) {
uint8_t *in_pointer = (uint8_t *) in;
diff --git a/src/filter/vignette/vignette.cpp b/src/filter/vignette/vignette.cpp
index 2de1aa0..7017621 100644
--- a/src/filter/vignette/vignette.cpp
+++ b/src/filter/vignette/vignette.cpp
@@ -142,7 +142,7 @@
for (int y = 0; y < m_height; y++) {
for (int x = 0; x < m_width; x++) {
- // Euclidian distance to the center, normalized to [0,1]
+ // Euclidean distance to the center, normalized to [0,1]
r = std::sqrt(std::pow(scaleX*(x-cx), 2) + std::pow(scaleY*(y-cy), 2))/rmax;
// Subtract the clear center
diff --git a/src/generator/partik0l/partik0l.cpp b/src/generator/partik0l/partik0l.cpp
index f7a1657..cb9ce19 100644
--- a/src/generator/partik0l/partik0l.cpp
+++ b/src/generator/partik0l/partik0l.cpp
@@ -210,7 +210,7 @@
double zx, zy;
/* here place a formula that draws on the screen
- the surface being drawed at this point is always blank */
+ the surface being drawn at this point is always blank */
for( a=0.0 ; asl, inst->w, inst->h);
break;
- case 5: //gama ckecking chart
+ case 5: //gama checking chart
gamatest(inst->sl, inst->w, inst->h);
break;
case 6: //for testing orthicon simulator
diff --git a/src/generator/test_pat/test_pat_R.c b/src/generator/test_pat/test_pat_R.c
index 55f15be..529fe89 100644
--- a/src/generator/test_pat/test_pat_R.c
+++ b/src/generator/test_pat/test_pat_R.c
@@ -513,7 +513,7 @@
}
//----------------------------------------------------------
-//fills frame with constand 2D spatial frequency
+//fills frame with constant 2D spatial frequency
//ar = pixel aspect ratio (not used currently)
void diags(float *sl, int w, int h, float a, float ar, float fh, float fv)
{
diff --git a/src/mixer2/burn/burn.cpp b/src/mixer2/burn/burn.cpp
index 66622d4..830cb7a 100644
--- a/src/mixer2/burn/burn.cpp
+++ b/src/mixer2/burn/burn.cpp
@@ -51,7 +51,7 @@
uint32_t b;
- /* FIXME: Is the burn effect supposed to be dependant on the sign of this
+ /* FIXME: Is the burn effect supposed to be dependent on the sign of this
* temporary variable? */
int tmp;
diff --git a/src/mixer2/cairoaffineblend/cairoaffineblend.c b/src/mixer2/cairoaffineblend/cairoaffineblend.c
index a475b52..31f7358 100644
--- a/src/mixer2/cairoaffineblend/cairoaffineblend.c
+++ b/src/mixer2/cairoaffineblend/cairoaffineblend.c
@@ -75,27 +75,27 @@
case 0:
info->name = "x";
info->type = F0R_PARAM_DOUBLE;
- info->explanation = "X position of second input, value interperted as range -2*width - 3*width";
+ info->explanation = "X position of second input, value interpreted as range -2*width - 3*width";
break;
case 1:
info->name = "y";
info->type = F0R_PARAM_DOUBLE;
- info->explanation = "Y position of second input, value interperted as range -2*height - 3*height";
+ info->explanation = "Y position of second input, value interpreted as range -2*height - 3*height";
break;
case 2:
info->name = "x scale";
info->type = F0R_PARAM_DOUBLE;
- info->explanation = "X scale of second input, value interperted as range 0 - 5";
+ info->explanation = "X scale of second input, value interpreted as range 0 - 5";
break;
case 3:
info->name = "y scale";
info->type = F0R_PARAM_DOUBLE;
- info->explanation = "Y scale of second input, value interperted as range 0 - 5";
+ info->explanation = "Y scale of second input, value interpreted as range 0 - 5";
break;
case 4:
info->name = "rotation";
info->type = F0R_PARAM_DOUBLE;
- info->explanation = "Rotation of second input, value interperted as range 0 - 360";
+ info->explanation = "Rotation of second input, value interpreted as range 0 - 360";
break;
case 5:
info->name = "opacity";
diff --git a/src/mixer2/color_only/color_only.cpp b/src/mixer2/color_only/color_only.cpp
index b83f21f..ff02184 100644
--- a/src/mixer2/color_only/color_only.cpp
+++ b/src/mixer2/color_only/color_only.cpp
@@ -64,7 +64,7 @@
r1 = r2;
g1 = g2;
- /* set the dstination */
+ /* set the destination */
hsl_to_rgb_int(&r1, &g1, &b1);
dst[0] = r1;
diff --git a/src/mixer2/euclid_eraser/euclid_eraser.cpp b/src/mixer2/euclid_eraser/euclid_eraser.cpp
index 35c9073..dc8c8e8 100644
--- a/src/mixer2/euclid_eraser/euclid_eraser.cpp
+++ b/src/mixer2/euclid_eraser/euclid_eraser.cpp
@@ -112,7 +112,7 @@
};
frei0r::construct plugin("euclid_eraser",
- "Erasing backgrounds with euclidian distance",
+ "Erasing backgrounds with euclidean distance",
"Erik H. Beck",
0,1,
F0R_COLOR_MODEL_RGBA8888);
diff --git a/src/mixer2/euclid_eraser/euclid_eraser.md b/src/mixer2/euclid_eraser/euclid_eraser.md
index 313ba70..28a30eb 100644
--- a/src/mixer2/euclid_eraser/euclid_eraser.md
+++ b/src/mixer2/euclid_eraser/euclid_eraser.md
@@ -21,16 +21,16 @@
background, and removes it from every frame in the video stream of the
second input.
-The alpha channel on the output is based on the euclidian distance of
+The alpha channel on the output is based on the euclidean distance of
the two input coordinates in 3-d RGB space. If the calculated distance
-betwen the two inputs for a given pixel is less than a provided
+between the two inputs for a given pixel is less than a provided
(variable) threshold amount, that indicates the pixel in the
background (reference) image is the same or similar enough to the
operational (second) input that is part of the background to be
removed, and the transparency is set to fully transparent via the
alpha channel (set to 0).
-If the calcuated distance exceeds the threshold, then that pixel is
+If the calculated distance exceeds the threshold, then that pixel is
part of the foreground image to be retained, and the transparency
of it is set to be fully opaque (alpha channel for that pixel set
to 255).
diff --git a/src/mixer2/hue/hue.cpp b/src/mixer2/hue/hue.cpp
index 4dc66b2..4f7b267 100644
--- a/src/mixer2/hue/hue.cpp
+++ b/src/mixer2/hue/hue.cpp
@@ -68,7 +68,7 @@
if (g2)
r1 = r2;
- /* set the dstination */
+ /* set the destination */
hsv_to_rgb_int (&r1, &g1, &b1);
dst[0] = r1;
diff --git a/src/mixer2/saturation/saturation.cpp b/src/mixer2/saturation/saturation.cpp
index 89a786e..4e60282 100644
--- a/src/mixer2/saturation/saturation.cpp
+++ b/src/mixer2/saturation/saturation.cpp
@@ -63,7 +63,7 @@
g1 = g2;
- /* set the dstination */
+ /* set the destination */
hsv_to_rgb_int(&r1, &g1, &b1);
dst[0] = r1;
diff --git a/src/mixer2/value/value.cpp b/src/mixer2/value/value.cpp
index 4788386..4c0ef3d 100644
--- a/src/mixer2/value/value.cpp
+++ b/src/mixer2/value/value.cpp
@@ -64,7 +64,7 @@
b1 = b2;
- /* set the dstination */
+ /* set the destination */
hsv_to_rgb_int(&r1, &g1, &b1);
dst[0] = r1;