C++ Images

Image Classes

template<typename T>
class AssignableToImage

AssignableToImage is a base class for anything that can be assigned to an Image.

It is the base class for both BaseImage, which has all the real image types and various composite types that are used to make im3 = im1 + im2 efficient.

Subclassed by galsim::BaseImage< T >

Public Functions

inline virtual ~AssignableToImage()

Destructor is public and virtual.

virtual void assignTo(ImageView<T> rhs) const = 0

Assign values to an ImageView.

inline const Bounds<int> &getBounds() const

Return the bounding box of the image.

template<typename T>
class BaseImage : public galsim::AssignableToImage<T>

BaseImage class defines the interface of what you can do with Images without modifying pixels.

BaseImage is the base class for the other Image types:

You should never need to declare an object of this class directly, using instead the various derived classes. However, if you are using an image as a parameter to a function in a non-modifying context, then it is convenient to declare the parameter “const BaseImage<T>&” so that any of the various image types can be used without requiring any casts.

Subclassed by galsim::ConstImageView< T >, galsim::ImageAlloc< T >, galsim::ImageView< T >

Public Functions

inline virtual ~BaseImage()

Destructor is virtual and public.

Note: There are no public constructors, since this is an abstract base class. But the destructor should be public (and virtual).

Nothing special needs to be done here, since shared_ptr takes care of deleting the data if this is the last thing to own the data.

inline shared_ptr<T> getOwner() const

Return a shared pointer that manages the lifetime of the image’s pixels.

The actual pointer will point to a parent image rather than the image itself if this is a subimage.

inline const T *getData() const

Return a pointer to the first pixel in the image.

inline const T *getMaxPtr() const
inline bool ok_ptr(const T *p) const

Check that the ptr is valid, properly accounting for step, stride.

inline ptrdiff_t getNElements() const

Return how many data elements are currently allocated in memory.

This is usually the same as getBounds().area(), but it may not be if the image has been resized.

inline int getStride() const

Return the number of elements between rows in memory.

inline int getStep() const

Return the number of elements between cols in memory.

inline int getNCol() const

Return the number of columns in the image.

inline int getNRow() const

Return the number of rows in the image.

inline int getNSkip() const

Return the number of columns to skip at the end of each row when iterating.

inline bool isContiguous() const

Return whether the data is contiguous in memory.

Shorthand for: (getStride() == getNCol()) or equivalently (getNSkip() == 0)

inline ImageAlloc<T> copy() const

Deep copy the image.

The returned image will have the same bounding box and pixel values as this, but will they will not share data.

inline ConstImageView<T> view() const

Create a new view of the image.

The returned image will share data with this image

ConstImageView<T> subImage(const Bounds<int> &bounds) const

New image that is a subimage of this (shares pixels)

inline ConstImageView<T> operator[](const Bounds<int> &bounds) const

im[bounds] is another syntax for making a sub-image

Bounds<int> nonZeroBounds() const

Return the smallest bounds that includes all non-zero elements of the image.

inline void shift(const Position<int> &delta)

Shift the bounding box of the image, changing the logical location of the pixels.

xmin_new = xmin + dx xmax_new = xmax + dx ymin_new = ymin + dy ymax_new = ymax + dy

inline int getXMin() const

Convenience accessors for the bounding box corners.

inline int getXMax() const
inline int getYMin() const
inline int getYMax() const
inline const T &operator()(int xpos, int ypos) const

Unchecked element access.

inline const T &operator()(const Position<int> &pos) const
const T &at(int xpos, int ypos) const

Element access - checked.

inline const T &at(const Position<int> &pos) const
inline const T *getPtr(int x, int y) const

Return a pointer to the data at an arbitrary pixel.

inline const T *getPtr(const Position<int> &pos) const
inline virtual void assignTo(ImageView<T> rhs) const

BaseImage’s assignTo just uses the normal copyFrom method.

T sumElements() const

Return the sum of the elements in the image.

Traits<T>::real_type maxAbsElement() const

Return the maximum absolute value in the image.

template<typename T>
class ImageAlloc : public galsim::BaseImage<T>

ImageAlloc class.

The ImageAlloc class is a 2-d array with pixel values stored contiguously in memory along rows (but not necessarily between rows). An image’s pixel values may be shared between multiple image objects (with reference counting), and a subimage may share data with its parent and multiple siblings. ImageAllocs may also share pixel values with NumPy arrays when the allocation happens in the C++ layer.

An ImageAlloc also contains a bounding box; its origin need not be (0,0) or (1,1).

The const semantics for this are pretty normal. You cannot change either the pixel values or the ancillary information (like bounds) for a const ImageAlloc, while you can change things about a non-const ImageAlloc.

ImageAlloc templates for uint16_t, uint32_t, int16_t, int32_t, float, and double are explicitly instantiated in Image.cpp.

Public Functions

inline ImageAlloc()

Default constructor leaves the image’s data pointer as null.

ImageAlloc(int ncol, int nrow)

Create a new image with origin at (1,1).

An exception is thrown if ncol or nrow <= 0

ImageAlloc(int ncol, int nrow, T init_value)

Create a new image with origin at (1,1), intialized with some init_value.

An exception is thrown if ncol or nrow <= 0

ImageAlloc(const Bounds<int> &bounds)

Create a new image with the given bounding box.

ImageAlloc(const Bounds<int> &bounds, T init_value)

Create a new image with the given bounding box and initial value.

inline ImageAlloc(const ImageAlloc<T> &rhs)

Deep copy constructor.

inline ImageAlloc(const AssignableToImage<T> &rhs)

Can construct from any AssignableToImage.

template<typename U>
inline ImageAlloc(const BaseImage<U> &rhs)

If rhs is a BaseImage, then type doesn’t have to match.

inline ImageAlloc<T> &operator=(const AssignableToImage<T> &rhs)

Deep assignment operator.

The bounds must be commensurate (i.e. the same shape). If not, an exception will be thrown.

inline ImageAlloc<T> &operator=(const ImageAlloc<T> &rhs)

Repeat for ImageAlloc to prevent compiler from making the default op=.

template<typename U>
inline ImageAlloc<T> &operator=(const BaseImage<U> &rhs)

Copy from BaseImage allowed for different types.

inline void fill(T x)

Assignment with a scalar.

inline ImageAlloc<T> &operator=(T x)
inline void setZero()
inline void invertSelf()

Set each element to its inverse: im(i,j) = 1/im(i,j)

Note that if an element is zero, then this function quietly returns its inverse as zero.

void resize(const Bounds<int> &new_bounds, bool release = true)

Resize the image to a new bounds. The values are left uninitialized.

Any views that share data with this ImageAlloc are still valid and still share data with each other, but the tie to this ImageAlloc is severed.

This typically allocates new memory for the array. The only exception is if the new size is the same as the current size and are there are no other views of the data. Then it just updates the bounds to the new bounds and keeps the current array.

You can also optionally keep the current array if you are shrinking the bounds to a smaller size, with the same limit of there not being other views. To get this behavior, set release=false, and it will not release the allocated memory when shrinking the size of the image.

inline T *getData()

Return a pointer to the first pixel in the image.

inline const T *getData() const
inline const T *getMaxPtr() const
inline ImageView<T> view()

Make a view of this image.

inline ConstImageView<T> view() const
inline ImageView<T> subImage(const Bounds<int> &bounds)

New image that is a subimage of this (shares pixels)

inline ConstImageView<T> subImage(const Bounds<int> &bounds) const
inline ImageView<T> operator[](const Bounds<int> &bounds)

im[bounds] is another syntax for making a sub-image

inline ConstImageView<T> operator[](const Bounds<int> &bounds) const
inline T &operator()(int xpos, int ypos)

Unchecked access.

inline const T &operator()(int xpos, int ypos) const
inline T &operator()(const Position<int> &pos)
inline const T &operator()(const Position<int> &pos) const
T &at(int xpos, int ypos)

Element access - checked.

const T &at(int xpos, int ypos) const
inline T &at(const Position<int> &pos)
inline const T &at(const Position<int> &pos) const
inline void setValue(int x, int y, T value)

Another way to set a value. Equivalent to im(x,y) = value.

The python layer can’t implement the im(x,y) = value syntax, so we need something else to set a single pixel. This function is unnecessary at the C++ level, but in the interest of trying to keep the two layers as close as possible, we might as well include it.

Note: This uses the checked element access.

template<typename U>
inline void copyFrom(const BaseImage<U> &rhs)

Deep-copy pixel values from rhs to this.

The bounds must be commensurate (i.e. the same shape). If not, an exception will be thrown.

template<typename T>
class ImageView : public galsim::BaseImage<T>

ImageView class is a mutable view of an Image.

The copy constructor is shallow, so ImageView’s can be cheaply returned by value. The data values persist until the last view of some data goes out of scope.

The op= is deep, though. This is the intuitive behavior, so you can write something like

im1[bounds] = im2

and the data in im2 will be copied to the sub-image of im1.

Also note that through the python interface, we can make an ImageView that views a numpy array rather than anything that was created as an ImageAlloc. We have some tricky stuff in pysrc/Image.cpp to get the C++ shared_ptr to interact correctly with numpy’s reference counting so the data are deleted when the last numpy array or ImageView finally goes out of scope.

You could do the same thing within the C++ layer too. You would just have to provide a shared_ptr explicitly to set up the ownership.

Public Functions

inline ImageView(T *data, const T *maxptr, ptrdiff_t nElements, const shared_ptr<T> &owner, int step, int stride, const Bounds<int> &b)

Direct constructor given all the necessary information.

inline ImageView(const ImageView<T> &rhs)

Shallow copy constructor.

The original image and its copy will share pixel values, but their bounding boxes will not be shared (even though they will be set to the same values initially).

inline ImageView(ImageAlloc<T> &rhs)

Shallow copy constructor from ImageAlloc.

The original image and its copy will share pixel values, but their bounding boxes will not be shared (even though they will be set to the same values initially).

inline ImageView<T> &operator=(const AssignableToImage<T> &rhs)

Deep assignment operator.

The bounds must be commensurate (i.e. the same shape). If not, an exception will be thrown.

inline ImageView<T> &operator=(const ImageView<T> &rhs)

Repeat for ImageView to prevent compiler from making the default op=.

template<typename U>
inline ImageView<T> &operator=(const BaseImage<U> &rhs)

Allow copy from a different type.

void fill(T x)

Assignment with a scalar.

inline ImageView<T> &operator=(T x)
inline void setZero()
void invertSelf()

Set each element to its inverse: im(i,j) = 1/im(i,j)

Note that if an element is zero, then this function quietly returns its inverse as zero.

void depixelizeSelf(const double *unit_integrals, const int n)

Make a depixelized version of the image.

inline T *getData()

Return a pointer to the first pixel in the image.

This overrides the version in BaseImage, since this one returns a non-const pointer. (T*, not const T*)

inline const T *getMaxPtr()
inline ImageView<T> view()

View just returns itself.

ImageView<T> subImage(const Bounds<int> &bounds)

New image that is a subimage of this (shares pixels)

inline ImageView<T> operator[](const Bounds<int> &bounds)

im[bounds] is another syntax for making a sub-image

inline T &operator()(int xpos, int ypos)

Unchecked access.

inline T &operator()(const Position<int> &pos)
T &at(int xpos, int ypos)

Element access - checked.

inline T &at(const Position<int> &pos)
inline void setValue(int x, int y, T value)

Another way to set a value. Equivalent to im(x,y) = value.

The python layer can’t implement the im(x,y) = value syntax, so we need something else to set a single pixel. This function is unnecessary at the C++ level, but in the interest of trying to keep the two layers as close as possible, we might as well include it.

Note: This uses the checked element access.

void copyFrom(const BaseImage<T> &rhs)

Deep-copy pixel values from rhs to this.

The bounds must be commensurate (i.e. the same shape). If not, an exception will be thrown.

template<class U>
inline void copyFrom(const BaseImage<U> &rhs)

Deep copy may be from a different type of image.

Do this inline, so we don’t have to worry about instantiating all pairs of types.

template<typename T>
class ConstImageView : public galsim::BaseImage<T>

ConstImageView class views an Image in a read-only context.

Read-only only refers to the data values. The bounds may be changed.

Public Functions

inline ConstImageView(T *data, const T *maxptr, ptrdiff_t nElements, const shared_ptr<T> &owner, int step, int stride, const Bounds<int> &b)

Direct constructor given all the necessary information.

inline ConstImageView(const BaseImage<T> &rhs)

Copy Constructor from a BaseImage makes a new view of the same data.

inline ConstImageView(const ConstImageView<T> &rhs)

Repeat the same copy constructor functionality for ConstImageView to make sure the compiler doesn’t make the default one.

inline ConstImageView<T> view() const

View just returns itself.