[DEV] add stupid edf simple image file
This commit is contained in:
parent
d7363f73e0
commit
929f4a4136
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <egami/Image.h>
|
||||
#include <egami/debug.h>
|
||||
|
||||
egami::Image::Image(const ivec2& _size) :
|
||||
m_size(_size) {
|
||||
@ -43,6 +44,21 @@ void egami::Image::resize(const ivec2& _size, const ivec2& _startPos) {
|
||||
}
|
||||
}
|
||||
|
||||
void egami::Image::scale(const ivec2& _size) {
|
||||
// TODO : Add capabilities ...
|
||||
int32_t stepX = m_size.x() / _size.x();
|
||||
int32_t stepY = m_size.y() / _size.y();
|
||||
stepX = etk_max(1, stepX);
|
||||
stepY = etk_max(1, stepY);
|
||||
EGAMI_VERBOSE("move : " << stepX << " , " << stepY << " from : " << m_size << " ==> " << _size);
|
||||
for (int32_t yyy = 0; yyy < _size.y(); ++yyy) {
|
||||
for (int32_t xxx = 0; xxx < _size.x(); ++xxx) {
|
||||
set(ivec2(xxx, yyy), get(ivec2(xxx*stepX, yyy*stepY)));
|
||||
}
|
||||
}
|
||||
resize(_size);
|
||||
}
|
||||
|
||||
|
||||
void egami::Image::clear(etk::Color<> _fill) {
|
||||
for (int32_t iii=0; iii<m_size.x()*m_size.y(); iii++) {
|
||||
|
@ -49,6 +49,12 @@ namespace egami {
|
||||
const etk::Color<>& get(const ivec2& _pos) const;
|
||||
void set(const ivec2& _pos, const etk::Color<>& _newColor);
|
||||
void insert(const ivec2& _pos, const egami::Image& _input);
|
||||
/**
|
||||
* @brief Scale an image in an other dimention.
|
||||
* @param[in] _size Destination size of the image.
|
||||
* @TODO Set this function more capacity like not a multiple ratio...
|
||||
*/
|
||||
void scale(const ivec2& _size);
|
||||
};
|
||||
|
||||
};
|
||||
|
127
egami/egami.cpp
127
egami/egami.cpp
@ -12,6 +12,8 @@
|
||||
#include <egami/wrapperSVG.h>
|
||||
#include <egami/wrapperPNG.h>
|
||||
#include <egami/wrapperBMP.h>
|
||||
#include <egami/wrapperEDF.h>
|
||||
#include <edtaa3/edtaa3func.h>
|
||||
|
||||
bool egami::scalable(const std::string& _fileName) {
|
||||
if (true == end_with(_fileName, ".svg") ) {
|
||||
@ -23,7 +25,12 @@ bool egami::scalable(const std::string& _fileName) {
|
||||
bool egami::load(egami::Image& _output, const std::string& _fileName, const ivec2& _size) {
|
||||
std::string tmpName = std::tolower(_fileName);
|
||||
// select the corect Loader :
|
||||
if (true == end_with(tmpName, ".bmp") ) {
|
||||
if (true == end_with(tmpName, ".edf") ) { // internal format for ewol distance field ==> simple sistance field image
|
||||
if (false == egami::loadEDF(_fileName, _output)) {
|
||||
EGAMI_ERROR("Error to load EDF file '" << _fileName << "'");
|
||||
return false;
|
||||
}
|
||||
} else if (true == end_with(tmpName, ".bmp") ) {
|
||||
if (false == egami::loadBMP(_fileName, _output)) {
|
||||
EGAMI_ERROR("Error to load BMP file '" << _fileName << "'");
|
||||
return false;
|
||||
@ -33,13 +40,14 @@ bool egami::load(egami::Image& _output, const std::string& _fileName, const ivec
|
||||
EGAMI_ERROR("Error to load SVG file '" << _fileName << "'");
|
||||
return false;
|
||||
}
|
||||
egami::storeEDF(_fileName + ".edf", _output);
|
||||
} else if (true == end_with(tmpName, ".png") ) {
|
||||
if (false == egami::loadPNG(_fileName, _output)) {
|
||||
EGAMI_ERROR("Error to load PNG file '" << _fileName << "'");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
EGAMI_ERROR("Extention not managed '" << _fileName << "' Sopported extention : .bmp / .svg / .png");
|
||||
EGAMI_ERROR("Extention not managed '" << _fileName << "' Sopported extention : .edf / .bmp / .svg / .png");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -47,8 +55,14 @@ bool egami::load(egami::Image& _output, const std::string& _fileName, const ivec
|
||||
|
||||
bool egami::store(const egami::Image& _input, const std::string& _fileName) {
|
||||
std::string tmpName = std::tolower(_fileName);
|
||||
EGAMI_DEBUG("Store file : " << _fileName);
|
||||
// select the corect Loader :
|
||||
if (true == end_with(tmpName, ".bmp") ) {
|
||||
if (true == end_with(tmpName, ".edf") ) {
|
||||
if (false == egami::storeEDF(_fileName, _input)) {
|
||||
EGAMI_ERROR("Error to load EDF file '" << _fileName << "'");
|
||||
return false;
|
||||
}
|
||||
} else if (true == end_with(tmpName, ".bmp") ) {
|
||||
if (false == egami::storeBMP(_fileName, _input)) {
|
||||
EGAMI_ERROR("Error to load BMP file '" << _fileName << "'");
|
||||
return false;
|
||||
@ -65,3 +79,110 @@ bool egami::store(const egami::Image& _input, const std::string& _fileName) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void generateDistanceField(const egami::ImageMono& _input, egami::Image& _output) {
|
||||
int32_t size = _input.getSize().x() * _input.getSize().y();
|
||||
std::vector<short> xdist(size);
|
||||
std::vector<short> ydist(size);
|
||||
std::vector<double> gx(size);
|
||||
std::vector<double> gy(size);
|
||||
std::vector<double> data(size);
|
||||
std::vector<double> outside(size);
|
||||
std::vector<double> inside(size);
|
||||
// Convert img into double (data)
|
||||
double img_min = 255, img_max = -255;
|
||||
for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) {
|
||||
for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) {
|
||||
int32_t iii = yyy * _input.getSize().x() + xxx;
|
||||
double v = _input.get(ivec2(xxx, yyy));
|
||||
data[iii] = v;
|
||||
if (v > img_max) {
|
||||
img_max = v;
|
||||
}
|
||||
if (v < img_min) {
|
||||
img_min = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Rescale image levels between 0 and 1
|
||||
for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) {
|
||||
for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) {
|
||||
int32_t iii = yyy * _input.getSize().x() + xxx;
|
||||
data[iii] = (_input.get(ivec2(xxx, yyy))-img_min)/img_max;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute outside = edtaa3(bitmap); % Transform background (0's)
|
||||
computegradient(&data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]);
|
||||
edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().x(), _input.getSize().y(), &xdist[0], &ydist[0], &outside[0]);
|
||||
for(size_t iii = 0; iii < outside.size(); ++iii) {
|
||||
if( outside[iii] < 0 ) {
|
||||
outside[iii] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute inside = edtaa3(1-bitmap); % Transform foreground (1's)
|
||||
for(size_t iii = 0; iii < gx.size(); ++iii) {
|
||||
gx[iii] = 0;
|
||||
}
|
||||
for(size_t iii = 0; iii < gy.size(); ++iii) {
|
||||
gy[iii] = 0;
|
||||
}
|
||||
for(size_t iii = 0; iii < data.size(); ++iii) {
|
||||
data[iii] = 1 - data[iii];
|
||||
}
|
||||
computegradient( &data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]);
|
||||
edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().x(), _input.getSize().y(), &xdist[0], &ydist[0], &inside[0]);
|
||||
for(size_t iii = 0; iii < inside.size(); ++iii) {
|
||||
if( inside[iii] < 0 ) {
|
||||
inside[iii] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
_output.resize(_input.getSize(), etk::Color<>(0));
|
||||
_output.clear(etk::Color<>(0));
|
||||
for (int32_t xxx = 0; xxx < _output.getSize().x(); ++xxx) {
|
||||
for (int32_t yyy = 0; yyy < _output.getSize().y(); ++yyy) {
|
||||
int32_t iii = yyy * _output.getSize().x() + xxx;
|
||||
outside[iii] -= inside[iii];
|
||||
outside[iii] = 128+outside[iii]*16;
|
||||
if( outside[iii] < 0 ) {
|
||||
outside[iii] = 0;
|
||||
}
|
||||
if( outside[iii] > 255 ) {
|
||||
outside[iii] = 255;
|
||||
}
|
||||
uint8_t val = 255 - (unsigned char) outside[iii];
|
||||
// TODO : Remove multiple size of the map ...
|
||||
_output.set(ivec2(xxx, yyy), etk::Color<>((int32_t)val,(int32_t)val,(int32_t)val,(int32_t)val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool egami::generateDistanceFieldFile(const std::string& _input, const std::string& _output) {
|
||||
egami::Image data;
|
||||
if (std::end_with(_input, ".edf") == true) {
|
||||
return false;
|
||||
}
|
||||
EGAMI_ERROR("Generate distance field : '" << _input << "' ==> '" << _output << "'");
|
||||
if (egami::load(data, _input, ivec2(64*5,64*5)) == false) {
|
||||
return false;
|
||||
}
|
||||
// Generate distance field :
|
||||
egami::ImageMono input;
|
||||
input.resize(data.getSize());
|
||||
for (size_t yyy = 0; yyy < data.getSize().y(); ++yyy) {
|
||||
for (size_t xxx = 0; xxx < data.getSize().x(); ++xxx) {
|
||||
input.set(ivec2(xxx, yyy), data.get(ivec2(xxx, yyy)).a() );
|
||||
}
|
||||
}
|
||||
generateDistanceField(input, data);
|
||||
// scale:
|
||||
data.scale(ivec2(64,64));
|
||||
// store:
|
||||
return egami::store(data, _output);
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,14 @@ namespace egami
|
||||
* @return true if the format is scalable.
|
||||
*/
|
||||
bool scalable(const std::string& _fileName);
|
||||
/**
|
||||
* @brief Generate a distance field output file from an input file;
|
||||
* @param[in] _input Input file name
|
||||
* @param[in] _output Output file name
|
||||
* @return true All done corectly.
|
||||
* @return false An error occured.
|
||||
*/
|
||||
bool generateDistanceFieldFile(const std::string& _input, const std::string& _output);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
125
egami/wrapperEDF.cpp
Normal file
125
egami/wrapperEDF.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license BSD v3 (see license file)
|
||||
*/
|
||||
|
||||
#include <etk/types.h>
|
||||
#include <egami/debug.h>
|
||||
#include <egami/Image.h>
|
||||
#include <egami/wrapperEDF.h>
|
||||
#include <etk/os/FSNode.h>
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "wrapperEDF"
|
||||
|
||||
//EDF format is a simple format for image in text for distance field image (special case)
|
||||
// it is composed of the fist line : description of type (starting with #EDF and some other information, the data start just after the first \n
|
||||
|
||||
bool egami::loadEDF(const std::string& _inputFile, egami::Image& _ouputImage) {
|
||||
|
||||
etk::FSNode file(_inputFile);
|
||||
if (false == file.exist()) {
|
||||
EGAMI_ERROR("File does not existed='" << file << "'");
|
||||
return false;
|
||||
}
|
||||
if(false == file.fileOpenRead() ) {
|
||||
EGAMI_ERROR("Can not find the file name='" << file << "'");
|
||||
return false;
|
||||
}
|
||||
std::string line;
|
||||
file.fileGets(line);
|
||||
if (std::start_with(line, "#edf", false) == false) {
|
||||
EGAMI_ERROR("This file seams not to be a EDF file ...");
|
||||
file.fileClose();
|
||||
return false;
|
||||
}
|
||||
// count number of colomn max an number of line max:
|
||||
ivec2 size(0,0);
|
||||
while (file.fileGets(line) == true) {
|
||||
if (line.size()/2 > (size_t)size.x()) {
|
||||
size.setValue(line.size()/2, size.y()+1);
|
||||
} else {
|
||||
size += ivec2(0,1);
|
||||
}
|
||||
}
|
||||
if (line.size()/2 > (size_t)size.x()) {
|
||||
size.setValue(line.size()/2, size.y()+1);
|
||||
} else {
|
||||
size += ivec2(0,1);
|
||||
}
|
||||
EGAMI_DEBUG("'" << file << "' ==> size=" << size);
|
||||
// jup to the start of the file
|
||||
file.fileSeek(0, etk::FSN_SEEK_START);
|
||||
// drop the first line
|
||||
file.fileGets(line);
|
||||
|
||||
|
||||
// resize output:
|
||||
_ouputImage.resize(size);
|
||||
int32_t currentLineId = 0;
|
||||
char tmp[3];
|
||||
tmp[2] = '\0';
|
||||
while (file.fileGets(line) == true) {
|
||||
if (line.size() <= 0) {
|
||||
continue;
|
||||
}
|
||||
for (size_t xxx = 0; xxx < line.size()-1; xxx+=2) {
|
||||
tmp[0] = line[xxx];
|
||||
tmp[1] = line[xxx+1];
|
||||
int32_t val = 0;
|
||||
sscanf(tmp, "%x", &val);
|
||||
_ouputImage.set(ivec2(xxx/2, currentLineId), etk::Color<>((uint8_t)val, (uint8_t)val, (uint8_t)val, (uint8_t)val));
|
||||
}
|
||||
++currentLineId;
|
||||
}
|
||||
if (line.size() > 0) {
|
||||
for (size_t xxx = 0; xxx < line.size()-1; xxx+=2) {
|
||||
tmp[0] = line[xxx];
|
||||
tmp[1] = line[xxx+1];
|
||||
int32_t val = 0;
|
||||
sscanf(tmp, "%x", &val);
|
||||
_ouputImage.set(ivec2(xxx/2, currentLineId), etk::Color<>((uint8_t)val, (uint8_t)val, (uint8_t)val, (uint8_t)val));
|
||||
}
|
||||
}
|
||||
file.fileClose();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool egami::storeEDF(const std::string& _fileName, const egami::Image& _inputImage) {
|
||||
bool anErrorEccured = false;
|
||||
etk::FSNode file(_fileName);
|
||||
if (file.fileOpenWrite() == false) {
|
||||
EGAMI_ERROR("Can not find the file name=\"" << file << "\"");
|
||||
return false;
|
||||
}
|
||||
anErrorEccured = file.filePuts( std::string("#EDF // Generate with EGAMI (")
|
||||
+ std::to_string(_inputImage.getSize().x())
|
||||
+ ","
|
||||
+ std::to_string(_inputImage.getSize().y()) + ")\n");
|
||||
|
||||
char tmp[256];
|
||||
for (int32_t yyy = 0; yyy < _inputImage.getSize().y(); ++yyy) {
|
||||
if (yyy != 0) {
|
||||
if (file.filePut('\n') == false) {
|
||||
anErrorEccured = false;
|
||||
}
|
||||
}
|
||||
for (int32_t xxx = 0; xxx < _inputImage.getSize().x(); ++xxx) {
|
||||
sprintf(tmp, "%02X", _inputImage.get(ivec2(xxx, yyy)).a());
|
||||
/*
|
||||
if (yyy == 25) {
|
||||
EGAMI_DEBUG(" set : " << _inputImage.get(ivec2(xxx, yyy)) << " : '" << tmp << "'");
|
||||
}
|
||||
*/
|
||||
if (file.filePuts(tmp) == false) {
|
||||
anErrorEccured = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.fileClose();
|
||||
return anErrorEccured;
|
||||
}
|
41
egami/wrapperEDF.h
Normal file
41
egami/wrapperEDF.h
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license BSD v3 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __EGAMI_WRAPPER_EDF_H__
|
||||
#define __EGAMI_WRAPPER_EDF_H__
|
||||
|
||||
#include <egami/egami.h>
|
||||
|
||||
namespace egami {
|
||||
/**
|
||||
* @breif Load a bmp file in the image.
|
||||
* A simple example of EDF file is :
|
||||
* [PRE]
|
||||
* #EDF //Example Of EDF file (5,5)
|
||||
* *
|
||||
* * *
|
||||
* * *
|
||||
* * *
|
||||
* *
|
||||
* [PRE]
|
||||
* @param[in] _fileName Name of the file.
|
||||
* @param[out] _ouputImage Read data.
|
||||
* @return true if all is done correctly, false otherwise.
|
||||
*/
|
||||
bool loadEDF(const std::string& _fileName, egami::Image& _ouputImage);
|
||||
/**
|
||||
* @breif Store a edf file in the image.
|
||||
* @param[in] _fileName Name of the file.
|
||||
* @param[in] _inputImage write data.
|
||||
* @return true if all is done correctly, false otherwise.
|
||||
*/
|
||||
bool storeEDF(const std::string& _fileName, const egami::Image& _inputImage);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -20,10 +20,11 @@ def create(target):
|
||||
'egami/debug.cpp',
|
||||
'egami/wrapperPNG.cpp',
|
||||
'egami/wrapperSVG.cpp',
|
||||
'egami/wrapperBMP.cpp'])
|
||||
'egami/wrapperBMP.cpp',
|
||||
'egami/wrapperEDF.cpp'])
|
||||
|
||||
# name of the dependency
|
||||
myModule.add_module_depend(['etk', 'png', 'esvg'])
|
||||
myModule.add_module_depend(['etk', 'png', 'esvg', 'edtaa3'])
|
||||
|
||||
myModule.compile_flags_CC([
|
||||
'-Wno-write-strings',
|
||||
|
Loading…
x
Reference in New Issue
Block a user