Remove dependency on opencv on Linux, fixes for Epsilon

This commit is contained in:
Deukhoofd 2022-01-16 13:18:17 +01:00
parent e8daa65e6c
commit 14234735c6
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
7 changed files with 235 additions and 82 deletions

View File

@ -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>

View File

@ -4,12 +4,11 @@ project("atomorph")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_compile_options(-Wall -Wextra -Werror)
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(DEMO "Whether or not the demo should be built." 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)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
@ -43,15 +42,21 @@ endif (WINDOWS)
if (STATICC)
message("Linking dependencies statically.")
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)
if (OPENCV)
include(CMakeLists.txt.in)
include_opencv()
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_definitions(-D ATOMORPH_OPENCV)
set(LINKS ${LINKS} ${OpenCV_LIBS})
if (STATICC)
set(LINKS ${LINKS} -Wl,-Bstatic opencv_core opencv_flann -Wl,-Bdynamic)
else()
set(LINKS ${LINKS} ${OpenCV_LIBS})
endif()
endif()
target_link_libraries(atomorph ${LINKS})

37
CMakeLists.txt.in Normal file
View File

@ -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()

View File

@ -1,14 +1,14 @@
/*
* See Copyright Notice in main.h
*/
#include <stdio.h>
#include <math.h>
#include <chrono>
#include <thread>
#include "main.h"
#include "lodepng.h"
#include <chrono>
#include <fstream>
#include <math.h>
#include <stdio.h>
#include <thread>
#include "../src/atomorph.h"
#include "lodepng.h"
MORPH_OPTIONS options;
@ -29,28 +29,28 @@ int main(int argc, char **argv) {
// Options should be set before any operations with
// the morph instance. However, they can be changed
// during the run time too.
morph.set_blob_delimiter (options.differ_blobs);
morph.set_blob_max_size (options.blob_max_size);
morph.set_blob_min_size (options.blob_min_size);
morph.set_blob_box_grip (options.blob_box_grip);
morph.set_blob_box_samples(options.blob_box_samples);
morph.set_blob_threshold (options.blob_threshold);
morph.set_blob_number (options.blob_number);
morph.set_seed (options.seed);
morph.set_blob_rgba_weight(options.blob_rgba_weight);
morph.set_blob_size_weight(options.blob_size_weight);
morph.set_blob_xy_weight (options.blob_xy_weight);
morph.set_degeneration (options.degenerate);
morph.set_density (options.density); // Higher than 1 sets fluid to 0.
morph.set_motion (options.motion);
morph.set_fading (options.fading);
morph.set_threads (options.threads);
morph.set_cycle_length (options.cycle_length);
morph.set_feather (options.feather);
morph.set_keep_background (options.keep_background);
morph.set_finite (options.finite);
morph.set_show_blobs (options.show_blobs);
morph.set_fluid (options.fluid); // Higher than 0 sets density to 1.
morph.set_blob_delimiter(am::HSP);
morph.set_blob_max_size(SIZE_MAX);
morph.set_blob_min_size(1);
morph.set_blob_box_grip(UINT16_MAX);
morph.set_blob_box_samples(100);
morph.set_blob_threshold(1.0);
morph.set_blob_number(1);
morph.set_seed(0);
morph.set_blob_rgba_weight(1);
morph.set_blob_size_weight(0);
morph.set_blob_xy_weight(0);
morph.set_degeneration(10000);
morph.set_density(2); // Higher than 1 sets fluid to 0.
morph.set_motion(am::SPLINE);
morph.set_fading(am::PERLIN);
morph.set_threads(8);
morph.set_cycle_length(100000);
morph.set_feather(0);
morph.set_keep_background(0);
morph.set_finite(1);
morph.set_show_blobs(am::TEXTURE);
morph.set_fluid(0); // Higher than 0 sets density to 1.
if (!load_files(&morph)) return -1;
@ -143,13 +143,37 @@ bool load_files(am::morph *morph) {
// Load input image files:
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());
error = lodepng::decode(image, width, height, buf.c_str());
if (error) {
std::cerr << lodepng_error_text(error) << "." << std::endl;
return false;
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());
if (error) {
std::cerr << lodepng_error_text(error) << "." << std::endl;
return false;
}
}
max_width = std::max(max_width, width);

View File

@ -41,9 +41,9 @@ class MORPH_OPTIONS {
int width = 0;
unsigned seed = 0;
unsigned frames_out= 0;
unsigned match_time= 1;
unsigned morph_time= 3;
unsigned feather = 0;
unsigned match_time= 0;
unsigned morph_time= 0;
unsigned feather = 1;
unsigned fluid = 0;
unsigned cycle_length=100000;

View File

@ -2,49 +2,142 @@
#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();
morph->set_blob_delimiter (am::HSP);
morph->set_blob_max_size (128);
morph->set_blob_min_size (3);
morph->set_blob_box_grip (16);
morph->set_blob_box_samples(-1);
morph->set_blob_threshold (128);
morph->set_blob_number (1);
morph->set_seed (0);
morph->set_blob_delimiter(am::HSP);
morph->set_blob_max_size(SIZE_MAX);
morph->set_blob_min_size(1);
morph->set_blob_box_grip(UINT16_MAX);
morph->set_blob_box_samples(100);
morph->set_blob_threshold(1.0);
morph->set_blob_number(1);
morph->set_seed(0);
morph->set_blob_rgba_weight(1);
morph->set_blob_size_weight(0);
morph->set_blob_xy_weight (0);
morph->set_degeneration (10000);
morph->set_density (2); // Higher than 1 sets fluid to 0.
morph->set_motion (am::SPLINE);
morph->set_fading (am::PERLIN);
morph->set_threads (8);
morph->set_cycle_length (100000);
morph->set_feather (0);
morph->set_keep_background (0);
morph->set_finite (1);
morph->set_show_blobs (am::TEXTURE);
morph->set_fluid (0); // Higher than 0 sets density to 1.
morph->set_blob_xy_weight(0);
morph->set_degeneration(10000);
morph->set_density(2); // Higher than 1 sets fluid to 0.
morph->set_motion(am::SPLINE);
morph->set_fading(am::PERLIN);
morph->set_threads(16);
morph->set_cycle_length(100000);
morph->set_feather(0);
morph->set_keep_background(0);
morph->set_finite(1);
morph->set_show_blobs(am::TEXTURE);
morph->set_fluid(0); // Higher than 0 sets density to 1.
morph->set_resolution(width, height);
for (int i = 0; i < width * height; i++) {
auto real_index = i * 4;
morph->add_pixel(0, am::create_pixel(i % width, i / width, img_a[real_index], img_a[real_index + 1],
img_a[real_index + 2], img_a[real_index + 3]));
}
for (int i = 0; i < width * height; i++) {
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]));
auto i1 = std::vector<uint8_t>(img_a, img_a + width * height * 4);
auto i2 = std::vector<uint8_t>(img_b, img_b + width * height * 4);
auto success = set_morph_frame(morph, 0, width, i1) && set_morph_frame(morph, 1, width, i2);
if (!success) {
return nullptr;
}
morph->compute();
while (true) {
morph->suspend();
morph->synchronize();
morph->compute();
auto state = morph->get_state();
if (state > am::STATE_BLOB_UNIFICATION) {
break;
}
}
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; }

View File

@ -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
// share the source with some other particle, but it will still
// 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) {
size_t pos = it->first;
size_t x = it->second;