static inline void zero_ (ImageBuf &buf) { int chans = buf.nchannels(); for (ImageBuf::Iterator<T> pixel (buf); pixel.valid(); ++pixel) for (int i = 0; i < chans; ++i) pixel[i] = 0; }
static inline void setpixel_ (ImageBuf &buf, int x, int y, int z, const float *data, int chans) { ImageBuf::Iterator<T> pixel (buf, x, y, z); if (pixel.valid()) { for (int i = 0; i < chans; ++i) pixel[i] = data[i]; } }
static inline void transfer_pixels_ (ImageBuf &buf, ColorTransfer *tfunc) { for (ImageBuf::Iterator<T> pixel (buf); pixel.valid(); ++pixel) { convert_types (buf.spec().format, pixel.rawptr(), buf.spec().format, pixel.rawptr(), buf.nchannels(), tfunc, buf.spec().alpha_channel, buf.spec().z_channel); } }
// Tests ImageBufAlgo::compare void test_compare () { std::cout << "test compare\n"; // Construct two identical 50% grey images const int WIDTH = 10, HEIGHT = 10, CHANNELS = 3; ImageSpec spec (WIDTH, HEIGHT, CHANNELS, TypeDesc::FLOAT); ImageBuf A (spec); ImageBuf B (spec); const float grey[CHANNELS] = { 0.5, 0.5, 0.5 }; ImageBufAlgo::fill (A, grey); ImageBufAlgo::fill (B, grey); // Introduce some minor differences const int NDIFFS = 10; ImageBuf::Iterator<float> a (A); for (int i = 0; i < NDIFFS && a.valid(); ++i, ++a) { for (int c = 0; c < CHANNELS; ++c) a[c] = a[c] + 0.01f * i; } // We expect the differences to be { 0, 0.01, 0.02, 0.03, 0.04, 0.05, // 0.06, 0.07, 0.08, 0.09, 0, 0, ...}. const float failthresh = 0.05; const float warnthresh = 0.025; ImageBufAlgo::CompareResults comp; ImageBufAlgo::compare (A, B, failthresh, warnthresh, comp); // We expect 5 pixels to exceed the fail threshold, 7 pixels to // exceed the warn threshold, the maximum difference to be 0.09, // and the maximally different pixel to be (9,0). // The total error should be 3 chans * sum{0.01,...,0.09} / (pixels*chans) // = 3 * 0.45 / (100*3) = 0.0045 std::cout << "Testing comparison: " << comp.nfail << " failed, " << comp.nwarn << " warned, max diff = " << comp.maxerror << " @ (" << comp.maxx << ',' << comp.maxy << ")\n"; std::cout << " mean err " << comp.meanerror << ", RMS err " << comp.rms_error << ", PSNR = " << comp.PSNR << "\n"; OIIO_CHECK_EQUAL (comp.nfail, 5); OIIO_CHECK_EQUAL (comp.nwarn, 7); OIIO_CHECK_EQUAL_THRESH (comp.maxerror, 0.09, 1e-6); OIIO_CHECK_EQUAL (comp.maxx, 9); OIIO_CHECK_EQUAL (comp.maxy, 0); OIIO_CHECK_EQUAL_THRESH (comp.meanerror, 0.0045, 1.0e-8); }
// DEPRECATED version bool ImageBufAlgo::add (ImageBuf &dst, const ImageBuf &A, const ImageBuf &B, int options) { // Sanity checks // dst must be distinct from A and B if ((const void *)&A == (const void *)&dst || (const void *)&B == (const void *)&dst) { dst.error ("destination image must be distinct from source"); return false; } // all three images must have the same number of channels if (A.spec().nchannels != B.spec().nchannels) { dst.error ("channel number mismatch: %d vs. %d", A.spec().nchannels, B.spec().nchannels); return false; } // If dst has not already been allocated, set it to the right size, // make it unconditinally float if (! dst.pixels_valid()) { ImageSpec dstspec = A.spec(); dstspec.set_format (TypeDesc::TypeFloat); dst.alloc (dstspec); } // Clear dst pixels if instructed to do so if (options & ADD_CLEAR_DST) { zero (dst); } ASSERT (A.spec().format == TypeDesc::FLOAT && B.spec().format == TypeDesc::FLOAT && dst.spec().format == TypeDesc::FLOAT); ImageBuf::ConstIterator<float,float> a (A); ImageBuf::ConstIterator<float,float> b (B); ImageBuf::Iterator<float> d (dst); int nchannels = A.nchannels(); // Loop over all pixels in A for ( ; a.valid(); ++a) { // Point the iterators for B and dst to the corresponding pixel if (options & ADD_RETAIN_WINDOWS) { b.pos (a.x(), a.y()); } else { // ADD_ALIGN_WINDOWS: make B line up with A b.pos (a.x()-A.xbegin()+B.xbegin(), a.y()-A.ybegin()+B.ybegin()); } d.pos (a.x(), b.y()); if (! b.valid() || ! d.valid()) continue; // Skip pixels that don't align // Add the pixel for (int c = 0; c < nchannels; ++c) d[c] = a[c] + b[c]; } return true; }