1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright (c) Contributors to the OpenEXR Project.
4 //
5
6 #ifdef NDEBUG
7 # undef NDEBUG
8 #endif
9
10 #include "compareB44.h"
11 #include "compareDwa.h"
12
13 #include <ImfTiledRgbaFile.h>
14 #include <ImfTiledOutputFile.h>
15 #include <ImfChannelList.h>
16 #include <ImfArray.h>
17 #include <ImfFrameBuffer.h>
18 #include <ImfHeader.h>
19 #include <ImfThreading.h>
20 #include <IlmThread.h>
21 #include <ImathRandom.h>
22 #include <string>
23 #include <stdio.h>
24 #include <assert.h>
25 #include <vector>
26 #include <math.h>
27 #include <algorithm>
28
29
30 using namespace OPENEXR_IMF_NAMESPACE;
31 using namespace std;
32 using namespace IMATH_NAMESPACE;
33
34
35 namespace {
36
37 void
fillPixels(Array2D<Rgba> & pixels,int w,int h)38 fillPixels (Array2D<Rgba> &pixels, int w, int h)
39 {
40 for (int y = 0; y < h; ++y)
41 {
42 for (int x = 0; x < w; ++x)
43 {
44 Rgba &p = pixels[y][x];
45
46 p.r = 0.5 + 0.5 * sin (0.1 * x + 0.1 * y);
47 p.g = 0.5 + 0.5 * sin (0.1 * x + 0.2 * y);
48 p.b = 0.5 + 0.5 * sin (0.1 * x + 0.3 * y);
49 p.a = (p.r + p.b + p.g) / 3.0;
50 }
51 }
52 }
53
54
55 void
writeReadRGBAONE(const char fileName[],int width,int height,RgbaChannels channels,Compression comp,int xSize,int ySize)56 writeReadRGBAONE (const char fileName[],
57 int width,
58 int height,
59 RgbaChannels channels,
60 Compression comp,
61 int xSize, int ySize)
62 {
63 cout << "levelMode 0" <<
64 ", compression " << comp <<
65 ", tileSize " << xSize << "x" << ySize << endl;
66
67 Header header (width, height);
68 header.lineOrder() = INCREASING_Y;
69 header.compression() = comp;
70
71 Array2D<Rgba> p1 (height, width);
72
73 {
74 cout << " writing" << flush;
75
76 remove (fileName);
77 TiledRgbaOutputFile out (fileName, header, channels,
78 xSize, ySize, ONE_LEVEL);
79
80 fillPixels (p1, width, height);
81 out.setFrameBuffer (&p1[0][0], 1, width);
82 out.writeTiles (0, out.numXTiles() - 1, 0, out.numYTiles() - 1);
83 }
84
85 {
86 cout << " reading" << flush;
87
88 TiledRgbaInputFile in (fileName);
89 const Box2i &dw = in.dataWindow();
90
91 int w = dw.max.x - dw.min.x + 1;
92 int h = dw.max.y - dw.min.y + 1;
93 int dwx = dw.min.x;
94 int dwy = dw.min.y;
95
96 Array2D<Rgba> p2 (h, w);
97 in.setFrameBuffer (&p2[-dwy][-dwx], 1, w);
98 in.readTiles (0, in.numXTiles() - 1, 0, in.numYTiles() - 1);
99
100 cout << " comparing" << endl << flush;
101
102 assert (in.displayWindow() == header.displayWindow());
103 assert (in.dataWindow() == header.dataWindow());
104 assert (in.pixelAspectRatio() == header.pixelAspectRatio());
105 assert (in.screenWindowCenter() == header.screenWindowCenter());
106 assert (in.screenWindowWidth() == header.screenWindowWidth());
107 assert (in.lineOrder() == header.lineOrder());
108 assert (in.compression() == header.compression());
109 assert (in.channels() == channels);
110
111 if (comp == B44_COMPRESSION ||
112 comp == B44A_COMPRESSION ||
113 comp == DWAA_COMPRESSION ||
114 comp == DWAB_COMPRESSION)
115 {
116 for (int y = 0; y < h; y += ySize)
117 {
118 for (int x = 0; x < w; x += xSize)
119 {
120 int nx = min (w - x, xSize);
121 int ny = min (h - y, ySize);
122
123 Array2D<Rgba> p3 (ny, nx);
124 Array2D<Rgba> p4 (ny, nx);
125
126 for (int y1 = 0; y1 < ny; ++y1)
127 {
128 for (int x1 = 0; x1 < nx; ++x1)
129 {
130 p3[y1][x1] = p1[y + y1][x + x1];
131 p4[y1][x1] = p2[y + y1][x + x1];
132 }
133 }
134
135 if (comp == B44_COMPRESSION ||
136 comp == B44A_COMPRESSION)
137 {
138 compareB44 (nx, ny, p3, p4, channels);
139 }
140 else if (comp == DWAA_COMPRESSION ||
141 comp == DWAB_COMPRESSION)
142 {
143 compareDwa (nx, ny, p3, p4, channels);
144 }
145 }
146 }
147 }
148 else
149 {
150 for (int y = 0; y < h; ++y)
151 {
152 for (int x = 0; x < w; ++x)
153 {
154 if (channels & WRITE_R)
155 assert (p2[y][x].r == p1[y][x].r);
156 else
157 assert (p2[y][x].r == 0);
158
159 if (channels & WRITE_G)
160 assert (p2[y][x].g == p1[y][x].g);
161 else
162 assert (p2[y][x].g == 0);
163
164 if (channels & WRITE_B)
165 assert (p2[y][x].b == p1[y][x].b);
166 else
167 assert (p2[y][x].b == 0);
168
169 if (channels & WRITE_A)
170 assert (p2[y][x].a == p1[y][x].a);
171 else
172 assert (p2[y][x].a == 1);
173 }
174 }
175 }
176 }
177
178 remove (fileName);
179 }
180
181
182 void
writeReadRGBAMIP(const char fileName[],int width,int height,RgbaChannels channels,Compression comp,int xSize,int ySize)183 writeReadRGBAMIP (const char fileName[],
184 int width,
185 int height,
186 RgbaChannels channels,
187 Compression comp,
188 int xSize, int ySize)
189 {
190 cout << "levelMode 1" <<
191 ", compression " << comp <<
192 ", tileSize " << xSize << "x" << ySize << endl;
193
194 Header header (width, height);
195 header.lineOrder() = INCREASING_Y;
196 header.compression() = comp;
197
198 Array < Array2D<Rgba> > levels;
199
200 {
201 cout << " writing" << flush;
202
203 remove (fileName);
204 TiledRgbaOutputFile out (fileName, header, channels,
205 xSize, ySize, MIPMAP_LEVELS, ROUND_DOWN);
206
207 int numLevels = out.numLevels();
208 levels.resizeErase (numLevels);
209
210 for (int level = 0; level < out.numLevels(); ++level)
211 {
212 int levelWidth = out.levelWidth(level);
213 int levelHeight = out.levelHeight(level);
214 levels[level].resizeErase(levelHeight, levelWidth);
215 fillPixels (levels[level], levelWidth, levelHeight);
216
217 out.setFrameBuffer (&(levels[level])[0][0], 1, levelWidth);
218 out.writeTiles (0, out.numXTiles(level) - 1,
219 0, out.numYTiles(level) - 1, level);
220 }
221 }
222
223 {
224 cout << " reading" << flush;
225
226 TiledRgbaInputFile in (fileName);
227 const Box2i &dw = in.dataWindow();
228 int dwx = dw.min.x;
229 int dwy = dw.min.y;
230
231 int numLevels = in.numLevels();
232 Array < Array2D<Rgba> > levels2 (numLevels);
233
234 for (int level = 0; level < numLevels; ++level)
235 {
236 int levelWidth = in.levelWidth(level);
237 int levelHeight = in.levelHeight(level);
238 levels2[level].resizeErase(levelHeight, levelWidth);
239
240 in.setFrameBuffer (&(levels2[level])[-dwy][-dwx], 1, levelWidth);
241 in.readTiles (0, in.numXTiles(level) - 1,
242 0, in.numYTiles(level) - 1, level);
243 }
244
245 cout << " comparing" << endl << flush;
246
247 assert (in.displayWindow() == header.displayWindow());
248 assert (in.dataWindow() == header.dataWindow());
249 assert (in.pixelAspectRatio() == header.pixelAspectRatio());
250 assert (in.screenWindowCenter() == header.screenWindowCenter());
251 assert (in.screenWindowWidth() == header.screenWindowWidth());
252 assert (in.lineOrder() == header.lineOrder());
253 assert (in.compression() == header.compression());
254 assert (in.channels() == channels);
255
256 for (int l = 0; l < numLevels; ++l)
257 {
258 for (int y = 0; y < in.levelHeight(l); ++y)
259 {
260 for (int x = 0; x < in.levelWidth(l); ++x)
261 {
262 if (channels & WRITE_R)
263 assert ((levels2[l])[y][x].r == (levels[l])[y][x].r);
264 else
265 assert ((levels2[l])[y][x].r == 0);
266
267 if (channels & WRITE_G)
268 assert ((levels2[l])[y][x].g == (levels[l])[y][x].g);
269 else
270 assert ((levels2[l])[y][x].g == 0);
271
272 if (channels & WRITE_B)
273 assert ((levels2[l])[y][x].b == (levels[l])[y][x].b);
274 else
275 assert ((levels2[l])[y][x].b == 0);
276
277 if (channels & WRITE_A)
278 assert ((levels2[l])[y][x].a == (levels[l])[y][x].a);
279 else
280 assert ((levels2[l])[y][x].a == 1);
281 }
282 }
283 }
284 }
285
286 remove (fileName);
287 }
288
289
290 void
writeReadRGBARIP(const char fileName[],int width,int height,RgbaChannels channels,Compression comp,int xSize,int ySize)291 writeReadRGBARIP (const char fileName[],
292 int width,
293 int height,
294 RgbaChannels channels,
295 Compression comp,
296 int xSize, int ySize)
297 {
298 cout << "levelMode 2" <<
299 ", compression " << comp <<
300 ", tileSize " << xSize << "x" << ySize << endl;
301
302 Header header (width, height);
303 header.lineOrder() = INCREASING_Y;
304 header.compression() = comp;
305
306 Array2D < Array2D<Rgba> > levels;
307
308 {
309 cout << " writing" << flush;
310
311 remove (fileName);
312 TiledRgbaOutputFile out (fileName, header, channels,
313 xSize, ySize, RIPMAP_LEVELS, ROUND_UP);
314
315 levels.resizeErase (out.numYLevels(), out.numXLevels());
316
317 for (int ylevel = 0; ylevel < out.numYLevels(); ++ylevel)
318 {
319 for (int xlevel = 0; xlevel < out.numXLevels(); ++xlevel)
320 {
321 int levelWidth = out.levelWidth(xlevel);
322 int levelHeight = out.levelHeight(ylevel);
323 levels[ylevel][xlevel].resizeErase(levelHeight, levelWidth);
324 fillPixels (levels[ylevel][xlevel], levelWidth, levelHeight);
325
326 out.setFrameBuffer (&(levels[ylevel][xlevel])[0][0], 1,
327 levelWidth);
328 out.writeTiles (0, out.numXTiles(xlevel) - 1,
329 0, out.numYTiles(ylevel) - 1, xlevel, ylevel);
330 }
331 }
332 }
333
334 {
335 cout << " reading" << flush;
336
337 TiledRgbaInputFile in (fileName);
338 const Box2i &dw = in.dataWindow();
339 int dwx = dw.min.x;
340 int dwy = dw.min.y;
341
342 int numXLevels = in.numXLevels();
343 int numYLevels = in.numYLevels();
344 Array2D < Array2D<Rgba> > levels2 (numYLevels, numXLevels);
345
346 for (int ylevel = 0; ylevel < numYLevels; ++ylevel)
347 {
348 for (int xlevel = 0; xlevel < numXLevels; ++xlevel)
349 {
350 int levelWidth = in.levelWidth(xlevel);
351 int levelHeight = in.levelHeight(ylevel);
352 levels2[ylevel][xlevel].resizeErase(levelHeight, levelWidth);
353 in.setFrameBuffer (&(levels2[ylevel][xlevel])[-dwy][-dwx], 1,
354 levelWidth);
355
356 in.readTiles (0, in.numXTiles(xlevel) - 1,
357 0, in.numYTiles(ylevel) - 1, xlevel, ylevel);
358 }
359 }
360
361 cout << " comparing" << endl << flush;
362
363 assert (in.displayWindow() == header.displayWindow());
364 assert (in.dataWindow() == header.dataWindow());
365 assert (in.pixelAspectRatio() == header.pixelAspectRatio());
366 assert (in.screenWindowCenter() == header.screenWindowCenter());
367 assert (in.screenWindowWidth() == header.screenWindowWidth());
368 assert (in.lineOrder() == header.lineOrder());
369 assert (in.compression() == header.compression());
370 assert (in.channels() == channels);
371
372 for (int ly = 0; ly < numYLevels; ++ly)
373 {
374 for (int lx = 0; lx < numXLevels; ++lx)
375 {
376 for (int y = 0; y < in.levelHeight(ly); ++y)
377 {
378 for (int x = 0; x < in.levelWidth(lx); ++x)
379 {
380 if (channels & WRITE_R)
381 assert ((levels2[ly][lx])[y][x].r ==
382 (levels[ly][lx])[y][x].r);
383 else
384 assert ((levels2[ly][lx])[y][x].r == 0);
385
386 if (channels & WRITE_G)
387 assert ((levels2[ly][lx])[y][x].g ==
388 (levels[ly][lx])[y][x].g);
389 else
390 assert ((levels2[ly][lx])[y][x].g == 0);
391
392 if (channels & WRITE_B)
393 assert ((levels2[ly][lx])[y][x].b ==
394 (levels[ly][lx])[y][x].b);
395 else
396 assert ((levels2[ly][lx])[y][x].b == 0);
397
398 if (channels & WRITE_A)
399 assert ((levels2[ly][lx])[y][x].a ==
400 (levels[ly][lx])[y][x].a);
401 else
402 assert ((levels2[ly][lx])[y][x].a == 1);
403 }
404 }
405 }
406 }
407 }
408
409 remove (fileName);
410 }
411
412
413 void
writeRead(const std::string & tempDir,int W,int H,Compression comp,int xSize,int ySize)414 writeRead (const std::string &tempDir,
415 int W,
416 int H,
417 Compression comp,
418 int xSize,
419 int ySize)
420 {
421 std::string filename = tempDir + "imf_test_tiled_rgba.exr";
422
423 writeReadRGBAONE (filename.c_str(), W, H, WRITE_RGBA, comp, xSize, ySize);
424
425 if (comp != B44_COMPRESSION &&
426 comp != B44A_COMPRESSION &&
427 comp != DWAA_COMPRESSION &&
428 comp != DWAB_COMPRESSION)
429 {
430 //
431 // Skip mipmaps and ripmaps with B44 or DWA compression; writing
432 // an image with a single resolution level, above, should be enough
433 // to verify that B44 and DWA compression work with tiled files.
434 //
435
436 writeReadRGBAMIP
437 (filename.c_str(), W, H, WRITE_RGBA, comp, xSize, ySize);
438
439 writeReadRGBARIP
440 (filename.c_str(), W, H, WRITE_RGBA, comp, xSize, ySize);
441 }
442 }
443
444
445 void
writeReadIncomplete(const std::string & tempDir)446 writeReadIncomplete (const std::string &tempDir)
447 {
448 cout << "\nfile with missing and broken tiles" << endl;
449
450 std::string fileName = tempDir + "imf_test_tiled_incomplete.exr";
451
452 //
453 // Write a file where every other tile is missing or broken.
454 // Then try read the file and verify that all existing good
455 // tiles can actually be read.
456 //
457
458 const int width = 400;
459 const int height = 300;
460 const int tileXSize = 30;
461 const int tileYSize = 40;
462
463 Array2D<Rgba> p1 (height, width);
464
465 for (int y = 0; y < height; ++y)
466 for (int x = 0; x < width; ++x)
467 p1[y][x] = Rgba (x % 5, x % 17, y % 23, y % 29);
468
469 {
470 cout << "writing" << endl;
471
472 remove (fileName.c_str());
473
474 Header header (width, height);
475 header.lineOrder() = RANDOM_Y;
476
477 TiledRgbaOutputFile out (fileName.c_str(), header, WRITE_RGBA,
478 tileXSize, tileYSize, ONE_LEVEL);
479
480 out.setFrameBuffer (&p1[0][0], 1, width);
481
482 out.writeTile (0, 0);
483
484 for (int tileY = 0; tileY < out.numYTiles(); ++tileY)
485 for (int tileX = 0; tileX < out.numXTiles(); ++tileX)
486 if ((tileX + tileY) & 1)
487 out.writeTile (tileX, tileY);
488
489 out.writeTile (2, 0);
490
491 out.breakTile (0, 0, 0, 0, 25, 10, 0xff); // destroy tiles
492 out.breakTile (2, 0, 0, 0, 25, 10, 0xff); // (0,0) and (2,0)
493 }
494
495 {
496 Array2D<Rgba> p2 (height, width);
497
498 for (int y = 0; y < height; ++y)
499 for (int x = 0; x < width; ++x)
500 p2[y][x] = Rgba (-1, -1, -1, -1);
501
502 cout << "reading one tile at a time," << flush;
503
504 TiledRgbaInputFile in (fileName.c_str());
505 const Box2i &dw = in.dataWindow();
506
507 assert (dw.max.x - dw.min.x + 1 == width);
508 assert (dw.max.y - dw.min.y + 1 == height);
509 assert (dw.min.x == 0);
510 assert (dw.min.y == 0);
511
512 in.setFrameBuffer (&p2[0][0], 1, width);
513
514 for (int tileY = 0; tileY < in.numYTiles(); ++tileY)
515 {
516 for (int tileX = 0; tileX < in.numXTiles(); ++tileX)
517 {
518 bool tilePresent = true;
519 bool tileBroken = false;
520
521 try
522 {
523 in.readTile (tileX, tileY);
524 }
525 catch (const IEX_NAMESPACE::InputExc &)
526 {
527 tilePresent = false; // tile is missing
528 }
529 catch (const IEX_NAMESPACE::IoExc &)
530 {
531 tileBroken = true; // tile cannot be decoded
532 }
533
534 assert (tileBroken || (tilePresent == ((tileX + tileY) & 1)));
535 }
536 }
537
538 cout << " comparing" << endl << flush;
539
540 for (int y = 0; y < height; ++y)
541 {
542 int tileY = y / tileYSize;
543
544 for (int x = 0; x < width; ++x)
545 {
546 int tileX = x / tileXSize;
547
548 const Rgba &s = p1[y][x];
549 const Rgba &t = p2[y][x];
550
551 if ((tileX + tileY) & 1)
552 {
553 assert (t.r == s.r &&
554 t.g == s.g &&
555 t.b == s.b &&
556 t.a == s.a);
557 }
558 else
559 {
560 assert (t.r == -1 &&
561 t.g == -1 &&
562 t.b == -1 &&
563 t.a == -1);
564 }
565 }
566 }
567 }
568
569 {
570 Array2D<Rgba> p2 (height, width);
571
572 for (int y = 0; y < height; ++y)
573 for (int x = 0; x < width; ++x)
574 p2[y][x] = Rgba (-1, -1, -1, -1);
575
576 cout << "reading multiple tiles at a time," << flush;
577
578 TiledRgbaInputFile in (fileName.c_str());
579 const Box2i &dw = in.dataWindow();
580
581 assert (dw.max.x - dw.min.x + 1 == width);
582 assert (dw.max.y - dw.min.y + 1 == height);
583 assert (dw.min.x == 0);
584 assert (dw.min.y == 0);
585
586 in.setFrameBuffer (&p2[0][0], 1, width);
587
588 for (int tileY = 0; tileY < in.numYTiles(); ++tileY)
589 {
590 bool tilesMissing = false;
591 bool tilesBroken = false;
592
593 try
594 {
595 in.readTiles (0, in.numXTiles() - 1, tileY, tileY);
596 }
597 catch (const IEX_NAMESPACE::InputExc &)
598 {
599 tilesMissing = true;
600 }
601 catch (const IEX_NAMESPACE::IoExc &)
602 {
603 tilesBroken = true;
604 }
605
606 assert (tilesMissing || tilesBroken);
607 }
608
609 cout << " comparing" << endl << flush;
610
611 for (int y = 0; y < height; ++y)
612 {
613 for (int x = 0; x < width; ++x)
614 {
615 const Rgba &s = p1[y][x];
616 const Rgba &t = p2[y][x];
617
618 assert ((t.r == -1 && t.g == -1 && t.b == -1 && t.a == -1) ||
619 (t.r == s.r && t.g == s.g && t.b == s.b && t.a == s.a));
620 }
621 }
622 }
623
624 remove (fileName.c_str());
625 }
626
627
628 void
writeReadLayers(const std::string & tempDir)629 writeReadLayers(const std::string &tempDir)
630 {
631 cout << "\nreading multi-layer file" << endl;
632
633 std::string fileName = tempDir + "imf_test_tiled_multi_layer_rgba.exr";
634
635 const int W = 237;
636 const int H = 119;
637
638 Array2D<half> p1 (H, W);
639 Array2D<half> p2 (H, W);
640
641 for (int y = 0; y < H; ++y)
642 {
643 for (int x = 0; x < W; ++x)
644 {
645 p1[y][x] = half (y % 23 + x % 17);
646 p2[y][x] = half (y % 29 + x % 19);
647 }
648 }
649
650 {
651 Header hdr (W, H);
652 hdr.setTileDescription (TileDescription());
653 hdr.channels().insert ("R", Channel (HALF));
654 hdr.channels().insert ("foo.R", Channel (HALF));
655
656 FrameBuffer fb;
657
658 fb.insert ("R",
659 Slice (HALF, // type
660 (char *) &p1[0][0], // base
661 sizeof (half), // xStride
662 sizeof (half) * W)); // yStride
663
664 fb.insert ("foo.R",
665 Slice (HALF, // type
666 (char *) &p2[0][0], // base
667 sizeof (half), // xStride
668 sizeof (half) * W)); // yStride
669
670 TiledOutputFile out (fileName.c_str(), hdr);
671 out.setFrameBuffer (fb);
672 out.writeTiles (0, out.numXTiles() - 1, 0, out.numYTiles() - 1);
673 }
674
675 {
676 TiledRgbaInputFile in (fileName.c_str(), "");
677
678 Array2D<Rgba> p3 (H, W);
679 in.setFrameBuffer (&p3[0][0], 1, W);
680 in.readTiles (0, in.numXTiles() - 1, 0, in.numYTiles() - 1);
681
682 for (int y = 0; y < H; ++y)
683 {
684 for (int x = 0; x < W; ++x)
685 {
686 assert (p3[y][x].r == p1[y][x]);
687 assert (p3[y][x].g == 0);
688 assert (p3[y][x].b == 0);
689 assert (p3[y][x].a == 1);
690 }
691 }
692 }
693
694 {
695 TiledRgbaInputFile in (fileName.c_str(), "foo");
696
697 Array2D<Rgba> p3 (H, W);
698 in.setFrameBuffer (&p3[0][0], 1, W);
699 in.readTiles (0, in.numXTiles() - 1, 0, in.numYTiles() - 1);
700
701 for (int y = 0; y < H; ++y)
702 {
703 for (int x = 0; x < W; ++x)
704 {
705 assert (p3[y][x].r == p2[y][x]);
706 assert (p3[y][x].g == 0);
707 assert (p3[y][x].b == 0);
708 assert (p3[y][x].a == 1);
709 }
710 }
711 }
712
713 {
714 TiledRgbaInputFile in (fileName.c_str(), "");
715
716 Array2D<Rgba> p3 (H, W);
717
718 in.setFrameBuffer (&p3[0][0], 1, W);
719
720 in.readTiles (0, in.numXTiles() - 1,
721 0, in.numYTiles() / 2 - 1);
722
723 in.setLayerName ("foo");
724
725 in.setFrameBuffer (&p3[0][0], 1, W);
726
727 in.readTiles (0, in.numXTiles() - 1,
728 in.numYTiles() / 2, in.numYTiles() - 1);
729
730 for (int y = 0; y < H; ++y)
731 {
732 for (int x = 0; x < W; ++x)
733 {
734 if (y < static_cast<int>( (in.numYTiles() / 2) * in.tileYSize()))
735 assert (p3[y][x].r == p1[y][x]);
736 else
737 assert (p3[y][x].r == p2[y][x]);
738
739 assert (p3[y][x].g == 0);
740 assert (p3[y][x].b == 0);
741 assert (p3[y][x].a == 1);
742 }
743 }
744 }
745
746 {
747 Header hdr (W, H);
748 hdr.setTileDescription (TileDescription());
749 hdr.channels().insert ("Y", Channel (HALF));
750 hdr.channels().insert ("foo.Y", Channel (HALF));
751
752 FrameBuffer fb;
753
754 fb.insert ("Y",
755 Slice (HALF, // type
756 (char *) &p1[0][0], // base
757 sizeof (half), // xStride
758 sizeof (half) * W)); // yStride
759
760 fb.insert ("foo.Y",
761 Slice (HALF, // type
762 (char *) &p2[0][0], // base
763 sizeof (half), // xStride
764 sizeof (half) * W)); // yStride
765
766 TiledOutputFile out (fileName.c_str(), hdr);
767 out.setFrameBuffer (fb);
768 out.writeTiles (0, out.numXTiles() - 1, 0, out.numYTiles() - 1);
769 }
770
771 {
772 TiledRgbaInputFile in (fileName.c_str(), "");
773
774 Array2D<Rgba> p3 (H, W);
775 in.setFrameBuffer (&p3[0][0], 1, W);
776 in.readTiles (0, in.numXTiles() - 1, 0, in.numYTiles() - 1);
777
778 for (int y = 0; y < H; ++y)
779 {
780 for (int x = 0; x < W; ++x)
781 {
782 assert (p3[y][x].r == p1[y][x]);
783 assert (p3[y][x].g == p1[y][x]);
784 assert (p3[y][x].b == p1[y][x]);
785 assert (p3[y][x].a == 1);
786 }
787 }
788 }
789
790 {
791 TiledRgbaInputFile in (fileName.c_str(), "foo");
792
793 Array2D<Rgba> p3 (H, W);
794 in.setFrameBuffer (&p3[0][0], 1, W);
795 in.readTiles (0, in.numXTiles() - 1, 0, in.numYTiles() - 1);
796
797 for (int y = 0; y < H; ++y)
798 {
799 for (int x = 0; x < W; ++x)
800 {
801 assert (p3[y][x].r == p2[y][x]);
802 assert (p3[y][x].g == p2[y][x]);
803 assert (p3[y][x].b == p2[y][x]);
804 assert (p3[y][x].a == 1);
805 }
806 }
807 }
808
809 {
810 TiledRgbaInputFile in (fileName.c_str(), "");
811
812 Array2D<Rgba> p3 (H, W);
813
814 in.setFrameBuffer (&p3[0][0], 1, W);
815
816 in.readTiles (0, in.numXTiles() - 1,
817 0, in.numYTiles() / 2 - 1);
818
819 in.setLayerName ("foo");
820
821 in.setFrameBuffer (&p3[0][0], 1, W);
822
823 in.readTiles (0, in.numXTiles() - 1,
824 in.numYTiles() / 2, in.numYTiles() - 1);
825
826 for (int y = 0; y < H; ++y)
827 {
828 for (int x = 0; x < W; ++x)
829 {
830 if (y < static_cast<int>((in.numYTiles() / 2) * in.tileYSize()))
831 {
832 assert (p3[y][x].r == p1[y][x]);
833 assert (p3[y][x].g == p1[y][x]);
834 assert (p3[y][x].b == p1[y][x]);
835 }
836 else
837 {
838 assert (p3[y][x].r == p2[y][x]);
839 assert (p3[y][x].g == p2[y][x]);
840 assert (p3[y][x].b == p2[y][x]);
841 }
842
843 assert (p3[y][x].a == 1);
844 }
845 }
846 }
847
848 remove (fileName.c_str());
849 }
850
851 } // namespace
852
853
854 void
testTiledRgba(const std::string & tempDir)855 testTiledRgba (const std::string &tempDir)
856 {
857 try
858 {
859 cout << "Testing the tiled RGBA image interface" << endl;
860
861 int maxThreads = ILMTHREAD_NAMESPACE::supportsThreads()? 3: 0;
862
863 for (int n = 0; n <= maxThreads; ++n)
864 {
865 if (ILMTHREAD_NAMESPACE::supportsThreads())
866 {
867 setGlobalThreadCount (n);
868 cout << "\nnumber of threads: " << globalThreadCount() << endl;
869 }
870
871 const int W[] = { 9, 69, 75, 80 };
872 const int H[] = { 7, 50, 52, 55 };
873
874 for (int i = 0; i < 4; ++i)
875 {
876 cout << "\nImage size = " << W[i] << " x " << H[i] << endl;
877
878 for (int comp = 0; comp < NUM_COMPRESSION_METHODS; ++comp)
879 {
880 //
881 // for tiled files, ZIPS and ZIP are the same thing
882 //
883
884 if (comp == ZIP_COMPRESSION)
885 comp++;
886
887 if (i == 0)
888 {
889 //
890 // for single-pixel tiles, we don't gain anything
891 // by testing multiple image sizes (and singe-pixel
892 // tiles are rather slow anyway)
893 //
894
895 writeRead (tempDir, W[i], H[i], Compression (comp), 1, 1);
896 }
897
898 writeRead (tempDir, W[i], H[i], Compression (comp), 35, 26);
899 writeRead (tempDir, W[i], H[i], Compression (comp), 75, 52);
900 writeRead (tempDir, W[i], H[i], Compression (comp), 264, 129);
901 }
902 }
903
904 writeReadIncomplete (tempDir);
905 }
906
907 writeReadLayers (tempDir);
908
909 cout << "ok\n" << endl;
910 }
911 catch (const std::exception &e)
912 {
913 cerr << "ERROR -- caught exception: " << e.what() << endl;
914 assert (false);
915 }
916 }
917