Remove dependency on opencv on Linux, fixes for Epsilon
This commit is contained in:
parent
e8daa65e6c
commit
14234735c6
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
|
@ -4,12 +4,11 @@ project("atomorph")
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
add_compile_options(-Wall -Wextra -Werror)
|
|
||||||
|
|
||||||
option(WINDOWS "Whether the build target is Windows or not." OFF)
|
option(WINDOWS "Whether the build target is Windows or not." OFF)
|
||||||
option(SHARED "Whether we should build a shared library, instead of a static one." OFF)
|
option(SHARED "Whether we should build a shared library, instead of a static one." OFF)
|
||||||
option(DEMO "Whether or not the demo should be built." OFF)
|
option(DEMO "Whether or not the demo should be built." OFF)
|
||||||
option(OPENCV "Whether or not opencv should be targeted." OFF)
|
option(OPENCV "Whether or not opencv should be targeted." OFF)
|
||||||
|
option(STATICC "Whether or not dependencies should be statically linked." ON)
|
||||||
|
|
||||||
if (NOT WINDOWS)
|
if (NOT WINDOWS)
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
@ -43,15 +42,21 @@ endif (WINDOWS)
|
||||||
if (STATICC)
|
if (STATICC)
|
||||||
message("Linking dependencies statically.")
|
message("Linking dependencies statically.")
|
||||||
set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
|
set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
|
||||||
set(LINKS -static-libgcc -static-libstdc++ -Wl,-Bstatic -lm -lstdc++ -lpthread -Wl,-Bdynamic ${LINKS})
|
set(LINKS -lm -lpthread -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic ${LINKS})
|
||||||
endif(STATICC)
|
endif(STATICC)
|
||||||
|
|
||||||
if (OPENCV)
|
if (OPENCV)
|
||||||
|
include(CMakeLists.txt.in)
|
||||||
|
include_opencv()
|
||||||
find_package( OpenCV REQUIRED )
|
find_package( OpenCV REQUIRED )
|
||||||
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
||||||
|
|
||||||
add_definitions(-D ATOMORPH_OPENCV)
|
add_definitions(-D ATOMORPH_OPENCV)
|
||||||
|
if (STATICC)
|
||||||
|
set(LINKS ${LINKS} -Wl,-Bstatic opencv_core opencv_flann -Wl,-Bdynamic)
|
||||||
|
else()
|
||||||
set(LINKS ${LINKS} ${OpenCV_LIBS})
|
set(LINKS ${LINKS} ${OpenCV_LIBS})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(atomorph ${LINKS})
|
target_link_libraries(atomorph ${LINKS})
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
|
||||||
|
project(atomorph-download NONE)
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
ExternalProject_Add(opencv
|
||||||
|
GIT_REPOSITORY https://github.com/opencv/opencv.git
|
||||||
|
GIT_TAG 4.x
|
||||||
|
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/opencv"
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
TEST_COMMAND ""
|
||||||
|
)
|
||||||
|
|
||||||
|
function(include_opencv)
|
||||||
|
configure_file(CMakeLists.txt.in opencv/download/CMakeLists.txt)
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . -DBUILD_SHARED_LIBS:BOOL=OFF
|
||||||
|
RESULT_VARIABLE result
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/opencv/download)
|
||||||
|
if (result)
|
||||||
|
message(FATAL_ERROR "CMake step for opencv failed: ${result}")
|
||||||
|
endif ()
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} --build .
|
||||||
|
RESULT_VARIABLE result
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/opencv/download)
|
||||||
|
if (result)
|
||||||
|
message(FATAL_ERROR "Build step for opencv failed: ${result}")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/opencv/src/opencv
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/opencv/bin
|
||||||
|
EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
|
set( OPENCV_ROOT_DIR ${CMAKE_BINARY_DIR}/INSTALL )
|
||||||
|
set( OPENCV_DIR ${CMAKE_BINARY_DIR}/INSTALL )
|
||||||
|
endfunction()
|
|
@ -1,14 +1,14 @@
|
||||||
/*
|
/*
|
||||||
* See Copyright Notice in main.h
|
* See Copyright Notice in main.h
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <chrono>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "lodepng.h"
|
#include <chrono>
|
||||||
|
#include <fstream>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <thread>
|
||||||
#include "../src/atomorph.h"
|
#include "../src/atomorph.h"
|
||||||
|
#include "lodepng.h"
|
||||||
|
|
||||||
MORPH_OPTIONS options;
|
MORPH_OPTIONS options;
|
||||||
|
|
||||||
|
@ -29,28 +29,28 @@ int main(int argc, char **argv) {
|
||||||
// Options should be set before any operations with
|
// Options should be set before any operations with
|
||||||
// the morph instance. However, they can be changed
|
// the morph instance. However, they can be changed
|
||||||
// during the run time too.
|
// during the run time too.
|
||||||
morph.set_blob_delimiter (options.differ_blobs);
|
morph.set_blob_delimiter(am::HSP);
|
||||||
morph.set_blob_max_size (options.blob_max_size);
|
morph.set_blob_max_size(SIZE_MAX);
|
||||||
morph.set_blob_min_size (options.blob_min_size);
|
morph.set_blob_min_size(1);
|
||||||
morph.set_blob_box_grip (options.blob_box_grip);
|
morph.set_blob_box_grip(UINT16_MAX);
|
||||||
morph.set_blob_box_samples(options.blob_box_samples);
|
morph.set_blob_box_samples(100);
|
||||||
morph.set_blob_threshold (options.blob_threshold);
|
morph.set_blob_threshold(1.0);
|
||||||
morph.set_blob_number (options.blob_number);
|
morph.set_blob_number(1);
|
||||||
morph.set_seed (options.seed);
|
morph.set_seed(0);
|
||||||
morph.set_blob_rgba_weight(options.blob_rgba_weight);
|
morph.set_blob_rgba_weight(1);
|
||||||
morph.set_blob_size_weight(options.blob_size_weight);
|
morph.set_blob_size_weight(0);
|
||||||
morph.set_blob_xy_weight (options.blob_xy_weight);
|
morph.set_blob_xy_weight(0);
|
||||||
morph.set_degeneration (options.degenerate);
|
morph.set_degeneration(10000);
|
||||||
morph.set_density (options.density); // Higher than 1 sets fluid to 0.
|
morph.set_density(2); // Higher than 1 sets fluid to 0.
|
||||||
morph.set_motion (options.motion);
|
morph.set_motion(am::SPLINE);
|
||||||
morph.set_fading (options.fading);
|
morph.set_fading(am::PERLIN);
|
||||||
morph.set_threads (options.threads);
|
morph.set_threads(8);
|
||||||
morph.set_cycle_length (options.cycle_length);
|
morph.set_cycle_length(100000);
|
||||||
morph.set_feather (options.feather);
|
morph.set_feather(0);
|
||||||
morph.set_keep_background (options.keep_background);
|
morph.set_keep_background(0);
|
||||||
morph.set_finite (options.finite);
|
morph.set_finite(1);
|
||||||
morph.set_show_blobs (options.show_blobs);
|
morph.set_show_blobs(am::TEXTURE);
|
||||||
morph.set_fluid (options.fluid); // Higher than 0 sets density to 1.
|
morph.set_fluid(0); // Higher than 0 sets density to 1.
|
||||||
|
|
||||||
if (!load_files(&morph)) return -1;
|
if (!load_files(&morph)) return -1;
|
||||||
|
|
||||||
|
@ -143,14 +143,38 @@ bool load_files(am::morph *morph) {
|
||||||
|
|
||||||
// Load input image files:
|
// Load input image files:
|
||||||
for (i=0; i<options.files.size(); ++i) {
|
for (i=0; i<options.files.size(); ++i) {
|
||||||
buf=options.indir; buf.append("/"); buf.append(options.files[i]);
|
buf=options.indir;
|
||||||
|
buf.append("/");
|
||||||
|
buf.append(options.files[i]);
|
||||||
|
image.clear();
|
||||||
|
|
||||||
if (options.verbose) printf("Loading %-30s ... ", buf.c_str());
|
if (options.verbose) printf("Loading %-30s ... ", buf.c_str());
|
||||||
|
if (options.files[i].ends_with(".raw")){
|
||||||
|
std::ifstream stream(buf.c_str(), std::ios::in | std::ios::binary);
|
||||||
|
stream.unsetf(std::ios::skipws);
|
||||||
|
image.insert(image.begin(),
|
||||||
|
std::istream_iterator<uint8_t>(stream),
|
||||||
|
std::istream_iterator<uint8_t>());
|
||||||
|
width = image[0];
|
||||||
|
height = image[1];
|
||||||
|
image.erase(image.begin());
|
||||||
|
image.erase(image.begin());
|
||||||
|
std::string buf_o = "foo_";
|
||||||
|
buf_o += std::to_string(i);
|
||||||
|
buf_o += ".png";
|
||||||
|
error = lodepng::encode(buf_o, image, width, height);
|
||||||
|
if (error) {
|
||||||
|
std::cerr << lodepng_error_text(error) << "." << std::endl;
|
||||||
|
//return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
error = lodepng::decode(image, width, height, buf.c_str());
|
error = lodepng::decode(image, width, height, buf.c_str());
|
||||||
if (error) {
|
if (error) {
|
||||||
std::cerr << lodepng_error_text(error) << "." << std::endl;
|
std::cerr << lodepng_error_text(error) << "." << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
max_width = std::max(max_width, width);
|
max_width = std::max(max_width, width);
|
||||||
max_height = std::max(max_height, height);
|
max_height = std::max(max_height, height);
|
||||||
|
|
|
@ -41,9 +41,9 @@ class MORPH_OPTIONS {
|
||||||
int width = 0;
|
int width = 0;
|
||||||
unsigned seed = 0;
|
unsigned seed = 0;
|
||||||
unsigned frames_out= 0;
|
unsigned frames_out= 0;
|
||||||
unsigned match_time= 1;
|
unsigned match_time= 0;
|
||||||
unsigned morph_time= 3;
|
unsigned morph_time= 0;
|
||||||
unsigned feather = 0;
|
unsigned feather = 1;
|
||||||
unsigned fluid = 0;
|
unsigned fluid = 0;
|
||||||
|
|
||||||
unsigned cycle_length=100000;
|
unsigned cycle_length=100000;
|
||||||
|
|
|
@ -2,49 +2,142 @@
|
||||||
|
|
||||||
#define export extern "C" [[maybe_unused]]
|
#define export extern "C" [[maybe_unused]]
|
||||||
|
|
||||||
export am::morph* create_morph(uint16_t width, uint16_t height, uint8_t img_a[], uint8_t img_b[]) {
|
static bool set_morph_frame(am::morph* morph, size_t frame, uint16_t width, const std::vector<uint8_t>& image) {
|
||||||
|
auto sz = image.size();
|
||||||
|
unsigned char r = 0, g = 0, b = 0, a = 0;
|
||||||
|
size_t pixel = 0;
|
||||||
|
|
||||||
|
if (width > UINT16_MAX)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < sz; ++j) {
|
||||||
|
switch (j % 4) {
|
||||||
|
case 0: r = image.at(j); break;
|
||||||
|
case 1: g = image.at(j); break;
|
||||||
|
case 2: b = image.at(j); break;
|
||||||
|
default: {
|
||||||
|
a = image.at(j);
|
||||||
|
|
||||||
|
if (a == 0) {
|
||||||
|
pixel++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
morph->add_pixel(frame, am::create_pixel(pixel % width, pixel / width, r, g, b, a));
|
||||||
|
pixel++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export am::morph* create_morph(uint16_t width, uint16_t height, uint8_t img_a[],
|
||||||
|
uint8_t img_b[]) {
|
||||||
auto* morph = new am::morph();
|
auto* morph = new am::morph();
|
||||||
|
|
||||||
morph->set_blob_delimiter (am::HSP);
|
morph->set_blob_delimiter(am::HSP);
|
||||||
morph->set_blob_max_size (128);
|
morph->set_blob_max_size(SIZE_MAX);
|
||||||
morph->set_blob_min_size (3);
|
morph->set_blob_min_size(1);
|
||||||
morph->set_blob_box_grip (16);
|
morph->set_blob_box_grip(UINT16_MAX);
|
||||||
morph->set_blob_box_samples(-1);
|
morph->set_blob_box_samples(100);
|
||||||
morph->set_blob_threshold (128);
|
morph->set_blob_threshold(1.0);
|
||||||
morph->set_blob_number (1);
|
morph->set_blob_number(1);
|
||||||
morph->set_seed (0);
|
morph->set_seed(0);
|
||||||
morph->set_blob_rgba_weight(1);
|
morph->set_blob_rgba_weight(1);
|
||||||
morph->set_blob_size_weight(0);
|
morph->set_blob_size_weight(0);
|
||||||
morph->set_blob_xy_weight (0);
|
morph->set_blob_xy_weight(0);
|
||||||
morph->set_degeneration (10000);
|
morph->set_degeneration(10000);
|
||||||
morph->set_density (2); // Higher than 1 sets fluid to 0.
|
morph->set_density(2); // Higher than 1 sets fluid to 0.
|
||||||
morph->set_motion (am::SPLINE);
|
morph->set_motion(am::SPLINE);
|
||||||
morph->set_fading (am::PERLIN);
|
morph->set_fading(am::PERLIN);
|
||||||
morph->set_threads (8);
|
morph->set_threads(16);
|
||||||
morph->set_cycle_length (100000);
|
morph->set_cycle_length(100000);
|
||||||
morph->set_feather (0);
|
morph->set_feather(0);
|
||||||
morph->set_keep_background (0);
|
morph->set_keep_background(0);
|
||||||
morph->set_finite (1);
|
morph->set_finite(1);
|
||||||
morph->set_show_blobs (am::TEXTURE);
|
morph->set_show_blobs(am::TEXTURE);
|
||||||
morph->set_fluid (0); // Higher than 0 sets density to 1.
|
morph->set_fluid(0); // Higher than 0 sets density to 1.
|
||||||
|
|
||||||
|
|
||||||
morph->set_resolution(width, height);
|
morph->set_resolution(width, height);
|
||||||
for (int i = 0; i < width * height; i++) {
|
|
||||||
auto real_index = i * 4;
|
auto i1 = std::vector<uint8_t>(img_a, img_a + width * height * 4);
|
||||||
morph->add_pixel(0, am::create_pixel(i % width, i / width, img_a[real_index], img_a[real_index + 1],
|
auto i2 = std::vector<uint8_t>(img_b, img_b + width * height * 4);
|
||||||
img_a[real_index + 2], img_a[real_index + 3]));
|
auto success = set_morph_frame(morph, 0, width, i1) && set_morph_frame(morph, 1, width, i2);
|
||||||
}
|
if (!success) {
|
||||||
for (int i = 0; i < width * height; i++) {
|
return nullptr;
|
||||||
auto real_index = i * 4;
|
|
||||||
morph->add_pixel(1, am::create_pixel(i % width, i / width, img_b[real_index], img_b[real_index + 1],
|
|
||||||
img_b[real_index + 2], img_b[real_index + 3]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
morph->compute();
|
morph->compute();
|
||||||
|
while (true) {
|
||||||
|
morph->suspend();
|
||||||
|
morph->synchronize();
|
||||||
|
morph->compute();
|
||||||
|
auto state = morph->get_state();
|
||||||
|
if (state > am::STATE_BLOB_UNIFICATION) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return morph;
|
return morph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export void run_blob_matching(am::morph* morph, size_t ms) {
|
||||||
|
std::chrono::steady_clock::time_point start, now;
|
||||||
|
start = std::chrono::steady_clock::now();
|
||||||
|
while (true) {
|
||||||
|
morph->suspend();
|
||||||
|
morph->synchronize();
|
||||||
|
morph->compute();
|
||||||
|
auto state = morph->get_state();
|
||||||
|
if (state < am::STATE_BLOB_MATCHING) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
now = std::chrono::steady_clock::now();
|
||||||
|
if ((size_t)std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count() >= ms) {
|
||||||
|
morph->next_state();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto state = morph->get_state();
|
||||||
|
while (state < am::STATE_ATOM_MORPHING) {
|
||||||
|
morph->suspend();
|
||||||
|
morph->synchronize();
|
||||||
|
morph->compute();
|
||||||
|
state = morph->get_state();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export void finish_atom_matching(am::morph* morph) {
|
||||||
|
morph->suspend();
|
||||||
|
auto state = morph->get_state();
|
||||||
|
while (state < am::STATE_ATOM_MORPHING) {
|
||||||
|
morph->suspend();
|
||||||
|
morph->synchronize();
|
||||||
|
morph->compute();
|
||||||
|
state = morph->get_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
morph->next_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
export void get_frame(am::morph* morph, size_t frame, size_t total_frames, uint32_t width, uint32_t height,
|
||||||
|
uint8_t out[]) {
|
||||||
|
double t = morph->get_time(frame, total_frames);
|
||||||
|
std::vector<am::pixel> pixels;
|
||||||
|
morph->get_pixels(t, &pixels);
|
||||||
|
auto size = width * height * 4;
|
||||||
|
while (!pixels.empty()) {
|
||||||
|
am::pixel px = pixels.back();
|
||||||
|
pixels.pop_back();
|
||||||
|
|
||||||
|
size_t pos = ((size_t)px.y * width + (size_t)px.x) * 4;
|
||||||
|
if (pos >= size)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
out[pos + 0] = px.c.r;
|
||||||
|
out[pos + 1] = px.c.g;
|
||||||
|
out[pos + 2] = px.c.b;
|
||||||
|
out[pos + 3] = px.c.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export void delete_morph(am::morph* morph) { delete morph; }
|
export void delete_morph(am::morph* morph) { delete morph; }
|
|
@ -939,7 +939,7 @@ void morph::step_fluid(size_t frame_key, double t, double time) {
|
||||||
// All sources are already occupied, this new particle must now
|
// All sources are already occupied, this new particle must now
|
||||||
// share the source with some other particle, but it will still
|
// share the source with some other particle, but it will still
|
||||||
// must get an unused destination. Search for such destination.
|
// must get an unused destination. Search for such destination.
|
||||||
bool destination_found = false;
|
[[maybe_unused]] bool destination_found = false;
|
||||||
for (it=destinations.begin(); it!=destinations.end(); ++it) {
|
for (it=destinations.begin(); it!=destinations.end(); ++it) {
|
||||||
size_t pos = it->first;
|
size_t pos = it->first;
|
||||||
size_t x = it->second;
|
size_t x = it->second;
|
||||||
|
|
Loading…
Reference in New Issue