From c708f01d59e44f1092708d9476f89baa31da315a Mon Sep 17 00:00:00 2001
From: JohannJEG <125712359+JohannJEG@users.noreply.github.com>
Date: Sun, 18 Aug 2024 15:24:08 -0400
Subject: [PATCH 1/7] mirr0r filter added
---
src/filter/CMakeLists.txt | 1 +
src/filter/mirr0r/CMakeLists.txt | 15 ++++
src/filter/mirr0r/mirr0r.cpp | 143 +++++++++++++++++++++++++++++++
3 files changed, 159 insertions(+)
create mode 100755 src/filter/mirr0r/CMakeLists.txt
create mode 100755 src/filter/mirr0r/mirr0r.cpp
diff --git a/src/filter/CMakeLists.txt b/src/filter/CMakeLists.txt
index 0c228521..8ede934c 100644
--- a/src/filter/CMakeLists.txt
+++ b/src/filter/CMakeLists.txt
@@ -12,6 +12,7 @@ endif (${OpenCV_FOUND})
if (${Cairo_FOUND})
add_subdirectory (cairoimagegrid)
add_subdirectory (cairogradient)
+ add_subdirectory (mirr0r)
endif (${Cairo_FOUND})
add_subdirectory (3dflippo)
diff --git a/src/filter/mirr0r/CMakeLists.txt b/src/filter/mirr0r/CMakeLists.txt
new file mode 100755
index 00000000..7a811bde
--- /dev/null
+++ b/src/filter/mirr0r/CMakeLists.txt
@@ -0,0 +1,15 @@
+set (SOURCES mirr0r.cpp)
+set (TARGET mirr0r)
+
+include_directories(${Cairo_INCLUDE_DIR})
+set(LIBS ${LIBS} ${Cairo_LIBRARY})
+
+if (MSVC)
+ set (SOURCES ${SOURCES} ${FREI0R_DEF})
+endif (MSVC)
+
+add_library (${TARGET} MODULE ${SOURCES})
+
+set_target_properties (${TARGET} PROPERTIES PREFIX "")
+target_link_libraries(mirr0r ${LIBS})
+install (TARGETS ${TARGET} LIBRARY DESTINATION ${LIBDIR})
diff --git a/src/filter/mirr0r/mirr0r.cpp b/src/filter/mirr0r/mirr0r.cpp
new file mode 100755
index 00000000..d687d057
--- /dev/null
+++ b/src/filter/mirr0r/mirr0r.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2024 Johann JEG (johannjeg1057@gmail.com)
+ *
+ * This file is a Frei0r plugin.
+ *
+ * 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 3 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, see .
+ */
+
+#include "frei0r.hpp"
+#include
+#include
+#include
+#include
+
+#define PI 3.14159265358979323846
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#define register
+
+#include "frei0r/cairo.h"
+
+#undef register
+
+#ifdef __cplusplus
+}
+#endif
+
+class Mirr0r : public frei0r::filter {
+
+private:
+ unsigned int width;
+ unsigned int height;
+ double x_offset;
+ double y_offset;
+ double zoom;
+ double rotation;
+
+public:
+
+ Mirr0r(unsigned int width, unsigned int height){
+ register_param(this->x_offset, "x_offset", "Horizontal offset for image positioning.");
+ register_param(this->y_offset, "y_offset", "Vertical offset for image positioning.");
+ register_param(this->zoom, "zoom", "Zoom level for image scaling.");
+ register_param(this->rotation, "rotation", "Rotation angle in degrees.");
+
+ this->width = width;
+ this->height = height;
+ this->x_offset = 0.5;
+ this->y_offset = 0.5;
+ this->zoom = 0.5;
+ this->rotation = 0.5;
+ }
+
+ ~Mirr0r(){
+
+ }
+
+ virtual void update(double time, uint32_t* out, const uint32_t* in){
+ const unsigned char* src = (unsigned char*)in;
+ unsigned char* dst = (unsigned char*)out;
+
+ int w = this->width;
+ int h = this->height;
+
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ // Zoom limit range from -0.9 to 2.0
+ float zoom = 1.0f + CLAMP(this->zoom, -0.9, 2.0);
+
+ int x_offset_px = (int)(this->x_offset * w);
+ int y_offset_px = (int)(this->y_offset * h);
+
+ // Calculate the center of the destination image
+ float center_x = (float)w / 2.0f;
+ float center_y = (float)h / 2.0f;
+
+ // Convert the rotation to radians
+ float angle = (float)(this->rotation * PI / 180.0f);
+ float cos_angle = cosf(angle);
+ float sin_angle = sinf(angle);
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ // Convert the destination coordinates to source coordinates with zoom
+ float src_x = (x - center_x) / zoom + center_x;
+ float src_y = (y - center_y) / zoom + center_y;
+
+ // Apply the rotation
+ float rotated_x = cos_angle * (src_x - center_x) - sin_angle * (src_y - center_y) + center_x;
+ float rotated_y = sin_angle * (src_x - center_x) + cos_angle * (src_y - center_y) + center_y;
+
+ // Apply the offset
+ rotated_x += x_offset_px;
+ rotated_y += y_offset_px;
+
+ int src_x_int = (int)rotated_x % (w * 2);
+ int src_y_int = (int)rotated_y % (h * 2);
+
+ // Reflect the image if coordinates are out of bounds
+ // If less than the bound
+ if (src_x_int < 0) {
+ src_x_int = 0 - src_x_int - 1;
+ }
+ if (src_y_int < 0) {
+ src_y_int = 0 - src_y_int - 1;
+ }
+ // If greater than the bounds
+ if (src_x_int >= w) {
+ src_x_int = w - (src_x_int - w) - 1;
+ }
+ if (src_y_int >= h) {
+ src_y_int = h - (src_y_int - h) - 1;
+ }
+
+ // Copy the pixel from the source image to the destination buffer
+ ((uint32_t*)dst)[y * w + x] = ((const uint32_t*)src)[src_y_int * w + src_x_int];
+ }
+ }
+ }
+};
+
+frei0r::construct plugin(
+ "Mirr0r",
+ "Repeats and flips the input image when it goes out of bounds, allowing for adjustable offset, zoom and rotation. A versatile tool for creative video effects.",
+ "Johann JEG",
+ 1, 0,
+ F0R_COLOR_MODEL_RGBA8888);
From a359faeffc5468bca10183dd7fff4e2b36d9f95b Mon Sep 17 00:00:00 2001
From: JohannJEG <125712359+JohannJEG@users.noreply.github.com>
Date: Mon, 19 Aug 2024 05:04:50 -0400
Subject: [PATCH 2/7] removed redundant and unused includes
---
.gitignore | 1 +
src/filter/CMakeLists.txt | 2 +-
src/filter/mirr0r/CMakeLists.txt | 3 ---
src/filter/mirr0r/mirr0r.cpp | 23 +++--------------------
4 files changed, 5 insertions(+), 24 deletions(-)
diff --git a/.gitignore b/.gitignore
index de08b02d..3a4e0e22 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,4 @@ doc/html
/out/
/.vs/
CMakeSettings.json
+.vscode
diff --git a/src/filter/CMakeLists.txt b/src/filter/CMakeLists.txt
index 8ede934c..9775a6fe 100644
--- a/src/filter/CMakeLists.txt
+++ b/src/filter/CMakeLists.txt
@@ -12,7 +12,6 @@ endif (${OpenCV_FOUND})
if (${Cairo_FOUND})
add_subdirectory (cairoimagegrid)
add_subdirectory (cairogradient)
- add_subdirectory (mirr0r)
endif (${Cairo_FOUND})
add_subdirectory (3dflippo)
@@ -66,6 +65,7 @@ add_subdirectory (luminance)
add_subdirectory (mask0mate)
add_subdirectory (medians)
add_subdirectory (measure)
+add_subdirectory (mirr0r)
add_subdirectory (ndvi)
add_subdirectory (nervous)
add_subdirectory (normaliz0r)
diff --git a/src/filter/mirr0r/CMakeLists.txt b/src/filter/mirr0r/CMakeLists.txt
index 7a811bde..0430c7ef 100755
--- a/src/filter/mirr0r/CMakeLists.txt
+++ b/src/filter/mirr0r/CMakeLists.txt
@@ -1,9 +1,6 @@
set (SOURCES mirr0r.cpp)
set (TARGET mirr0r)
-include_directories(${Cairo_INCLUDE_DIR})
-set(LIBS ${LIBS} ${Cairo_LIBRARY})
-
if (MSVC)
set (SOURCES ${SOURCES} ${FREI0R_DEF})
endif (MSVC)
diff --git a/src/filter/mirr0r/mirr0r.cpp b/src/filter/mirr0r/mirr0r.cpp
index d687d057..54463619 100755
--- a/src/filter/mirr0r/mirr0r.cpp
+++ b/src/filter/mirr0r/mirr0r.cpp
@@ -18,26 +18,9 @@
*/
#include "frei0r.hpp"
-#include
-#include
+#include "frei0r/math.h"
+#define _USE_MATH_DEFINES
#include
-#include
-
-#define PI 3.14159265358979323846
-
-#ifdef __cplusplus
-extern "C"{
-#endif
-
-#define register
-
-#include "frei0r/cairo.h"
-
-#undef register
-
-#ifdef __cplusplus
-}
-#endif
class Mirr0r : public frei0r::filter {
@@ -91,7 +74,7 @@ class Mirr0r : public frei0r::filter {
float center_y = (float)h / 2.0f;
// Convert the rotation to radians
- float angle = (float)(this->rotation * PI / 180.0f);
+ float angle = (float)(this->rotation * M_PI / 180.0f);
float cos_angle = cosf(angle);
float sin_angle = sinf(angle);
From db1dfc43db1ce0c47060b80381bcb0b5562beead Mon Sep 17 00:00:00 2001
From: JohannJEG <125712359+JohannJEG@users.noreply.github.com>
Date: Thu, 22 Aug 2024 05:07:48 -0400
Subject: [PATCH 3/7] Using Cairo graphics library
---
src/filter/CMakeLists.txt | 2 +-
src/filter/mirr0r/CMakeLists.txt | 3 +
src/filter/mirr0r/mirr0r.cpp | 117 +++++++++++++++----------------
3 files changed, 62 insertions(+), 60 deletions(-)
diff --git a/src/filter/CMakeLists.txt b/src/filter/CMakeLists.txt
index 9775a6fe..8ede934c 100644
--- a/src/filter/CMakeLists.txt
+++ b/src/filter/CMakeLists.txt
@@ -12,6 +12,7 @@ endif (${OpenCV_FOUND})
if (${Cairo_FOUND})
add_subdirectory (cairoimagegrid)
add_subdirectory (cairogradient)
+ add_subdirectory (mirr0r)
endif (${Cairo_FOUND})
add_subdirectory (3dflippo)
@@ -65,7 +66,6 @@ add_subdirectory (luminance)
add_subdirectory (mask0mate)
add_subdirectory (medians)
add_subdirectory (measure)
-add_subdirectory (mirr0r)
add_subdirectory (ndvi)
add_subdirectory (nervous)
add_subdirectory (normaliz0r)
diff --git a/src/filter/mirr0r/CMakeLists.txt b/src/filter/mirr0r/CMakeLists.txt
index 0430c7ef..7a811bde 100755
--- a/src/filter/mirr0r/CMakeLists.txt
+++ b/src/filter/mirr0r/CMakeLists.txt
@@ -1,6 +1,9 @@
set (SOURCES mirr0r.cpp)
set (TARGET mirr0r)
+include_directories(${Cairo_INCLUDE_DIR})
+set(LIBS ${LIBS} ${Cairo_LIBRARY})
+
if (MSVC)
set (SOURCES ${SOURCES} ${FREI0R_DEF})
endif (MSVC)
diff --git a/src/filter/mirr0r/mirr0r.cpp b/src/filter/mirr0r/mirr0r.cpp
index 54463619..4e41ff52 100755
--- a/src/filter/mirr0r/mirr0r.cpp
+++ b/src/filter/mirr0r/mirr0r.cpp
@@ -19,8 +19,9 @@
#include "frei0r.hpp"
#include "frei0r/math.h"
+#include
#define _USE_MATH_DEFINES
-#include
+#include
class Mirr0r : public frei0r::filter {
@@ -52,69 +53,66 @@ class Mirr0r : public frei0r::filter {
}
- virtual void update(double time, uint32_t* out, const uint32_t* in){
- const unsigned char* src = (unsigned char*)in;
- unsigned char* dst = (unsigned char*)out;
-
+ virtual void update(double time, uint32_t* out, const uint32_t* in) {
+
int w = this->width;
int h = this->height;
- if (w <= 0 || h <= 0) {
- return;
- }
-
- // Zoom limit range from -0.9 to 2.0
- float zoom = 1.0f + CLAMP(this->zoom, -0.9, 2.0);
-
- int x_offset_px = (int)(this->x_offset * w);
- int y_offset_px = (int)(this->y_offset * h);
-
- // Calculate the center of the destination image
+ // Calculate the stride for the image surface based on width and format
+ int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w);
+
+ // Create a Cairo surface for the destination image
+ cairo_surface_t* dest_image = cairo_image_surface_create_for_data((unsigned char*)out,
+ CAIRO_FORMAT_ARGB32,
+ w,
+ h,
+ stride);
+
+ // Create a Cairo drawing context for the destination surface
+ cairo_t *cr = cairo_create(dest_image);
+
+ // Create a Cairo surface for the source image
+ cairo_surface_t *image = cairo_image_surface_create_for_data((unsigned char*)in,
+ CAIRO_FORMAT_ARGB32,
+ w,
+ h,
+ stride);
+ // Create a pattern from the source image surface
+ cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
+ // Set the pattern extend mode to reflect (mirror) when the pattern is out of bounds
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT);
+
+ // Initialize the transformation matrix
+ cairo_matrix_t matrix;
+ cairo_matrix_init_identity(&matrix);
+
+ // Calculate the center coordinates of the destination image
float center_x = (float)w / 2.0f;
float center_y = (float)h / 2.0f;
-
- // Convert the rotation to radians
- float angle = (float)(this->rotation * M_PI / 180.0f);
- float cos_angle = cosf(angle);
- float sin_angle = sinf(angle);
-
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- // Convert the destination coordinates to source coordinates with zoom
- float src_x = (x - center_x) / zoom + center_x;
- float src_y = (y - center_y) / zoom + center_y;
-
- // Apply the rotation
- float rotated_x = cos_angle * (src_x - center_x) - sin_angle * (src_y - center_y) + center_x;
- float rotated_y = sin_angle * (src_x - center_x) + cos_angle * (src_y - center_y) + center_y;
-
- // Apply the offset
- rotated_x += x_offset_px;
- rotated_y += y_offset_px;
-
- int src_x_int = (int)rotated_x % (w * 2);
- int src_y_int = (int)rotated_y % (h * 2);
-
- // Reflect the image if coordinates are out of bounds
- // If less than the bound
- if (src_x_int < 0) {
- src_x_int = 0 - src_x_int - 1;
- }
- if (src_y_int < 0) {
- src_y_int = 0 - src_y_int - 1;
- }
- // If greater than the bounds
- if (src_x_int >= w) {
- src_x_int = w - (src_x_int - w) - 1;
- }
- if (src_y_int >= h) {
- src_y_int = h - (src_y_int - h) - 1;
- }
-
- // Copy the pixel from the source image to the destination buffer
- ((uint32_t*)dst)[y * w + x] = ((const uint32_t*)src)[src_y_int * w + src_x_int];
- }
- }
+
+ float scale_factor = 1.0f - CLAMP(this->zoom, -0.99, 0.99);
+
+ // Apply transformations
+ cairo_matrix_translate(&matrix, center_x - (this->x_offset) * w, center_y - (this->y_offset) * h);
+ cairo_matrix_scale(&matrix, scale_factor, scale_factor);
+ cairo_matrix_rotate(&matrix, this->rotation * M_PI / 180.0);
+ cairo_matrix_translate(&matrix, -center_x, -center_y);
+
+ // Set the transformation matrix for the pattern
+ cairo_pattern_set_matrix(pattern, &matrix);
+ // Set the source pattern to be used for drawing
+ cairo_set_source(cr, pattern);
+
+ // Draw a rectangle covering the entire image area
+ cairo_rectangle(cr, 0, 0, w, h);
+ // Fill the rectangle with the source pattern
+ cairo_fill(cr);
+
+ // Clean up resources
+ cairo_pattern_destroy (pattern);
+ cairo_surface_destroy (image);
+ cairo_surface_destroy (dest_image);
+ cairo_destroy (cr);
}
};
@@ -124,3 +122,4 @@ frei0r::construct plugin(
"Johann JEG",
1, 0,
F0R_COLOR_MODEL_RGBA8888);
+
\ No newline at end of file
From 185b53724871aec4aea869d8c0920db2ccf8f90b Mon Sep 17 00:00:00 2001
From: JohannJEG <125712359+JohannJEG@users.noreply.github.com>
Date: Thu, 22 Aug 2024 23:44:29 -0400
Subject: [PATCH 4/7] fixed parameters range
---
src/filter/mirr0r/mirr0r.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/filter/mirr0r/mirr0r.cpp b/src/filter/mirr0r/mirr0r.cpp
index 4e41ff52..abad27e9 100755
--- a/src/filter/mirr0r/mirr0r.cpp
+++ b/src/filter/mirr0r/mirr0r.cpp
@@ -43,10 +43,10 @@ class Mirr0r : public frei0r::filter {
this->width = width;
this->height = height;
- this->x_offset = 0.5;
- this->y_offset = 0.5;
+ this->x_offset = 0.0;
+ this->y_offset = 0.0;
this->zoom = 0.5;
- this->rotation = 0.5;
+ this->rotation = 0.0;
}
~Mirr0r(){
@@ -90,12 +90,12 @@ class Mirr0r : public frei0r::filter {
float center_x = (float)w / 2.0f;
float center_y = (float)h / 2.0f;
- float scale_factor = 1.0f - CLAMP(this->zoom, -0.99, 0.99);
-
+ float scale_factor = 1.5f - this->zoom;
+
// Apply transformations
cairo_matrix_translate(&matrix, center_x - (this->x_offset) * w, center_y - (this->y_offset) * h);
cairo_matrix_scale(&matrix, scale_factor, scale_factor);
- cairo_matrix_rotate(&matrix, this->rotation * M_PI / 180.0);
+ cairo_matrix_rotate(&matrix, this->rotation * M_PI);
cairo_matrix_translate(&matrix, -center_x, -center_y);
// Set the transformation matrix for the pattern
From 53e5f25c34977e5f2cad40bb20d735bb077657d4 Mon Sep 17 00:00:00 2001
From: JohannJEG <125712359+JohannJEG@users.noreply.github.com>
Date: Fri, 23 Aug 2024 05:04:19 -0400
Subject: [PATCH 5/7] Clear the screen before drawing, to avoid problems with
image sources with transparency.
---
src/filter/mirr0r/mirr0r.cpp | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/filter/mirr0r/mirr0r.cpp b/src/filter/mirr0r/mirr0r.cpp
index abad27e9..555bb1b7 100755
--- a/src/filter/mirr0r/mirr0r.cpp
+++ b/src/filter/mirr0r/mirr0r.cpp
@@ -53,6 +53,14 @@ class Mirr0r : public frei0r::filter {
}
+ void clearScreen(cairo_t* cr, int width, int height) {
+ cairo_save (cr);
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+ cairo_restore (cr);
+ }
+
virtual void update(double time, uint32_t* out, const uint32_t* in) {
int w = this->width;
@@ -71,6 +79,9 @@ class Mirr0r : public frei0r::filter {
// Create a Cairo drawing context for the destination surface
cairo_t *cr = cairo_create(dest_image);
+ // Clear the screen
+ clearScreen(cr, w, h);
+
// Create a Cairo surface for the source image
cairo_surface_t *image = cairo_image_surface_create_for_data((unsigned char*)in,
CAIRO_FORMAT_ARGB32,
From df67d905a057c10753d427edd7458c92ab947b48 Mon Sep 17 00:00:00 2001
From: JohannJEG <125712359+JohannJEG@users.noreply.github.com>
Date: Fri, 23 Aug 2024 10:22:04 -0400
Subject: [PATCH 6/7] Remove unused import
---
src/filter/mirr0r/mirr0r.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/filter/mirr0r/mirr0r.cpp b/src/filter/mirr0r/mirr0r.cpp
index 555bb1b7..a6113db1 100755
--- a/src/filter/mirr0r/mirr0r.cpp
+++ b/src/filter/mirr0r/mirr0r.cpp
@@ -18,7 +18,6 @@
*/
#include "frei0r.hpp"
-#include "frei0r/math.h"
#include
#define _USE_MATH_DEFINES
#include
@@ -26,6 +25,7 @@
class Mirr0r : public frei0r::filter {
private:
+
unsigned int width;
unsigned int height;
double x_offset;
From b1f53681e1efffae805864c6c60a7b074f6427d2 Mon Sep 17 00:00:00 2001
From: JohannJEG <125712359+JohannJEG@users.noreply.github.com>
Date: Sun, 25 Aug 2024 07:54:30 -0400
Subject: [PATCH 7/7] Added new filter effect shakeoscillate
---
src/filter/CMakeLists.txt | 1 +
src/filter/shakeoscillate/CMakeLists.txt | 15 ++
src/filter/shakeoscillate/shakeoscillate.cpp | 195 +++++++++++++++++++
3 files changed, 211 insertions(+)
create mode 100755 src/filter/shakeoscillate/CMakeLists.txt
create mode 100755 src/filter/shakeoscillate/shakeoscillate.cpp
diff --git a/src/filter/CMakeLists.txt b/src/filter/CMakeLists.txt
index 8ede934c..030679bb 100644
--- a/src/filter/CMakeLists.txt
+++ b/src/filter/CMakeLists.txt
@@ -13,6 +13,7 @@ if (${Cairo_FOUND})
add_subdirectory (cairoimagegrid)
add_subdirectory (cairogradient)
add_subdirectory (mirr0r)
+ add_subdirectory (shakeoscillate)
endif (${Cairo_FOUND})
add_subdirectory (3dflippo)
diff --git a/src/filter/shakeoscillate/CMakeLists.txt b/src/filter/shakeoscillate/CMakeLists.txt
new file mode 100755
index 00000000..573a78af
--- /dev/null
+++ b/src/filter/shakeoscillate/CMakeLists.txt
@@ -0,0 +1,15 @@
+set (SOURCES shakeoscillate.cpp)
+set (TARGET shakeoscillate)
+
+include_directories(${Cairo_INCLUDE_DIR})
+set(LIBS ${LIBS} ${Cairo_LIBRARY})
+
+if (MSVC)
+ set (SOURCES ${SOURCES} ${FREI0R_DEF})
+endif (MSVC)
+
+add_library (${TARGET} MODULE ${SOURCES})
+
+set_target_properties (${TARGET} PROPERTIES PREFIX "")
+target_link_libraries(shakeoscillate ${LIBS})
+install (TARGETS ${TARGET} LIBRARY DESTINATION ${LIBDIR})
diff --git a/src/filter/shakeoscillate/shakeoscillate.cpp b/src/filter/shakeoscillate/shakeoscillate.cpp
new file mode 100755
index 00000000..88913eec
--- /dev/null
+++ b/src/filter/shakeoscillate/shakeoscillate.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2024 Johann JEG (johannjeg1057@gmail.com)
+ *
+ * This file is a Frei0r plugin.
+ *
+ * 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 3 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, see .
+ */
+
+#include "frei0r.hpp"
+#include
+#define _USE_MATH_DEFINES
+#include
+
+class ShakeOscillate : public frei0r::filter {
+
+private:
+
+ unsigned int width;
+ unsigned int height;
+ double movement_amount_x;
+ double movement_speed_x;
+ double movement_amount_y;
+ double movement_speed_y;
+ double rotation_amount;
+ double rotation_speed;
+ double scale;
+ double phase;
+ bool mirrored;
+
+ const float MOVEMENT_AMOUNT_MULTIPLIER = 0.3f;
+ const float ROTATION_AMOUNT_MULTIPLIER = 0.2f;
+ const float SPEED_MULTIPLIER = 10.0f;
+
+public:
+
+ ShakeOscillate(unsigned int width, unsigned int height) {
+ register_param(this->movement_amount_x, "movement_amount_x", "Amount of the X movement.");
+ register_param(this->movement_speed_x, "movement_speed_x", "X Movement Speed.");
+ register_param(this->movement_amount_y, "movement_amount_y", "Amount of the Y movement.");
+ register_param(this->movement_speed_y, "movement_speed_y", "Y Movement Speed.");
+ register_param(this->rotation_amount, "rotation_amount", "Rotation amount.");
+ register_param(this->rotation_speed, "rotation_speed", "Rotation Speed.");
+ register_param(this->scale, "scale", "Scale level.");
+ register_param(this->phase, "phase", "The phase of the sin and cos functions of this effect.");
+ register_param(this->mirrored, "mirrored", "On/Off Image Mirror Extend");
+
+ this->width = width;
+ this->height = height;
+ this->movement_amount_x = 0.5; // Movement amount off is 0.5
+ this->movement_speed_x = 0.2;
+ this->movement_amount_y = 0.5; // Movement amount off is 0.5
+ this->movement_speed_y = 0.1;
+ this->rotation_amount = 0.5; // Rotation amount off is 0.5
+ this->rotation_speed = 0.2;
+ this->scale = 0.5; // Original image size is 0.5
+ this->phase = 0.0;
+ this->mirrored = true;
+ }
+
+ ~ShakeOscillate() {
+
+ }
+
+ void clearScreen(cairo_t* cr, int width, int height) {
+ cairo_save (cr);
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+ cairo_restore (cr);
+ }
+
+ void oscillate(cairo_matrix_t* matrix, double time) {
+ float x = 0.0f;
+ float y = 0.0f;
+
+ // Operations for the translation amount do not depend on the screen size
+ float movement_range_x = MOVEMENT_AMOUNT_MULTIPLIER * this->height;
+ float movement_range_y = MOVEMENT_AMOUNT_MULTIPLIER * this->width;
+
+ // Translate X
+ if(this->movement_amount_x != 0.5){
+ float movement_x = (this->movement_amount_x - 0.5f) * 2.0f;
+ float movement_speed_value_x = this->movement_speed_x * SPEED_MULTIPLIER * time;
+ x = movement_x * movement_range_x * std::sin(movement_speed_value_x + this->phase);
+ }
+
+ // Translate Y
+ if(this->movement_amount_y != 0.5){
+ float movement_y = (this->movement_amount_y - 0.5f) * 2.0f;
+ float movement_speed_value_y = this->movement_speed_y * SPEED_MULTIPLIER * time;
+ y = movement_y * movement_range_y * std::cos(movement_speed_value_y + this->phase);
+ }
+
+ // Translate by adding the half screen coordinates to scale and rotate from center
+ float center_x = this->width / 2.0f;
+ float center_y = this->height / 2.0f;
+ cairo_matrix_translate(matrix, center_x + x, center_y + y);
+
+ // Scale
+ if(this->scale != 0.5){
+ float scale_factor = 1.5f - this->scale;
+ cairo_matrix_scale(matrix, scale_factor, scale_factor);
+ }
+
+ // Rotation
+ if(this->rotation_amount != 0.5){
+ float rotation_speed_value = (this->rotation_speed * SPEED_MULTIPLIER * time) + this->phase;
+ float rotation = ((this->rotation_amount - 0.5f) * ROTATION_AMOUNT_MULTIPLIER) * std::sin(rotation_speed_value) * M_PI;
+ cairo_matrix_rotate(matrix, rotation);
+ }
+
+ // Restore translate coordinates
+ cairo_matrix_translate(matrix, -center_x, -center_y);
+ }
+
+ virtual void update(double time, uint32_t* out, const uint32_t* in) {
+ int w = this->width;
+ int h = this->height;
+
+ // Calculate the stride for the image surface based on width and format
+ int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w);
+
+ // Create a Cairo surface for the destination image
+ cairo_surface_t* dest_image = cairo_image_surface_create_for_data((unsigned char*)out,
+ CAIRO_FORMAT_ARGB32,
+ w,
+ h,
+ stride);
+
+ // Create a Cairo drawing context for the destination surface
+ cairo_t *cr = cairo_create(dest_image);
+
+ // Clear the screen
+ clearScreen(cr, w, h);
+
+ // Create a Cairo surface for the source image
+ cairo_surface_t *image = cairo_image_surface_create_for_data((unsigned char*)in,
+ CAIRO_FORMAT_ARGB32,
+ w,
+ h,
+ stride);
+
+ // Create a pattern from the source image surface
+ cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
+
+ if(this->mirrored){
+ // Set the pattern extend mode to reflect (mirror) when the pattern is out of bounds
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT);
+ } else {
+ // Set the pattern extend mode to none (mirroring does not apply)
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_NONE);
+ }
+
+ // Initialize the transformation matrix
+ cairo_matrix_t matrix;
+ cairo_matrix_init_identity(&matrix);
+
+ // Call the function that applies the movement
+ oscillate(&matrix, time);
+
+ // Set the transformation matrix for the pattern
+ cairo_pattern_set_matrix(pattern, &matrix);
+ // Set the source pattern to be used for drawing
+ cairo_set_source(cr, pattern);
+
+ // Draw a rectangle covering the entire image area
+ cairo_rectangle(cr, 0, 0, w, h);
+ // Fill the rectangle with the source pattern
+ cairo_fill(cr);
+
+ // Clean up resources
+ cairo_pattern_destroy (pattern);
+ cairo_surface_destroy (image);
+ cairo_surface_destroy (dest_image);
+ cairo_destroy (cr);
+ }
+};
+
+frei0r::construct plugin(
+ "ShakeOscillate",
+ "Animate the input image with adjustable parameters such as amount, speed, rotation, scale and option to mirror the image if it goes outside the screen bounds.",
+ "Johann JEG",
+ 1, 0,
+ F0R_COLOR_MODEL_RGBA8888);