1 // Copyright 2002, 2003, 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * image.h: Abstract base class for the internal representations of images used
31 #include "exposure/exposure.h"
33 #define IMAGE_BAYER_NONE 0
36 * This constant indicates that some other default value should be filled in.
39 #define IMAGE_BAYER_DEFAULT 0x8
42 * Do not change these values without inspecting
43 * image_bayer_ale_real::r_*_offset().
45 #define IMAGE_BAYER_RGBG 0x4 /* binary 100 */
46 #define IMAGE_BAYER_GBGR 0x5 /* binary 101 */
47 #define IMAGE_BAYER_GRGB 0x6 /* binary 110 */
48 #define IMAGE_BAYER_BGRG 0x7 /* binary 111 */
50 class image
: protected exposure::listener
{
52 static double resident
;
53 unsigned int _dimx
, _dimy
, _depth
;
56 mutable exposure
*_exp
;
59 static void set_resident(double r
) {
63 static double get_resident() {
67 image (unsigned int dimy
, unsigned int dimx
, unsigned int depth
,
68 const char *name
= "anonymous", exposure
*_exp
= NULL
,
69 unsigned int bayer
= IMAGE_BAYER_NONE
) {
76 _offset
= point(0, 0);
82 _exp
->add_listener(this, name
);
85 unsigned int get_bayer() const {
89 virtual char get_channels(int i
, int j
) const {
93 virtual unsigned int bayer_color(unsigned int i
, unsigned int j
) const {
97 double storage_size() const {
98 if (bayer
!= IMAGE_BAYER_NONE
)
99 return _dimx
* _dimy
* sizeof(ale_real
);
101 return 3 * _dimx
* _dimy
* sizeof(ale_real
);
104 exposure
&exp() const {
108 point
offset() const {
112 void set_offset(int i
, int j
) {
117 void set_offset(point p
) {
121 unsigned int width() const {
125 unsigned int height() const {
129 unsigned int depth() const {
133 virtual void set_pixel(unsigned int y
, unsigned int x
, spixel p
) = 0;
135 virtual spixel
get_pixel(unsigned int y
, unsigned int x
) const = 0;
137 virtual spixel
get_raw_pixel(unsigned int y
, unsigned int x
) const {
138 return ((const image
*)this)->get_pixel(y
, x
);
141 virtual void add_pixel(unsigned int y
, unsigned int x
, pixel p
) {
145 virtual void mul_pixel(unsigned int y
, unsigned int x
, pixel p
) {
149 virtual void div_pixel(unsigned int y
, unsigned int x
, pixel p
) {
153 virtual void add_chan(unsigned int y
, unsigned int x
, unsigned int k
, ale_real c
) {
157 virtual void div_chan(unsigned int y
, unsigned int x
, unsigned int k
, ale_real c
) {
161 virtual void set_chan(unsigned int y
, unsigned int x
, unsigned int k
, ale_sreal c
) = 0;
163 virtual ale_sreal
get_chan(unsigned int y
, unsigned int x
, unsigned int k
) const = 0;
165 ale_real
maxval() const {
166 ale_real result
= get_pixel(0, 0)[0];
168 for (unsigned int i
= 0; i
< _dimy
; i
++)
169 for (unsigned int j
= 0; j
< _dimx
; j
++) {
170 pixel p
= get_pixel(i
, j
);
172 for (unsigned int k
= 0; k
< _depth
; k
++)
173 if (p
[k
] > result
|| !finite(result
))
180 ale_real
minval() const {
181 ale_real result
= get_pixel(0, 0)[0];
183 for (unsigned int i
= 0; i
< _dimy
; i
++)
184 for (unsigned int j
= 0; j
< _dimx
; j
++) {
185 pixel p
= get_pixel(i
, j
);
187 for (unsigned int k
= 0; k
< _depth
; k
++)
188 if (p
[k
] < result
|| !finite(result
))
196 * Get the maximum difference among adjacent pixels.
199 pixel
get_max_diff(unsigned int i
, unsigned int j
) const {
200 assert(i
<= _dimy
- 1);
201 assert(j
<= _dimx
- 1);
203 pixel max
= get_pixel(i
, j
), min
= get_pixel(i
, j
);
205 for (int ii
= -1; ii
<= 1; ii
++)
206 for (int jj
= -1; jj
<= 1; jj
++) {
214 if ((unsigned int) iii
> _dimy
- 1)
216 if ((unsigned int) jjj
> _dimx
- 1)
219 pixel p
= get_pixel(iii
, jjj
);
221 for (int d
= 0; d
< 3; d
++) {
232 pixel
get_max_diff(point x
) const {
235 assert (x
[0] <= _dimy
- 1);
236 assert (x
[1] <= _dimx
- 1);
238 unsigned int i
= (unsigned int) round(x
[0]);
239 unsigned int j
= (unsigned int) round(x
[1]);
241 return get_max_diff(i
, j
);
244 int in_bounds(point x
) const {
247 || x
[0] > height() - 1
248 || x
[1] > width() - 1)
256 * Get a color value at a given position using bilinear interpolation between the
257 * four nearest pixels.
259 pixel
get_bl(point x
, int defined
= 0) const {
260 // fprintf(stderr, "get_bl x=%f %f\n", (double) x[0], (double) x[1]);
266 assert (x
[0] <= _dimy
- 1);
267 assert (x
[1] <= _dimx
- 1);
269 int lx
= (int) floor(x
[1]);
270 int hx
= (int) floor(x
[1]) + 1;
271 int ly
= (int) floor(x
[0]);
272 int hy
= (int) floor(x
[0]) + 1;
274 // fprintf(stderr, "get_bl l=%d %d h=%d %d\n", ly, lx, hy, hx);
279 neighbor
[0] = get_pixel(ly
, lx
);
280 neighbor
[1] = get_pixel(hy
% _dimy
, lx
);
281 neighbor
[2] = get_pixel(hy
% _dimy
, hx
% _dimx
);
282 neighbor
[3] = get_pixel(ly
, hx
% _dimx
);
284 // for (int d = 0; d < 4; d++)
285 // fprintf(stderr, "neighbor_%d=%f %f %f\n", d,
286 // (double) neighbor[d][0],
287 // (double) neighbor[d][1],
288 // (double) neighbor[d][2]);
290 factor
[0] = (ale_real
) (hx
- x
[1]) * (ale_real
) (hy
- x
[0]);
291 factor
[1] = (ale_real
) (hx
- x
[1]) * (ale_real
) (x
[0] - ly
);
292 factor
[2] = (ale_real
) (x
[1] - lx
) * (ale_real
) (x
[0] - ly
);
293 factor
[3] = (ale_real
) (x
[1] - lx
) * (ale_real
) (hy
- x
[0]);
295 // for (int d = 0; d < 4; d++)
296 // fprintf(stderr, "factor_%d=%f\n", d,
297 // (double) factor[d]);
300 * Use bilinear and/or geometric interpolation
304 result
= pixel(0, 0, 0);
306 for (int n
= 0; n
< 4; n
++)
307 result
+= factor
[n
] * neighbor
[n
];
311 * Calculating the geometric mean may be expensive on
312 * some platforms (e.g., those without floating-point
316 result
= pixel(1, 1, 1);
318 for (int n
= 0; n
< 4; n
++)
319 result
*= ppow(neighbor
[n
], factor
[n
]);
322 * Taking the minimum value may be cheaper than
323 * calculating a geometric mean.
326 result
= neighbor
[0];
328 for (int n
= 1; n
< 4; n
++)
329 for (int k
= 0; k
< 3; k
++)
330 if (neighbor
[n
][k
] < result
[k
])
331 result
[k
] = neighbor
[n
][k
];
335 // fprintf(stderr, "result=%f %f %f\n",
336 // (double) result[0],
337 // (double) result[1],
338 // (double) result[2]);
343 pixel
get_scaled_bl(point x
, ale_pos f
, int defined
= 0) const {
345 x
[0]/f
<= height() - 1
347 : (ale_pos
) (height() - 1),
348 x
[1]/f
<= width() - 1
350 : (ale_pos
) (width() - 1));
352 return get_bl(scaled
, defined
);
357 * Make a new image suitable for receiving scaled values.
359 virtual image
*scale_generator(int height
, int width
, int depth
, const char *name
) const = 0;
362 * Generate an image of medians within a given radius
365 image
*medians(int radius
) const {
367 assert (radius
>= 0);
369 image
*is
= scale_generator(height(), width(), depth(), "median");
372 for (unsigned int i
= 0; i
< height(); i
++)
373 for (unsigned int j
= 0; j
< width(); j
++) {
375 std::vector
<ale_real
> p
[3];
377 for (int ii
= -radius
; ii
<= radius
; ii
++)
378 for (int jj
= -radius
; jj
<= radius
; jj
++) {
382 if (in_bounds(point(iii
, jjj
)))
383 for (int k
= 0; k
< 3; k
++)
384 if (finite(get_pixel(iii
, jjj
)[k
]))
385 p
[k
].push_back(get_pixel(iii
, jjj
)[k
]);
388 is
->set_pixel(i
, j
, d2::pixel::undefined());
390 for (int k
= 0; k
< 3; k
++) {
391 std::sort(p
[k
].begin(), p
[k
].end());
393 unsigned int pkc
= p
[k
].size();
399 is
->set_chan(i
, j
, k
,
400 (p
[k
][pkc
/ 2] + p
[k
][pkc
/ 2 - 1]) / 2);
402 is
->set_chan(i
, j
, k
,
411 * Generate an image of differences of the first channel. The first
412 * coordinate differences are stored in the first channel, second in the
416 image
*fcdiffs() const {
417 image
*is
= scale_generator(height(), width(), depth(), "diff");
421 for (unsigned int i
= 0; i
< height(); i
++)
422 for (unsigned int j
= 0; j
< width(); j
++) {
426 && !finite(get_chan(i
, j
, 0))) {
428 is
->set_chan(i
, j
, 0, (get_chan(i
+ 1, j
, 0)
429 - get_chan(i
- 1, j
, 0)) / 2);
431 } else if (i
+ 1 < height()
433 && finite(get_chan(i
+ 1, j
, 0))
434 && finite(get_chan(i
- 1, j
, 0))) {
436 is
->set_chan(i
, j
, 0, ((get_chan(i
, j
, 0) - get_chan(i
- 1, j
, 0))
437 + (get_chan(i
+ 1, j
, 0) - get_chan(i
, j
, 0))) / 2);
439 } else if (i
+ 1 < height()
440 && finite(get_chan(i
+ 1, j
, 0))) {
442 is
->set_chan(i
, j
, 0, get_chan(i
+ 1, j
, 0) - get_chan(i
, j
, 0));
445 && finite(get_chan(i
- 1, j
, 0))) {
447 is
->set_chan(i
, j
, 0, get_chan(i
, j
, 0) - get_chan(i
- 1, j
, 0));
450 is
->set_chan(i
, j
, 0, 0);
455 && !finite(get_chan(i
, j
, 0))) {
457 is
->set_chan(i
, j
, 1, (get_chan(i
, j
+ 1, 0) - get_chan(i
, j
- 1, 0)) / 2);
459 } else if (j
+ 1 < width()
461 && finite(get_chan(i
, j
+ 1, 0))
462 && finite(get_chan(i
, j
- 1, 0))) {
464 is
->set_chan(i
, j
, 1, ((get_chan(i
, j
, 0) - get_chan(i
, j
- 1, 0))
465 + (get_chan(i
, j
+ 1, 0) - get_chan(i
, j
, 0))) / 2);
467 } else if (j
+ 1 < width() && finite(get_chan(i
, j
+ 1, 0))) {
469 is
->set_chan(i
, j
, 1, get_chan(i
, j
+ 1, 0) - get_chan(i
, j
, 0));
471 } else if (j
> 0 && finite(get_chan(i
, j
- 1, 0))) {
473 is
->set_chan(i
, j
, 1, get_chan(i
, j
, 0) - get_chan(i
, j
- 1, 0));
476 is
->set_chan(i
, j
, 1, 0);
484 * Generate an image of median (within a given radius) difference of the
488 image
*fcdiff_median(int radius
) const {
489 image
*diff
= fcdiffs();
493 image
*median
= diff
->medians(radius
);
503 * Scale by half. We use the following filter:
509 * At the edges, these values are normalized so that the sum of the
510 * weights of contributing pixels is 1.
512 class scale_by_half_threaded
: public thread::decompose_domain
{
516 void subdomain_algorithm(unsigned int thread
,
517 int i_min
, int i_max
, int j_min
, int j_max
) {
519 ale_real _0625
= (ale_real
) 0.0625;
520 ale_real _125
= (ale_real
) 0.125;
521 ale_real _25
= (ale_real
) 0.25;
522 ale_real _0
= (ale_real
) 0;
524 unsigned int ui_min
= (unsigned int) i_min
;
525 unsigned int ui_max
= (unsigned int) i_max
;
526 unsigned int uj_min
= (unsigned int) j_min
;
527 unsigned int uj_max
= (unsigned int) j_max
;
529 for (unsigned int i
= ui_min
; i
< ui_max
; i
++)
530 for (unsigned int j
= uj_min
; j
< uj_max
; j
++) {
533 ( ( ((i
> 0 && j
> 0)
534 ? iu
->get_pixel(2 * i
- 1, 2 * j
- 1) * _0625
537 ? iu
->get_pixel(2 * i
- 1, 2 * j
) * _125
539 + ((i
> 0 && j
< is
->width() - 1)
540 ? iu
->get_pixel(2 * i
- 1, 2 * j
+ 1) * _0625
543 ? iu
->get_pixel(2 * i
, 2 * j
- 1) * _125
545 + iu
->get_pixel(2 * i
, 2 * j
) * _25
546 + ((j
< is
->width() - 1)
547 ? iu
->get_pixel(2 * i
, 2 * j
+ 1) * _125
549 + ((i
< is
->height() - 1 && j
> 0)
550 ? iu
->get_pixel(2 * i
+ 1, 2 * j
- 1) * _0625
552 + ((i
< is
->height() - 1)
553 ? iu
->get_pixel(2 * i
+ 1, 2 * j
) * _125
555 + ((i
< is
->height() && j
< is
->width() - 1)
556 ? iu
->get_pixel(2 * i
+ 1, 2 * j
+ 1) * _0625
567 + ((i
> 0 && j
< is
->width() - 1)
574 + ((j
< is
->width() - 1)
577 + ((i
< is
->height() - 1 && j
> 0)
580 + ((i
< is
->height() - 1)
583 + ((i
< is
->height() && j
< is
->width() - 1)
590 scale_by_half_threaded(image
*_is
, const image
*_iu
)
591 : decompose_domain(0, _is
->height(),
598 image
*scale_by_half(const char *name
) const {
601 image
*is
= scale_generator(
602 (int) floor(height() * (double) f
),
603 (int) floor(width() * (double) f
), depth(), name
);
607 scale_by_half_threaded
sbht(is
, this);
610 is
->_offset
= point(_offset
[0] * f
, _offset
[1] * f
);
616 * Scale by half. This function uses externally-provided weights,
617 * multiplied by the following filter:
623 * Values are normalized so that the sum of the weights of contributing
626 image
*scale_by_half(const image
*weights
, const char *name
) const {
629 return scale_by_half(name
);
633 image
*is
= scale_generator(
634 (int) floor(height() * (double) f
),
635 (int) floor(width() * (double) f
), depth(), name
);
639 for (unsigned int i
= 0; i
< is
->height(); i
++)
640 for (unsigned int j
= 0; j
< is
->width(); j
++) {
644 ( ( ((i
> 0 && j
> 0)
645 ? (pixel
) get_pixel(2 * i
- 1, 2 * j
- 1)
646 * (pixel
) weights
->get_pixel(2 * i
- 1, 2 * j
- 1)
650 ? (pixel
) get_pixel(2 * i
- 1, 2 * j
)
651 * (pixel
) weights
->get_pixel(2 * i
- 1, 2 * j
)
654 + ((i
> 0 && j
< is
->width() - 1)
655 ? (pixel
) get_pixel(2 * i
- 1, 2 * j
+ 1)
656 * (pixel
) weights
->get_pixel(2 * i
- 1, 2 * j
+ 1)
660 ? (pixel
) get_pixel(2 * i
, 2 * j
- 1)
661 * (pixel
) weights
->get_pixel(2 * i
, 2 * j
- 1)
664 + get_pixel(2 * i
, 2 * j
)
665 * (pixel
) weights
->get_pixel(2 * i
, 2 * j
)
667 + ((j
< is
->width() - 1)
668 ? (pixel
) get_pixel(2 * i
, 2 * j
+ 1)
669 * (pixel
) weights
->get_pixel(2 * i
, 2 * j
+ 1)
672 + ((i
< is
->height() - 1 && j
> 0)
673 ? (pixel
) get_pixel(2 * i
+ 1, 2 * j
- 1)
674 * (pixel
) weights
->get_pixel(2 * i
+ 1, 2 * j
- 1)
677 + ((i
< is
->height() - 1)
678 ? (pixel
) get_pixel(2 * i
+ 1, 2 * j
)
679 * (pixel
) weights
->get_pixel(2 * i
+ 1, 2 * j
)
682 + ((i
< is
->height() && j
< is
->width() - 1)
683 ? (pixel
) get_pixel(2 * i
+ 1, 2 * j
+ 1)
684 * (pixel
) weights
->get_pixel(2 * i
+ 1, 2 * j
+ 1)
691 ? weights
->get_pixel(2 * i
- 1, 2 * j
- 1)
695 ? weights
->get_pixel(2 * i
- 1, 2 * j
)
698 + ((i
> 0 && j
< is
->width() - 1)
699 ? weights
->get_pixel(2 * i
- 1, 2 * j
+ 1)
703 ? weights
->get_pixel(2 * i
, 2 * j
- 1)
706 + weights
->get_pixel(2 * i
, 2 * j
)
708 + ((j
< is
->width() - 1)
709 ? weights
->get_pixel(2 * i
, 2 * j
+ 1)
712 + ((i
< is
->height() - 1 && j
> 0)
713 ? weights
->get_pixel(2 * i
+ 1, 2 * j
- 1)
716 + ((i
< is
->height() - 1)
717 ? weights
->get_pixel(2 * i
+ 1, 2 * j
)
720 + ((i
< is
->height() && j
< is
->width() - 1)
721 ? weights
->get_pixel(2 * i
+ 1, 2 * j
+ 1)
723 : pixel(0, 0, 0)) ) );
725 for (int k
= 0; k
< 3; k
++)
726 if (!finite(value
[k
]))
729 is
->set_pixel(i
, j
, value
);
732 is
->_offset
= point(_offset
[0] * f
, _offset
[1] * f
);
738 * Scale an image definition array by 1/2.
740 * ALE considers an image definition array as a special kind of image
741 * weight array (typedefs of which should appear below the definition
742 * of this class). ALE uses nonzero pixel values to mean 'defined' and
743 * zero values to mean 'undefined'. Through this interpretation, the
744 * image weight array implementation that ALE uses allows image weight
745 * arrays to also serve as image definition arrays.
747 * Whereas scaling of image weight arrays is not generally obvious in
748 * either purpose or method, ALE requires that image definition arrays
749 * be scalable. (Note that in the special case where weight is treated
750 * as certainty, using a geometric mean is probably correct.)
752 * We currently use a geometric mean to implement scaling of
756 class defined_scale_by_half_threaded
: public thread::decompose_domain
{
760 void subdomain_algorithm(unsigned int thread
,
761 int i_min
, int i_max
, int j_min
, int j_max
) {
764 ale_real _0625
= (ale_real
) 0.0625;
765 ale_real _125
= (ale_real
) 0.125;
766 ale_real _25
= (ale_real
) 0.25;
769 int ui_min
= (int) i_min
;
770 int ui_max
= (int) i_max
;
771 int uj_min
= (int) j_min
;
772 int uj_max
= (int) j_max
;
774 for (int i
= ui_min
; i
< ui_max
; i
++)
775 for (int j
= uj_min
; j
< uj_max
; j
++) {
780 * Calculate a geometric mean; this approach
781 * may be expensive on some platforms (e.g.,
782 * those without floating-point support in
788 ( ( ((i
> 0 && j
> 0)
789 ? ppow(iu
->get_pixel(2 * i
- 1, 2 * j
- 1), _0625
)
792 ? ppow(iu
->get_pixel(2 * i
- 1, 2 * j
), _125
)
794 * ((i
> 0 && j
< is
->width() - 1)
795 ? ppow(iu
->get_pixel(2 * i
- 1, 2 * j
+ 1), _0625
)
798 ? ppow(iu
->get_pixel(2 * i
, 2 * j
- 1), _125
)
800 * ppow(iu
->get_pixel(2 * i
, 2 * j
), _25
)
801 * ((j
< is
->width() - 1)
802 ? ppow(iu
->get_pixel(2 * i
, 2 * j
+ 1), _125
)
804 * ((i
< is
->height() - 1 && j
> 0)
805 ? ppow(iu
->get_pixel(2 * i
+ 1, 2 * j
- 1), _0625
)
807 * ((i
< is
->height() - 1)
808 ? ppow(iu
->get_pixel(2 * i
+ 1, 2 * j
), _125
)
810 * ((i
< is
->height() && j
< is
->width() - 1)
811 ? ppow(iu
->get_pixel(2 * i
+ 1, 2 * j
+ 1), _0625
)
815 pixel value
= iu
->get_pixel(2 * i
, 2 * j
);
817 for (int ii
= 2 * i
- 1; ii
<= 2 * i
+ 1; ii
++)
818 for (int jj
= 2 * j
- 1; jj
<= 2 * j
+ 1; jj
++) {
821 || ii
> (int) iu
->height() - 1
822 || jj
> (int) iu
->height() - 1)
825 pixel value2
= iu
->get_pixel(ii
, jj
);
827 for (int k
= 0; k
< 3; k
++)
828 if (value2
[k
] < value
[k
]
829 || !finite(value2
[k
])) /* propagate non-finites */
830 value
[k
] = value2
[k
];
836 for (int k
= 0; k
< 3; k
++)
837 if (!finite(value
[k
]))
840 is
->set_pixel(i
, j
, value
);
845 defined_scale_by_half_threaded(image
*_is
, const image
*_iu
)
846 : decompose_domain(0, _is
->height(),
853 image
*defined_scale_by_half(const char *name
) const {
856 image
*is
= scale_generator(
857 (int) floor(height() * (double) f
),
858 (int) floor(width() * (double) f
), depth(), name
);
862 defined_scale_by_half_threaded
dsbht(is
, this);
865 is
->_offset
= point(_offset
[0] * f
, _offset
[1] * f
);
871 * Return an image scaled by some factor != 1.0, using bilinear
874 image
*scale(ale_pos f
, const char *name
, int defined
= 0) const {
877 * We probably don't want to scale images by a factor of 1.0,
878 * or by non-positive values.
880 assert (f
!= 1.0 && f
> 0);
883 image
*is
= scale_generator(
884 (int) floor(height() * (double) f
),
885 (int) floor(width() * (double) f
), depth(), name
);
889 unsigned int i
, j
, k
;
891 for (i
= 0; i
< is
->height(); i
++)
892 for (j
= 0; j
< is
->width(); j
++)
893 for (k
= 0; k
< is
->depth(); k
++)
895 get_scaled_bl(point(i
, j
), f
, defined
));
897 is
->_offset
= point(_offset
[0] * f
, _offset
[1] * f
);
900 } else if (f
== 0.5) {
902 return scale_by_half(name
);
904 return defined_scale_by_half(name
);
906 image
*is
= scale(2*f
, name
, defined
);
907 image
*result
= is
->scale(0.5, name
, defined
);
915 * Extend the image area to the top, bottom, left, and right,
916 * initializing the new image areas with black pixels. Negative values
919 virtual image
*_extend(int top
, int bottom
, int left
, int right
) = 0;
921 static void extend(image
**i
, int top
, int bottom
, int left
, int right
) {
922 image
*is
= (*i
)->_extend(top
, bottom
, left
, right
);
933 image
*clone(const char *name
) const {
934 image
*ic
= scale_generator(
935 height(), width(), depth(), name
);
939 for (unsigned int i
= 0; i
< height(); i
++)
940 for (unsigned int j
= 0; j
< width(); j
++)
945 ic
->_offset
= _offset
;