File size: 5,524 Bytes
9913017 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | ///////////////////////////////////////////////////////////////////////////
//
// NAME
// Image.cpp -- a simple reference-counted image structure
//
// SEE ALSO
// Image.h definition and explanation of these classes
//
// Copyright � Richard Szeliski, 2001.
// See Copyright.h for more details
//
///////////////////////////////////////////////////////////////////////////
#include "Image.h"
#include "Error.h"
//
// struct CShape: shape of image (width x height x nbands)
//
bool CShape::operator==(const CShape& ref)
{
// Are two shapes the same?
return (width == ref.width &&
height == ref.height &&
nBands == ref.nBands);
}
bool CShape::SameIgnoringNBands(const CShape& ref)
{
// Are two shapes the same ignoring the number of bands?
return (width == ref.width &&
height == ref.height);
}
bool CShape::operator!=(const CShape& ref)
{
// Are two shapes not the same?
return ! ((*this) == ref);
}
//
// class CImage : generic (weakly typed) image
//
void CImage::SetDefaults()
{
// Set internal state to default values
m_pTI = 0; // pointer to type_info class
m_bandSize = 0; // size of each band in bytes
m_pixSize = 0; // stride between pixels in bytes
m_rowSize = 0; // stride between rows in bytes
m_memStart = 0; // start of addressable memory
alphaChannel = 3; // which channel contains alpha (for compositing)
// Set default attribute values
alphaChannel = 3; // which channel contains alpha (for compositing)
origin[0] = 0; // x and y coordinate origin (for some operations)
origin[1] = 0; // x and y coordinate origin (for some operations)
borderMode = eBorderReplicate; // border behavior for neighborhood operations...
}
CImage::CImage()
{
// Default constructor
SetDefaults();
}
CImage::CImage(CShape s, const type_info& ti, int cS)
{
SetDefaults();
ReAllocate(s, ti, cS, 0, true, 0);
}
void CImage::ReAllocate(CShape s, const type_info& ti, int bandSize,
bool evenIfSameShape)
{
if (! evenIfSameShape && s == m_shape && ti == *m_pTI && bandSize == m_bandSize)
return;
ReAllocate(s, ti, bandSize, 0, true, 0);
}
void CImage::ReAllocate(CShape s, const type_info& ti, int bandSize,
void *memory, bool deleteWhenDone, int rowSize)
{
// Set up the type_id, shape, and size info
m_shape = s; // image shape (dimensions)
m_pTI = &ti; // pointer to type_info class
m_bandSize = bandSize; // size of each band in bytes
m_pixSize = m_bandSize * s.nBands; // stride between pixels in bytes
// Do the real allocation work
m_rowSize = (rowSize) ? rowSize : // stride between rows in bytes
(m_pixSize * s.width + 7) & -8; // round up to 8 (quadwords)
int nBytes = m_rowSize * s.height;
if (memory == 0 && nBytes > 0) // allocate if necessary
{
memory = new double[(nBytes + 7)/ 8];
if (memory == 0)
throw CError("CImage::Reallocate: could not allocate %d bytes", nBytes);
}
m_memStart = (char *) memory; // start of addressable memory
m_memory.ReAllocate(nBytes, memory, deleteWhenDone);
}
void CImage::DeAllocate()
{
// Release the memory & set to default values
ReAllocate(CShape(), *(const type_info *) 0, 0, 0, false, 0);
SetDefaults();
}
void CImage::SetSubImage(int x, int y, int width, int height)
{
// Adjust the start of memory pointer
m_memStart = (char *) PixelAddress(x, y, 0);
// Compute area of intersection and adjust the shape and origin
int x1 = __min(m_shape.width, x+width); // end column
int y1 = __min(m_shape.height, y+height); // end row
x = __max(0, __min(x, m_shape.width)); // clip to original shape
y = __max(0, __min(y, m_shape.height)); // clip to original shape
m_shape.width = x1 - x; // actual width
m_shape.height = y1 - y; // actual height
}
void CImage::SetPixels(void *val_ptr)
{
// Fill the image with a value
uchar *vc = (uchar *) val_ptr;
// Test if all the bytes are the same
bool all_same = true;
for (int b = 0; b < m_bandSize; b++)
all_same = all_same && (vc[b] == vc[0]);
// Iterate over the rows
int nC = m_shape.width * m_shape.nBands;
for (int y = 0; y < m_shape.height; y++)
{
uchar *rp = (uchar *) PixelAddress(0, y, 0);
if (all_same)
memset(rp, vc[0], nC * m_bandSize);
else if (m_bandSize == sizeof(int))
{
int vi = *(int *) val_ptr;
int *ip = (int *) rp;
for (int c = 0; c < nC; c++)
ip[c] = vi;
}
else
{
for (int c = 0; c < nC; c++, rp += m_bandSize)
memcpy(rp, vc, m_bandSize);
}
}
}
//
// class CImageOf<T>: strongly typed image
//
template <> uchar CImageOf<uchar>::MinVal(void) { return 0; }
template <> uchar CImageOf<uchar>::MaxVal(void) { return 255; }
template <> int CImageOf<int >::MinVal(void) { return 0x80000000; }
template <> int CImageOf<int >::MaxVal(void) { return 0x7fffffff; }
template <> float CImageOf<float>::MinVal(void) { return -FLT_MAX; }
template <> float CImageOf<float>::MaxVal(void) { return FLT_MAX; }
|