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; }