Add basic tiled image type.
This commit is contained in:
parent
3af56f6619
commit
007ad2284e
2
TODO.md
2
TODO.md
|
@ -14,4 +14,4 @@
|
||||||
[ ] Cut image in tiles
|
[ ] Cut image in tiles
|
||||||
|
|
||||||
# Quality
|
# Quality
|
||||||
[ ] Interpolate using SIMD, SSE
|
[X] Interpolate using SIMD, SSE (no big gain)
|
||||||
|
|
131
rotation.cpp
131
rotation.cpp
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
#include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,7 +76,7 @@ struct Image {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool save(string const& path)
|
bool save(string const& path) const
|
||||||
{
|
{
|
||||||
ofstream os(path);
|
ofstream os(path);
|
||||||
if (!os.is_open())
|
if (!os.is_open())
|
||||||
|
@ -111,7 +110,7 @@ struct Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
bool read_header(std::ifstream& istr)
|
bool read_header(std::ifstream& istr)
|
||||||
{
|
{
|
||||||
// check magic
|
// check magic
|
||||||
|
@ -169,7 +168,7 @@ struct Image {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_header(std::ofstream& ostr)
|
bool write_header(std::ofstream& ostr) const
|
||||||
{
|
{
|
||||||
ostr << "P6" << endl;
|
ostr << "P6" << endl;
|
||||||
ostr << width << " " << height << endl;
|
ostr << width << " " << height << endl;
|
||||||
|
@ -177,7 +176,7 @@ struct Image {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_body(std::ifstream& istr)
|
virtual bool read_body(std::ifstream& istr)
|
||||||
{
|
{
|
||||||
unsigned int const nb_pixels = width * height;
|
unsigned int const nb_pixels = width * height;
|
||||||
buffer = new uint8_t[nb_pixels * 3];
|
buffer = new uint8_t[nb_pixels * 3];
|
||||||
|
@ -192,7 +191,7 @@ struct Image {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_body(std::ofstream& ostr)
|
virtual bool write_body(std::ofstream& ostr) const
|
||||||
{
|
{
|
||||||
unsigned int const nb_pixels = width * height;
|
unsigned int const nb_pixels = width * height;
|
||||||
uint8_t* buf_index = buffer;
|
uint8_t* buf_index = buffer;
|
||||||
|
@ -206,6 +205,121 @@ struct Image {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<unsigned int W, unsigned int H>
|
||||||
|
struct TiledImage : public Image {
|
||||||
|
uint8_t** tiles;
|
||||||
|
unsigned int static const tile_w = W;
|
||||||
|
unsigned int static const tile_h = H;
|
||||||
|
unsigned int static const tile_size = W * H;
|
||||||
|
unsigned int nb_col_tile;
|
||||||
|
unsigned int nb_row_tile;
|
||||||
|
|
||||||
|
TiledImage()
|
||||||
|
: Image()
|
||||||
|
, tiles(NULL)
|
||||||
|
, nb_col_tile(0)
|
||||||
|
, nb_row_tile(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
TiledImage(unsigned int w, unsigned int h)
|
||||||
|
{
|
||||||
|
allocate_memory(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
TiledImage(string const& path)
|
||||||
|
: TiledImage()
|
||||||
|
{
|
||||||
|
ifstream is(path);
|
||||||
|
if (!is.is_open())
|
||||||
|
{
|
||||||
|
cerr << "Cannot open file '" << path << "'" << endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->read_header(is))
|
||||||
|
{
|
||||||
|
cerr << "Invalid header." << endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->read_body(is))
|
||||||
|
{
|
||||||
|
// TODO: delete tiles
|
||||||
|
cerr << "Invalid header." << endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void allocate_memory(unsigned int w, unsigned int h)
|
||||||
|
{
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
|
||||||
|
nb_col_tile = width / tile_w;
|
||||||
|
if (width % tile_w != 0)
|
||||||
|
++nb_col_tile;
|
||||||
|
|
||||||
|
nb_row_tile = height / tile_h;
|
||||||
|
if (height % tile_h != 0)
|
||||||
|
++nb_row_tile;
|
||||||
|
|
||||||
|
unsigned int const nb_tiles = nb_col_tile * nb_row_tile;
|
||||||
|
tiles = new uint8_t*[nb_tiles];
|
||||||
|
for (unsigned int i = 0; i < nb_tiles; ++i)
|
||||||
|
{
|
||||||
|
tiles[i] = new uint8_t[tile_w * tile_h * 3];
|
||||||
|
memset(tiles[i], 0, tile_w * tile_h * 3 * sizeof (uint8_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool read_body(std::ifstream& istr)
|
||||||
|
{
|
||||||
|
this->allocate_memory(width, height);
|
||||||
|
|
||||||
|
unsigned int const tile_width = tile_w * 3;
|
||||||
|
|
||||||
|
// Pixel loading
|
||||||
|
for (unsigned int j = 0; j < height; ++j)
|
||||||
|
for (unsigned int i = 0; i < width; ++i)
|
||||||
|
{
|
||||||
|
unsigned int const tile_index = (j / tile_h) * nb_col_tile + (i / tile_w);
|
||||||
|
uint8_t* tile = tiles[tile_index];
|
||||||
|
unsigned int const tile_j = j % tile_h;
|
||||||
|
unsigned int const tile_i = i % tile_w;
|
||||||
|
// if (i % 3 == 0)
|
||||||
|
// cout << "pixel (" << i / 3 << ", " << j << ") goes in tile (" << i / (tile_w * 3) << ", " << j / tile_h << ")" << endl;
|
||||||
|
tile += tile_j * tile_width + (tile_i * 3);
|
||||||
|
*(tile++) = istr.get();
|
||||||
|
*(tile++) = istr.get();
|
||||||
|
*(tile++) = istr.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool write_body(std::ofstream& ostr) const override
|
||||||
|
{
|
||||||
|
unsigned int const tile_width = tile_w * 3;
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < height; ++j)
|
||||||
|
for (unsigned int i = 0; i < width; ++i)
|
||||||
|
{
|
||||||
|
unsigned int const tile_index = (j / tile_h) * nb_col_tile + (i / tile_w);
|
||||||
|
uint8_t* tile = tiles[tile_index];
|
||||||
|
unsigned int const tile_j = j % tile_h;
|
||||||
|
unsigned int const tile_i = i % tile_w;
|
||||||
|
tile += tile_j * tile_width + (tile_i * 3);
|
||||||
|
ostr << (char) *(tile++);
|
||||||
|
ostr << (char) *(tile++);
|
||||||
|
ostr << (char) *(tile++);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -742,6 +856,10 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TiledImage<8, 8> tiled_img(argv[1]);
|
||||||
|
tiled_img.save("tiled.ppm");
|
||||||
|
return 0;
|
||||||
|
|
||||||
Image img(argv[1]);
|
Image img(argv[1]);
|
||||||
|
|
||||||
for (double rotation = 0; rotation < 360; rotation += 5)
|
for (double rotation = 0; rotation < 360; rotation += 5)
|
||||||
|
@ -754,6 +872,7 @@ int main(int argc, char* argv[])
|
||||||
auto const after = chrono::high_resolution_clock::now();
|
auto const after = chrono::high_resolution_clock::now();
|
||||||
auto const duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(after - before);
|
auto const duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(after - before);
|
||||||
cout << "rotate(" << rotation << "): " << duration_ms.count() << " ms" << endl;
|
cout << "rotate(" << rotation << "): " << duration_ms.count() << " ms" << endl;
|
||||||
|
// TODO: compare implementation
|
||||||
|
|
||||||
stringstream filename;
|
stringstream filename;
|
||||||
// filename << "/tmp/";
|
// filename << "/tmp/";
|
||||||
|
|
Loading…
Reference in a new issue