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_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})
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
#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,15 +143,39 @@ 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.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());
|
||||
if (error) {
|
||||
std::cerr << lodepng_error_text(error) << "." << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
max_width = std::max(max_width, width);
|
||||
max_height = std::max(max_height, height);
|
||||
|
||||
|
|
|
@ -41,11 +41,11 @@ 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;
|
||||
unsigned threads =8;
|
||||
|
||||
|
|
|
@ -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; }
|
|
@ -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;
|
||||
|
@ -954,7 +954,7 @@ void morph::step_fluid(size_t frame_key, double t, double time) {
|
|||
p->destination_pos = pos;
|
||||
particles_by_destination[pos].push_back(p);
|
||||
destination_found = true;
|
||||
|
||||
|
||||
{
|
||||
// Destination was found but all the sources were already
|
||||
// occupied. Now see the pt1 of this destination even if
|
||||
|
|
Loading…
Reference in New Issue