mirror of https://github.com/KLayout/klayout.git
WIP: added new lay::Image class
This commit is contained in:
parent
e49b9a5e8a
commit
0b48cb9020
|
|
@ -0,0 +1,201 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2022 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 "layImage.h"
|
||||
#include "tlAssert.h"
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
Image::Image (unsigned int w, unsigned int h, lay::color_t *data)
|
||||
{
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
m_data.reset (new ImageData (data, w * h));
|
||||
}
|
||||
|
||||
Image::Image (unsigned int w, unsigned int h, const lay::color_t *data, unsigned int stride)
|
||||
{
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
|
||||
lay::color_t *d = new color_t [w * h];
|
||||
|
||||
if (data) {
|
||||
for (unsigned int i = 0; i < h; ++i) {
|
||||
for (unsigned int i = 0; i < h; ++i) {
|
||||
*d++ = *data++;
|
||||
}
|
||||
if (stride > w) {
|
||||
data += stride - w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_data.reset (new ImageData (d, w * h));
|
||||
}
|
||||
|
||||
Image::Image ()
|
||||
{
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
}
|
||||
|
||||
Image::Image (const Image &other)
|
||||
{
|
||||
operator= (other);
|
||||
}
|
||||
|
||||
Image::Image (Image &&other)
|
||||
{
|
||||
swap (other);
|
||||
}
|
||||
|
||||
Image::~Image ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
Image &
|
||||
Image::operator= (const Image &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_width = other.m_width;
|
||||
m_height = other.m_height;
|
||||
m_data = other.m_data;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Image &
|
||||
Image::operator= (Image &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
swap (other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
Image::swap (Image &other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::swap (m_width, other.m_width);
|
||||
std::swap (m_height, other.m_height);
|
||||
m_data.swap (other.m_data);
|
||||
}
|
||||
|
||||
void
|
||||
Image::fill (lay::color_t c)
|
||||
{
|
||||
color_t *d = data ();
|
||||
for (unsigned int i = 0; i < m_height; ++i) {
|
||||
for (unsigned int j = 0; j < m_width; ++j) {
|
||||
*d++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
color_t *
|
||||
Image::scan_line (unsigned int n)
|
||||
{
|
||||
tl_assert (n < m_height);
|
||||
return m_data->data () + n * m_width;
|
||||
}
|
||||
|
||||
const color_t *
|
||||
Image::scan_line (unsigned int n) const
|
||||
{
|
||||
tl_assert (n < m_height);
|
||||
return m_data->data () + n * m_width;
|
||||
}
|
||||
|
||||
color_t *
|
||||
Image::data ()
|
||||
{
|
||||
return m_data->data ();
|
||||
}
|
||||
|
||||
const color_t *
|
||||
Image::data () const
|
||||
{
|
||||
return m_data->data ();
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
QImage
|
||||
Image::to_image () const
|
||||
{
|
||||
return QImage ((const uchar *) data (), m_width, m_height, QImage::Format_ARGB32);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Image::patch (const Image &other)
|
||||
{
|
||||
tl_assert (width () == other.width ());
|
||||
tl_assert (height () == other.height ());
|
||||
|
||||
const color_t *d = other.data ();
|
||||
color_t *dd = data ();
|
||||
for (unsigned int i = 0; i < m_height; ++i) {
|
||||
for (unsigned int j = 0; j < m_width; ++j) {
|
||||
color_t c = *d++;
|
||||
if ((c & 0x80000000) != 0) {
|
||||
*dd = c;
|
||||
}
|
||||
++dd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image
|
||||
Image::diff (const Image &other) const
|
||||
{
|
||||
tl_assert (width () == other.width ());
|
||||
tl_assert (height () == other.height ());
|
||||
|
||||
Image res (m_width, m_height);
|
||||
|
||||
const color_t *d2 = other.data ();
|
||||
const color_t *d1 = data ();
|
||||
color_t *dd = res.data ();
|
||||
|
||||
for (unsigned int i = 0; i < m_height; ++i) {
|
||||
for (unsigned int j = 0; j < m_width; ++j) {
|
||||
if (((*d1 ^ *d2) & 0xffffff) != 0) {
|
||||
*dd++ = *d2 | 0xff000000;
|
||||
} else {
|
||||
*dd++ = 0;
|
||||
}
|
||||
++d1;
|
||||
++d2;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2022 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_layImage
|
||||
#define HDR_layImage
|
||||
|
||||
#include "laybasicCommon.h"
|
||||
#include "layColor.h"
|
||||
#include "tlCopyOnWrite.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
# include <QImage>
|
||||
#endif
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief An 32bit RGBA image class
|
||||
*
|
||||
* This class substitutes QImage in Qt-less applications.
|
||||
* It provides 32bit RGBA pixels with the format used by lay::Color.
|
||||
*/
|
||||
|
||||
class LAYBASIC_PUBLIC Image
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates an image with the given height and width
|
||||
*
|
||||
* If data is given, the image is initialized with the given data and will take ownership over the
|
||||
* data block.
|
||||
*
|
||||
* The size of the data block needs to be w*h elements.
|
||||
*/
|
||||
Image (unsigned int w, unsigned int h, lay::color_t *data);
|
||||
|
||||
/**
|
||||
* @brief Creates an image with the given height and width
|
||||
*
|
||||
* If data is given, the image is initialized with the given data. A copy of the data is created.
|
||||
*
|
||||
* "stride" specifies the stride (distance between two rows of data).
|
||||
* The size of the data block needs to be stride*h elements or w*h if stride is not given.
|
||||
*/
|
||||
Image (unsigned int w, unsigned int h, const lay::color_t *data = 0, unsigned int stride = 0);
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
Image ();
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
Image (const Image &other);
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
*/
|
||||
Image (Image &&other);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~Image ();
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
Image &operator= (const Image &other);
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
*/
|
||||
Image &operator= (Image &&other);
|
||||
|
||||
/**
|
||||
* @brief Swaps this image with another one
|
||||
*/
|
||||
void swap (Image &other);
|
||||
|
||||
/**
|
||||
* @brief Gets the images width
|
||||
*/
|
||||
unsigned int width () const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the images width
|
||||
*/
|
||||
unsigned int height () const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fills the image with the given color
|
||||
*/
|
||||
void fill (lay::color_t);
|
||||
|
||||
/**
|
||||
* @brief Gets the scanline for row n
|
||||
*/
|
||||
color_t *scan_line (unsigned int n);
|
||||
|
||||
/**
|
||||
* @brief Gets the scanline for row n (const version)
|
||||
*/
|
||||
const color_t *scan_line (unsigned int n) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the data pointer
|
||||
*/
|
||||
color_t *data ();
|
||||
|
||||
/**
|
||||
* @brief Gets the data pointer (const version)
|
||||
*/
|
||||
const color_t *data () const;
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
/**
|
||||
* @brief Produces a QImage object from the image
|
||||
*/
|
||||
QImage to_image () const;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Overlays the other image with this one
|
||||
*
|
||||
* This feature does not implement real alpha blending. Instead all
|
||||
* pixels with an alpha value >= 128 from the other image are patched into this image.
|
||||
*/
|
||||
void patch (const Image &other);
|
||||
|
||||
/**
|
||||
* @brief Generates the image difference
|
||||
*
|
||||
* This feature produces a binary-alpha image of *this and other. The
|
||||
* result can be patched into this image to render the same image than
|
||||
* "other".
|
||||
*
|
||||
* alpha values from this and other are ignored.
|
||||
*/
|
||||
Image diff (const Image &other) const;
|
||||
|
||||
private:
|
||||
class ImageData
|
||||
{
|
||||
public:
|
||||
ImageData ()
|
||||
: mp_data (0), m_length (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
ImageData (lay::color_t *data, size_t length)
|
||||
: mp_data (data), m_length (length)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
ImageData (const ImageData &other)
|
||||
{
|
||||
m_length = other.length ();
|
||||
mp_data = new lay::color_t [other.length ()];
|
||||
memcpy (mp_data, other.data (), m_length * sizeof (lay::color_t));
|
||||
}
|
||||
|
||||
~ImageData ()
|
||||
{
|
||||
delete[] mp_data;
|
||||
mp_data = 0;
|
||||
}
|
||||
|
||||
size_t length () const { return m_length; }
|
||||
lay::color_t *data () { return mp_data; }
|
||||
const lay::color_t *data () const { return mp_data; }
|
||||
|
||||
private:
|
||||
lay::color_t *mp_data;
|
||||
size_t m_length;
|
||||
size_t m_stride;
|
||||
|
||||
ImageData &operator= (const ImageData &other);
|
||||
};
|
||||
|
||||
unsigned int m_width, m_height;
|
||||
tl::copy_on_write_ptr<ImageData> m_data;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -118,6 +118,7 @@ DEFINES += MAKE_LAYBASIC_LIBRARY
|
|||
layGenericSyntaxHighlighter.cc \
|
||||
layGridNetConfigPage.cc \
|
||||
layHierarchyControlPanel.cc \
|
||||
layImage.cc \
|
||||
layIndexedNetlistModel.cc \
|
||||
layItemDelegates.cc \
|
||||
layLayerControlPanel.cc \
|
||||
|
|
@ -191,6 +192,7 @@ DEFINES += MAKE_LAYBASIC_LIBRARY
|
|||
layGenericSyntaxHighlighter.h \
|
||||
layGridNetConfigPage.h \
|
||||
layHierarchyControlPanel.h \
|
||||
layImage.h \
|
||||
layIndexedNetlistModel.h \
|
||||
layItemDelegates.h \
|
||||
layLayerControlPanel.h \
|
||||
|
|
|
|||
|
|
@ -10,13 +10,14 @@ SOURCES = \
|
|||
layAnnotationShapes.cc \
|
||||
layBitmap.cc \
|
||||
layBitmapsToImage.cc \
|
||||
layImageTests.cc \
|
||||
layColorTests.cc \
|
||||
layLayerProperties.cc \
|
||||
layParsedLayerSource.cc \
|
||||
layRenderer.cc \
|
||||
layNetlistBrowserModelTests.cc \
|
||||
layNetlistBrowserTreeModelTests.cc \
|
||||
layAbstractMenuTests.cc \
|
||||
layNetlistBrowserTreeModelTests.cc \
|
||||
layAbstractMenuTests.cc \
|
||||
laySnapTests.cc
|
||||
|
||||
INCLUDEPATH += $$TL_INC $$LAYBASIC_INC $$DB_INC $$GSI_INC $$OUT_PWD/../laybasic
|
||||
|
|
|
|||
|
|
@ -143,6 +143,22 @@ public:
|
|||
release ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Swaps two pointers
|
||||
*/
|
||||
void swap (copy_on_write_ptr<X, Dup> &other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return;
|
||||
}
|
||||
|
||||
tl::MutexLocker locker1 (&ms_lock);
|
||||
tl::MutexLocker locker2 (&other.ms_lock);
|
||||
|
||||
std::swap (mp_x, other.mp_x);
|
||||
std::swap (mp_holder, other.mp_holder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a writable object
|
||||
* This is when we will create a new copy if the object is shared.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ SOURCES = \
|
|||
tlFileSystemWatcherTests.cc \
|
||||
tlFileUtilsTests.cc \
|
||||
tlHttpStreamTests.cc \
|
||||
tlImageTests.cc \
|
||||
tlIncludeTests.cc \
|
||||
tlInt128SupportTests.cc \
|
||||
tlIntervalMapTests.cc \
|
||||
|
|
@ -36,11 +37,10 @@ SOURCES = \
|
|||
tlUniqueIdTests.cc \
|
||||
tlListTests.cc \
|
||||
tlEquivalenceClustersTests.cc \
|
||||
tlUniqueNameTests.cc \
|
||||
tlGlobPatternTests.cc \
|
||||
tlRecipeTests.cc \
|
||||
tlUriTests.cc \
|
||||
tlUtilsTests.cc \
|
||||
tlUniqueNameTests.cc \
|
||||
tlGlobPatternTests.cc \
|
||||
tlRecipeTests.cc \
|
||||
tlUriTests.cc \
|
||||
tlVariantTests.cc \
|
||||
tlWebDAVTests.cc \
|
||||
tlXMLParserTests.cc
|
||||
|
|
|
|||
Loading…
Reference in New Issue