[DEV] start integration of JPEG, add test, correct the orientation of the image in the image and better storing of image in bmp

This commit is contained in:
Edouard DUPIN 2016-12-19 21:22:16 +01:00
parent 25e6b83253
commit 2d8af2d99c
22 changed files with 668 additions and 88 deletions

BIN
data/read.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

BIN
data/read.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
data/read.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

113
data/read.svg Normal file
View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
id="svg4152"
version="1.1"
inkscape:version="0.91 r13725"
viewBox="0 0 64 64"
sodipodi:docname="test.svg">
<defs
id="defs4154">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective4706" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="-1"
inkscape:cy="32"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1021"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata4157">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#f0d200;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4700"
width="43.454544"
height="33.454544"
x="7.818182"
y="6.909091" />
<ellipse
style="fill:#0002f0;fill-opacity:1;stroke:#00db92;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4702"
cx="44.272728"
cy="45.545456"
rx="16.09091"
ry="15.181818" />
<path
sodipodi:type="star"
style="fill:#00f04d;fill-opacity:1;stroke:#db0000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4704"
sodipodi:sides="5"
sodipodi:cx="24.727274"
sodipodi:cy="40.545455"
sodipodi:r1="16.39996"
sodipodi:r2="8.1999798"
sodipodi:arg1="0.066568164"
sodipodi:arg2="0.69488669"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 41.09091,41.636365 -10.065016,4.159525 -2.279495,10.649418 -7.066204,-8.287035 -10.832601,1.122923 5.697862,-9.281195 -4.415422,-9.955413 10.587677,2.550942 8.103721,-7.275707 0.845682,10.857763 z"
inkscape:transform-center-x="-1.2419781"
inkscape:transform-center-y="0.33710945" />
<path
sodipodi:type="star"
style="fill:#d000f0;fill-opacity:1;stroke:#001bdb;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4722"
sodipodi:sides="5"
sodipodi:cx="-8.181818"
sodipodi:cy="-6.3636365"
sodipodi:r1="43.930073"
sodipodi:r2="35.540176"
sodipodi:arg1="0.68572951"
sodipodi:arg2="1.314048"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 25.818183,21.454546 -49.950086,13.114031 -27.90761,-43.4528968 32.702234,-39.9693982 48.118702,18.750451 z"
inkscape:transform-center-x="3.447227"
inkscape:transform-center-y="-0.77893397" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
data/read2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
data/read3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
data/read4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -42,6 +42,39 @@ std::ostream& egami::operator <<(std::ostream& _os, const enum egami::colorType
return _os; return _os;
} }
int32_t egami::getFormatColorSize(enum colorType _type) {
switch (_type) {
case egami::colorType::undefined:
return 1;
break;
case egami::colorType::RGBA8:
return 1*4;
break;
case egami::colorType::RGB8:
return 1*3;
break;
case egami::colorType::RGBAf:
return 4*4;
break;
case egami::colorType::RGBf:
return 4*3;
break;
case egami::colorType::unsignedInt16:
return 2;
break;
case egami::colorType::unsignedInt32:
return 4;
break;
case egami::colorType::float32:
return 4;
break;
case egami::colorType::float64:
return 8;
break;
}
return 1;
}
egami::Image::Image() : egami::Image::Image() :
m_data(nullptr) { m_data(nullptr) {

View File

@ -26,6 +26,12 @@ namespace egami {
float64, float64,
}; };
std::ostream& operator <<(std::ostream& _os, const enum egami::colorType _obj); std::ostream& operator <<(std::ostream& _os, const enum egami::colorType _obj);
/**
* @brief Get the Color size use in octet
* @param[in] type of the color
* @return Number of byte requested by the color
*/
int32_t getFormatColorSize(enum colorType _type);
class ImagePrivate { class ImagePrivate {
public: public:
@ -134,6 +140,7 @@ namespace egami {
void set(const std::vector<etk::Color<float,4>>& _data, const ivec2& _size); void set(const std::vector<etk::Color<float,4>>& _data, const ivec2& _size);
void set(const std::vector<etk::Color<uint8_t,4>>& _data, const ivec2& _size); void set(const std::vector<etk::Color<uint8_t,4>>& _data, const ivec2& _size);
void swap(egami::Image& _image);
}; };
} }

View File

@ -7,10 +7,24 @@
#include <egami/egami.hpp> #include <egami/egami.hpp>
#include <egami/debug.hpp> #include <egami/debug.hpp>
#include <egami/wrapperSVG.hpp> #ifdef EGAMI_BUILD_ESVG
#include <egami/wrapperPNG.hpp> #include <egami/wrapperSVG.hpp>
#endif
#ifdef EGAMI_BUILD_PNG
#include <egami/wrapperPNG.hpp>
#endif
#include <egami/wrapperBMP.hpp> #include <egami/wrapperBMP.hpp>
#include <egami/wrapperEDF.hpp> #include <egami/wrapperEDF.hpp>
#ifdef EGAMI_BUILD_JPEG
#include <egami/wrapperJPG.hpp>
#endif
#ifdef EGAMI_BUILD_JPEG2000
#include <egami/wrapperJPG2000.hpp>
#endif
#ifdef EGAMI_BUILD_TIFF
#include <egami/wrapperTIFF.hpp>
#endif
#include <edtaa3/edtaa3func.h> #include <edtaa3/edtaa3func.h>
bool egami::scalable(const std::string& _fileName) { bool egami::scalable(const std::string& _fileName) {
@ -36,18 +50,52 @@ egami::Image egami::load(const std::string& _fileName, const ivec2& _size) {
EGAMI_ERROR("Error to load BMP file '" << _fileName << "'"); EGAMI_ERROR("Error to load BMP file '" << _fileName << "'");
} }
} else if (etk::end_with(tmpName, ".svg") == true) { } else if (etk::end_with(tmpName, ".svg") == true) {
#ifdef EGAMI_BUILD_ESVG
out = egami::loadSVG(_fileName, _size); out = egami::loadSVG(_fileName, _size);
if (out.exist() == false) { if (out.exist() == false) {
EGAMI_ERROR("Error to load SVG file '" << _fileName << "'"); EGAMI_ERROR("Error to load SVG file '" << _fileName << "'");
} }
//egami::storeEDF(_fileName + ".edf", _output); #else
EGAMI_WARNING("egamy not compile with the ESVG dependency for file '" << _fileName << "'");
#endif
} else if (etk::end_with(tmpName, ".png") == true) { } else if (etk::end_with(tmpName, ".png") == true) {
#ifdef EGAMI_BUILD_PNG
out = egami::loadPNG(_fileName); out = egami::loadPNG(_fileName);
if (out.exist() == false) { if (out.exist() == false) {
EGAMI_ERROR("Error to load PNG file '" << _fileName << "'"); EGAMI_ERROR("Error to load PNG file '" << _fileName << "'");
} }
#else
EGAMI_WARNING("egamy not compile with the PNG dependency for file '" << _fileName << "'");
#endif
} else if (etk::end_with(tmpName, ".jpg") == true) {
#ifdef EGAMI_BUILD_JPEG
out = egami::loadJPG(_fileName);
if (out.exist() == false) {
EGAMI_ERROR("Error to load JPG file '" << _fileName << "'");
}
#else
EGAMI_WARNING("egamy not compile with the JPEG dependency for file '" << _fileName << "'");
#endif
} else if (etk::end_with(tmpName, ".j2k") == true) {
#ifdef EGAMI_BUILD_JPEG2000
out = egami::loadJPG2000(_fileName);
if (out.exist() == false) {
EGAMI_ERROR("Error to load JPEG2000 file '" << _fileName << "'");
}
#else
EGAMI_WARNING("egamy not compile with the JPEG 2000 (openjpeg) dependency for file '" << _fileName << "'");
#endif
} else if (etk::end_with(tmpName, ".tif") == true) {
#ifdef EGAMI_BUILD_TIFF
out = egami::loadTIFF(_fileName);
if (out.exist() == false) {
EGAMI_ERROR("Error to load TIFF file '" << _fileName << "'");
}
#else
EGAMI_WARNING("egamy not compile with the TIFF dependency for file '" << _fileName << "'");
#endif
} else { } else {
EGAMI_ERROR("Extention not managed '" << _fileName << "' Sopported extention : .edf / .bmp / .svg / .png"); EGAMI_ERROR("Extention not managed '" << _fileName << "' Sopported extention : .edf / .bmp / .svg / .png / .jpg / .j2k / .tif");
} }
return out; return out;
} }
@ -72,8 +120,17 @@ bool egami::store(const egami::Image& _input, const std::string& _fileName) {
} else if (etk::end_with(tmpName, ".png") == true) { } else if (etk::end_with(tmpName, ".png") == true) {
EGAMI_ERROR("Can not store in PNG file '" << _fileName << "'"); EGAMI_ERROR("Can not store in PNG file '" << _fileName << "'");
return false; return false;
} else if (etk::end_with(tmpName, ".jpg") == true) {
EGAMI_ERROR("Can not store in JPEG file '" << _fileName << "'");
return false;
} else if (etk::end_with(tmpName, ".j2k") == true) {
EGAMI_ERROR("Can not store in JPEG 2000 file '" << _fileName << "'");
return false;
} else if (etk::end_with(tmpName, ".tif") == true) {
EGAMI_ERROR("Can not store in TIFF file '" << _fileName << "'");
return false;
} else { } else {
EGAMI_ERROR("Extention not managed '" << _fileName << "' Sopported extention: .edf / .bmp / .svg / .png"); EGAMI_ERROR("Extention not managed '" << _fileName << "' Sopported extention: .edf / .bmp / .svg / .png / .jpg / .j2k / .tif");
return false; return false;
} }
return true; return true;

View File

@ -40,6 +40,54 @@ enum modeBitmap {
BITS_32_A8R8G8B8 BITS_32_A8R8G8B8
}; };
static void display(struct bitmapFileHeader _header, struct bitmapInfoHeader _info) {
EGAMI_DEBUG(" -----------------------------------------------------------");
EGAMI_DEBUG("Display caracteristic of the bitmap : ");
EGAMI_DEBUG(" Header of file :");
EGAMI_DEBUG(" bfType =" << _header.bfType << " 19778 : must always be set to 'BM' to declare that this is a .bmp-file.");
EGAMI_DEBUG(" bfSize =" << _header.bfSize << " specifies the size of the file in bytes.");
EGAMI_DEBUG(" bfReserved=" << _header.bfReserved << " must always be set to zero.");
EGAMI_DEBUG(" bfOffBits =" << _header.bfOffBits << " 1078 : specifies the offset from the beginning of the file to the bitmap data.");
EGAMI_DEBUG(" info header of file :");
EGAMI_DEBUG(" biSize =" << _info.biSize << " specifies the size of the BITMAPINFOHEADER structure, in bytes.");
EGAMI_DEBUG(" biWidth =" << _info.biWidth << " specifies the width of the image, in pixels.");
EGAMI_DEBUG(" biHeight =" << _info.biHeight << " specifies the height of the image, in pixels.");
EGAMI_DEBUG(" biPlanes =" << _info.biPlanes << " specifies the number of planes of the target device, must be set to zero.");
EGAMI_DEBUG(" biBitCount =" << _info.biBitCount << " specifies the number of bits per pixel.");
EGAMI_DEBUG(" biCompression =" << _info.biCompression << " Specifies the type of compression, usually set to zero (no compression).");
EGAMI_DEBUG(" biSizeImage =" << _info.biSizeImage << " specifies the size of the image data, in bytes. If there is no compression, it is valid to set this member to zero.");
EGAMI_DEBUG(" biXPelsPerMeter=" << _info.biXPelsPerMeter << " specifies the the horizontal pixels per meter on the designated targer device, usually set to zero.");
EGAMI_DEBUG(" biYPelsPerMeter=" << _info.biYPelsPerMeter << " specifies the the vertical pixels per meter on the designated targer device, usually set to zero.");
EGAMI_DEBUG(" biClrUsed =" << _info.biClrUsed << " speglTexImage2Dcifies the number of colors used in the bitmap, if set to zero the number of colors is calculated using the biBitCount member.");
EGAMI_DEBUG(" biClrImportant =" << _info.biClrImportant << " specifies the number of color that are 'important' for the bitmap, if set to zero, all colors are important.");
/*
EGAMI_DEBUG("Bitmap : " << m_width << "x" << m_height);
switch(m_dataMode)
{
case BITS_16_R5G6B5:
EGAMI_DEBUG(" mode = 16 bits R5G6B5");
break;
case BITS_16_X1R5G5B5:
EGAMI_DEBUG(" mode = 16 bits X1R5G5B5");
break;
case BITS_24_R8G8B8:
EGAMI_DEBUG(" mode = 24 bits R8G8B8");
break;
case BITS_32_X8R8G8B8:
EGAMI_DEBUG(" mode = 32 bits X8R8G8B8");
break;
case BITS_32_A8R8G8B8:
EGAMI_DEBUG(" mode = 32 bits A8R8G8B8");
break;
default:
EGAMI_DEBUG(" mode = ERROR");
break;
}*/
}
egami::Image egami::loadBMP(const std::string& _inputFile) { egami::Image egami::loadBMP(const std::string& _inputFile) {
egami::Image out; egami::Image out;
enum modeBitmap m_dataMode = BITS_16_R5G6B5; enum modeBitmap m_dataMode = BITS_16_R5G6B5;
@ -51,7 +99,7 @@ egami::Image egami::loadBMP(const std::string& _inputFile) {
etk::FSNode fileName(_inputFile); etk::FSNode fileName(_inputFile);
// get the fileSize ... // get the fileSize ...
/*if (fileName.size() < (int32_t)(sizeof(struct bitmapFileHeader) + sizeof(struct bitmapFileHeader) ) ) { /*if (fileName.size() < (int32_t)(sizeof(struct bitmapFileHeader) + sizeof(struct bitmapFileHeader) ) ) {
EWOL_ERROR("not enought data in the file named=\"" << fileName << "\""); EGAMI_ERROR("not enought data in the file named=\"" << fileName << "\"");
return; return;
}*/ }*/
if (fileName.exist() == false) { if (fileName.exist() == false) {
@ -73,6 +121,8 @@ egami::Image egami::loadBMP(const std::string& _inputFile) {
fileName.fileClose(); fileName.fileClose();
return out; return out;
} }
//display(m_FileHeader, m_InfoHeader);
//EGAMI_ERROR("plopppppppppppppp " << m_FileHeader.bfOffBits);
if(fileName.fileSeek(m_FileHeader.bfOffBits, etk::seekNode_start) == false) { if(fileName.fileSeek(m_FileHeader.bfOffBits, etk::seekNode_start) == false) {
EGAMI_ERROR("error with the 'bfOffBits' in the file named=\"" << fileName << "\""); EGAMI_ERROR("error with the 'bfOffBits' in the file named=\"" << fileName << "\"");
fileName.fileClose(); fileName.fileClose();
@ -158,6 +208,15 @@ egami::Image egami::loadBMP(const std::string& _inputFile) {
} }
break; break;
case BITS_24_R8G8B8: { case BITS_24_R8G8B8: {
int32_t offset = 0;
int32_t baseLine = m_width * 3;
if ((baseLine%4) == 1) {
offset = 3;
} else if ((baseLine%4) == 2) {
offset = 2;
} else if ((baseLine%4) == 3) {
offset = 1;
}
uint8_t * pointer = (&m_data[0]); uint8_t * pointer = (&m_data[0]);
for(int32_t yyy=0; yyy<m_height; yyy++) { for(int32_t yyy=0; yyy<m_height; yyy++) {
for(int32_t xxx=0; xxx<m_width; xxx++) { for(int32_t xxx=0; xxx<m_width; xxx++) {
@ -167,6 +226,9 @@ egami::Image egami::loadBMP(const std::string& _inputFile) {
tmpColor.setA(0xFF); tmpColor.setA(0xFF);
out.set(ivec2(xxx,yyy), tmpColor); out.set(ivec2(xxx,yyy), tmpColor);
} }
for(int32_t xxx=0; xxx<offset; xxx++) {
pointer++;
}
} }
} }
break; break;
@ -211,12 +273,13 @@ bool egami::storeBMP(const std::string& _fileName, const egami::Image& _inputIma
m_FileHeader.bfType = 0x4D42; m_FileHeader.bfType = 0x4D42;
m_FileHeader.bfSize = sizeof(struct bitmapFileHeader); m_FileHeader.bfSize = sizeof(struct bitmapFileHeader);
m_FileHeader.bfReserved = 0; m_FileHeader.bfReserved = 0;
m_FileHeader.bfOffBits = 40; m_FileHeader.bfOffBits = sizeof(struct bitmapFileHeader) + sizeof(struct bitmapInfoHeader);
//EGAMI_ERROR("plopppppppppppppp " << m_FileHeader.bfOffBits);
m_InfoHeader.biSize = sizeof(struct bitmapInfoHeader); m_InfoHeader.biSize = sizeof(struct bitmapInfoHeader);
m_InfoHeader.biWidth = _inputImage.getSize().x(); m_InfoHeader.biWidth = _inputImage.getSize().x();
m_InfoHeader.biHeight = _inputImage.getSize().y(); m_InfoHeader.biHeight = _inputImage.getSize().y();
m_InfoHeader.biPlanes = 1; m_InfoHeader.biPlanes = 1;
int32_t offset = 0;
if (_inputImage.getType() == egami::colorType::RGBA8) { if (_inputImage.getType() == egami::colorType::RGBA8) {
m_InfoHeader.biBitCount = 32; m_InfoHeader.biBitCount = 32;
m_InfoHeader.biCompression = 0; m_InfoHeader.biCompression = 0;
@ -224,19 +287,29 @@ bool egami::storeBMP(const std::string& _fileName, const egami::Image& _inputIma
} else { } else {
m_InfoHeader.biBitCount = 24; m_InfoHeader.biBitCount = 24;
m_InfoHeader.biCompression = 0; m_InfoHeader.biCompression = 0;
m_InfoHeader.biSizeImage = _inputImage.getSize().x()*_inputImage.getSize().y()*3; int32_t baseLine = _inputImage.getSize().x() * 3;
if ((baseLine%4) == 1) {
offset = 3;
} else if ((baseLine%4) == 2) {
offset = 2;
} else if ((baseLine%4) == 3) {
offset = 1;
}
m_InfoHeader.biSizeImage = (baseLine+offset)*_inputImage.getSize().y();
} }
m_InfoHeader.biXPelsPerMeter = 75; m_InfoHeader.biXPelsPerMeter = 75;
m_InfoHeader.biYPelsPerMeter = 75; m_InfoHeader.biYPelsPerMeter = 75;
m_InfoHeader.biClrUsed = 0; m_InfoHeader.biClrUsed = 0;
m_InfoHeader.biClrImportant = 0; m_InfoHeader.biClrImportant = 0;
//display(m_FileHeader, m_InfoHeader);
etk::FSNode fileName(_fileName); etk::FSNode fileName(_fileName);
if(false == fileName.fileOpenWrite() ) { if(false == fileName.fileOpenWrite() ) {
EGAMI_ERROR("Can not find the file name=\"" << fileName << "\""); EGAMI_ERROR("Can not find the file name=\"" << fileName << "\"");
return false; return false;
} }
// get the data: // Write header:
if (fileName.fileWrite(&m_FileHeader,sizeof(struct bitmapFileHeader),1) != 1) { if (fileName.fileWrite(&m_FileHeader,sizeof(struct bitmapFileHeader),1) != 1) {
EGAMI_ERROR("error loading file header"); EGAMI_ERROR("error loading file header");
fileName.fileClose(); fileName.fileClose();
@ -247,6 +320,7 @@ bool egami::storeBMP(const std::string& _fileName, const egami::Image& _inputIma
fileName.fileClose(); fileName.fileClose();
return false; return false;
} }
/* TODO: Avec ca, ca ne fonctionne pas ... ==> check /* TODO: Avec ca, ca ne fonctionne pas ... ==> check
if(fileName.fileSeek(m_FileHeader.bfOffBits, etk::FSN_SEEK_START) == false) { if(fileName.fileSeek(m_FileHeader.bfOffBits, etk::FSN_SEEK_START) == false) {
EGAMI_ERROR("error with the 'bfOffBits' in the file named=\"" << fileName << "\""); EGAMI_ERROR("error with the 'bfOffBits' in the file named=\"" << fileName << "\"");
@ -278,61 +352,17 @@ bool egami::storeBMP(const std::string& _fileName, const egami::Image& _inputIma
*pointer++ = tmpColor.b(); *pointer++ = tmpColor.b();
fileName.fileWrite(data,3,1); fileName.fileWrite(data,3,1);
} }
if (offset != 0) {
uint8_t pointer[4];
pointer[0] = 0;
pointer[1] = 0;
pointer[2] = 0;
pointer[3] = 0;
fileName.fileWrite(pointer,1,offset);
}
} }
} }
fileName.fileClose(); fileName.fileClose();
return true; return true;
} }
/*
void ewol::texture::TextureBMP::display()
{
if (NULL == m_data) {
EWOL_ERROR("Might loading error of this Bitmap ...");
return;
}
EWOL_DEBUG(" -----------------------------------------------------------");
if (false) {
EWOL_DEBUG("Display caracteristic of the bitmap : ");
EWOL_DEBUG(" Header of file :");
EWOL_DEBUG(" bfType =" << m_FileHeader.bfType << " 19778 : must always be set to 'BM' to declare that this is a .bmp-file.");
EWOL_DEBUG(" bfSize =" << m_FileHeader.bfSize << " specifies the size of the file in bytes.");
EWOL_DEBUG(" bfReserved=" << m_FileHeader.bfReserved << " must always be set to zero.");
EWOL_DEBUG(" bfOffBits =" << m_FileHeader.bfOffBits << " 1078 : specifies the offset from the beginning of the file to the bitmap data.");
EWOL_DEBUG(" info header of file :");
EWOL_DEBUG(" biSize =" << m_InfoHeader.biSize << " specifies the size of the BITMAPINFOHEADER structure, in bytes.");
EWOL_DEBUG(" biWidth =" << m_InfoHeader.biWidth << " specifies the width of the image, in pixels.");
EWOL_DEBUG(" biHeight =" << m_InfoHeader.biHeight << " specifies the height of the image, in pixels.");
EWOL_DEBUG(" biPlanes =" << m_InfoHeader.biPlanes << " specifies the number of planes of the target device, must be set to zero.");
EWOL_DEBUG(" biBitCount =" << m_InfoHeader.biBitCount << " specifies the number of bits per pixel.");
EWOL_DEBUG(" biCompression =" << m_InfoHeader.biCompression << " Specifies the type of compression, usually set to zero (no compression).");
EWOL_DEBUG(" biSizeImage =" << m_InfoHeader.biSizeImage << " specifies the size of the image data, in bytes. If there is no compression, it is valid to set this member to zero.");
EWOL_DEBUG(" biXPelsPerMeter=" << m_InfoHeader.biXPelsPerMeter << " specifies the the horizontal pixels per meter on the designated targer device, usually set to zero.");
EWOL_DEBUG(" biYPelsPerMeter=" << m_InfoHeader.biYPelsPerMeter << " specifies the the vertical pixels per meter on the designated targer device, usually set to zero.");
EWOL_DEBUG(" biClrUsed =" << m_InfoHeader.biClrUsed << " speglTexImage2Dcifies the number of colors used in the bitmap, if set to zero the number of colors is calculated using the biBitCount member.");
EWOL_DEBUG(" biClrImportant =" << m_InfoHeader.biClrImportant << " specifies the number of color that are 'important' for the bitmap, if set to zero, all colors are important.");
}
EWOL_DEBUG("Bitmap : " << m_width << "x" << m_height);
switch(m_dataMode)
{
case BITS_16_R5G6B5:
EWOL_DEBUG(" mode = 16 bits R5G6B5");
break;
case BITS_16_X1R5G5B5:
EWOL_DEBUG(" mode = 16 bits X1R5G5B5");
break;
case BITS_24_R8G8B8:
EWOL_DEBUG(" mode = 24 bits R8G8B8");
break;
case BITS_32_X8R8G8B8:
EWOL_DEBUG(" mode = 32 bits X8R8G8B8");
break;
case BITS_32_A8R8G8B8:
EWOL_DEBUG(" mode = 32 bits A8R8G8B8");
break;
default:
EWOL_DEBUG(" mode = ERROR");
break;
}
}
*/

131
egami/wrapperJPG.cpp Normal file
View File

@ -0,0 +1,131 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <egami/debug.hpp>
#include <egami/Image.hpp>
#include <egami/wrapperJPG.hpp>
#include <etk/os/FSNode.hpp>
extern "C" {
#include "jpeglib.h"
}
#include <setjmp.h>
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;
/*
* Here's the routine that will replace the standard error_exit method:
*/
METHODDEF(void) my_error_exit(j_common_ptr _cinfo) {
// cinfo->err really points to a my_error_mgr struct, so coerce pointer
my_error_ptr myerr = (my_error_ptr)_cinfo->err;
// Always display the message.
// We could postpone this until after returning, if we chose.
(*_cinfo->err->output_message)(_cinfo);
// Return control to the setjmp point
longjmp(myerr->setjmp_buffer, 1);
}
void put_scanline_someplace(const uint8_t* _buffer, int32_t _row_stride) {
EGAMI_ERROR("plop " << uint64_t(_buffer) << " row=" << _row_stride << " " << (_row_stride/3));
}
egami::Image egami::loadJPG(const std::string& _inputFile) {
egami::Image out;
etk::FSNode fileName(_inputFile);
if (fileName.exist() == false) {
EGAMI_ERROR("File does not existed='" << fileName << "'");
return out;
}
if(fileName.fileOpenRead() == false) {
EGAMI_ERROR("Can not find the file name='" << fileName << "'");
return out;
}
std::vector<uint8_t> allData = fileName.fileReadAll<uint8_t>();
fileName.fileClose();
// This struct contains the JPEG decompression parameters and pointers to working space (which is allocated as needed by the JPEG library).
struct jpeg_decompress_struct cinfo;
// We use our private extension JPEG error handler. Note that this struct must live as long as the main JPEG parameter struct, to avoid dangling-pointer problems.
struct my_error_mgr jerr;
// More stuff
JSAMPARRAY buffer;
int row_stride;
// Step 1: allocate and initialize JPEG decompression object
// We set up the normal JPEG error routines, then override error_exit.
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
// Establish the setjmp return context for my_error_exit to use.
if (setjmp(jerr.setjmp_buffer)) {
// If we get here, the JPEG code has signaled an error. We need to clean up the JPEG object, close the input file, and return.
jpeg_destroy_decompress(&cinfo);
return out;
}
// Now we can initialize the JPEG decompression object.
jpeg_create_decompress(&cinfo);
// Step 2: specify data source (eg, a file)
jpeg_mem_src(&cinfo, &allData[0], allData.size());
// Step 3: read file parameters with jpeg_read_header()
(void)jpeg_read_header(&cinfo, TRUE);
// We can ignore the return value from jpeg_read_header since
// (a) suspension is not possible with the stdio data source, and
// (b) we passed TRUE to reject a tables-only JPEG file as an error.
// See libjpeg.txt for more info.
// Step 4: set parameters for decompression
// In this example, we don't need to change any of the defaults set by jpeg_read_header(), so we do nothing here.
// Step 5: Start decompressor
(void) jpeg_start_decompress(&cinfo);
// We can ignore the return value since suspension is not possible with the stdio data source.
// We may need to do some setup of our own at this point before reading the data.
// After jpeg_start_decompress() we have the correct scaled output image dimensions available, as well as the output colormap if we asked for color quantization.
// In this example, we need to make an output work buffer of the right size.
// JSAMPLEs per row in output buffer
row_stride = cinfo.output_width * cinfo.output_components;
// Make a one-row-high sample array that will go away when done with image
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
// Step 6: while (scan lines remain to be read) jpeg_read_scanlines(...);
// Resize output image:
out.configure(ivec2(cinfo.output_width,cinfo.output_height), egami::colorType::RGB8);
uint8_t* dataOutPointer = (uint8_t*)out.getTextureDataPointer();
// Here we use the library's state variable cinfo.output_scanline as the loop counter, so that we don't have to keep track ourselves.
int32_t yyy = 1;
while (cinfo.output_scanline < cinfo.output_height) {
// Get a simple line:
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
// Direst push on the output (got output format RGB8)
uint8_t* tmpp = dataOutPointer + (row_stride*(cinfo.output_height-yyy));
memcpy(tmpp, buffer[0], row_stride);
yyy++;
}
// Step 7: Finish decompression
(void) jpeg_finish_decompress(&cinfo);
// We can ignore the return value since suspension is not possible with the stdio data source.
// Step 8: Release JPEG decompression object
// This is an important step since it will release a good deal of memory.
jpeg_destroy_decompress(&cinfo);
// At this point you may want to check to see whether any corrupt-data warnings occurred (test whether jerr.pub.num_warnings is nonzero).
return out;
}

18
egami/wrapperJPG.hpp Normal file
View File

@ -0,0 +1,18 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <egami/egami.hpp>
namespace egami {
/**
* @breif Load a jpeg file in the image.
* @param[in] _fileName Name of the file.
* @return Read Image.
*/
egami::Image loadJPG(const std::string& _fileName);
}

32
egami/wrapperJPG2000.cpp Normal file
View File

@ -0,0 +1,32 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <egami/debug.hpp>
#include <egami/Image.hpp>
#include <egami/wrapperJPG2000.hpp>
#include <etk/os/FSNode.hpp>
egami::Image egami::loadJPG2000(const std::string& _inputFile) {
egami::Image out;
etk::FSNode fileName(_inputFile);
if (fileName.exist() == false) {
EGAMI_ERROR("File does not existed='" << fileName << "'");
return out;
}
if(fileName.fileOpenRead() == false) {
EGAMI_ERROR("Can not find the file name='" << fileName << "'");
return out;
}
return out;
}

18
egami/wrapperJPG2000.hpp Normal file
View File

@ -0,0 +1,18 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <egami/egami.hpp>
namespace egami {
/**
* @breif Load a jpeg 2000 file in the image.
* @param[in] _fileName Name of the file.
* @return Read Image.
*/
egami::Image loadJPG2000(const std::string& _fileName);
}

View File

@ -211,7 +211,7 @@ egami::Image egami::loadPNG(const std::string& _inputFile) {
for (png_uint_32 xxx = 0; xxx < width; ++xxx) { for (png_uint_32 xxx = 0; xxx < width; ++xxx) {
png_byte* ptr = &(row[xxx*4]); png_byte* ptr = &(row[xxx*4]);
tmpColor.set(ptr[0], ptr[1], ptr[2], ptr[3]); tmpColor.set(ptr[0], ptr[1], ptr[2], ptr[3]);
out.set(ivec2(xxx,yyy), tmpColor); out.set(ivec2(xxx,height-yyy-1), tmpColor);
} }
} }
break; break;
@ -223,7 +223,7 @@ egami::Image egami::loadPNG(const std::string& _inputFile) {
for (png_uint_32 xxx = 0; xxx < width; ++xxx) { for (png_uint_32 xxx = 0; xxx < width; ++xxx) {
png_byte* ptr = &(row[xxx*3]); png_byte* ptr = &(row[xxx*3]);
tmpColor.set(ptr[0], ptr[1], ptr[2]); tmpColor.set(ptr[0], ptr[1], ptr[2]);
out.set(ivec2(xxx,yyy), tmpColor); out.set(ivec2(xxx,height-yyy-1), tmpColor);
} }
} }
break; break;
@ -235,7 +235,7 @@ egami::Image egami::loadPNG(const std::string& _inputFile) {
for (png_uint_32 xxx = 0; xxx < width; ++xxx) { for (png_uint_32 xxx = 0; xxx < width; ++xxx) {
png_byte* ptr = &(row[xxx]); png_byte* ptr = &(row[xxx]);
tmpColor.set(ptr[0], ptr[0], ptr[0]); tmpColor.set(ptr[0], ptr[0], ptr[0]);
out.set(ivec2(xxx,yyy), tmpColor); out.set(ivec2(xxx,height-yyy-1), tmpColor);
} }
} }
break; break;
@ -247,7 +247,7 @@ egami::Image egami::loadPNG(const std::string& _inputFile) {
for (png_uint_32 xxx = 0; xxx < width; ++xxx) { for (png_uint_32 xxx = 0; xxx < width; ++xxx) {
png_byte* ptr = &(row[xxx*2]); png_byte* ptr = &(row[xxx*2]);
tmpColor.set(ptr[0], ptr[0], ptr[0], ptr[1]); tmpColor.set(ptr[0], ptr[0], ptr[0], ptr[1]);
out.set(ivec2(xxx,yyy), tmpColor); out.set(ivec2(xxx,height-yyy-1), tmpColor);
} }
} }
break; break;

33
egami/wrapperTIFF.cpp Normal file
View File

@ -0,0 +1,33 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <egami/debug.hpp>
#include <egami/Image.hpp>
#include <egami/wrapperTIFF.hpp>
#include <etk/os/FSNode.hpp>
egami::Image egami::loadTIFF(const std::string& _inputFile) {
egami::Image out;
etk::FSNode fileName(_inputFile);
if (fileName.exist() == false) {
EGAMI_ERROR("File does not existed='" << fileName << "'");
return out;
}
if(fileName.fileOpenRead() == false) {
EGAMI_ERROR("Can not find the file name='" << fileName << "'");
return out;
}
return out;
}

18
egami/wrapperTIFF.hpp Normal file
View File

@ -0,0 +1,18 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <egami/egami.hpp>
namespace egami {
/**
* @breif Load a tiff file in the image.
* @param[in] _fileName Name of the file.
* @return Read Image.
*/
egami::Image loadTIFF(const std::string& _fileName);
}

View File

@ -25,15 +25,16 @@ def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"] return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def configure(target, my_module): def configure(target, my_module):
my_module.add_depend(['egami', 'test-debug']) my_module.add_depend([
'egami',
'test-debug'
])
my_module.add_src_file([ my_module.add_src_file([
'sample/main.cpp', 'sample/main.cpp',
'sample/read.cpp', 'sample/read.cpp',
'sample/write.cpp' 'sample/write.cpp'
]) ])
my_module.copy_path('sample/read.bmp') my_module.copy_path('data/*')
my_module.copy_path('sample/read.svg')
my_module.copy_path('sample/read.png')
return True return True

View File

@ -25,11 +25,16 @@ def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"] return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def configure(target, my_module): def configure(target, my_module):
my_module.add_depend(['egami', 'gtest', 'test-debug']) my_module.add_depend([
'egami',
'gtest',
'test-debug',
'algue',
])
my_module.add_src_file([ my_module.add_src_file([
'test/main.cpp' 'test/main.cpp'
]) ])
#my_module.add_export_path(tools.get_current_path(__file__)) my_module.copy_path('data/*')
return True return True

View File

@ -31,8 +31,6 @@ def configure(target, my_module):
'egami/ImageMono.cpp', 'egami/ImageMono.cpp',
'egami/egami.cpp', 'egami/egami.cpp',
'egami/debug.cpp', 'egami/debug.cpp',
'egami/wrapperPNG.cpp',
'egami/wrapperSVG.cpp',
'egami/wrapperBMP.cpp', 'egami/wrapperBMP.cpp',
'egami/wrapperEDF.cpp' 'egami/wrapperEDF.cpp'
]) ])
@ -43,14 +41,47 @@ def configure(target, my_module):
]) ])
my_module.add_depend([ my_module.add_depend([
'etk', 'etk',
'png',
'esvg',
'edtaa3' 'edtaa3'
]) ])
my_module.add_flag('c++', [ my_module.add_flag('c++', [
'-Wno-write-strings', '-Wno-write-strings',
'-Wall' '-Wall'
]) ])
my_module.add_optionnal_depend(
'png',
["c++", "-DEGAMI_BUILD_PNG"],
src_file=[
'egami/wrapperPNG.cpp',
]
)
my_module.add_optionnal_depend(
'esvg',
["c++", "-DEGAMI_BUILD_ESVG"],
src_file=[
'egami/wrapperSVG.cpp',
]
)
my_module.add_optionnal_depend(
'jpeg',
["c++", "-DEGAMI_BUILD_JPEG"],
src_file=[
'egami/wrapperJPG.cpp',
]
)
my_module.add_optionnal_depend(
'openjpeg',
["c++", "-DEGAMI_BUILD_JPEG2000"],
src_file=[
'egami/wrapperJPG2000.cpp',
]
)
my_module.add_optionnal_depend(
'tiff',
["c++", "-DEGAMI_BUILD_TIFF"],
src_file=[
'egami/wrapperTIFF.cpp',
]
)
my_module.add_path(".") my_module.add_path(".")
return True return True

View File

@ -7,6 +7,8 @@
#include <test-debug/debug.hpp> #include <test-debug/debug.hpp>
#include <etk/etk.hpp> #include <etk/etk.hpp>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <egami/egami.hpp>
#include <algue/sha512.hpp>
int main(int argc, const char *argv[]) { int main(int argc, const char *argv[]) {
@ -18,9 +20,60 @@ int main(int argc, const char *argv[]) {
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }
TEST(TestBMP, read) {
TEST(TestPng, read) { egami::Image image = egami::load("DATA:read.bmp");
// TODO : Do real test ... egami::store(image, "out/read.bmp.bmp");
EXPECT_EQ(5, 6); // Check if image is loaded
EXPECT_EQ(true, image.exist());
// check image correct size
EXPECT_EQ(ivec2(227,149), image.getSize());
// check image correct type
EXPECT_EQ(egami::colorType::RGB8, image.getType());
// check integrity
std::string sha512 = algue::stringConvert(algue::sha512::encode((const uint8_t *)image.getTextureDataPointer(), egami::getFormatColorSize(image.getType()) * image.getSize().x() * image.getSize().y()));
EXPECT_EQ("3518a9693a349044d23c3a95262831144011086fdb339ef8532f9c6cebffe76b2c994b0a3e6d69addca15538a1cb559af3be445c5b622b5cf80c9291e7b8ca5b", sha512);
} }
TEST(TestPNG, read) {
egami::Image image = egami::load("DATA:read.png");
egami::store(image, "out/read.png.bmp");
// Check if image is loaded
EXPECT_EQ(true, image.exist());
// check image correct size
EXPECT_EQ(ivec2(227,149), image.getSize());
// check image correct type
EXPECT_EQ(egami::colorType::RGB8, image.getType());
// check integrity
std::string sha512 = algue::stringConvert(algue::sha512::encode((const uint8_t *)image.getTextureDataPointer(), egami::getFormatColorSize(image.getType()) * image.getSize().x() * image.getSize().y()));
EXPECT_EQ("42dbad7abf1e651da58c9df06521d63a878b5bd0db6e1cbe129db3c9782ce640a6709583ba9e6571d314f39b259321dcc392f98bf4412deb5ce8392566d2bc0f", sha512);
}
TEST(TestSVG, read) {
egami::Image image = egami::load("DATA:read.svg");
egami::store(image, "out/read.svg.bmp");
// Check if image is loaded
EXPECT_EQ(true, image.exist());
// check image correct size
EXPECT_EQ(ivec2(64,64), image.getSize());
// check image correct type
EXPECT_EQ(egami::colorType::RGBA8, image.getType());
// check integrity
std::string sha512 = algue::stringConvert(algue::sha512::encode((const uint8_t *)image.getTextureDataPointer(), egami::getFormatColorSize(image.getType()) * image.getSize().x() * image.getSize().y()));
EXPECT_EQ("7975d12caae94e67e85909f26b6dc0672d7e4686808d851b3207be6272b6d0153572cd643eea819c2f4dae9f7837165b4d5b34353da9f847d77afc2701945284", sha512);
}
TEST(TestJPG, read) {
egami::Image image = egami::load("DATA:read.jpg");
egami::store(image, "out/read.jpg.bmp");
// Check if image is loaded
EXPECT_EQ(true, image.exist());
// check image correct size
EXPECT_EQ(ivec2(227,149), image.getSize());
// check image correct type
EXPECT_EQ(egami::colorType::RGB8, image.getType());
// check integrity
std::string sha512 = algue::stringConvert(algue::sha512::encode((const uint8_t *)image.getTextureDataPointer(), egami::getFormatColorSize(image.getType()) * image.getSize().x() * image.getSize().y()));
EXPECT_EQ("42dbad7abf1e651da58c9df06521d63a878b5bd0db6e1cbe129db3c9782ce640a6709583ba9e6571d314f39b259321dcc392f98bf4412deb5ce8392566d2bc0f", sha512);
}