3 This class represents a 2D raster image; a rectangular 2D
6 Orion Sky Lawlor, olawlor@acm.org, 5/15/2002
15 inline int min(int a
,int b
) {return (a
<b
)?a
:b
;}
16 inline int max(int a
,int b
) {return (a
>b
)?a
:b
;}
19 int l
,r
; //X boundaries of rectangle
20 int t
,b
; //Y boundaries of rectangle
21 CkRect() {l
=r
=t
=b
=-1;}
22 CkRect(int l_
,int t_
,int r_
,int b_
)
23 :l(l_
), r(r_
), t(t_
), b(b_
) {}
25 :l(0), r(w
), t(0), b(h
) {}
26 //Default copy constructor, assignment operator
27 int wid(void) const {return r
-l
;}
28 int ht(void) const {return b
-t
;}
29 int getWidth(void) const {return r
-l
;}
30 int getHeight(void) const {return b
-t
;}
31 inline int operator==(const CkRect
&a
)
32 {return l
==a
.l
&& r
==a
.r
&& t
==a
.t
&& b
==a
.b
;}
33 CkRect
getUnion(const CkRect
&a
) {
34 return CkRect(min(l
,a
.l
),min(t
,a
.t
), max(r
,a
.r
),max(b
,a
.b
));
36 CkRect
getIntersect(const CkRect
&a
) {
37 return CkRect(max(l
,a
.l
),max(t
,a
.t
), min(r
,a
.r
),min(b
,a
.b
));
39 CkRect
getShift(int dx
,int dy
) {
40 return CkRect(l
+dx
,t
+dy
,r
+dx
,b
+dy
);
42 CmiBool
isEmpty(void) const {return (CmiBool
)((l
>=r
) || (t
>=b
));}
43 CmiBool
inbounds(int x
,int y
) const {
44 if (x
<l
|| x
>=r
) return CmiFalse
;
45 if (y
<t
|| y
>=b
) return CmiFalse
;
48 void makeEmpty(void) {l
=t
=1000000000; b
=r
=-1000000000;}
49 void empty(void) {makeEmpty();}
50 void add(int x
,int y
) {
51 l
=min(x
,l
); r
=max(x
,r
);
52 t
=min(y
,t
); b
=max(y
,b
);
54 void enlarge(int dx
,int dy
) {
55 l
-=dx
; r
+=dx
; t
-=dy
; b
+=dy
;
57 void zero(void) {l
=r
=t
=b
=0;}
58 int area(void) const {return (r
-l
)*(b
-t
);}
60 void pup(PUP::er
&p
) {
67 This class describes an image, represented as a flat byte array.
68 Pixels are stored first by color (e.g., r,g,b), then by row in the usual
73 //This is the data type of a color channel, such as the red channel.
74 typedef unsigned char channel_t
;
75 /// This is the maximum value of a color channel
76 enum {channel_max
=255};
78 /// This describes the various data layouts used by image pixels:
81 The default layout: ARGB.
82 With one color, pure luminance.
83 With 3 colors, [0]=R, [1]=G, [2]=B.
84 With 4 colors, [0]=A, [1]=R, [2]=G, [3]=B.
88 The "reversed" layout: BGRA.
89 With one color, pure luminance.
90 With 3 colors, [0]=B, [1]=G, [2]=R.
91 With 4 colors, [0]=B, [1]=G, [2]=R, [3]=A.
96 int row
,colors
; ///< channel_ts per line, channel_ts per pixel
97 int layout
; ///< Image pixel format.
98 int wid
,ht
; ///< Image size: cols and rows
99 channel_t
*data
; ///< Image pixel data
101 CkImage(const CkImage
&im
) ; ///< DO NOT USE
102 void operator=(const CkImage
&im
);
104 CkImage() {row
=colors
=wid
=ht
=-1; setLayout(layout_default
); data
=NULL
;}
105 CkImage(int w_
,int h_
,int colors_
,channel_t
*data_
)
106 :row(w_
*colors_
), colors(colors_
),
107 wid(w_
), ht(h_
), data(data_
) { setLayout(layout_default
); }
109 /// Get/set the whole image's data
110 channel_t
*getData(void) {return data
;}
111 void setData(channel_t
*d
) {data
=d
;}
113 CkRect
getRect(void) const {return CkRect(0,0,wid
,ht
);}
114 /// Return the number of channel_t's per row of the image
115 int getRow(void) const {return row
;}
116 /// Return the number of colors (channel_t's) per pixel
117 int getColors(void) const {return colors
;}
119 /// Get/set the pixel format.
120 layout_t
getLayout(void) const {return (layout_t
)layout
;}
121 void setLayout(layout_t a
) {layout
=(layout_t
)a
;}
123 /// Return the number of pixels per row of the image
124 int getWidth(void) const {return wid
;}
125 /// Return the number of pixels per column of the image
126 int getHeight(void) const {return ht
;}
128 //Copy the pixel at src onto the one at dest
129 inline void copyPixel(const channel_t
*src
,channel_t
*dest
) {
130 for (int i
=0;i
<colors
;i
++)
133 //Set this pixel to this value
134 inline void setPixel(const channel_t src
,channel_t
*dest
) {
135 for (int i
=0;i
<colors
;i
++)
138 //Add the pixel at src to the one at dest, ignoring overflow
139 inline void addPixel(const channel_t
*src
,channel_t
*dest
) {
140 for (int i
=0;i
<colors
;i
++)
143 //Add the pixel at src to the one at dest, clipping instead of overflowing
144 inline void addPixelClip(const channel_t
*src
,channel_t
*dest
,
145 const channel_t
*clip
)
147 for (int i
=0;i
<colors
;i
++)
148 dest
[i
]=clip
[(int)dest
[i
]+(int)src
[i
]];
153 inline channel_t
*getPixel(int x
,int y
) {return data
+x
*colors
+y
*row
;}
154 inline const channel_t
*getPixel(int x
,int y
) const {return data
+x
*colors
+y
*row
;}
158 Clip out this subregion of this image-- make us a subregion
160 void window(const CkRect
&src
) {
161 data
+=src
.t
*row
+src
.l
*colors
;
162 wid
=src
.wid(); ht
=src
.ht();
166 Zero out this image-- make it all black.
171 Copy all of src onto this image starting at (x,y).
173 void put(int sx
,int sy
,const CkImage
&src
);
176 Add all of src onto this image starting at (x,y).
178 void add(int sx
,int sy
,const CkImage
&src
);
180 Add all of src onto this image starting at (x,y), clipping
181 values instead of overflowing.
183 void addClip(int sx
,int sy
,const CkImage
&src
,const channel_t
*clip
);
185 //Allocate clipping array for above routine
186 static channel_t
*newClip(void);
188 //Pup only the image *size*, not the image *data*.
189 void pup(PUP::er
&p
) {
190 p
|wid
; p
|ht
; p
|colors
; p
|layout
; p
|row
;
196 //A heap-allocated image
197 class CkAllocImage
: public CkImage
{
198 channel_t
*allocData
;
200 CkAllocImage() {allocData
=NULL
;}
201 CkAllocImage(int w
,int h
,int c
)
202 :CkImage(w
,h
,c
,new channel_t
[w
*h
*c
])
206 ~CkAllocImage() {delete[] allocData
;}
208 // Allocate the image with its current size.
209 void allocate(void) {
210 int len
=getRect().area()*getColors();
211 allocData
=new channel_t
[len
];
215 // Deallocate the image data (does not change size).
216 void deallocate(void) {
217 delete[] allocData
; allocData
=0;
221 //Pup both image size as well as image data.
222 void pup(PUP::er
&p
);
224 PUPmarshall(CkAllocImage
)