Added some overloads of serialize/deserialize for array2d objects

which contain simple 8bit POD pixel types.  This makes the serialize
routines much faster in these cases.
This commit is contained in:
Davis King 2011-08-25 20:20:17 -04:00
parent ec09a0400e
commit ba08e28386
3 changed files with 460 additions and 1 deletions

View File

@ -5,6 +5,7 @@
#include "array2d/array2d_kernel_1.h"
#include "array2d/serialize_pixel_overloads.h"
#endif // DLIB_ARRAY2d_

View File

@ -0,0 +1,303 @@
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ARRAY2D_SERIALIZE_PIXEL_OvERLOADS_H__
#define DLIB_ARRAY2D_SERIALIZE_PIXEL_OvERLOADS_H__
#include "array2d_kernel_1.h"
#include "../pixel.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
/*
This file contains overloads of the serialize functions for array2d object
for the case where they contain simple 8bit POD pixel types. In these
cases we can perform a much faster serialization by writing data in chunks
instead of one pixel at a time (this avoids a lot of function call overhead
inside the iostreams).
*/
// ----------------------------------------------------------------------------------------
template <
typename mem_manager
>
void serialize (
const array2d<rgb_pixel,mem_manager>& item,
std::ostream& out
)
{
try
{
serialize(item.nc(),out);
serialize(item.nr(),out);
COMPILE_TIME_ASSERT(sizeof(rgb_pixel) == 3);
// write each row
for (long r = 0; r < item.nr(); ++r)
out.write((char*)&item[r][0], sizeof(rgb_pixel)*item.nc());
}
catch (serialization_error e)
{
throw serialization_error(e.info + "\n while serializing object of type array2d");
}
}
template <
typename mem_manager
>
void deserialize (
array2d<rgb_pixel,mem_manager>& item,
std::istream& in
)
{
try
{
COMPILE_TIME_ASSERT(sizeof(rgb_pixel) == 3);
long nc, nr;
deserialize(nc,in);
deserialize(nr,in);
item.set_size(nr,nc);
// write each row
for (long r = 0; r < item.nr(); ++r)
in.read((char*)&item[r][0], sizeof(rgb_pixel)*item.nc());
}
catch (serialization_error e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type array2d");
}
}
// ----------------------------------------------------------------------------------------
template <
typename mem_manager
>
void serialize (
const array2d<bgr_pixel,mem_manager>& item,
std::ostream& out
)
{
try
{
serialize(item.nc(),out);
serialize(item.nr(),out);
COMPILE_TIME_ASSERT(sizeof(bgr_pixel) == 3);
// write each row
for (long r = 0; r < item.nr(); ++r)
out.write((char*)&item[r][0], sizeof(bgr_pixel)*item.nc());
}
catch (serialization_error e)
{
throw serialization_error(e.info + "\n while serializing object of type array2d");
}
}
template <
typename mem_manager
>
void deserialize (
array2d<bgr_pixel,mem_manager>& item,
std::istream& in
)
{
try
{
COMPILE_TIME_ASSERT(sizeof(bgr_pixel) == 3);
long nc, nr;
deserialize(nc,in);
deserialize(nr,in);
item.set_size(nr,nc);
// write each row
for (long r = 0; r < item.nr(); ++r)
in.read((char*)&item[r][0], sizeof(bgr_pixel)*item.nc());
}
catch (serialization_error e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type array2d");
}
}
// ----------------------------------------------------------------------------------------
template <
typename mem_manager
>
void serialize (
const array2d<hsi_pixel,mem_manager>& item,
std::ostream& out
)
{
try
{
serialize(item.nc(),out);
serialize(item.nr(),out);
COMPILE_TIME_ASSERT(sizeof(hsi_pixel) == 3);
// write each row
for (long r = 0; r < item.nr(); ++r)
out.write((char*)&item[r][0], sizeof(hsi_pixel)*item.nc());
}
catch (serialization_error e)
{
throw serialization_error(e.info + "\n while serializing object of type array2d");
}
}
template <
typename mem_manager
>
void deserialize (
array2d<hsi_pixel,mem_manager>& item,
std::istream& in
)
{
try
{
COMPILE_TIME_ASSERT(sizeof(hsi_pixel) == 3);
long nc, nr;
deserialize(nc,in);
deserialize(nr,in);
item.set_size(nr,nc);
// write each row
for (long r = 0; r < item.nr(); ++r)
in.read((char*)&item[r][0], sizeof(hsi_pixel)*item.nc());
}
catch (serialization_error e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type array2d");
}
}
// ----------------------------------------------------------------------------------------
template <
typename mem_manager
>
void serialize (
const array2d<rgb_alpha_pixel,mem_manager>& item,
std::ostream& out
)
{
try
{
serialize(item.nc(),out);
serialize(item.nr(),out);
COMPILE_TIME_ASSERT(sizeof(rgb_alpha_pixel) == 4);
// write each row
for (long r = 0; r < item.nr(); ++r)
out.write((char*)&item[r][0], sizeof(rgb_alpha_pixel)*item.nc());
}
catch (serialization_error e)
{
throw serialization_error(e.info + "\n while serializing object of type array2d");
}
}
template <
typename mem_manager
>
void deserialize (
array2d<rgb_alpha_pixel,mem_manager>& item,
std::istream& in
)
{
try
{
COMPILE_TIME_ASSERT(sizeof(rgb_alpha_pixel) == 4);
long nc, nr;
deserialize(nc,in);
deserialize(nr,in);
item.set_size(nr,nc);
// write each row
for (long r = 0; r < item.nr(); ++r)
in.read((char*)&item[r][0], sizeof(rgb_alpha_pixel)*item.nc());
}
catch (serialization_error e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type array2d");
}
}
// ----------------------------------------------------------------------------------------
template <
typename mem_manager
>
void serialize (
const array2d<unsigned char,mem_manager>& item,
std::ostream& out
)
{
try
{
serialize(item.nc(),out);
serialize(item.nr(),out);
// write each row
for (long r = 0; r < item.nr(); ++r)
out.write((char*)&item[r][0], sizeof(unsigned char)*item.nc());
}
catch (serialization_error e)
{
throw serialization_error(e.info + "\n while serializing object of type array2d");
}
}
template <
typename mem_manager
>
void deserialize (
array2d<unsigned char,mem_manager>& item,
std::istream& in
)
{
try
{
long nc, nr;
deserialize(nc,in);
deserialize(nr,in);
item.set_size(nr,nc);
// write each row
for (long r = 0; r < item.nr(); ++r)
in.read((char*)&item[r][0], sizeof(unsigned char)*item.nc());
}
catch (serialization_error e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type array2d");
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ARRAY2D_SERIALIZE_PIXEL_OvERLOADS_H__

View File

@ -9,6 +9,8 @@
#include <dlib/interfaces/enumerable.h>
#include <dlib/array2d.h>
#include "tester.h"
#include <dlib/pixel.h>
#include <dlib/image_transforms.h>
namespace
{
@ -395,6 +397,157 @@ namespace
}
void test_serialization()
{
// Do these tests because there are overloads of the serialize routines
// specifically for these types of pixel (except for unsigned short,
// we do that because you can never have too many tests).
{
array2d<rgb_alpha_pixel> img, img2;
img.set_size(3,2);
assign_all_pixels(img, 5);
img[1][1].red = 9;
img[1][1].green = 8;
img[1][1].blue = 7;
img[1][1].alpha = 3;
ostringstream sout;
serialize(img, sout);
istringstream sin(sout.str());
deserialize(img2, sin);
DLIB_TEST(img2.nr() == 3);
DLIB_TEST(img2.nc() == 2);
for (long r = 0; r < img.nr(); ++r)
{
for (long c = 0; c < img.nc(); ++c)
{
DLIB_TEST(img[r][c].red == img2[r][c].red);
DLIB_TEST(img[r][c].green == img2[r][c].green);
DLIB_TEST(img[r][c].blue == img2[r][c].blue);
DLIB_TEST(img[r][c].alpha == img2[r][c].alpha);
}
}
}
{
array2d<hsi_pixel> img, img2;
img.set_size(3,2);
assign_all_pixels(img, 5);
img[1][1].h = 9;
img[1][1].s = 2;
img[1][1].i = 3;
ostringstream sout;
serialize(img, sout);
istringstream sin(sout.str());
deserialize(img2, sin);
DLIB_TEST(img2.nr() == 3);
DLIB_TEST(img2.nc() == 2);
for (long r = 0; r < img.nr(); ++r)
{
for (long c = 0; c < img.nc(); ++c)
{
DLIB_TEST(img[r][c].h == img2[r][c].h);
DLIB_TEST(img[r][c].s == img2[r][c].s);
DLIB_TEST(img[r][c].i == img2[r][c].i);
}
}
}
{
array2d<bgr_pixel> img, img2;
img.set_size(3,2);
assign_all_pixels(img, 5);
img[1][1].red = 1;
img[1][1].green = 2;
img[1][1].blue = 3;
ostringstream sout;
serialize(img, sout);
istringstream sin(sout.str());
deserialize(img2, sin);
DLIB_TEST(img2.nr() == 3);
DLIB_TEST(img2.nc() == 2);
for (long r = 0; r < img.nr(); ++r)
{
for (long c = 0; c < img.nc(); ++c)
{
DLIB_TEST(img[r][c].red == img2[r][c].red);
DLIB_TEST(img[r][c].green == img2[r][c].green);
DLIB_TEST(img[r][c].blue == img2[r][c].blue);
}
}
}
{
array2d<rgb_pixel> img, img2;
img.set_size(3,2);
assign_all_pixels(img, 5);
img[1][1].red = 1;
img[1][1].green = 2;
img[1][1].blue = 3;
ostringstream sout;
serialize(img, sout);
istringstream sin(sout.str());
deserialize(img2, sin);
DLIB_TEST(img2.nr() == 3);
DLIB_TEST(img2.nc() == 2);
for (long r = 0; r < img.nr(); ++r)
{
for (long c = 0; c < img.nc(); ++c)
{
DLIB_TEST(img[r][c].red == img2[r][c].red);
DLIB_TEST(img[r][c].green == img2[r][c].green);
DLIB_TEST(img[r][c].blue == img2[r][c].blue);
}
}
}
{
array2d<unsigned short> img, img2;
img.set_size(3,2);
assign_all_pixels(img, 5);
img[1][1] = 9;
ostringstream sout;
serialize(img, sout);
istringstream sin(sout.str());
deserialize(img2, sin);
DLIB_TEST(img2.nr() == 3);
DLIB_TEST(img2.nc() == 2);
for (long r = 0; r < img.nr(); ++r)
{
for (long c = 0; c < img.nc(); ++c)
{
DLIB_TEST(img[r][c] == img2[r][c]);
}
}
}
{
array2d<unsigned char> img, img2;
img.set_size(3,2);
assign_all_pixels(img, 5);
img[1][1] = 9;
ostringstream sout;
serialize(img, sout);
istringstream sin(sout.str());
deserialize(img2, sin);
DLIB_TEST(img2.nr() == 3);
DLIB_TEST(img2.nc() == 2);
for (long r = 0; r < img.nr(); ++r)
{
for (long c = 0; c < img.nc(); ++c)
{
DLIB_TEST(img[r][c] == img2[r][c]);
}
}
}
}
class array2d_tester : public tester
{
@ -409,7 +562,9 @@ namespace
)
{
dlog << LINFO << "testing kernel_1a";
array2d_kernel_test<array2d<unsigned long> > ();
array2d_kernel_test<array2d<unsigned long> >();
print_spinner();
test_serialization();
print_spinner();
}
} a;