diff --git a/.gitignore b/.gitignore index e721454..e7f7afe 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ tags cmake_install.cmake CMakeFiles CMakeCache.txt +install_manifest.txt *~ Makefile.in Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 62bc56c..f6c5b51 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -60,6 +60,7 @@ plugin_LTLIBRARIES = \ G.la \ gamma.la \ glow.la \ + glitch0r.la \ grain_extract.la \ grain_merge.la \ hardlight.la \ @@ -222,6 +223,7 @@ flippo_la_SOURCES = filter/flippo/flippo.c G_la_SOURCES = filter/RGB/G.c gamma_la_SOURCES = filter/gamma/gamma.c glow_la_SOURCES = filter/glow/glow.c +glitch0r_la_SOURCES = filter/glitch0r/glitch0r.c hqdn3d_la_SOURCES = filter/denoise/hqdn3d.c hueshift0r_la_SOURCES = filter/hueshift0r/hueshift0r.c filter/hueshift0r/matrix.h IIRblur_la_SOURCES = filter/blur/IIRblur.c filter/blur/fibe.h diff --git a/src/filter/CMakeLists.txt b/src/filter/CMakeLists.txt index 27fce2f..fd7d8d0 100644 --- a/src/filter/CMakeLists.txt +++ b/src/filter/CMakeLists.txt @@ -47,6 +47,7 @@ add_subdirectory (equaliz0r) add_subdirectory (flippo) add_subdirectory (gamma) add_subdirectory (glow) +add_subdirectory (glitch0r) #add_subdirectory (host_param_test) add_subdirectory (hueshift0r) add_subdirectory (invert0r) diff --git a/src/filter/glitch0r/CMakeLists.txt b/src/filter/glitch0r/CMakeLists.txt new file mode 100644 index 0000000..55abe62 --- /dev/null +++ b/src/filter/glitch0r/CMakeLists.txt @@ -0,0 +1,12 @@ +set (SOURCES glitch0r.c) +set (TARGET glitch0r) + +if (MSVC) + set_source_files_properties (glitch0r.c PROPERTIES LANGUAGE CXX) + set (SOURCES ${SOURCES} ${FREI0R_DEF}) +endif (MSVC) + +add_library (${TARGET} MODULE ${SOURCES}) +set_target_properties (${TARGET} PROPERTIES PREFIX "") + +install (TARGETS ${TARGET} LIBRARY DESTINATION ${LIBDIR}) diff --git a/src/filter/glitch0r/glitch0r.c b/src/filter/glitch0r/glitch0r.c new file mode 100644 index 0000000..857146d --- /dev/null +++ b/src/filter/glitch0r/glitch0r.c @@ -0,0 +1,355 @@ +/* glitch0r.c + * Copyright (C) 2016 IDENT Software ~ http://identsoft.org + * Inspired by the test video on frei0r.dune.org + * + * 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 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 +#include + +#include "frei0r.h" + +/* cheap & fast randomizer (by Fukuchi Kentarou) */ +static uint32_t randval; +inline static uint32_t fastrand() { return (randval=randval*1103515245+12345); }; +static void fastsrand(uint32_t seed) { randval = seed; }; + +struct glitch0r_state // helps to save time when allocating in a loop +{ + unsigned int currentBlock; + unsigned int currentPos; + unsigned int currentY; + unsigned int blkShift; + + uint32_t distortionSeed1; + uint32_t distortionSeed2; + + short int howToDistort1; + short int howToDistort2; + short int passThisLine; +} g0r_state; + +typedef struct glitch0r_instance +{ + unsigned int width; + unsigned int height; + + unsigned int maxBlockSize; + unsigned int maxBlockShift; + + short int colorGlitchIntensity; + short int doColorDistortion; + short int glitchChance; +} glitch0r_instance_t; + + +inline static unsigned int rnd (unsigned int min, unsigned int max) +{ + return fastrand() % (max - min + 1) + min; +} + +inline static void glitch0r_state_reset(glitch0r_instance_t *inst) +{ + g0r_state.currentPos = 0; + g0r_state.currentBlock = rnd(1, inst->maxBlockSize); + g0r_state.blkShift = rnd(1, inst->maxBlockShift); + g0r_state.passThisLine = (inst->glitchChance < rnd(1, 101)) ? 1 : 0; + + if (inst->doColorDistortion) + { + g0r_state.distortionSeed1 = rnd(0x00000000, 0xfffffffe); + g0r_state.distortionSeed2 = rnd(0x00000000, 0xfffffffe); + g0r_state.howToDistort1 = rnd (0, inst->colorGlitchIntensity); + g0r_state.howToDistort2 = rnd (0, inst->colorGlitchIntensity); + } +} + +inline static void glitch0r_pixel_dist0rt (uint32_t *pixel, + uint32_t distortionSeed, short int howToDistort) +{ + + // Save alpha + uint8_t *px = (uint8_t *)pixel; + uint8_t alpha = px[3]; + + // Choose from five levels of madness: + switch (howToDistort) + { + case 0 : return; // ok, let this pixel live (just shift) + + case 1 : // lightest distortion: just invert + *(pixel) = ~*(pixel); + break; + + case 2 : // add some unneeded colors + *(pixel) = distortionSeed | *(pixel); + break; + + case 3 : // change some colors + *(pixel) = distortionSeed ^ *(pixel); + break; + + case 4 : // oh shi... + *(pixel) = distortionSeed & *(pixel); + break; + } + + // Restore alpha + px[3] = alpha; +} + +int f0r_init() +{ + fastsrand((uint32_t)time(0)); + return 1; +} + +void f0r_deinit() +{ /* no initialization required */ } + +void f0r_get_plugin_info(f0r_plugin_info_t* glitch0rInfo) +{ + glitch0rInfo->name = "Glitch0r"; + glitch0rInfo->author = "IDENT Software"; + glitch0rInfo->plugin_type = F0R_PLUGIN_TYPE_FILTER; + glitch0rInfo->color_model = F0R_COLOR_MODEL_RGBA8888; + glitch0rInfo->frei0r_version = FREI0R_MAJOR_VERSION; + glitch0rInfo->major_version = 0; + glitch0rInfo->minor_version = 1; + glitch0rInfo->num_params = 4; + glitch0rInfo->explanation = "Adds glitches and block shifting"; +} + +void f0r_get_param_info(f0r_param_info_t* info, int param_index) +{ + switch(param_index) { + case 0: + { + info->name = "Glitch frequency"; + info->type = F0R_PARAM_DOUBLE; + info->explanation = "How frequently the glitch should be applied"; + break; + } + + case 1: + { + info->name = "Block height"; + info->type = F0R_PARAM_DOUBLE; + info->explanation = "Height range of the block that will be shifted/glitched"; + break; + } + + case 2: + { + info->name = "Shift intensity"; + info->type = F0R_PARAM_DOUBLE; + info->explanation = "How much we should move blocks when glitching"; + break; + } + + case 3: + { + info->name = "Color glitching intensity"; + info->type = F0R_PARAM_DOUBLE; + info->explanation = "How intensive should be color distortion"; + break; + } + } +} + +f0r_instance_t f0r_construct(unsigned int width, unsigned int height) +{ + glitch0r_instance_t* inst = (glitch0r_instance_t*)calloc(1, sizeof(*inst)); + inst->width = width; inst->height = height; + inst->maxBlockSize = (unsigned int)(inst->height / 2); + inst->maxBlockShift = (unsigned int)(inst->width / 2); + inst->colorGlitchIntensity = 3; + inst->doColorDistortion = 1; + + glitch0r_state_reset(inst); + + return (f0r_instance_t)inst; +} + +void f0r_destruct(f0r_instance_t instance) +{ + free(instance); +} + +void f0r_set_param_value(f0r_instance_t instance, + f0r_param_t param, int param_index) +{ + assert(instance); + glitch0r_instance_t * inst = (glitch0r_instance_t*)instance; + + switch (param_index) + { + + case 0 : // glitch frequency + { + double glitchChance = *((double*)param); + // convert frei0r range [0, 1] to range between 0 and 100 + glitchChance = (100 * glitchChance); + inst->glitchChance = (short int)glitchChance; + break; + } + + case 1 : // block height + { + double mbHeight = *((double*)param); + // convert frei0r range [0, 1] to range between 1 and maximal height + mbHeight = (1 + (inst->height - 1) * mbHeight); + inst->maxBlockSize = (unsigned int)mbHeight; + + // zero size is a bad idea + if (inst->maxBlockSize == 0) + inst->maxBlockSize = (unsigned int)(inst->height / 2); + break; + } + + case 2 : // shift intensity + { + double intensity = *((double*)param); + // convert frei0r range [0, 1] to range between 1 and maximal width + intensity = (1 + (inst->width - 1) * intensity); + inst->maxBlockShift = (unsigned int)intensity; + + // zero shift is a bad idea + if (inst->maxBlockShift == 0) + inst->maxBlockShift = (unsigned int)(inst->width / 2); + break; + } + + case 3 : // color intensity + { + double intensity = *((double*)param); + // convert frei0r range [0, 1] to range between 0 and 5 + intensity = (5 * intensity); + inst->colorGlitchIntensity = (short int)intensity; + + if (inst->colorGlitchIntensity > 0) + { + inst->doColorDistortion = 1; + } + else + inst->doColorDistortion = 0; + + break; + } + } +} + +void f0r_get_param_value(f0r_instance_t instance, + f0r_param_t param, int param_index) +{ + + assert(instance); + glitch0r_instance_t * inst = (glitch0r_instance_t*)instance; + + switch (param_index) + { + case 0 : // glitch frequency + { + // convert plugin's param to frei0r range + *((double*)param) = (inst->glitchChance) / 100; + break; + } + + case 1 : // block height + { + // convert plugin's param to frei0r range + *((double*)param) = (inst->maxBlockSize - 1.0) / (inst->height - 1.0); + break; + } + + case 2 : // block shift intensity + { + *((double*)param) = (inst->maxBlockShift - 1.0) / (inst->width - 1.0); + break; + } + + case 3 : // color glitch intensity + { + *((double*)param) = (inst->colorGlitchIntensity) / 5; // 5 levels of madness + break; + } + } + +} + +void f0r_update(f0r_instance_t instance, double time, + const uint32_t* inframe, uint32_t* outframe) +{ + assert(instance); + glitch0r_instance_t* inst = (glitch0r_instance_t*)instance; + unsigned int x, y; + + uint32_t* dst = outframe; + const uint32_t* src = inframe; + uint32_t *pixel; + + g0r_state.currentBlock = rnd(1, inst->maxBlockSize); + + for (y = 0; y < inst->height; y++) + { + + if (g0r_state.currentPos > g0r_state.currentBlock) + { + glitch0r_state_reset(inst); + } + else + g0r_state.currentPos++; + + g0r_state.currentY = y*inst->width; + pixel = dst + g0r_state.currentY; + + if (g0r_state.passThisLine) + { + memcpy((uint32_t *)(dst + g0r_state.currentY), + (uint32_t *)(src + g0r_state.currentY), + (inst->width) * sizeof(uint32_t)); + continue; + } + + for (x = g0r_state.blkShift; x < (inst->width); x++) + { + *(pixel) = *(src + g0r_state.currentY + x); + + if (inst->doColorDistortion) + glitch0r_pixel_dist0rt(pixel, + g0r_state.distortionSeed1, g0r_state.howToDistort1); + + pixel++; + } + + for (x = 0; x < g0r_state.blkShift; x++) + { + *(pixel) = *(src + g0r_state.currentY + x); + + if (inst->doColorDistortion) + glitch0r_pixel_dist0rt(pixel, + g0r_state.distortionSeed2, g0r_state.howToDistort2); + + pixel++; + } + + } +} +