Skip to content

Commit 55d42f7

Browse files
JohannJEGjaromil
authored andcommitted
Added new filter effect shakeoscillate
1 parent 0dbbac5 commit 55d42f7

3 files changed

Lines changed: 211 additions & 0 deletions

File tree

src/filter/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ if (${Cairo_FOUND})
1313
add_subdirectory (cairoimagegrid)
1414
add_subdirectory (cairogradient)
1515
add_subdirectory (mirr0r)
16+
add_subdirectory (shakeoscillate)
1617
endif (${Cairo_FOUND})
1718

1819
add_subdirectory (3dflippo)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
set (SOURCES shakeoscillate.cpp)
2+
set (TARGET shakeoscillate)
3+
4+
include_directories(${Cairo_INCLUDE_DIR})
5+
set(LIBS ${LIBS} ${Cairo_LIBRARY})
6+
7+
if (MSVC)
8+
set (SOURCES ${SOURCES} ${FREI0R_DEF})
9+
endif (MSVC)
10+
11+
add_library (${TARGET} MODULE ${SOURCES})
12+
13+
set_target_properties (${TARGET} PROPERTIES PREFIX "")
14+
target_link_libraries(shakeoscillate ${LIBS})
15+
install (TARGETS ${TARGET} LIBRARY DESTINATION ${LIBDIR})
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/*
2+
* Copyright (C) 2024 Johann JEG (johannjeg1057@gmail.com)
3+
*
4+
* This file is a Frei0r plugin.
5+
*
6+
* This program is free software: you can redistribute it and/or
7+
* modify it under the terms of the GNU General Public License
8+
* as published by the Free Software Foundation, either version 3 of
9+
* the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "frei0r.hpp"
21+
#include <cairo.h>
22+
#define _USE_MATH_DEFINES
23+
#include <math.h>
24+
25+
class ShakeOscillate : public frei0r::filter {
26+
27+
private:
28+
29+
unsigned int width;
30+
unsigned int height;
31+
double movement_amount_x;
32+
double movement_speed_x;
33+
double movement_amount_y;
34+
double movement_speed_y;
35+
double rotation_amount;
36+
double rotation_speed;
37+
double scale;
38+
double phase;
39+
bool mirrored;
40+
41+
const float MOVEMENT_AMOUNT_MULTIPLIER = 0.3f;
42+
const float ROTATION_AMOUNT_MULTIPLIER = 0.2f;
43+
const float SPEED_MULTIPLIER = 10.0f;
44+
45+
public:
46+
47+
ShakeOscillate(unsigned int width, unsigned int height) {
48+
register_param(this->movement_amount_x, "movement_amount_x", "Amount of the X movement.");
49+
register_param(this->movement_speed_x, "movement_speed_x", "X Movement Speed.");
50+
register_param(this->movement_amount_y, "movement_amount_y", "Amount of the Y movement.");
51+
register_param(this->movement_speed_y, "movement_speed_y", "Y Movement Speed.");
52+
register_param(this->rotation_amount, "rotation_amount", "Rotation amount.");
53+
register_param(this->rotation_speed, "rotation_speed", "Rotation Speed.");
54+
register_param(this->scale, "scale", "Scale level.");
55+
register_param(this->phase, "phase", "The phase of the sin and cos functions of this effect.");
56+
register_param(this->mirrored, "mirrored", "On/Off Image Mirror Extend");
57+
58+
this->width = width;
59+
this->height = height;
60+
this->movement_amount_x = 0.5; // Movement amount off is 0.5
61+
this->movement_speed_x = 0.2;
62+
this->movement_amount_y = 0.5; // Movement amount off is 0.5
63+
this->movement_speed_y = 0.1;
64+
this->rotation_amount = 0.5; // Rotation amount off is 0.5
65+
this->rotation_speed = 0.2;
66+
this->scale = 0.5; // Original image size is 0.5
67+
this->phase = 0.0;
68+
this->mirrored = true;
69+
}
70+
71+
~ShakeOscillate() {
72+
73+
}
74+
75+
void clearScreen(cairo_t* cr, int width, int height) {
76+
cairo_save (cr);
77+
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
78+
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
79+
cairo_paint (cr);
80+
cairo_restore (cr);
81+
}
82+
83+
void oscillate(cairo_matrix_t* matrix, double time) {
84+
float x = 0.0f;
85+
float y = 0.0f;
86+
87+
// Operations for the translation amount do not depend on the screen size
88+
float movement_range_x = MOVEMENT_AMOUNT_MULTIPLIER * this->height;
89+
float movement_range_y = MOVEMENT_AMOUNT_MULTIPLIER * this->width;
90+
91+
// Translate X
92+
if(this->movement_amount_x != 0.5){
93+
float movement_x = (this->movement_amount_x - 0.5f) * 2.0f;
94+
float movement_speed_value_x = this->movement_speed_x * SPEED_MULTIPLIER * time;
95+
x = movement_x * movement_range_x * std::sin(movement_speed_value_x + this->phase);
96+
}
97+
98+
// Translate Y
99+
if(this->movement_amount_y != 0.5){
100+
float movement_y = (this->movement_amount_y - 0.5f) * 2.0f;
101+
float movement_speed_value_y = this->movement_speed_y * SPEED_MULTIPLIER * time;
102+
y = movement_y * movement_range_y * std::cos(movement_speed_value_y + this->phase);
103+
}
104+
105+
// Translate by adding the half screen coordinates to scale and rotate from center
106+
float center_x = this->width / 2.0f;
107+
float center_y = this->height / 2.0f;
108+
cairo_matrix_translate(matrix, center_x + x, center_y + y);
109+
110+
// Scale
111+
if(this->scale != 0.5){
112+
float scale_factor = 1.5f - this->scale;
113+
cairo_matrix_scale(matrix, scale_factor, scale_factor);
114+
}
115+
116+
// Rotation
117+
if(this->rotation_amount != 0.5){
118+
float rotation_speed_value = (this->rotation_speed * SPEED_MULTIPLIER * time) + this->phase;
119+
float rotation = ((this->rotation_amount - 0.5f) * ROTATION_AMOUNT_MULTIPLIER) * std::sin(rotation_speed_value) * M_PI;
120+
cairo_matrix_rotate(matrix, rotation);
121+
}
122+
123+
// Restore translate coordinates
124+
cairo_matrix_translate(matrix, -center_x, -center_y);
125+
}
126+
127+
virtual void update(double time, uint32_t* out, const uint32_t* in) {
128+
int w = this->width;
129+
int h = this->height;
130+
131+
// Calculate the stride for the image surface based on width and format
132+
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w);
133+
134+
// Create a Cairo surface for the destination image
135+
cairo_surface_t* dest_image = cairo_image_surface_create_for_data((unsigned char*)out,
136+
CAIRO_FORMAT_ARGB32,
137+
w,
138+
h,
139+
stride);
140+
141+
// Create a Cairo drawing context for the destination surface
142+
cairo_t *cr = cairo_create(dest_image);
143+
144+
// Clear the screen
145+
clearScreen(cr, w, h);
146+
147+
// Create a Cairo surface for the source image
148+
cairo_surface_t *image = cairo_image_surface_create_for_data((unsigned char*)in,
149+
CAIRO_FORMAT_ARGB32,
150+
w,
151+
h,
152+
stride);
153+
154+
// Create a pattern from the source image surface
155+
cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
156+
157+
if(this->mirrored){
158+
// Set the pattern extend mode to reflect (mirror) when the pattern is out of bounds
159+
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT);
160+
} else {
161+
// Set the pattern extend mode to none (mirroring does not apply)
162+
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_NONE);
163+
}
164+
165+
// Initialize the transformation matrix
166+
cairo_matrix_t matrix;
167+
cairo_matrix_init_identity(&matrix);
168+
169+
// Call the function that applies the movement
170+
oscillate(&matrix, time);
171+
172+
// Set the transformation matrix for the pattern
173+
cairo_pattern_set_matrix(pattern, &matrix);
174+
// Set the source pattern to be used for drawing
175+
cairo_set_source(cr, pattern);
176+
177+
// Draw a rectangle covering the entire image area
178+
cairo_rectangle(cr, 0, 0, w, h);
179+
// Fill the rectangle with the source pattern
180+
cairo_fill(cr);
181+
182+
// Clean up resources
183+
cairo_pattern_destroy (pattern);
184+
cairo_surface_destroy (image);
185+
cairo_surface_destroy (dest_image);
186+
cairo_destroy (cr);
187+
}
188+
};
189+
190+
frei0r::construct<ShakeOscillate> plugin(
191+
"ShakeOscillate",
192+
"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.",
193+
"Johann JEG",
194+
1, 0,
195+
F0R_COLOR_MODEL_RGBA8888);

0 commit comments

Comments
 (0)