Added lyimg format for image file persistence.

This commit is contained in:
Matthias Koefferlein 2020-04-28 00:32:01 +02:00
parent 1939ce683d
commit ccb8e8831f
11 changed files with 955 additions and 47 deletions

View File

@ -1344,7 +1344,7 @@ public:
{
if (mp_image) {
db::Matrix3d m = db::Matrix3d::disp ((p0 - db::DPoint ()) + db::DVector (nx * dx * 0.5, ny * dy * 0.5)) * db::Matrix3d::mag (dx, dy);
*mp_image = img::Object (nx, ny, m, false);
*mp_image = img::Object (nx, ny, m, false, false);
}
}

View File

@ -15,7 +15,8 @@ HEADERS = \
imgService.h \
imgWidgets.h \
imgForceLink.h \
imgCommon.h
imgCommon.h \
imgStream.h
FORMS = \
AddNewImageDialog.ui \
@ -31,7 +32,8 @@ SOURCES = \
imgPropertiesPage.cc \
imgService.cc \
imgWidgets.cc \
imgForceLink.cc
imgForceLink.cc \
imgStream.cc
INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC $$LAYBASIC_INC $$DB_INC
DEPENDPATH += $$TL_INC $$DB_INC $$GSI_INC $$LAYBASIC_INC $$DB_INC

View File

@ -710,31 +710,16 @@ Object::Object ()
mp_pixel_data = 0;
}
Object::Object (size_t w, size_t h, const db::DCplxTrans &trans, bool color)
Object::Object (size_t w, size_t h, const db::DCplxTrans &trans, bool color, bool byte_data)
: m_trans (trans), m_id (make_id ()), m_min_value (0.0), m_max_value (1.0), m_min_value_set (false), m_max_value_set (false), m_visible (true), m_z_position (0)
{
m_updates_enabled = false;
mp_pixel_data = 0;
mp_data = new DataHeader (w, h, color, false);
mp_data = new DataHeader (w, h, color, byte_data);
mp_data->add_ref ();
// The default data type is float
tl_assert (! is_byte_data ());
if (is_color ()) {
for (unsigned int c = 0; c < 3; ++c) {
float *d = mp_data->float_data (c);
for (size_t i = data_length (); i > 0; --i) {
*d++ = 0.0;
}
}
} else {
float *d = mp_data->float_data ();
for (size_t i = data_length (); i > 0; --i) {
*d++ = 0.0;
}
}
clear ();
m_updates_enabled = true;
}
Object::Object (size_t w, size_t h, const db::DCplxTrans &trans, unsigned char *d)
@ -808,32 +793,15 @@ Object::Object (const std::string &filename, const db::DCplxTrans &trans)
m_updates_enabled = true;
}
Object::Object (size_t w, size_t h, const db::Matrix3d &trans, bool color)
Object::Object (size_t w, size_t h, const db::Matrix3d &trans, bool color, bool byte_data)
: m_trans (trans), m_id (make_id ()), m_min_value (0.0), m_max_value (1.0), m_min_value_set (false), m_max_value_set (false), m_visible (true), m_z_position (0)
{
m_updates_enabled = false;
mp_pixel_data = 0;
mp_data = new DataHeader (w, h, color, false);
mp_data = new DataHeader (w, h, color, byte_data);
mp_data->add_ref ();
// The default data type is float
tl_assert (! is_byte_data ());
if (is_color ()) {
for (unsigned int c = 0; c < 3; ++c) {
float *d = mp_data->float_data (c);
for (size_t i = data_length (); i > 0; --i) {
*d++ = 0.0;
}
}
} else {
float *d = mp_data->float_data ();
for (size_t i = data_length (); i > 0; --i) {
*d++ = 0.0;
}
}
clear ();
m_updates_enabled = true;
}
@ -1084,6 +1052,48 @@ Object::clone () const
return new img::Object (*this);
}
void
Object::clear ()
{
if (is_byte_data ()) {
if (is_color ()) {
for (unsigned int c = 0; c < 3; ++c) {
unsigned char *d = mp_data->byte_data (c);
for (size_t i = data_length (); i > 0; --i) {
*d++ = 0.0;
}
}
} else {
unsigned char *d = mp_data->byte_data ();
for (size_t i = data_length (); i > 0; --i) {
*d++ = 0.0;
}
}
} else if (is_color ()) {
for (unsigned int c = 0; c < 3; ++c) {
float *d = mp_data->float_data (c);
for (size_t i = data_length (); i > 0; --i) {
*d++ = 0.0;
}
}
} else {
float *d = mp_data->float_data ();
for (size_t i = data_length (); i > 0; --i) {
*d++ = 0.0;
}
}
}
db::DPolygon
Object::image_box_poly (const db::DBox vp, const db::DCplxTrans &vpt) const
{

View File

@ -52,6 +52,8 @@ class DataHeader;
struct IMG_PUBLIC DataMapping
{
public:
typedef std::vector< std::pair<double, std::pair<QColor, QColor> > > false_color_nodes_type;
/**
* @brief The constructor
*/
@ -73,7 +75,7 @@ public:
* Each node is a pair or x-value (normalized to a range of 0..1) and a corresponding color.
* The list should have an element with x value of 0.0 and one with an x value of 1.0.
*/
std::vector< std::pair<double, std::pair<QColor, QColor> > > false_color_nodes;
false_color_nodes_type false_color_nodes;
/**
* @brief The brightness value
@ -177,8 +179,9 @@ public:
* @param h The height of the image
* @param trans The transformation from pixel space to micron space
* @param color True to create a color image.
* @param byte_data True to make the image store the data in bytes
*/
Object (size_t w, size_t h, const db::DCplxTrans &trans, bool color);
Object (size_t w, size_t h, const db::DCplxTrans &trans, bool color, bool byte_data);
/**
* @brief Constructor for a monochrome image with the given pixel values
@ -301,8 +304,9 @@ public:
* @param h The height of the image
* @param matrix The 3d transformation matrix from pixel space to micron space
* @param color True to create a color image.
* @param byte_data True to create n image using bytes rather than floats
*/
Object (size_t w, size_t h, const db::Matrix3d &matrix, bool color);
Object (size_t w, size_t h, const db::Matrix3d &matrix, bool color, bool byte_data);
/**
* @brief Constructor for a monochrome image with the given pixel values
@ -734,6 +738,11 @@ public:
*/
void set_data (size_t width, size_t height, const std::vector<double> &red, const std::vector<double> &green, const std::vector<double> &blue);
/**
* @brief Clears the pixel data (sets the values to 0)
*/
void clear ();
/**
* @brief Set the transformation matrix
*

470
src/img/img/imgStream.cc Normal file
View File

@ -0,0 +1,470 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "imgStream.h"
#include "tlXMLParser.h"
#include "tlXMLWriter.h"
#include "tlTimer.h"
#include "layConverters.h"
#include <memory>
namespace img
{
class ImageProxy
{
public:
ImageProxy (const img::Object *img = 0)
: mp_img (img),
m_width (1), m_height (1),
m_min_value (0.0), m_max_value (1.0),
m_color (false)
{
init ();
}
bool is_color () const
{
return mp_img->is_color ();
}
void set_color (bool f)
{
m_color = f;
}
size_t width () const
{
return mp_img->width ();
}
void set_width (size_t w)
{
m_width = w;
}
size_t height () const
{
return mp_img->height ();
}
void set_height (size_t h)
{
m_height = h;
}
std::list<std::string>::const_iterator begin_byte_data () const
{
return m_byte_data.begin ();
}
std::list<std::string>::const_iterator end_byte_data () const
{
return m_byte_data.end ();
}
void push_byte_data (const std::string &s)
{
m_byte_data.push_back (s);
}
std::list<std::string>::const_iterator begin_data () const
{
return m_data.begin ();
}
std::list<std::string>::const_iterator end_data () const
{
return m_data.end ();
}
void push_data (const std::string &s)
{
m_data.push_back (s);
}
const db::Matrix3d &matrix () const
{
return mp_img->matrix ();
}
void set_matrix (const db::Matrix3d &m)
{
m_matrix = m;
}
double min_value () const
{
return mp_img->min_value ();
}
void set_min_value (double h)
{
m_min_value = h;
}
double max_value () const
{
return mp_img->max_value ();
}
void set_max_value (double h)
{
m_max_value = h;
}
const img::DataMapping &data_mapping () const
{
return mp_img->data_mapping ();
}
void set_data_mapping (const img::DataMapping &dm)
{
m_data_mapping = dm;
}
const img::Object::landmarks_type &landmarks () const
{
return mp_img->landmarks ();
}
void set_landmarks (const img::Object::landmarks_type &lm)
{
m_landmarks = lm;
}
img::Object *get_image () const;
private:
const img::Object *mp_img;
// reader mode
size_t m_width, m_height;
img::Object::landmarks_type m_landmarks;
img::DataMapping m_data_mapping;
double m_min_value, m_max_value;
db::Matrix3d m_matrix;
std::list<std::string> m_byte_data, m_data;
bool m_color;
void init ();
};
template <class T1, class T2>
static void
string_to_pixels (img::Object *img, const std::string &s, size_t row, size_t w, bool color)
{
tl::Extractor ex (s.c_str ());
size_t column = 0;
while (! ex.at_end () && column < w) {
T1 r = 0;
T1 g = 0;
T1 b = 0;
T2 m = 0;
unsigned int i = 0;
bool has_mask = false;
while (! ex.at_end () && ! ex.test (";")) {
if (i == 0) {
ex.read (r);
} else if (color && i == 1) {
ex.read (g);
} else if (color && i == 2) {
ex.read (b);
} else {
ex.read (m);
has_mask = true;
}
++i;
ex.test (",");
}
if (color) {
img->set_pixel (column, row, double (r), double (g), double (b));
} else {
img->set_pixel (column, row, double (r));
}
if (has_mask) {
img->set_mask (column, row, m);
}
++column;
}
}
img::Object *
ImageProxy::get_image () const
{
std::auto_ptr<img::Object> img (new Object (std::max (size_t (1), m_width), std::max (size_t (1), m_height), m_matrix, m_color, ! m_byte_data.empty ()));
img->set_min_value (m_min_value);
img->set_max_value (m_max_value);
img->set_data_mapping (m_data_mapping);
img->set_landmarks (m_landmarks);
if (! m_byte_data.empty ()) {
std::list<std::string>::const_iterator s = m_byte_data.begin ();
for (size_t i = 0; i < m_height; ++i) {
string_to_pixels<unsigned char, unsigned char> (img.get (), *s++, i, m_width, m_color);
}
} else {
std::list<std::string>::const_iterator s = m_data.begin ();
for (size_t i = 0; i < m_height; ++i) {
string_to_pixels<float, unsigned char> (img.get (), *s++, i, m_width, m_color);
}
}
return img.release ();
}
static void add_entry (std::string &heap, const float *&b, bool &first)
{
if (b) {
if (! first) {
heap += ",";
}
heap += tl::to_string (*b++);
first = false;
}
}
static void add_entry (std::string &heap, const unsigned char *&b, bool &first)
{
if (b) {
if (! first) {
heap += ",";
}
heap += tl::to_string ((unsigned int) *b++);
first = false;
}
}
template <class T1, class T2, class T3, class T4>
static const std::string &data_to_string (std::string &heap, size_t l, const T1 *r, const T2 *g, const T3 *b, const T4 *m)
{
heap.clear ();
while (l-- > 0) {
bool first = true;
add_entry (heap, r, first);
add_entry (heap, g, first);
add_entry (heap, b, first);
add_entry (heap, m, first);
if (l > 0) {
heap += ";";
}
}
return heap;
}
void
ImageProxy::init ()
{
if (!mp_img) {
return;
}
size_t w = mp_img->width ();
size_t h = mp_img->height ();
static std::string s;
if (mp_img->is_color ()) {
if (mp_img->is_byte_data ()) {
const unsigned char *r = mp_img->byte_data (0);
const unsigned char *g = mp_img->byte_data (1);
const unsigned char *b = mp_img->byte_data (2);
const unsigned char *m = mp_img->mask ();
for (size_t i = 0; i < h; ++i) {
m_byte_data.push_back (data_to_string (s, w, r + i * w, g + i * w, b + i * w, m ? (m + i * w) : 0));
}
} else {
const float *r = mp_img->float_data (0);
const float *g = mp_img->float_data (1);
const float *b = mp_img->float_data (2);
const unsigned char *m = mp_img->mask ();
for (size_t i = 0; i < h; ++i) {
m_data.push_back (data_to_string (s, w, r + i * w, g + i * w, b + i * w, m ? (m + i * w) : 0));
}
}
} else {
if (mp_img->is_byte_data ()) {
const unsigned char *g = mp_img->byte_data ();
const unsigned char *m = mp_img->mask ();
for (size_t i = 0; i < h; ++i) {
m_byte_data.push_back (data_to_string (s, w, g + i * w, (const unsigned char *) 0, (const unsigned char *) 0, m ? (m + i * w) : 0));
}
} else {
const float *g = mp_img->float_data ();
const unsigned char *m = mp_img->mask ();
for (size_t i = 0; i < h; ++i) {
m_data.push_back (data_to_string (s, w, g + i * w, (const float *) 0, (const float *) 0, m ? (m + i * w) : 0));
}
}
}
}
// --------------------------------------------------------------------------------------------------------------------------
namespace {
struct PointConverter
{
std::string to_string (const db::DPoint &p) const
{
return p.to_string ();
}
void from_string (const std::string &s, db::DPoint &p) const
{
tl::Extractor ex (s.c_str ());
ex.read (p);
}
};
struct ColorMapConverter
{
std::string to_string (const std::pair<double, std::pair<QColor, QColor> > &cm) const
{
std::string s;
s = tl::to_string (cm.first);
s += ":";
lay::ColorConverter cc;
s += tl::to_word_or_quoted_string (cc.to_string (cm.second.first));
if (cm.second.first != cm.second.second) {
s += ",";
s += tl::to_word_or_quoted_string (cc.to_string (cm.second.second));
}
return s;
}
void from_string (const std::string &s, std::pair<double, std::pair<QColor, QColor> > &cm) const
{
tl::Extractor ex (s.c_str ());
ex.read (cm.first);
ex.test (":");
lay::ColorConverter cc;
std::string w;
ex.read_word_or_quoted (w);
cc.from_string (w, cm.second.first);
if (ex.test (",")) {
w.clear ();
ex.read_word_or_quoted (w);
cc.from_string (w, cm.second.second);
} else {
cm.second.second = cm.second.first;
}
}
};
}
tl::XMLStruct<ImageProxy> s_img_structure ("image-data",
tl::make_member (&ImageProxy::is_color, &ImageProxy::set_color, "color") +
tl::make_member (&ImageProxy::width, &ImageProxy::set_width, "width") +
tl::make_member (&ImageProxy::height, &ImageProxy::set_height, "height") +
tl::make_member (&ImageProxy::matrix, &ImageProxy::set_matrix, "matrix") +
tl::make_member (&ImageProxy::min_value, &ImageProxy::set_min_value, "min-value") +
tl::make_member (&ImageProxy::max_value, &ImageProxy::set_max_value, "max-value") +
tl::make_element (&ImageProxy::data_mapping, &ImageProxy::set_data_mapping, "data-mapping",
tl::make_element (&img::DataMapping::false_color_nodes, "color-map",
tl::make_member (&img::DataMapping::false_color_nodes_type::begin, &img::DataMapping::false_color_nodes_type::end, &img::DataMapping::false_color_nodes_type::push_back, "color-map-entry", ColorMapConverter ())
) +
tl::make_member (&img::DataMapping::brightness, "brightness") +
tl::make_member (&img::DataMapping::contrast, "contrast") +
tl::make_member (&img::DataMapping::gamma, "gamma") +
tl::make_member (&img::DataMapping::red_gain, "red-gain") +
tl::make_member (&img::DataMapping::green_gain, "green-gain") +
tl::make_member (&img::DataMapping::blue_gain, "blue-gain")
) +
tl::make_element (&ImageProxy::landmarks, &ImageProxy::set_landmarks, "landmarks",
tl::make_member (&img::Object::landmarks_type::begin, &img::Object::landmarks_type::end, &img::Object::landmarks_type::push_back, "landmark", PointConverter ())
) +
tl::make_member (&ImageProxy::begin_byte_data, &ImageProxy::end_byte_data, &ImageProxy::push_byte_data, "byte-data") +
tl::make_member (&ImageProxy::begin_data, &ImageProxy::end_data, &ImageProxy::push_data, "data")
);
// --------------------------------------------------------------------------------------------------------------------------
img::Object *
ImageStreamer::read (tl::InputStream &stream)
{
ImageProxy proxy;
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading image file: ")) + stream.source ());
tl::XMLStreamSource in (stream, tl::to_string (tr ("Image file")));
s_img_structure.parse (in, proxy);
return proxy.get_image ();
}
void
ImageStreamer::write (tl::OutputStream &stream, const img::Object &img)
{
ImageProxy proxy (&img);
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Writing image file: ")) + stream.path ());
s_img_structure.write (stream, proxy);
}
} // namespace img

60
src/img/img/imgStream.h Normal file
View File

@ -0,0 +1,60 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_imgStream
#define HDR_imgStream
#include "imgCommon.h"
#include "imgObject.h"
#include "tlStream.h"
namespace img {
/**
* @brief An object streaming image data from or to files
*/
struct IMG_PUBLIC ImageStreamer
{
public:
/**
* @brief The constructor
*/
ImageStreamer () { }
/**
* @brief Reads an image Object from a stream
*
* This method returns a new'd object. It's the responsibility of the caller to delete the object.
*/
static Object *read(tl::InputStream &stream);
/**
* @brief Writes an image object to a stream
*/
static void write (tl::OutputStream &stream, const img::Object &img);
};
}
#endif

View File

@ -0,0 +1,291 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "imgStream.h"
#include "tlUnitTest.h"
#include <memory>
TEST(1_FloatMono)
{
img::Object image (12, 8, db::DCplxTrans (1.5, 90.0, true, db::DVector (17, -42)), false, false);
image.set_min_value (-0.25);
image.set_max_value (0.75);
std::vector<db::DPoint> lm;
lm.push_back (db::DPoint (1, 2));
lm.push_back (db::DPoint (-101, 102));
image.set_landmarks (lm);
img::DataMapping dm;
dm.blue_gain = 0.5;
dm.green_gain = 0.75;
dm.red_gain = 0.25;
dm.contrast = -0.5;
dm.gamma = 1.5;
dm.brightness = 1.25;
dm.false_color_nodes.push_back (std::make_pair (0.0, std::make_pair (QColor (0, 0, 0), QColor (0, 0, 0))));
dm.false_color_nodes.push_back (std::make_pair (0.5, std::make_pair (QColor (255, 0, 0), QColor (0, 255, 0))));
dm.false_color_nodes.push_back (std::make_pair (1.0, std::make_pair (QColor (255, 255, 255), QColor (255, 255, 255))));
image.set_data_mapping (dm);
image.set_pixel (0, 0, 0.25);
image.set_pixel (2, 5, 0.25);
image.set_pixel (7, 1, 0.125);
std::string path = tmp_file ("tmp.lyimg");
{
tl::OutputFile file (path);
tl::OutputStream stream (file);
img::ImageStreamer::write (stream, image);
}
std::auto_ptr<img::Object> read;
{
tl::InputFile file (path);
tl::InputStream stream (file);
read.reset (img::ImageStreamer::read (stream));
}
EXPECT_EQ (image.to_string (), read->to_string ());
}
TEST(2_FloatMonoWithMask)
{
img::Object image (12, 8, db::DCplxTrans (1.5, 90.0, true, db::DVector (17, -42)), false, false);
image.set_min_value (-0.25);
image.set_max_value (0.75);
image.set_pixel (0, 0, 0.25);
image.set_pixel (2, 5, 0.25);
image.set_pixel (7, 1, 0.125);
image.set_mask (1, 0, 1);
image.set_mask (1, 2, 1);
image.set_mask (1, 3, 0);
std::string path = tmp_file ("tmp.lyimg");
{
tl::OutputFile file (path);
tl::OutputStream stream (file);
img::ImageStreamer::write (stream, image);
}
std::auto_ptr<img::Object> read;
{
tl::InputFile file (path);
tl::InputStream stream (file);
read.reset (img::ImageStreamer::read (stream));
}
EXPECT_EQ (image.to_string (), read->to_string ());
}
TEST(3_ByteMono)
{
img::Object image (12, 8, db::Matrix3d (db::DCplxTrans (1.5, 90.0, true, db::DVector (17, -42))), false, true);
image.set_min_value (10);
image.set_max_value (240);
image.set_pixel (0, 0, 50);
image.set_pixel (2, 5, 70);
image.set_pixel (7, 1, 120);
std::string path = tmp_file ("tmp.lyimg");
{
tl::OutputFile file (path);
tl::OutputStream stream (file);
img::ImageStreamer::write (stream, image);
}
std::auto_ptr<img::Object> read;
{
tl::InputFile file (path);
tl::InputStream stream (file);
read.reset (img::ImageStreamer::read (stream));
}
EXPECT_EQ (image.to_string (), read->to_string ());
}
TEST(4_ByteMonoWithMask)
{
img::Object image (12, 8, db::DCplxTrans (1.5, 90.0, true, db::DVector (17, -42)), false, true);
image.set_min_value (10);
image.set_max_value (240);
image.set_pixel (0, 0, 50);
image.set_pixel (2, 5, 70);
image.set_pixel (7, 1, 120);
image.set_mask (1, 0, 1);
image.set_mask (1, 2, 1);
image.set_mask (1, 3, 0);
std::string path = tmp_file ("tmp.lyimg");
{
tl::OutputFile file (path);
tl::OutputStream stream (file);
img::ImageStreamer::write (stream, image);
}
std::auto_ptr<img::Object> read;
{
tl::InputFile file (path);
tl::InputStream stream (file);
read.reset (img::ImageStreamer::read (stream));
}
EXPECT_EQ (image.to_string (), read->to_string ());
}
TEST(5_FloatColor)
{
img::Object image (12, 8, db::DCplxTrans (1.5, 90.0, true, db::DVector (17, -42)), true, false);
image.set_min_value (-0.25);
image.set_max_value (0.75);
image.set_pixel (0, 0, 0.25, -0.25, -0.125);
image.set_pixel (2, 5, 0.25, 0.125, 0.625);
image.set_pixel (7, 1, 0.125, 0.25, 0.75);
std::string path = tmp_file ("tmp.lyimg");
{
tl::OutputFile file (path);
tl::OutputStream stream (file);
img::ImageStreamer::write (stream, image);
}
std::auto_ptr<img::Object> read;
{
tl::InputFile file (path);
tl::InputStream stream (file);
read.reset (img::ImageStreamer::read (stream));
}
EXPECT_EQ (image.to_string (), read->to_string ());
}
TEST(6_FloatColorWithMask)
{
img::Object image (12, 8, db::DCplxTrans (1.5, 90.0, true, db::DVector (17, -42)), true, false);
image.set_min_value (-0.25);
image.set_max_value (0.75);
image.set_pixel (0, 0, 0.25, -0.25, -0.125);
image.set_pixel (2, 5, 0.25, 0.125, 0.625);
image.set_pixel (7, 1, 0.125, 0.25, 0.75);
image.set_mask (1, 0, 1);
image.set_mask (1, 2, 1);
image.set_mask (1, 3, 0);
std::string path = tmp_file ("tmp.lyimg");
{
tl::OutputFile file (path);
tl::OutputStream stream (file);
img::ImageStreamer::write (stream, image);
}
std::auto_ptr<img::Object> read;
{
tl::InputFile file (path);
tl::InputStream stream (file);
read.reset (img::ImageStreamer::read (stream));
}
EXPECT_EQ (image.to_string (), read->to_string ());
}
TEST(7_ByteColor)
{
img::Object image (12, 8, db::DCplxTrans (1.5, 90.0, true, db::DVector (17, -42)), true, true);
image.set_min_value (10);
image.set_max_value (240);
image.set_pixel (0, 0, 10, 20, 30);
image.set_pixel (2, 5, 11, 21, 31);
image.set_pixel (7, 1, 12, 22, 32);
std::string path = tmp_file ("tmp.lyimg");
{
tl::OutputFile file (path);
tl::OutputStream stream (file);
img::ImageStreamer::write (stream, image);
}
std::auto_ptr<img::Object> read;
{
tl::InputFile file (path);
tl::InputStream stream (file);
read.reset (img::ImageStreamer::read (stream));
}
EXPECT_EQ (image.to_string (), read->to_string ());
}
TEST(8_ByteColorWithMask)
{
img::Object image (12, 8, db::DCplxTrans (1.5, 90.0, true, db::DVector (17, -42)), true, true);
image.set_min_value (10);
image.set_max_value (240);
image.set_pixel (0, 0, 10, 20, 30);
image.set_pixel (2, 5, 11, 21, 31);
image.set_pixel (7, 1, 12, 22, 32);
image.set_mask (1, 0, 1);
image.set_mask (1, 2, 1);
image.set_mask (1, 3, 0);
std::string path = tmp_file ("tmp.lyimg");
{
tl::OutputFile file (path);
tl::OutputStream stream (file);
img::ImageStreamer::write (stream, image);
}
std::auto_ptr<img::Object> read;
{
tl::InputFile file (path);
tl::InputStream stream (file);
read.reset (img::ImageStreamer::read (stream));
}
EXPECT_EQ (image.to_string (), read->to_string ());
}

View File

@ -34,7 +34,7 @@ static img::Object from_s (const std::string &s)
TEST(1)
{
img::Object image (12, 8, db::DCplxTrans (), false);
img::Object image (12, 8, db::DCplxTrans (), false, false);
EXPECT_EQ (image.is_color (), false);
EXPECT_EQ (image.is_byte_data (), false);
@ -150,7 +150,7 @@ TEST(1)
TEST(2)
{
for (unsigned int channel = 0; channel < 3; ++channel) {
img::Object image (12, 8, db::DCplxTrans (), true);
img::Object image (12, 8, db::DCplxTrans (), true, false);
EXPECT_EQ (image.is_color (), true);

View File

@ -8,6 +8,7 @@ include($$PWD/../../lib_ut.pri)
SOURCES = \
imgObject.cc \
imgFile.cc
INCLUDEPATH += $$IMG_INC $$DB_INC $$TL_INC $$LAYBASIC_INC $$GSI_INC
DEPENDPATH += $$IMG_INC $$DB_INC $$TL_INC $$LAYBASIC_INC $$GSI_INC

View File

@ -940,6 +940,15 @@ Extractor::read (unsigned int &value)
return *this;
}
Extractor &
Extractor::read (unsigned char &value)
{
if (! try_read (value)) {
error (tl::to_string (tr ("Expected an unsigned byte value")));
}
return *this;
}
Extractor &
Extractor::read (unsigned long &value)
{
@ -967,6 +976,15 @@ Extractor::read (double &value)
return *this;
}
Extractor &
Extractor::read (float &value)
{
if (! try_read (value)) {
error (tl::to_string (tr ("Expected a real number")));
}
return *this;
}
Extractor &
Extractor::read (int &value)
{
@ -1099,6 +1117,14 @@ namespace
return tl::to_string (tr ("Range overflow on unsigned integer"));
}
};
template <> struct overflow_msg_func<unsigned char>
{
std::string operator() () const
{
return tl::to_string (tr ("Range overflow on unsigned byte"));
}
};
}
template <class T> bool
@ -1167,6 +1193,12 @@ Extractor::try_read_unsigned_int (T &value)
return true;
}
bool
Extractor::try_read (unsigned char &value)
{
return try_read_unsigned_int (value);
}
bool
Extractor::try_read (unsigned int &value)
{
@ -1202,6 +1234,19 @@ Extractor::try_read (long long &value)
{
return try_read_signed_int (value);
}
bool
Extractor::try_read (float &value)
{
double d = value;
if (try_read (d)) {
value = d;
return true;
} else {
return false;
}
}
bool
Extractor::try_read (double &value)
{

View File

@ -468,6 +468,11 @@ public:
*/
Extractor &read (unsigned int &value);
/**
* @brief Read an unsigned char int (see read of an unsigned int)
*/
Extractor &read (unsigned char &value);
/**
* @brief Read an unsigned long (see read of an unsigned int)
*/
@ -483,6 +488,11 @@ public:
*/
Extractor &read (double &value);
/**
* @brief Read a float (see read of an unsigned int)
*/
Extractor &read (float &value);
/**
* @brief Read a signed int (see read of an unsigned int)
*/
@ -576,6 +586,11 @@ public:
*/
bool try_read (int &value);
/**
* @brief Try to read an unsigned char int (see try to read an unsigned int)
*/
bool try_read (unsigned char &value);
/**
* @brief Try to read an unsigned long (see try to read an unsigned int)
*/
@ -601,6 +616,11 @@ public:
*/
bool try_read (double &value);
/**
* @brief Try to read a float (see try to read an unsigned int)
*/
bool try_read (float &value);
/**
* @brief Try to read a boolean value (see try to read an unsigned int)
*