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
|
||||
|
||||
# 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>
|
||||
|
||||
|
||||
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/";
|
||||
|
|
Loading…
Reference in a new issue