Archived
1
Fork 0

Added a second way to save an image

This commit is contained in:
Joshua Moerman 2013-12-01 17:37:54 +01:00
parent 8103b7fbf4
commit 41869d8cb0
6 changed files with 101 additions and 12 deletions

View file

@ -1,11 +1,19 @@
#pragma once #pragma once
#include <string> #include <string>
#include <chrono>
inline bool is_pow_of_two(int n){ inline bool is_pow_of_two(int n){
return (n & (n - 1)) == 0; return (n & (n - 1)) == 0;
} }
// calculates integer 2-log such that:
// 2^(two_log(x)) >= x > 2^(two_log(x) - 1)
unsigned int two_log(unsigned int x){
if(x <= 1) return 0;
return 8*sizeof(unsigned int) - __builtin_clz(x-1);
}
inline std::string human_string(int n){ inline std::string human_string(int n){
static const std::string names [] = {"", "K", "M", "G"}; static const std::string names [] = {"", "K", "M", "G"};
int i = 0; int i = 0;
@ -22,3 +30,23 @@ inline std::string field(std::string const & str){
auto add = length - str.size(); auto add = length - str.size();
return str + ":" + std::string(add, ' ') + "\t"; return str + ":" + std::string(add, ' ') + "\t";
} }
struct timer{
typedef std::chrono::high_resolution_clock clock;
typedef std::chrono::time_point<clock> time;
typedef std::chrono::duration<double> seconds;
std::string name;
time begin;
timer(std::string name)
: name(name)
, begin(clock::now())
{}
~timer(){
time end = clock::now();
seconds elapsed = end - begin;
std::cout << name << "\t" << elapsed.count() << std::endl;
}
};

View file

@ -43,6 +43,9 @@ namespace jcmp {
} }
}; };
// Way of writing does not matter for performance
// timings: http://i.imgur.com/cskC43O.png (300 points per method)
// It's not surprising as filebuf is already a buffer
inline void write_to_file(image const & image, std::string filename){ inline void write_to_file(image const & image, std::string filename){
std::filebuf file; std::filebuf file;
file.open(filename, std::ios_base::out|std::ios_base::trunc); file.open(filename, std::ios_base::out|std::ios_base::trunc);
@ -50,6 +53,23 @@ namespace jcmp {
file.sputn(reinterpret_cast<const char*>(image.data.data()), image.data.size() * sizeof(coefficient)); file.sputn(reinterpret_cast<const char*>(image.data.data()), image.data.size() * sizeof(coefficient));
} }
// Assumes Iterator points to a coefficient]
// length in header is not used
template <typename Iterator>
inline void write_to_file(header h, Iterator begin, Iterator end, std::string filename){
h.length = 0;
std::filebuf file;
file.open(filename, std::ios_base::out|std::ios_base::trunc);
file.sputn(reinterpret_cast<const char*>(&h), sizeof(header));
while(begin != end){
file.sputn(reinterpret_cast<const char*>(&*begin++), sizeof(coefficient));
h.length++;
}
// http://stackoverflow.com/questions/2530274/how-to-overwrite-only-part-of-a-file-in-c
file.pubseekpos(0);
file.sputn(reinterpret_cast<const char*>(&h), sizeof(header));
}
inline image read_from_file(std::string const& filename){ inline image read_from_file(std::string const& filename){
std::filebuf file; std::filebuf file;
file.open(filename, std::ios_base::in); file.open(filename, std::ios_base::in);
@ -60,5 +80,4 @@ namespace jcmp {
file.sgetn(reinterpret_cast<char*>(image.data.data()), image.data.size() * sizeof(coefficient)); file.sgetn(reinterpret_cast<char*>(image.data.data()), image.data.size() * sizeof(coefficient));
return image; return image;
} }
} }

View file

@ -1,4 +1,5 @@
#include <includes.hpp> #include <includes.hpp>
#include <utilities.hpp>
#include "compressed_image.hpp" #include "compressed_image.hpp"
namespace jcmp{ namespace jcmp{
@ -21,22 +22,63 @@ struct gen{
} }
}; };
int main(){ void test_correctness(){
const int w = 1024, h = 512; const int w = 1024, h = 512;
srand(time(0));
std::vector<jcmp::coefficient> v(w*h / 100); std::vector<jcmp::coefficient> v(w*h / 100);
std::generate(v.begin(), v.end(), gen{w, 0, 0}); std::generate(v.begin(), v.end(), gen{w, 0, 0});
jcmp::image i(w, h, std::move(v)); { // iterator method
jcmp::write_to_file({w, h}, v.begin(), v.end(), "test.jcmp");
auto j = jcmp::read_from_file("test.jcmp");
jcmp::write_to_file(i, "test.jcmp"); assert(w == j.header.width);
auto j = jcmp::read_from_file("test.jcmp"); assert(h == j.header.height);
assert(v == j.data);
}
assert(w == j.header.width); { // copy method
assert(h == j.header.height); jcmp::image i(w, h, std::move(v));
assert(i.data.size() == j.data.size());
assert(i.data == j.data);
std::cout << "Test succeeded" << std::endl; jcmp::write_to_file(i, "test.jcmp");
auto j = jcmp::read_from_file("test.jcmp");
assert(w == j.header.width);
assert(h == j.header.height);
assert(i.data == j.data);
}
}
void test_speed(){
const int w = 4000, h = 8000;
std::vector<jcmp::coefficient> input(w*h / 20);
std::generate(input.begin(), input.end(), gen{w, 0, 0});
for(int i = 0; i < 10; ++i){
{ timer t("stream");
jcmp::write_to_file({w, h}, input.begin(), input.end(), "stream.jcmp");
}
std::vector<jcmp::coefficient> copy(w*h / 20);
std::copy(input.begin(), input.end(), copy.begin());
{ timer t("move");
jcmp::image i(w, h, std::move(copy));
jcmp::write_to_file(i, "move.jcmp");
}
{ timer t("copy");
jcmp::image i(w, h, input);
jcmp::write_to_file(i, "copy.jcmp");
}
}
}
int main(){
srand(time(0));
test_correctness();
std::cout << "Test succeeded" << std::endl;
test_speed();
std::cout << "Test completed" << std::endl;
} }

0
wavelet/file_test.cpp Normal file
View file

0
wavelet/wavelet2.hpp Normal file
View file

View file