コード例 #1
0
ImageBuf
ImageBufAlgo::add(Image_or_Const A, Image_or_Const B, ROI roi, int nthreads)
{
    ImageBuf result;
    bool ok = add(result, A, B, roi, nthreads);
    if (!ok && !result.has_error())
        result.error("ImageBufAlgo::add() error");
    return result;
}
コード例 #2
0
bool
ImageBufAlgo::ociolook (ImageBuf &dst, const ImageBuf &src,
                        string_view looks, string_view from, string_view to,
                        bool inverse, bool unpremult,
                        string_view key, string_view value,
                        ColorConfig *colorconfig,
                        ROI roi, int nthreads)
{
    if (from.empty() || from == "current") {
        from = src.spec().get_string_attribute ("oiio:Colorspace", "Linear");
    }
    if (to.empty() || to == "current") {
        to = src.spec().get_string_attribute ("oiio:Colorspace", "Linear");
    }
    if (from.empty() || to.empty()) {
        dst.error ("Unknown color space name");
        return false;
    }
    ColorProcessor *processor = NULL;
    {
        spin_lock lock (colorconfig_mutex);
        if (! colorconfig)
            colorconfig = default_colorconfig.get();
        if (! colorconfig)
            default_colorconfig.reset (colorconfig = new ColorConfig);
        processor = colorconfig->createLookTransform (looks, from, to, inverse,
                                                 key, value);
        if (! processor) {
            if (colorconfig->error())
                dst.error ("%s", colorconfig->geterror());
            else
                dst.error ("Could not construct the color transform");
            return false;
        }
    }
    bool ok = colorconvert (dst, src, processor, unpremult, roi, nthreads);
    if (ok)
        dst.specmod().attribute ("oiio:ColorSpace", to);
    {
        spin_lock lock (colorconfig_mutex);
        colorconfig->deleteColorProcessor (processor);
    }
    return ok;
}
コード例 #3
0
bool
ImageBufAlgo::reorient (ImageBuf &dst, const ImageBuf &src, int nthreads)
{
    ImageBuf tmp;
    bool ok = false;
    switch (src.orientation()) {
    case 1:
        ok = dst.copy (src);
        break;
    case 2:
        ok = ImageBufAlgo::flop (dst, src);
        break;
    case 3:
        ok = ImageBufAlgo::rotate180 (dst, src);
        break;
    case 4:
        ok = ImageBufAlgo::flip (dst, src);
        break;
    case 5:
        ok = ImageBufAlgo::rotate270 (tmp, src);
        if (ok)
            ok = ImageBufAlgo::flop (dst, tmp);
        else
            dst.error ("%s", tmp.geterror());
        break;
    case 6:
        ok = ImageBufAlgo::rotate90 (dst, src);
        break;
    case 7:
        ok = ImageBufAlgo::flip (tmp, src);
        if (ok)
            ok = ImageBufAlgo::rotate90 (dst, tmp);
        else
            dst.error ("%s", tmp.geterror());
        break;
    case 8:
        ok = ImageBufAlgo::rotate270 (dst, src);
        break;
    }
    dst.set_orientation (1);
    return ok;
}
コード例 #4
0
ファイル: imagebufalgo.cpp プロジェクト: nerd93/oiio
bool
ImageBufAlgo::resample (ImageBuf &dst, const ImageBuf &src,
                        bool interpolate, ROI roi, int nthreads)
{
    if (! IBAprep (roi, &dst, &src))
        return false;
    if (dst.nchannels() != src.nchannels()) {
        dst.error ("channel number mismatch: %d vs. %d", 
                   dst.spec().nchannels, src.spec().nchannels);
        return false;
    }
    if (dst.spec().depth > 1 || src.spec().depth > 1) {
        dst.error ("ImageBufAlgo::resample does not support volume images");
        return false;
    }
    OIIO_DISPATCH_TYPES2 ("resample", resample_,
                          dst.spec().format, src.spec().format,
                          dst, src, interpolate, roi, nthreads);
    return false;
}
コード例 #5
0
bool
ImageBufAlgo::add(ImageBuf& dst, Image_or_Const A_, Image_or_Const B_, ROI roi,
                  int nthreads)
{
    pvt::LoggedTimer logtime("IBA::add");
    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, "add", add_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());
        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, "add", add_impl, dst.spec().format,
                                    A.spec().format, dst, A, b, roi, nthreads);
        return ok;
    }
    // Remaining cases: error
    dst.error("ImageBufAlgo::add(): at least one argument must be an image");
    return false;
}
コード例 #6
0
bool
ImageBufAlgo::histogram (const ImageBuf &A, int channel,
                         std::vector<imagesize_t> &histogram, int bins,
                         float min, float max, imagesize_t *submin,
                         imagesize_t *supermax, ROI roi)
{
    if (A.spec().format != TypeDesc::TypeFloat) {
        A.error ("Unsupported pixel data format '%s'", A.spec().format);
        return false;
    }

    if (A.nchannels() == 0) {
        A.error ("Input image must have at least 1 channel");
        return false;
    }

    if (channel < 0 || channel >= A.nchannels()) {
        A.error ("Invalid channel %d for input image with channels 0 to %d",
                  channel, A.nchannels()-1);
        return false;
    }

    if (bins < 1) {
        A.error ("The number of bins must be at least 1");
        return false;
    }

    if (max <= min) {
        A.error ("Invalid range, min must be strictly smaller than max");
        return false;
    }

    // Specified ROI -> use it. Unspecified ROI -> initialize from A.
    if (! roi.defined())
        roi = get_roi (A.spec());

    histogram_impl<float> (A, channel, histogram, bins, min, max,
                                  submin, supermax, roi);

    return ! A.has_error();
}
コード例 #7
0
ファイル: imagebufalgo_opencv.cpp プロジェクト: AheadIO/oiio
bool
ImageBufAlgo::capture_image (ImageBuf &dst, int cameranum, TypeDesc convert)
{
#ifdef USE_OPENCV
    IplImage *frame = NULL;
    {
        // This block is mutex-protected
        lock_guard lock (opencv_mutex);
        CvCapture *cvcam = cameras[cameranum];
        if (! cvcam) {
            dst.error ("Could not create a capture camera (OpenCV error)");
            return false;  // failed somehow
        }
        frame = cvQueryFrame (cvcam);
        if (! frame) {
            dst.error ("Could not cvQueryFrame (OpenCV error)");
            return false;  // failed somehow
        }
    }

    time_t now;
    time (&now);
    struct tm tmtime;
    Sysutil::get_local_time (&now, &tmtime);
    std::string datetime = Strutil::format ("%4d:%02d:%02d %02d:%02d:%02d",
                                   tmtime.tm_year+1900, tmtime.tm_mon+1,
                                   tmtime.tm_mday, tmtime.tm_hour,
                                   tmtime.tm_min, tmtime.tm_sec);

    bool ok = ImageBufAlgo::from_IplImage (dst, frame, convert);
    // cvReleaseImage (&frame);   // unnecessary?
    if (ok)
        dst.specmod().attribute ("DateTime", datetime);

    return ok;
#else
    dst.error ("capture_image not supported -- no OpenCV support at compile time");
    return false;
#endif
}
コード例 #8
0
ファイル: imagebufalgo.cpp プロジェクト: nerd93/oiio
bool
ImageBufAlgo::resize (ImageBuf &dst, const ImageBuf &src,
                      Filter2D *filter, ROI roi, int nthreads)
{
    if (! IBAprep (roi, &dst, &src))
        return false;
    if (dst.nchannels() != src.nchannels()) {
        dst.error ("channel number mismatch: %d vs. %d", 
                   dst.spec().nchannels, src.spec().nchannels);
        return false;
    }
    if (dst.spec().depth > 1 || src.spec().depth > 1) {
        dst.error ("ImageBufAlgo::resize does not support volume images");
        return false;
    }

    // Set up a shared pointer with custom deleter to make sure any
    // filter we allocate here is properly destroyed.
    boost::shared_ptr<Filter2D> filterptr ((Filter2D*)NULL, Filter2D::destroy);
    bool allocfilter = (filter == NULL);
    if (allocfilter) {
        // If no filter was provided, punt and just linearly interpolate.
        const ImageSpec &srcspec (src.spec());
        const ImageSpec &dstspec (dst.spec());
        float wratio = float(dstspec.full_width) / float(srcspec.full_width);
        float hratio = float(dstspec.full_height) / float(srcspec.full_height);
        float w = 2.0f * std::max (1.0f, wratio);
        float h = 2.0f * std::max (1.0f, hratio);
        filter = Filter2D::create ("triangle", w, h);
        filterptr.reset (filter);
    }

    OIIO_DISPATCH_TYPES2 ("resize", resize_,
                          dst.spec().format, src.spec().format,
                          dst, src, filter, roi, nthreads);

    return false;
}
コード例 #9
0
ファイル: imagebufalgo_deep.cpp プロジェクト: jproccia/oiio
bool
ImageBufAlgo::flatten (ImageBuf &dst, const ImageBuf &src,
                       ROI roi, int nthreads)
{
    if (! src.deep()) {
        // For some reason, we were asked to flatten an already-flat image.
        // So just copy it.
        return dst.copy (src);
    }

    // Construct an ideal spec for dst, which is like src but not deep.
    ImageSpec force_spec = src.spec();
    force_spec.deep = false;
    force_spec.channelformats.clear();

    if (! IBAprep (roi, &dst, &src, NULL, &force_spec, IBAprep_SUPPORT_DEEP))
        return false;
    if (dst.spec().deep) {
        dst.error ("Cannot flatten to a deep image");
        return false;
    }

    const ImageSpec &srcspec (src.spec());
    int alpha_channel, RA_channel, GA_channel, BA_channel;
    int R_channel, G_channel, B_channel, Z_channel, Zback_channel;
    if (! find_deep_channels (srcspec, alpha_channel,
                              RA_channel, GA_channel, BA_channel,
                              R_channel, G_channel, B_channel,
                              Z_channel, Zback_channel)) {
        dst.error ("No alpha channel could be identified");
        return false;
    }

    bool ok;
    OIIO_DISPATCH_TYPES (ok, "flatten", flatten_, dst.spec().format,
                         dst, src, roi, nthreads);
    return ok;
}
コード例 #10
0
bool
ImageBufAlgo::mad (ImageBuf &dst, const ImageBuf &A, const float *B,
                   const float *C, ROI roi, int nthreads)
{
    if (!A.initialized()) {
        dst.error ("Uninitialized input image");
        return false;
    }
    if (! IBAprep (roi, &dst, &A))
        return false;
    bool ok;
    OIIO_DISPATCH_COMMON_TYPES2 (ok, "mad", mad_implf, dst.spec().format,
                                 A.spec().format, dst, A, B, C,
                                 roi, nthreads);
    return ok;
}
コード例 #11
0
// DEPRECATED 2-argument version
bool
ImageBufAlgo::fixNonFinite (ImageBuf &dst, const ImageBuf &src,
                            NonFiniteFixMode mode, int *pixelsFixed)
{
    ROI roi;
    IBAprep (roi, &dst, &src);
    if (dst.nchannels() != src.nchannels()) {
        dst.error ("channel number mismatch: %d vs. %d", 
                   dst.spec().nchannels, src.spec().nchannels);
        return false;
    }
    if ((const ImageBuf *)&dst != &src)
        if (! dst.copy (src))
            return false;
    return fixNonFinite (dst, mode, pixelsFixed, roi);
}
コード例 #12
0
ファイル: imagebufalgo.cpp プロジェクト: nerd93/oiio
bool
ImageBufAlgo::convolve (ImageBuf &dst, const ImageBuf &src,
                        const ImageBuf &kernel, bool normalize,
                        ROI roi, int nthreads)
{
    if (! IBAprep (roi, &dst, &src))
        return false;
    if (dst.nchannels() != src.nchannels()) {
        dst.error ("channel number mismatch: %d vs. %d", 
                   dst.spec().nchannels, src.spec().nchannels);
        return false;
    }
    OIIO_DISPATCH_TYPES2 ("convolve", convolve_,
                          dst.spec().format, src.spec().format,
                          dst, src, kernel, normalize, roi, nthreads);
    return false;
}
コード例 #13
0
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;
}
コード例 #14
0
bool
ImageBufAlgo::mad (ImageBuf &dst, const ImageBuf &A, float b,
                   float c, ROI roi, int nthreads)
{
    if (!A.initialized()) {
        dst.error ("Uninitialized input image");
        return false;
    }
    if (! IBAprep (roi, &dst, &A))
        return false;
    std::vector<float> B (roi.chend, b);
    std::vector<float> C (roi.chend, c);
    bool ok;
    OIIO_DISPATCH_COMMON_TYPES2 (ok, "mad", mad_implf, dst.spec().format,
                                 A.spec().format, dst, A, &B[0], &C[0],
                                 roi, nthreads);
    return ok;
}
コード例 #15
0
bool
ImageBufAlgo::computePixelStats (PixelStats &stats, const ImageBuf &src,
                                 ROI roi, int nthreads)
{
    if (! roi.defined())
        roi = get_roi (src.spec());
    else
        roi.chend = std::min (roi.chend, src.nchannels());
    int nchannels = src.spec().nchannels;
    if (nchannels == 0) {
        src.error ("%d-channel images not supported", nchannels);
        return false;
    }

    OIIO_DISPATCH_TYPES ("computePixelStats", computePixelStats_,
                         src.spec().format, src, stats, roi, nthreads);
    return false;
}
コード例 #16
0
static bool
histogram_impl (const ImageBuf &A, int channel,
                std::vector<imagesize_t> &histogram, int bins,
                float min, float max, imagesize_t *submin,
                imagesize_t *supermax, ROI roi)
{
    // Double check A's type.
    if (A.spec().format != BaseTypeFromC<Atype>::value) {
        A.error ("Unsupported pixel data format '%s'", A.spec().format);
        return false;
    }

    // Initialize.
    ImageBuf::ConstIterator<Atype, float> a (A, roi);
    float ratio = bins / (max-min);
    int bins_minus_1 = bins-1;
    bool submin_ok = submin != NULL;
    bool supermax_ok = supermax != NULL;
    if (submin_ok)
        *submin = 0;
    if (supermax_ok)
        *supermax = 0;
    histogram.assign(bins, 0);

    // Compute histogram.
    for ( ; ! a.done(); a++) {
        float c = a[channel];
        if (c >= min && c < max) {
            // Map range min->max to 0->(bins-1).
            histogram[ (int) ((c-min) * ratio) ]++;
        } else if (c == max) {
            histogram[bins_minus_1]++;
        } else {
            if (submin_ok && c < min)
                (*submin)++;
            else if (supermax_ok)
                (*supermax)++;
        }
    }
    return true;
}
コード例 #17
0
bool
ImageBufAlgo::histogram_draw (ImageBuf &R,
                              const std::vector<imagesize_t> &histogram)
{
    // Fail if there are no bins to draw.
    int bins = histogram.size();
    if (bins == 0) {
        R.error ("There are no bins to draw, the histogram is empty");
        return false;
    }

    // Check R and modify it if needed.
    int height = R.spec().height;
    if (R.spec().format != TypeDesc::TypeFloat || R.nchannels() != 1 ||
        R.spec().width != bins) {
        ImageSpec newspec = ImageSpec (bins, height, 1, TypeDesc::FLOAT);
        R.reset ("dummy", newspec);
    }

    // Fill output image R with white color.
    ImageBuf::Iterator<float, float> r (R);
    for ( ; ! r.done(); ++r)
        r[0] = 1;

    // Draw histogram left->right, bottom->up.
    imagesize_t max = *std::max_element (histogram.begin(), histogram.end());
    for (int b = 0; b < bins; b++) {
        int bin_height = (int) ((float)histogram[b]/(float)max*height + 0.5f);
        if (bin_height != 0) {
            // Draw one bin at column b.
            for (int j = 1; j <= bin_height; j++) {
                int row = height - j;
                r.pos (b, row);
                r[0] = 0;
            }
        }
    }
    return true;
}
コード例 #18
0
ファイル: imagebufalgo_draw.cpp プロジェクト: ElaraFX/oiio
bool
ImageBufAlgo::noise (ImageBuf &dst, string_view noisetype,
                     float A, float B, bool mono, int seed,
                     ROI roi, int nthreads)
{
    if (! IBAprep (roi, &dst))
        return false;
    bool ok;
    if (noisetype == "gaussian" || noisetype == "normal") {
        OIIO_DISPATCH_TYPES (ok, "noise_gaussian", noise_gaussian_, dst.spec().format,
                             dst, A, B, mono, seed, roi, nthreads);
    } else if (noisetype == "uniform") {
        OIIO_DISPATCH_TYPES (ok, "noise_uniform", noise_uniform_, dst.spec().format,
                             dst, A, B, mono, seed, roi, nthreads);
    } else if (noisetype == "salt") {
        OIIO_DISPATCH_TYPES (ok, "noise_salt", noise_salt_, dst.spec().format,
                             dst, A, B, mono, seed, roi, nthreads);
    } else {
        ok = false;
        dst.error ("noise", "unknown noise type \"%s\"", noisetype);
    }
    return ok;
}
コード例 #19
0
bool
ImageBufAlgo::mad (ImageBuf &dst, const ImageBuf &A_, const ImageBuf &B_,
                   const ImageBuf &C_, ROI roi, int nthreads)
{
    const ImageBuf *A = &A_, *B = &B_, *C = &C_;
    if (!A->initialized() || !B->initialized() || !C->initialized()) {
        dst.error ("Uninitialized input image");
        return false;
    }

    // To avoid the full cross-product of dst/A/B/C types, force A,B,C to
    // all be the same data type, copying if we have to.
    TypeDesc abc_type = type_merge (A->spec().format, B->spec().format,
                                    C->spec().format);
    ImageBuf Anew, Bnew, Cnew;
    if (A->spec().format != abc_type) {
        Anew.copy (*A, abc_type);
        A = &Anew;
    }
    if (B->spec().format != abc_type) {
        Bnew.copy (*B, abc_type);
        B = &Bnew;
    }
    if (C->spec().format != abc_type) {
        Cnew.copy (*C, abc_type);
        C = &Cnew;
    }
    ASSERT (A->spec().format == B->spec().format &&
            A->spec().format == C->spec().format);

    if (! IBAprep (roi, &dst, A, B, C))
        return false;
    bool ok;
    OIIO_DISPATCH_COMMON_TYPES2 (ok, "mad", mad_impl, dst.spec().format,
                                 abc_type, dst, *A, *B, *C, roi, nthreads);
    return ok;
}
コード例 #20
0
bool
ImageBufAlgo::zover (ImageBuf &R, const ImageBuf &A, const ImageBuf &B,
                     bool z_zeroisinf, ROI roi, int nthreads)
{
    const ImageSpec &specR = R.spec();
    const ImageSpec &specA = A.spec();
    const ImageSpec &specB = B.spec();

    int nchannels_R, nchannels_A, nchannels_B;
    int alpha_R, alpha_A, alpha_B;
    int z_R, z_A, z_B;
    int colors_R, colors_A, colors_B;
    bool initialized_R = decode_over_channels (R, nchannels_R, alpha_R,
                                               z_R, colors_R);
    bool initialized_A = decode_over_channels (A, nchannels_A, alpha_A,
                                               z_A, colors_A);
    bool initialized_B = decode_over_channels (B, nchannels_B, alpha_B,
                                               z_B, colors_B);

    if (! initialized_A || ! initialized_B) {
        R.error ("Can't 'zover' uninitialized images");
        return false;
    }
    // Fail if the input images don't have a Z channel.
    if (z_A < 0 || z_B < 0 || (initialized_R && z_R < 0)) {
        R.error ("'zover' requires Z channels");
        return false;
    }
    // Fail if the input images don't have an alpha channel.
    if (alpha_A < 0 || alpha_B < 0 || (initialized_R && alpha_R < 0)) {
        R.error ("'zover' requires alpha channels");
        return false;
    }
    // Fail for mismatched channel counts
    if (colors_A != colors_B || colors_A < 1) {
        R.error ("Can't 'zover' images with mismatched color channel counts (%d vs %d)",
                 colors_A, colors_B);
        return false;
    }
    // Fail for unaligned alpha or z channels
    if (alpha_A != alpha_B || z_A != z_B ||
        (initialized_R && alpha_R != alpha_A) ||
        (initialized_R && z_R != z_A)) {
        R.error ("Can't 'zover' images with mismatched channel order",
                 colors_A, colors_B);
        return false;
    }
    
    // At present, this operation only supports ImageBuf's containing
    // float pixel data.
    if ((initialized_R && specR.format != TypeDesc::TypeFloat) ||
        specA.format != TypeDesc::TypeFloat ||
        specB.format != TypeDesc::TypeFloat) {
        R.error ("Unsupported pixel data format combination '%s = %s zover %s'",
                 specR.format, specA.format, specB.format);
        return false;
    }

    // Uninitialized R -> size it to the union of A and B.
    if (! initialized_R) {
        ImageSpec newspec = specA;
        set_roi (newspec, roi_union (get_roi(specA), get_roi(specB)));
        R.reset ("zover", newspec);
    }

    // Specified ROI -> use it. Unspecified ROI -> initialize from R.
    if (! roi.defined())
        roi = get_roi (R.spec());

    parallel_image (boost::bind (over_impl<float,float,float>, boost::ref(R),
                                 boost::cref(A), boost::cref(B), _1,
                                 true, z_zeroisinf),
                    roi, nthreads);
    return ! R.has_error();
}
コード例 #21
0
// 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;
}
コード例 #22
0
ファイル: imagebufalgo_deep.cpp プロジェクト: jproccia/oiio
static bool
flatten_ (ImageBuf &dst, const ImageBuf &src, 
          ROI roi, int nthreads)
{
    if (nthreads != 1 && roi.npixels() >= 1000) {
        // Possible multiple thread case -- recurse via parallel_image
        ImageBufAlgo::parallel_image (
            boost::bind(flatten_<DSTTYPE>, boost::ref(dst), boost::cref(src),
                        _1 /*roi*/, 1 /*nthreads*/),
            roi, nthreads);
        return true;
    }

    const ImageSpec &srcspec (src.spec());
    int nc = srcspec.nchannels;

    int alpha_channel, RA_channel, GA_channel, BA_channel;
    int R_channel, G_channel, B_channel;
    int Z_channel, Zback_channel;
    if (! find_deep_channels (srcspec, alpha_channel,
                              RA_channel, GA_channel, BA_channel,
                              R_channel, G_channel, B_channel,
                              Z_channel, Zback_channel)) {
        dst.error ("No alpha channel could be identified");
        return false;
    }
    ASSERT (alpha_channel >= 0 ||
            (RA_channel >= 0 && GA_channel >= 0 && BA_channel >= 0));
    float *val = ALLOCA (float, nc);
    float &RAval (RA_channel >= 0 ? val[RA_channel] : val[alpha_channel]);
    float &GAval (GA_channel >= 0 ? val[GA_channel] : val[alpha_channel]);
    float &BAval (BA_channel >= 0 ? val[BA_channel] : val[alpha_channel]);

    for (ImageBuf::Iterator<DSTTYPE> r (dst, roi);  !r.done();  ++r) {
        int x = r.x(), y = r.y(), z = r.z();
        int samps = src.deep_samples (x, y, z);
        // Clear accumulated values for this pixel (0 for colors, big for Z)
        memset (val, 0, nc*sizeof(float));
        if (Z_channel >= 0 && samps == 0)
            val[Z_channel] = 1.0e30;
        if (Zback_channel >= 0 && samps == 0)
            val[Zback_channel] = 1.0e30;
        for (int s = 0;  s < samps;  ++s) {
            float RA = RAval, GA = GAval, BA = BAval;  // make copies
            float alpha = (RA + GA + BA) / 3.0f;
            if (alpha >= 1.0f)
                break;
            for (int c = 0;  c < nc;  ++c) {
                float v = src.deep_value (x, y, z, c, s);
                if (c == Z_channel || c == Zback_channel)
                    val[c] *= alpha;  // because Z are not premultiplied
                float a;
                if (c == R_channel)
                    a = RA;
                else if (c == G_channel)
                    a = GA;
                else if (c == B_channel)
                    a = BA;
                else
                    a = alpha;
                val[c] += (1.0f - a) * v;
            }
        }

        for (int c = roi.chbegin;  c < roi.chend;  ++c)
            r[c] = val[c];
    }

    return true;
}
コード例 #23
0
ファイル: imagebufalgo_opencv.cpp プロジェクト: AheadIO/oiio
OIIO_NAMESPACE_BEGIN



bool
ImageBufAlgo::from_IplImage (ImageBuf &dst, const IplImage *ipl,
                             TypeDesc convert)
{
    if (! ipl) {
        DASSERT (0 && "ImageBufAlgo::fromIplImage called with NULL ipl");
        dst.error ("Passed NULL source IplImage");
        return false;
    }
#ifdef USE_OPENCV
    TypeDesc srcformat;
    switch (ipl->depth) {
    case int(IPL_DEPTH_8U) :
        srcformat = TypeDesc::UINT8;  break;
    case int(IPL_DEPTH_8S) :
        srcformat = TypeDesc::INT8;  break;
    case int(IPL_DEPTH_16U) :
        srcformat = TypeDesc::UINT16;  break;
    case int(IPL_DEPTH_16S) :
        srcformat = TypeDesc::INT16;  break;
    case int(IPL_DEPTH_32F) :
        srcformat = TypeDesc::FLOAT;  break;
    case int(IPL_DEPTH_64F) :
        srcformat = TypeDesc::DOUBLE;  break;
    default:
        DASSERT (0 && "unknown IplImage type");
        dst.error ("Unsupported IplImage depth %d", (int)ipl->depth);
        return false;
    }

    TypeDesc dstformat = (convert != TypeDesc::UNKNOWN) ? convert : srcformat;
    ImageSpec spec (ipl->width, ipl->height, ipl->nChannels, dstformat);
    // N.B. The OpenCV headers say that ipl->alphaChannel,
    // ipl->colorModel, and ipl->channelSeq are ignored by OpenCV.

    if (ipl->dataOrder != IPL_DATA_ORDER_PIXEL) {
        // We don't handle separate color channels, and OpenCV doesn't either
        dst.error ("Unsupported IplImage data order %d", (int)ipl->dataOrder);
        return false;
    }

    dst.reset (dst.name(), spec);
    size_t pixelsize = srcformat.size()*spec.nchannels;
    // Account for the origin in the line step size, to end up with the
    // standard OIIO origin-at-upper-left:
    size_t linestep = ipl->origin ? -ipl->widthStep : ipl->widthStep;
    // Block copy and convert
    convert_image (spec.nchannels, spec.width, spec.height, 1,
                   ipl->imageData, srcformat,
                   pixelsize, linestep, 0,
                   dst.pixeladdr(0,0), dstformat,
                   spec.pixel_bytes(), spec.scanline_bytes(), 0);
    // FIXME - honor dataOrder.  I'm not sure if it is ever used by
    // OpenCV.  Fix when it becomes a problem.

    // OpenCV uses BGR ordering
    // FIXME: what do they do with alpha?
    if (spec.nchannels >= 3) {
        float pixel[4];
        for (int y = 0;  y < spec.height;  ++y) {
            for (int x = 0;  x < spec.width;  ++x) {
                dst.getpixel (x, y, pixel, 4);
                float tmp = pixel[0];  pixel[0] = pixel[2]; pixel[2] = tmp;
                dst.setpixel (x, y, pixel, 4);
            }
        }
    }
    // FIXME -- the copy and channel swap should happen all as one loop,
    // probably templated by type.

    return true;
#else
    dst.error ("fromIplImage not supported -- no OpenCV support at compile time");
    return false;
#endif
}
コード例 #24
0
ファイル: imagebufalgo_draw.cpp プロジェクト: ElaraFX/oiio
bool
ImageBufAlgo::render_text (ImageBuf &R, int x, int y, string_view text,
                           int fontsize, string_view font_,
                           const float *textcolor)
{
    if (R.spec().depth > 1) {
        R.error ("ImageBufAlgo::render_text does not support volume images");
        return false;
    }

#ifdef USE_FREETYPE
    // If we know FT is broken, don't bother trying again
    if (ft_broken)
        return false;

    // Thread safety
    lock_guard ft_lock (ft_mutex);
    int error = 0;

    // If FT not yet initialized, do it now.
    if (! ft_library) {
        error = FT_Init_FreeType (&ft_library);
        if (error) {
            ft_broken = true;
            R.error ("Could not initialize FreeType for font rendering");
            return false;
        }
    }

    // A set of likely directories for fonts to live, across several systems.
    std::vector<std::string> search_dirs;
    const char *home = getenv ("HOME");
    if (home && *home) {
        std::string h (home);
        search_dirs.push_back (h + "/fonts");
        search_dirs.push_back (h + "/Fonts");
        search_dirs.push_back (h + "/Library/Fonts");
    }
    const char *systemRoot = getenv ("SystemRoot");
    if (systemRoot && *systemRoot)
        search_dirs.push_back (std::string(systemRoot) + "/Fonts");
    search_dirs.push_back ("/usr/share/fonts");
    search_dirs.push_back ("/Library/Fonts");
    search_dirs.push_back ("C:/Windows/Fonts");
    search_dirs.push_back ("/usr/local/share/fonts");
    search_dirs.push_back ("/opt/local/share/fonts");
    // Try $OPENIMAGEIOHOME/fonts
    const char *oiiohomedir = getenv ("OPENIMAGEIOHOME");
    if (oiiohomedir && *oiiohomedir)
        search_dirs.push_back (std::string(oiiohomedir) + "/fonts");
    // Try ../fonts relative to where this executing binary came from
    std::string this_program = OIIO::Sysutil::this_program_path ();
    if (this_program.size()) {
        std::string path = Filesystem::parent_path (this_program);
        path = Filesystem::parent_path (path);
        search_dirs.push_back (path+"/fonts");
    }

    // Try to find the font.  Experiment with several extensions
    std::string font = font_;
    if (font.empty()) {
        // nothing specified -- look for something to use as a default.
        for (int j = 0;  default_font_name[j] && font.empty(); ++j) {
            static const char *extensions[] = { "", ".ttf", ".pfa", ".pfb", NULL };
            for (int i = 0;  font.empty() && extensions[i];  ++i)
                font = Filesystem::searchpath_find (std::string(default_font_name[j])+extensions[i],
                                                 search_dirs, true, true);
        }
        if (font.empty()) {
            R.error ("Could not set default font face");
            return false;
        }
    } else if (Filesystem::is_regular (font)) {
        // directly specified a filename -- use it
    } else {
        // A font name was specified but it's not a full path, look for it
        std::string f;
        static const char *extensions[] = { "", ".ttf", ".pfa", ".pfb", NULL };
        for (int i = 0;  f.empty() && extensions[i];  ++i)
            f = Filesystem::searchpath_find (font+extensions[i],
                                             search_dirs, true, true);
        if (f.empty()) {
            R.error ("Could not set font face to \"%s\"", font);
            return false;
        }
        font = f;
    }

    ASSERT (! font.empty());
    if (! Filesystem::is_regular (font)) {
        R.error ("Could not find font \"%s\"", font);
        return false;
    }

    FT_Face face;      // handle to face object
    error = FT_New_Face (ft_library, font.c_str(), 0 /* face index */, &face);
    if (error) {
        R.error ("Could not set font face to \"%s\"", font);
        return false;  // couldn't open the face
    }

    error = FT_Set_Pixel_Sizes (face,        // handle to face object
                                0,           // pixel_width
                                fontsize);   // pixel_heigh
    if (error) {
        FT_Done_Face (face);
        R.error ("Could not set font size to %d", fontsize);
        return false;  // couldn't set the character size
    }

    FT_GlyphSlot slot = face->glyph;  // a small shortcut
    int nchannels = R.spec().nchannels;
    float *pixelcolor = ALLOCA (float, nchannels);
    if (! textcolor) {
        float *localtextcolor = ALLOCA (float, nchannels);
        for (int c = 0;  c < nchannels;  ++c)
            localtextcolor[c] = 1.0f;
        textcolor = localtextcolor;
    }
コード例 #25
0
ファイル: imagebufalgo_deep.cpp プロジェクト: jproccia/oiio
bool
ImageBufAlgo::deepen (ImageBuf &dst, const ImageBuf &src, float zvalue,
                      ROI roi, int nthreads)
{
    if (src.deep()) {
        // For some reason, we were asked to deepen an already-deep image.
        // So just copy it.
        return dst.copy (src);
        // FIXME: once paste works for deep files, this should really be
        // return paste (dst, roi.xbegin, roi.ybegin, roi.zbegin, roi.chbegin,
        //               src, roi, nthreads);
    }

    // Construct an ideal spec for dst, which is like src but deep.
    const ImageSpec &srcspec (src.spec());
    int nc = srcspec.nchannels;
    int zback_channel = -1;
    ImageSpec force_spec = srcspec;
    force_spec.deep = true;
    force_spec.set_format (TypeDesc::FLOAT);
    force_spec.channelformats.clear();
    for (int c = 0; c < nc; ++c) {
        if (force_spec.channelnames[c] == "Z")
            force_spec.z_channel = c;
        else if (force_spec.channelnames[c] == "Zback")
            zback_channel = c;
    }
    bool add_z_channel = (force_spec.z_channel < 0);
    if (add_z_channel) {
        // No z channel? Make one.
        force_spec.z_channel = force_spec.nchannels++;
        force_spec.channelnames.push_back ("Z");
    }

    if (! IBAprep (roi, &dst, &src, NULL, &force_spec, IBAprep_SUPPORT_DEEP))
        return false;
    if (! dst.deep()) {
        dst.error ("Cannot deepen to a flat image");
        return false;
    }

    float *pixel = OIIO_ALLOCA (float, nc);

    // First, figure out which pixels get a sample and which do not
    for (int z = roi.zbegin; z < roi.zend; ++z)
    for (int y = roi.ybegin; y < roi.yend; ++y)
    for (int x = roi.xbegin; x < roi.xend; ++x) {
        bool has_sample = false;
        src.getpixel (x, y, z, pixel);
        for (int c = 0; c < nc; ++c)
            if (c != force_spec.z_channel && c != zback_channel
                  && pixel[c] != 0.0f) {
                has_sample = true;
                break;
            }
        if (! has_sample && ! add_z_channel)
            for (int c = 0; c < nc; ++c)
                if ((c == force_spec.z_channel || c == zback_channel)
                    && (pixel[c] != 0.0f && pixel[c] < 1e30)) {
                    has_sample = true;
                    break;
                }
        if (has_sample)
            dst.set_deep_samples (x, y, z, 1);
    }

    dst.deep_alloc ();

    // Now actually set the values
    for (int z = roi.zbegin; z < roi.zend; ++z)
    for (int y = roi.ybegin; y < roi.yend; ++y)
    for (int x = roi.xbegin; x < roi.xend; ++x) {
        if (dst.deep_samples (x, y, z) == 0)
            continue;
        for (int c = 0; c < nc; ++c)
            dst.set_deep_value (x, y, z, c, 0 /*sample*/,
                                src.getchannel (x, y, z, c));
        if (add_z_channel)
            dst.set_deep_value (x, y, z, nc, 0, zvalue);
    }

    bool ok = true;
    // FIXME -- the above doesn't split into threads. Someday, it should
    // be refactored like this:
    // OIIO_DISPATCH_COMMON_TYPES2 (ok, "deepen", deepen_,
    //                              dst.spec().format, srcspec.format,
    //                              dst, src, add_z_channel, z, roi, nthreads);
    return ok;
}