Skip to content

Commit

Permalink
mirr0r filter added (#196)
Browse files Browse the repository at this point in the history
* mirr0r filter added

* removed redundant and unused includes

* Using Cairo graphics library

* fixed parameters range

* Clear the screen before drawing, to avoid problems with image sources with transparency.

* Remove unused import
  • Loading branch information
JohannJEG authored Nov 15, 2024
1 parent 475c9a4 commit 9178c72
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ doc/html
/out/
/.vs/
CMakeSettings.json
.vscode
1 change: 1 addition & 0 deletions src/filter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
15 changes: 15 additions & 0 deletions src/filter/mirr0r/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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})
136 changes: 136 additions & 0 deletions src/filter/mirr0r/mirr0r.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/

#include "frei0r.hpp"
#include <cairo.h>
#define _USE_MATH_DEFINES
#include <cmath>

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.0;
this->y_offset = 0.0;
this->zoom = 0.5;
this->rotation = 0.0;
}

~Mirr0r(){

}

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;
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);
// 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;

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);
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);
}
};

frei0r::construct<Mirr0r> 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);

0 comments on commit 9178c72

Please sign in to comment.