Add basic tiled image type.

master
Fabien Freling 2014-07-01 21:52:40 +02:00
parent 3af56f6619
commit 007ad2284e
2 changed files with 126 additions and 7 deletions

View File

@ -14,4 +14,4 @@
[ ] Cut image in tiles
# Quality
[ ] Interpolate using SIMD, SSE
[X] Interpolate using SIMD, SSE (no big gain)

View File

@ -9,7 +9,6 @@
#include <xmmintrin.h>
using namespace std;
@ -77,7 +76,7 @@ struct Image {
}
}
bool save(string const& path)
bool save(string const& path) const
{
ofstream os(path);
if (!os.is_open())
@ -111,7 +110,7 @@ struct Image {
}
private:
protected:
bool read_header(std::ifstream& istr)
{
// check magic
@ -169,7 +168,7 @@ struct Image {
return true;
}
bool write_header(std::ofstream& ostr)
bool write_header(std::ofstream& ostr) const
{
ostr << "P6" << endl;
ostr << width << " " << height << endl;
@ -177,7 +176,7 @@ struct Image {
return true;
}
bool read_body(std::ifstream& istr)
virtual bool read_body(std::ifstream& istr)
{
unsigned int const nb_pixels = width * height;
buffer = new uint8_t[nb_pixels * 3];
@ -192,7 +191,7 @@ struct Image {
return true;
}
bool write_body(std::ofstream& ostr)
virtual bool write_body(std::ofstream& ostr) const
{
unsigned int const nb_pixels = width * height;
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]);
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 duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(after - before);
cout << "rotate(" << rotation << "): " << duration_ms.count() << " ms" << endl;
// TODO: compare implementation
stringstream filename;
// filename << "/tmp/";