Files
test/source/blender/freestyle/intern/image/Image.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

406 lines
10 KiB
C
Raw Normal View History

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
2008-04-30 15:41:54 +00:00
#pragma once
2008-04-30 15:41:54 +00:00
/** \file
* \ingroup freestyle
* \brief Class to encapsulate an array of RGB or Gray level values
*/
2008-04-30 15:41:54 +00:00
#include <string.h> // for memcpy
2008-04-30 15:41:54 +00:00
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
#endif
Attempt to fix a potential name conflict between Freestyle and the compositor. A crash in the Freestyle renderer was reported by Ton on IRC with a stack trace below. Note that #2 is in Freestyle, whereas #1 is in the compositor. The problem was observed in a debug build on OS X 10.7 (gcc 4.2, openmp disabled, no llvm). ---------------------------------------------------------------------- Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 [Switching to process 72386 thread 0xf303] 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 43 delete (this->m_outputsockets.back()); Current language: auto; currently c++ (gdb) where #0 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 #1 0x0000000100c29066 in Node::~Node (this=0x10e501c80) at COM_Node.h:49 #2 0x000000010089c273 in NodeShape::~NodeShape (this=0x10e501c80) at NodeShape.cpp:43 #3 0x000000010089910b in NodeGroup::destroy (this=0x10e501da0) at NodeGroup.cpp:61 #4 0x00000001008990cd in NodeGroup::destroy (this=0x10e5014b0) at NodeGroup.cpp:59 #5 0x00000001008990cd in NodeGroup::destroy (this=0x114e18da0) at NodeGroup.cpp:59 #6 0x00000001007e6602 in Controller::ClearRootNode (this=0x114e19640) at Controller.cpp:329 #7 0x00000001007ea52e in Controller::LoadMesh (this=0x114e19640, re=0x10aba4638, srl=0x1140f5258) at Controller.cpp:302 #8 0x00000001008030ad in prepare (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:302 #9 0x000000010080457a in FRS_do_stroke_rendering (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:600 #10 0x00000001006aeb9d in add_freestyle (re=0x10aba4638) at pipeline.c:1584 #11 0x00000001006aceb7 in do_render_3d (re=0x10aba4638) at pipeline.c:1094 #12 0x00000001006ae061 in do_render_fields_blur_3d (re=0x10aba4638) at pipeline.c:1367 #13 0x00000001006afa16 in do_render_composite_fields_blur_3d (re=0x10aba4638) at pipeline.c:1815 #14 0x00000001006b04e4 in do_render_all_options (re=0x10aba4638) at pipeline.c:2021 ---------------------------------------------------------------------- Apparently a name conflict between the two Blender modules is taking place. The present commit hence intends to address it by putting all the Freestyle C++ classes in the namespace 'Freestyle'. This revision will also prevent potential name conflicts with other Blender modules in the future. Special thanks to Lukas Toenne for the help with C++ namespace.
2013-04-09 00:46:49 +00:00
namespace Freestyle {
2008-04-30 15:41:54 +00:00
//
// Image base class, for all types of images
//
///////////////////////////////////////////////////////////////////////////////
/** This class allows the storing of part of an image, while allowing a normal access to its pixel
* values. You can for example only a rectangle of sw*sh, whose lower-left corner is at (ox, oy),
* of an image of size w*h, and access these pixels using x,y coordinates specified in the whole
* image coordinate system.
2008-04-30 15:41:54 +00:00
*/
class FrsImage {
public:
/** Default constructor */
FrsImage()
{
_storedWidth = 0;
_storedHeight = 0;
_width = 0;
_height = 0;
_Ox = 0;
_Oy = 0;
}
/** Copy constructor */
FrsImage(const FrsImage &brother)
{
_storedWidth = brother._storedWidth;
_storedHeight = brother._storedHeight;
_width = brother._width;
_height = brother._height;
_Ox = brother._Ox;
_Oy = brother._Oy;
}
/** Builds an FrsImage from its width and height.
* The memory is allocated consequently.
*/
FrsImage(uint w, uint h)
{
_width = w;
_height = h;
_storedWidth = w;
_storedHeight = h;
_Ox = 0;
_Oy = 0;
}
/** Builds a partial-storing image.
* \param w:
* The width of the complete image
* \param h:
* The height of the complete image
* \param sw:
* The width of the rectangle that will actually be stored.
* \param sh:
* The height of the rectangle that will actually be stored.
* \param ox:
* The x-abscissa of the origin of the rectangle that will actually be stored.
* \param oy:
* The x-abscissa of the origin of the rectangle that will actually be stored.
*/
FrsImage(uint w, uint h, uint sw, uint sh, uint ox, uint oy)
{
_width = w;
_height = h;
_storedWidth = sw;
_storedHeight = sh;
_Ox = ox;
_Oy = oy;
}
/** Operator= */
FrsImage &operator=(const FrsImage &brother)
{
_width = brother._width;
_height = brother._height;
_storedWidth = brother._storedWidth;
_storedHeight = brother._storedHeight;
_Ox = brother._Ox;
_Oy = brother._Oy;
return *this;
}
/** Destructor */
virtual ~FrsImage() {}
/** Returns the width of the complete image */
inline uint width() const
{
return _width;
}
/** Returns the height of the complete image */
inline uint height() const
{
return _height;
}
/** Returns the gray value for pixel x,y */
virtual float pixel(uint x, uint y) const = 0;
/** Sets the array.
* \param array:
* The array containing the values we wish to store.
* Its size is sw*sh.
* \param width:
* The width of the complete image
* \param height:
* The height of the complete image
* \param sw:
* The width of the rectangle that will actually be stored.
* \param sh:
* The height of the rectangle that will actually be stored.
* \param ox:
* The x-abscissa of the origin of the rectangle that will actually be stored.
* \param oy:
* The x-abscissa of the origin of the rectangle that will actually be stored.
* \param copy:
* If true, the array is copied, otherwise the pointer is copied
*/
virtual void setArray(float *array,
uint width,
uint height,
uint sw,
uint sh,
uint x,
uint y,
bool copy = true) = 0;
/** Returns the array containing the pixels values.
* Its size is sw*sh, i.e. potentially a smaller rectangular part of the complete image.
*/
virtual float *getArray() = 0;
protected:
uint _width;
uint _height;
uint _storedWidth;
uint _storedHeight;
uint _Ox; // origin of the stored part
uint _Oy; // origin of the stored part
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FrsImage")
#endif
2008-04-30 15:41:54 +00:00
};
//
// RGBImage
//
///////////////////////////////////////////////////////////////////////////////
class RGBImage : public FrsImage {
public:
RGBImage() : FrsImage()
{
_rgb = 0;
}
RGBImage(const RGBImage &brother) : FrsImage(brother)
{
_rgb = new float[3 * _storedWidth * _storedHeight];
memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
}
RGBImage(uint w, uint h) : FrsImage(w, h)
{
_rgb = new float[3 * _width * _height];
}
RGBImage(float *rgb, uint w, uint h) : FrsImage(w, h)
{
_rgb = new float[3 * _width * _height];
memcpy(_rgb, rgb, 3 * _width * _height * sizeof(float));
}
/** Builds an RGB partial image from the useful part buffer.
* \param rgb:
* The array of size 3*sw*sh containing the RGB values of the sw*sh pixels we need to stored.
* These sw*sh pixels constitute a rectangular part of a bigger
* RGB image containing w*h pixels.
* \param w:
* The width of the complete image
* \param h:
* The height of the complete image
* \param sw:
* The width of the part of the image we want to store and work on
* \param sh:
* The height of the part of the image we want to store and work on
*/
RGBImage(float *rgb, uint w, uint h, uint sw, uint sh, uint ox, uint oy)
: FrsImage(w, h, sw, sh, ox, oy)
{
_rgb = new float[3 * _storedWidth * _storedHeight];
memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
}
RGBImage &operator=(const RGBImage &brother)
{
dynamic_cast<FrsImage &>(*this) = brother;
_rgb = new float[3 * _storedWidth * _storedHeight];
memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
return *this;
}
virtual ~RGBImage()
{
if (_rgb) {
delete[] _rgb;
}
}
inline float getR(uint x, uint y) const
{
return _rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3];
}
inline float getG(uint x, uint y) const
{
return _rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3 + 1];
}
inline float getB(uint x, uint y) const
{
return _rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3 + 2];
}
virtual void setPixel(uint x, uint y, float r, float g, float b)
{
float *tmp = &(_rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3]);
*tmp = r;
tmp++;
*tmp = g;
tmp++;
*tmp = b;
}
virtual float pixel(uint x, uint y) const
{
float res = 0.0f;
float *tmp = &(_rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3]);
res += 11.0f * (*tmp);
tmp++;
res += 16.0f * (*tmp);
tmp++;
res += 5.0f * (*tmp);
return res / 32.0f;
}
/** Sets the RGB array.
* copy
* If true, the array is copied, otherwise the pointer is copied
*/
virtual void setArray(
float *rgb, uint width, uint height, uint sw, uint sh, uint x, uint y, bool copy = true)
{
_width = width;
_height = height;
_storedWidth = sw;
_storedHeight = sh;
_Ox = x;
_Oy = y;
if (!copy) {
_rgb = rgb;
return;
}
memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
}
virtual float *getArray()
{
return _rgb;
}
protected:
float *_rgb;
2008-04-30 15:41:54 +00:00
};
//
// GrayImage
//
///////////////////////////////////////////////////////////////////////////////
class GrayImage : public FrsImage {
public:
GrayImage() : FrsImage()
{
_lvl = 0;
}
GrayImage(const GrayImage &brother) : FrsImage(brother)
{
_lvl = new float[_storedWidth * _storedHeight];
memcpy(_lvl, brother._lvl, _storedWidth * _storedHeight * sizeof(*_lvl));
}
/** Builds an empty gray image */
GrayImage(uint w, uint h) : FrsImage(w, h)
{
_lvl = new float[_width * _height];
}
GrayImage(float *lvl, uint w, uint h) : FrsImage(w, h)
{
_lvl = new float[_width * _height];
memcpy(_lvl, lvl, _width * _height * sizeof(*_lvl));
}
/** Builds a partial image from the useful part buffer.
* \param lvl:
* The array of size sw*sh containing the gray values of the sw*sh pixels we need to stored.
* These sw*sh pixels constitute a rectangular part of a bigger
* gray image containing w*h pixels.
* \param w:
* The width of the complete image
* \param h:
* The height of the complete image
* \param sw:
* The width of the part of the image we want to store and work on
* \param sh:
* The height of the part of the image we want to store and work on
*/
GrayImage(float *lvl, uint w, uint h, uint sw, uint sh, uint ox, uint oy)
: FrsImage(w, h, sw, sh, ox, oy)
{
_lvl = new float[_storedWidth * _storedHeight];
memcpy(_lvl, lvl, _storedWidth * _storedHeight * sizeof(float));
}
GrayImage &operator=(const GrayImage &brother)
{
dynamic_cast<FrsImage &>(*this) = brother;
_lvl = new float[_storedWidth * _storedHeight];
memcpy(_lvl, brother._lvl, _storedWidth * _storedHeight * sizeof(float));
return *this;
}
virtual ~GrayImage()
{
if (_lvl) {
delete[] _lvl;
}
}
inline void setPixel(uint x, uint y, float v)
{
_lvl[(y - _Oy) * _storedWidth + (x - _Ox)] = v;
}
inline float pixel(uint x, uint y) const
{
return _lvl[(y - _Oy) * _storedWidth + (x - _Ox)];
}
/** Sets the array.
* copy
2020-07-21 15:58:16 +10:00
* If true, the array is copied, otherwise the pounsigneder is copied
*/
void setArray(
float *lvl, uint width, uint height, uint sw, uint sh, uint x, uint y, bool copy = true)
{
_width = width;
_height = height;
_storedWidth = sw;
_storedHeight = sh;
_Ox = x;
_Oy = y;
if (!copy) {
_lvl = lvl;
return;
}
memcpy(_lvl, lvl, _storedWidth * _storedHeight * sizeof(float));
}
/** Returns the array containing the gray values. */
virtual float *getArray()
{
return _lvl;
}
protected:
float *_lvl;
2008-04-30 15:41:54 +00:00
};
Attempt to fix a potential name conflict between Freestyle and the compositor. A crash in the Freestyle renderer was reported by Ton on IRC with a stack trace below. Note that #2 is in Freestyle, whereas #1 is in the compositor. The problem was observed in a debug build on OS X 10.7 (gcc 4.2, openmp disabled, no llvm). ---------------------------------------------------------------------- Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 [Switching to process 72386 thread 0xf303] 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 43 delete (this->m_outputsockets.back()); Current language: auto; currently c++ (gdb) where #0 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 #1 0x0000000100c29066 in Node::~Node (this=0x10e501c80) at COM_Node.h:49 #2 0x000000010089c273 in NodeShape::~NodeShape (this=0x10e501c80) at NodeShape.cpp:43 #3 0x000000010089910b in NodeGroup::destroy (this=0x10e501da0) at NodeGroup.cpp:61 #4 0x00000001008990cd in NodeGroup::destroy (this=0x10e5014b0) at NodeGroup.cpp:59 #5 0x00000001008990cd in NodeGroup::destroy (this=0x114e18da0) at NodeGroup.cpp:59 #6 0x00000001007e6602 in Controller::ClearRootNode (this=0x114e19640) at Controller.cpp:329 #7 0x00000001007ea52e in Controller::LoadMesh (this=0x114e19640, re=0x10aba4638, srl=0x1140f5258) at Controller.cpp:302 #8 0x00000001008030ad in prepare (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:302 #9 0x000000010080457a in FRS_do_stroke_rendering (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:600 #10 0x00000001006aeb9d in add_freestyle (re=0x10aba4638) at pipeline.c:1584 #11 0x00000001006aceb7 in do_render_3d (re=0x10aba4638) at pipeline.c:1094 #12 0x00000001006ae061 in do_render_fields_blur_3d (re=0x10aba4638) at pipeline.c:1367 #13 0x00000001006afa16 in do_render_composite_fields_blur_3d (re=0x10aba4638) at pipeline.c:1815 #14 0x00000001006b04e4 in do_render_all_options (re=0x10aba4638) at pipeline.c:2021 ---------------------------------------------------------------------- Apparently a name conflict between the two Blender modules is taking place. The present commit hence intends to address it by putting all the Freestyle C++ classes in the namespace 'Freestyle'. This revision will also prevent potential name conflicts with other Blender modules in the future. Special thanks to Lukas Toenne for the help with C++ namespace.
2013-04-09 00:46:49 +00:00
} /* namespace Freestyle */