bool
ImageBufAlgo::sub(ImageBuf& dst, Image_or_Const A_, Image_or_Const B_, ROI roi,
                  int nthreads)
{
    pvt::LoggedTimer logtime("IBA::sub");
    if (A_.is_img() && B_.is_img()) {
        const ImageBuf &A(A_.img()), &B(B_.img());
        if (!IBAprep(roi, &dst, &A, &B))
            return false;
        ROI origroi = roi;
        roi.chend = std::min(roi.chend, std::min(A.nchannels(), B.nchannels()));
        bool ok;
        OIIO_DISPATCH_COMMON_TYPES3(ok, "sub", sub_impl, dst.spec().format,
                                    A.spec().format, B.spec().format, dst, A, B,
                                    roi, nthreads);
        if (roi.chend < origroi.chend && A.nchannels() != B.nchannels()) {
            // Edge case: A and B differed in nchannels, we allocated dst to be
            // the bigger of them, but adjusted roi to be the lesser. Now handle
            // the channels that got left out because they were not common to
            // all the inputs.
            ASSERT(roi.chend <= dst.nchannels());
            roi.chbegin = roi.chend;
            roi.chend   = origroi.chend;
            if (A.nchannels() > B.nchannels()) {  // A exists
                copy(dst, A, dst.spec().format, roi, nthreads);
            } else {  // B exists
                copy(dst, B, dst.spec().format, roi, nthreads);
            }
        }
        return ok;
    }
    if (A_.is_val() && B_.is_img())  // canonicalize to A_img, B_val
        A_.swap(B_);
    if (A_.is_img() && B_.is_val()) {
        const ImageBuf& A(A_.img());
        cspan<float> b = B_.val();
        if (!IBAprep(roi, &dst, &A,
                     IBAprep_CLAMP_MUTUAL_NCHANNELS | IBAprep_SUPPORT_DEEP))
            return false;
        IBA_FIX_PERCHAN_LEN_DEF(b, A.nchannels());
        // Negate b (into a copy)
        int nc      = A.nchannels();
        float* vals = ALLOCA(float, nc);
        for (int c = 0; c < nc; ++c)
            vals[c] = -b[c];
        b = cspan<float>(vals, nc);
        if (dst.deep()) {
            // While still serial, set up all the sample counts
            dst.deepdata()->set_all_samples(A.deepdata()->all_samples());
            return add_impl_deep(dst, A, b, roi, nthreads);
        }
        bool ok;
        OIIO_DISPATCH_COMMON_TYPES2(ok, "sub", add_impl, dst.spec().format,
                                    A.spec().format, dst, A, b, roi, nthreads);
        return ok;
    }
    // Remaining cases: error
    dst.error("ImageBufAlgo::sub(): at least one argument must be an image");
    return false;
}
bool
ImageBufAlgo::div(ImageBuf& dst, Image_or_Const A_, Image_or_Const B_, ROI roi,
                  int nthreads)
{
    pvt::LoggedTimer logtime("IBA::div");
    if (A_.is_img() && B_.is_img()) {
        const ImageBuf &A(A_.img()), &B(B_.img());
        if (!IBAprep(roi, &dst, &A, &B, IBAprep_CLAMP_MUTUAL_NCHANNELS))
            return false;
        bool ok;
        OIIO_DISPATCH_COMMON_TYPES3(ok, "div", div_impl, dst.spec().format,
                                    A.spec().format, B.spec().format, dst, A, B,
                                    roi, nthreads);
        return ok;
    }
    if (A_.is_val() && B_.is_img())  // canonicalize to A_img, B_val
        A_.swap(B_);
    if (A_.is_img() && B_.is_val()) {
        const ImageBuf& A(A_.img());
        cspan<float> b = B_.val();
        if (!IBAprep(roi, &dst, &A,
                     IBAprep_CLAMP_MUTUAL_NCHANNELS | IBAprep_SUPPORT_DEEP))
            return false;

        IBA_FIX_PERCHAN_LEN_DEF(b, dst.nchannels());
        int nc      = dst.nchannels();
        float* binv = OIIO_ALLOCA(float, nc);
        for (int c = 0; c < nc; ++c)
            binv[c] = (b[c] == 0.0f) ? 0.0f : 1.0f / b[c];
        b = cspan<float>(binv, nc);  // re-wrap

        if (dst.deep()) {
            // While still serial, set up all the sample counts
            dst.deepdata()->set_all_samples(A.deepdata()->all_samples());
            return mul_impl_deep(dst, A, b, roi, nthreads);
        }
        bool ok;
        OIIO_DISPATCH_COMMON_TYPES2(ok, "div", mul_impl, dst.spec().format,
                                    A.spec().format, dst, A, b, roi, nthreads);
        return ok;
    }
    // Remaining cases: error
    dst.error("ImageBufAlgo::div(): at least one argument must be an image");
    return false;
}
static bool
add_impl_deep(ImageBuf& R, const ImageBuf& A, cspan<float> b, ROI roi,
              int nthreads)
{
    ASSERT(R.deep());
    ImageBufAlgo::parallel_image(roi, nthreads, [&](ROI roi) {
        cspan<TypeDesc> channeltypes(R.deepdata()->all_channeltypes());
        ImageBuf::Iterator<float> r(R, roi);
        ImageBuf::ConstIterator<float> a(A, roi);
        for (; !r.done(); ++r, ++a) {
            for (int samp = 0, samples = r.deep_samples(); samp < samples;
                 ++samp) {
                for (int c = roi.chbegin; c < roi.chend; ++c) {
                    if (channeltypes[c].basetype == TypeDesc::UINT32)
                        r.set_deep_value(c, samp, a.deep_value_uint(c, samp));
                    else
                        r.set_deep_value(c, samp, a.deep_value(c, samp) + b[c]);
                }
            }
        }
    });
    return true;
}
示例#4
0
static void
print_stats (Oiiotool &ot,
             const std::string &filename,
             const ImageSpec &originalspec,
             int subimage=0, int miplevel=0, bool indentmip=false)
{
    const char *indent = indentmip ? "      " : "    ";
    ImageBuf input;
    
    if (! read_input (filename, input, subimage, miplevel)) {
        ot.error ("stats", input.geterror());
        return;
    }
    PixelStats stats;
    if (! computePixelStats (stats, input)) {
        std::string err = input.geterror();
        ot.error ("stats", Strutil::format ("unable to compute: %s",
                                            err.empty() ? "unspecified error" : err.c_str()));
        return;
    }
    
    // The original spec is used, otherwise the bit depth will
    // be reported incorrectly (as FLOAT)
    unsigned int maxval = (unsigned int)get_intsample_maxval (originalspec);
    
    printf ("%sStats Min: ", indent);
    for (unsigned int i=0; i<stats.min.size(); ++i) {
        print_stats_num (stats.min[i], maxval, true);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");
    
    printf ("%sStats Max: ", indent);
    for (unsigned int i=0; i<stats.max.size(); ++i) {
        print_stats_num (stats.max[i], maxval, true);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");
    
    printf ("%sStats Avg: ", indent);
    for (unsigned int i=0; i<stats.avg.size(); ++i) {
        print_stats_num (stats.avg[i], maxval, false);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");
    
    printf ("%sStats StdDev: ", indent);
    for (unsigned int i=0; i<stats.stddev.size(); ++i) {
        print_stats_num (stats.stddev[i], maxval, false);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");
    
    printf ("%sStats NanCount: ", indent);
    for (unsigned int i=0; i<stats.nancount.size(); ++i) {
        printf ("%llu ", (unsigned long long)stats.nancount[i]);
    }
    printf ("\n");
    
    printf ("%sStats InfCount: ", indent);
    for (unsigned int i=0; i<stats.infcount.size(); ++i) {
        printf ("%llu ", (unsigned long long)stats.infcount[i]);
    }
    printf ("\n");
    
    printf ("%sStats FiniteCount: ", indent);
    for (unsigned int i=0; i<stats.finitecount.size(); ++i) {
        printf ("%llu ", (unsigned long long)stats.finitecount[i]);
    }
    printf ("\n");
    
    if (input.deep()) {
        const DeepData *dd (input.deepdata());
        size_t npixels = dd->pixels();
        size_t totalsamples = 0, emptypixels = 0;
        size_t maxsamples = 0, minsamples = std::numeric_limits<size_t>::max();
        size_t maxsamples_npixels = 0;
        float mindepth = std::numeric_limits<float>::max();
        float maxdepth = -std::numeric_limits<float>::max();
        Imath::V3i maxsamples_pixel(-1,-1,-1), minsamples_pixel(-1,-1,-1);
        Imath::V3i mindepth_pixel(-1,-1,-1), maxdepth_pixel(-1,-1,-1);
        Imath::V3i nonfinite_pixel(-1,-1,-1);
        int nonfinite_pixel_samp(-1), nonfinite_pixel_chan(-1);
        size_t sampoffset = 0;
        int nchannels = dd->channels();
        int depthchannel = -1;
        long long nonfinites = 0;
        for (int c = 0; c < nchannels; ++c)
            if (Strutil::iequals (originalspec.channelnames[c], "Z"))
                depthchannel = c;
        int xend = originalspec.x + originalspec.width;
        int yend = originalspec.y + originalspec.height;
        int zend = originalspec.z + originalspec.depth;
        size_t p = 0;
        std::vector<size_t> nsamples_histogram;
        for (int z = originalspec.z; z < zend; ++z) {
            for (int y = originalspec.y; y < yend; ++y) {
                for (int x = originalspec.x; x < xend; ++x, ++p) {
                    size_t samples = input.deep_samples (x, y, z);
                    totalsamples += samples;
                    if (samples == maxsamples)
                        ++maxsamples_npixels;
                    if (samples > maxsamples) {
                        maxsamples = samples;
                        maxsamples_pixel.setValue (x, y, z);
                        maxsamples_npixels = 1;
                    }
                    if (samples < minsamples)
                        minsamples = samples;
                    if (samples == 0)
                        ++emptypixels;
                    if (samples >= nsamples_histogram.size())
                        nsamples_histogram.resize (samples+1, 0);
                    nsamples_histogram[samples] += 1;
                    for (unsigned int s = 0;  s < samples;  ++s) {
                        for (int c = 0;  c < nchannels; ++c) {
                            float d = input.deep_value (x, y, z, c, s);
                            if (! isfinite(d)) {
                                if (nonfinites++ == 0) {
                                    nonfinite_pixel.setValue (x, y, z);
                                    nonfinite_pixel_samp = s;
                                    nonfinite_pixel_chan = c;
                                }
                            }
                            if (depthchannel == c) {
                                if (d < mindepth) {
                                    mindepth = d;
                                    mindepth_pixel.setValue (x, y, z);
                                }
                                if (d > maxdepth) {
                                    maxdepth = d;
                                    maxdepth_pixel.setValue (x, y, z);
                                }
                            }
                        }
                    }
                    sampoffset += samples;
                }
            }
        }
        printf ("%sMin deep samples in any pixel : %llu\n", indent, (unsigned long long)minsamples);
        printf ("%sMax deep samples in any pixel : %llu\n", indent, (unsigned long long)maxsamples);
        printf ("%s%llu pixel%s had the max of %llu samples, including (x=%d, y=%d)\n",
                indent, (unsigned long long)maxsamples_npixels,
                maxsamples_npixels > 1 ? "s" : "",
                (unsigned long long)maxsamples,
                maxsamples_pixel.x, maxsamples_pixel.y);
        printf ("%sAverage deep samples per pixel: %.2f\n", indent, double(totalsamples)/double(npixels));
        printf ("%sTotal deep samples in all pixels: %llu\n", indent, (unsigned long long)totalsamples);
        printf ("%sPixels with deep samples   : %llu\n", indent, (unsigned long long)(npixels-emptypixels));
        printf ("%sPixels with no deep samples: %llu\n", indent, (unsigned long long)emptypixels);
        printf ("%sSamples/pixel histogram:\n", indent);
        size_t grandtotal = 0;
        for (size_t i = 0, e = nsamples_histogram.size();  i < e;  ++i)
            grandtotal += nsamples_histogram[i];
        size_t binstart = 0, bintotal = 0;
        for (size_t i = 0, e = nsamples_histogram.size();  i < e;  ++i) {
            bintotal += nsamples_histogram[i];
            if (i < 8 || i == (e-1) || OIIO::ispow2(i+1)) {
                // batch by powers of 2, unless it's a small number
                if (i == binstart)
                    printf ("%s  %3lld    ", indent, (long long)i);
                else
                    printf ("%s  %3lld-%3lld", indent,
                            (long long)binstart, (long long)i);
                printf (" : %8lld (%4.1f%%)\n", (long long)bintotal,
                        (100.0*bintotal)/grandtotal);
                binstart = i+1;
                bintotal = 0;
            }
        }
        if (depthchannel >= 0) {
            printf ("%sMinimum depth was %g at (%d, %d)\n", indent, mindepth,
                    mindepth_pixel.x, mindepth_pixel.y);
            printf ("%sMaximum depth was %g at (%d, %d)\n", indent, maxdepth,
                    maxdepth_pixel.x, maxdepth_pixel.y);
        }
        if (nonfinites > 0) {
            printf ("%sNonfinite values: %lld, including (x=%d, y=%d, chan=%s, samp=%d)\n",
                    indent, nonfinites, nonfinite_pixel.x, nonfinite_pixel.y,
                    input.spec().channelnames[nonfinite_pixel_chan].c_str(),
                    nonfinite_pixel_samp);
        }
    } else {
        std::vector<float> constantValues(input.spec().nchannels);
        if (isConstantColor(input, &constantValues[0])) {
            printf ("%sConstant: Yes\n", indent);
            printf ("%sConstant Color: ", indent);
            for (unsigned int i=0; i<constantValues.size(); ++i) {
                print_stats_num (constantValues[i], maxval, false);
                printf (" ");
            }
            print_stats_footer (maxval);
            printf ("\n");
        }
        else {
            printf ("%sConstant: No\n", indent);
        }
    
        if( isMonochrome(input)) {
            printf ("%sMonochrome: Yes\n", indent);
        } else {
            printf ("%sMonochrome: No\n", indent);
        }
    }
}
示例#5
0
static void
print_stats (const std::string &filename,
             const ImageSpec &originalspec,
             int subimage=0, int miplevel=0, bool indentmip=false)
{
    const char *indent = indentmip ? "      " : "    ";
    ImageBuf input;

    if (! read_input (filename, input, subimage, miplevel)) {
        std::cerr << "Stats: read error: " << input.geterror() << "\n";
        return;
    }

    PixelStats stats;
    if (! computePixelStats (stats, input)) {
        printf ("%sStats: (unable to compute)\n", indent);
        return;
    }

    // The original spec is used, otherwise the bit depth will
    // be reported incorrectly (as FLOAT)
    unsigned int maxval = (unsigned int)get_intsample_maxval (originalspec);

    printf ("%sStats Min: ", indent);
    for (unsigned int i=0; i<stats.min.size(); ++i) {
        print_stats_num (stats.min[i], maxval, true);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");

    printf ("%sStats Max: ", indent);
    for (unsigned int i=0; i<stats.max.size(); ++i) {
        print_stats_num (stats.max[i], maxval, true);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");

    printf ("%sStats Avg: ", indent);
    for (unsigned int i=0; i<stats.avg.size(); ++i) {
        print_stats_num (stats.avg[i], maxval, false);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");

    printf ("%sStats StdDev: ", indent);
    for (unsigned int i=0; i<stats.stddev.size(); ++i) {
        print_stats_num (stats.stddev[i], maxval, false);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");

    printf ("%sStats NanCount: ", indent);
    for (unsigned int i=0; i<stats.nancount.size(); ++i) {
        printf ("%llu ", (unsigned long long)stats.nancount[i]);
    }
    printf ("\n");

    printf ("%sStats InfCount: ", indent);
    for (unsigned int i=0; i<stats.infcount.size(); ++i) {
        printf ("%llu ", (unsigned long long)stats.infcount[i]);
    }
    printf ("\n");

    printf ("%sStats FiniteCount: ", indent);
    for (unsigned int i=0; i<stats.finitecount.size(); ++i) {
        printf ("%llu ", (unsigned long long)stats.finitecount[i]);
    }
    printf ("\n");

    if (input.deep()) {
        const DeepData *dd (input.deepdata());
        size_t npixels = dd->nsamples.size();
        size_t totalsamples = 0, emptypixels = 0;
        size_t maxsamples = 0, minsamples = std::numeric_limits<size_t>::max();
        for (size_t p = 0;  p < npixels;  ++p) {
            size_t c = size_t(dd->nsamples[p]);
            totalsamples += c;
            if (c > maxsamples)
                maxsamples = c;
            if (c < minsamples)
                minsamples = c;
            if (c == 0)
                ++emptypixels;
        }
        printf ("%sMin deep samples in any pixel : %llu\n", indent, (unsigned long long)minsamples);
        printf ("%sMax deep samples in any pixel : %llu\n", indent, (unsigned long long)maxsamples);
        printf ("%sAverage deep samples per pixel: %.2f\n", indent, double(totalsamples)/double(npixels));
        printf ("%sTotal deep samples in all pixels: %llu\n", indent, (unsigned long long)totalsamples);
        printf ("%sPixels with deep samples   : %llu\n", indent, (unsigned long long)(npixels-emptypixels));
        printf ("%sPixels with no deep samples: %llu\n", indent, (unsigned long long)emptypixels);
    } else {
        std::vector<float> constantValues(input.spec().nchannels);
        if (isConstantColor(input, &constantValues[0])) {
            printf ("%sConstant: Yes\n", indent);
            printf ("%sConstant Color: ", indent);
            for (unsigned int i=0; i<constantValues.size(); ++i) {
                print_stats_num (constantValues[i], maxval, false);
                printf (" ");
            }
            print_stats_footer (maxval);
            printf ("\n");
        }
        else {
            printf ("%sConstant: No\n", indent);
        }

        if( isMonochrome(input)) {
            printf ("%sMonochrome: Yes\n", indent);
        } else {
            printf ("%sMonochrome: No\n", indent);
        }
    }
}
示例#6
0
static void
print_stats (const std::string &filename,
             const ImageSpec &originalspec,
             int subimage=0, int miplevel=0, bool indentmip=false)
{
    const char *indent = indentmip ? "      " : "    ";
    ImageBuf input;

    if (! read_input (filename, input, subimage, miplevel)) {
        std::cerr << "Stats: read error: " << input.geterror() << "\n";
        return;
    }

    PixelStats stats;
    if (! computePixelStats (stats, input)) {
        printf ("%sStats: (unable to compute)\n", indent);
        return;
    }

    // The original spec is used, otherwise the bit depth will
    // be reported incorrectly (as FLOAT)
    unsigned int maxval = (unsigned int)get_intsample_maxval (originalspec);

    printf ("%sStats Min: ", indent);
    for (unsigned int i=0; i<stats.min.size(); ++i) {
        print_stats_num (stats.min[i], maxval, true);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");

    printf ("%sStats Max: ", indent);
    for (unsigned int i=0; i<stats.max.size(); ++i) {
        print_stats_num (stats.max[i], maxval, true);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");

    printf ("%sStats Avg: ", indent);
    for (unsigned int i=0; i<stats.avg.size(); ++i) {
        print_stats_num (stats.avg[i], maxval, false);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");

    printf ("%sStats StdDev: ", indent);
    for (unsigned int i=0; i<stats.stddev.size(); ++i) {
        print_stats_num (stats.stddev[i], maxval, false);
        printf (" ");
    }
    print_stats_footer (maxval);
    printf ("\n");

    printf ("%sStats NanCount: ", indent);
    for (unsigned int i=0; i<stats.nancount.size(); ++i) {
        printf ("%llu ", (unsigned long long)stats.nancount[i]);
    }
    printf ("\n");

    printf ("%sStats InfCount: ", indent);
    for (unsigned int i=0; i<stats.infcount.size(); ++i) {
        printf ("%llu ", (unsigned long long)stats.infcount[i]);
    }
    printf ("\n");

    printf ("%sStats FiniteCount: ", indent);
    for (unsigned int i=0; i<stats.finitecount.size(); ++i) {
        printf ("%llu ", (unsigned long long)stats.finitecount[i]);
    }
    printf ("\n");

    if (input.deep()) {
        const DeepData *dd (input.deepdata());
        size_t npixels = dd->nsamples.size();
        size_t totalsamples = 0, emptypixels = 0;
        size_t maxsamples = 0, minsamples = std::numeric_limits<size_t>::max();
        size_t maxsamples_npixels = 0;
        float mindepth = std::numeric_limits<float>::max();
        float maxdepth = -std::numeric_limits<float>::max();
        Imath::V3i maxsamples_pixel(-1,-1,-1), minsamples_pixel(-1,-1,-1);
        Imath::V3i mindepth_pixel(-1,-1,-1), maxdepth_pixel(-1,-1,-1);
        size_t sampoffset = 0;
        int depthchannel = -1;
        for (int c = 0; c < input.nchannels(); ++c)
            if (Strutil::iequals (originalspec.channelnames[c], "Z"))
                depthchannel = c;
        int xend = originalspec.x + originalspec.width;
        int yend = originalspec.y + originalspec.height;
        int zend = originalspec.z + originalspec.depth;
        size_t p = 0;
        for (int z = originalspec.z; z < zend; ++z) {
            for (int y = originalspec.y; y < yend; ++y) {
                for (int x = originalspec.x; x < xend; ++x, ++p) {
                    size_t c = input.deep_samples (x, y, z);
                    totalsamples += c;
                    if (c == maxsamples)
                        ++maxsamples_npixels;
                    if (c > maxsamples) {
                        maxsamples = c;
                        maxsamples_pixel.setValue (x, y, z);
                        maxsamples_npixels = 1;
                    }
                    if (c < minsamples)
                        minsamples = c;
                    if (c == 0)
                        ++emptypixels;
                    if (depthchannel >= 0) {
                        for (unsigned int s = 0;  s < c;  ++s) {
                            float d = input.deep_value (x, y, z, depthchannel, s);
                            if (d < mindepth) {
                                mindepth = d;
                                mindepth_pixel.setValue (x, y, z);
                            }
                            if (d > maxdepth) {
                                maxdepth = d;
                                maxdepth_pixel.setValue (x, y, z);
                            }
                        }
                    }
                    sampoffset += c;
                }
            }
        }
        printf ("%sMin deep samples in any pixel : %llu\n", indent, (unsigned long long)minsamples);
        printf ("%sMax deep samples in any pixel : %llu\n", indent, (unsigned long long)maxsamples);
        printf ("%s%llu pixel%s had the max of %llu samples, including (x=%d, y=%d)\n",
                indent, (unsigned long long)maxsamples_npixels,
                maxsamples_npixels > 1 ? "s" : "",
                (unsigned long long)maxsamples,
                maxsamples_pixel.x, maxsamples_pixel.y);
        printf ("%sAverage deep samples per pixel: %.2f\n", indent, double(totalsamples)/double(npixels));
        printf ("%sTotal deep samples in all pixels: %llu\n", indent, (unsigned long long)totalsamples);
        printf ("%sPixels with deep samples   : %llu\n", indent, (unsigned long long)(npixels-emptypixels));
        printf ("%sPixels with no deep samples: %llu\n", indent, (unsigned long long)emptypixels);
        printf ("%sMinimum depth was %g at (%d, %d)\n", indent, mindepth,
                mindepth_pixel.x, mindepth_pixel.y);
        printf ("%sMaximum depth was %g at (%d, %d)\n", indent, maxdepth,
                maxdepth_pixel.x, maxdepth_pixel.y);
    } else {
        std::vector<float> constantValues(input.spec().nchannels);
        if (isConstantColor(input, &constantValues[0])) {
            printf ("%sConstant: Yes\n", indent);
            printf ("%sConstant Color: ", indent);
            for (unsigned int i=0; i<constantValues.size(); ++i) {
                print_stats_num (constantValues[i], maxval, false);
                printf (" ");
            }
            print_stats_footer (maxval);
            printf ("\n");
        }
        else {
            printf ("%sConstant: No\n", indent);
        }

        if( isMonochrome(input)) {
            printf ("%sMonochrome: Yes\n", indent);
        } else {
            printf ("%sMonochrome: No\n", indent);
        }
    }
}