コード例 #1
0
bool fcExrContext::addLayerTexture(void *tex, fcPixelFormat fmt, int channel, const char *name)
{
    if (m_dev == nullptr) {
        fcDebugLog("fcExrContext::addLayerTexture(): gfx device is null.");
        return false;
    }
    if (m_task == nullptr) {
        fcDebugLog("fcExrContext::addLayerTexture(): maybe beginFrame() is not called.");
        return false;
    }

    Buffer *raw_frame = nullptr;

    if (tex == m_frame_prev)
    {
        raw_frame = m_src_prev;
        fmt = m_fmt_prev;
    }
    else
    {
        m_frame_prev = tex;

        m_task->pixels.push_back(Buffer());
        raw_frame = &m_task->pixels.back();
        raw_frame->resize(m_task->width * m_task->height * fcGetPixelSize(fmt));

        // get frame buffer
        if (!m_dev->readTexture(&(*raw_frame)[0], raw_frame->size(), tex, m_task->width, m_task->height, fmt))
        {
            m_task->pixels.pop_back();
            return false;
        }
        m_src_prev = raw_frame;

        // convert pixel format if it is not supported by exr
        if ((fmt & fcPixelFormat_TypeMask) == fcPixelFormat_Type_u8) {
            m_task->pixels.emplace_back(Buffer());
            auto *buf = &m_task->pixels.back();

            int channels = fmt & fcPixelFormat_ChannelMask;
            auto src_fmt = fmt;
            fmt = fcPixelFormat(fcPixelFormat_Type_f16 | channels);
            buf->resize(m_task->width * m_task->height * fcGetPixelSize(fmt));
            fcConvertPixelFormat(&(*buf)[0], fmt, &(*raw_frame)[0], src_fmt, m_task->width * m_task->height);

            m_src_prev = raw_frame = buf;
        }

        m_fmt_prev = fmt;
    }

    return addLayerImpl(&(*raw_frame)[0], fmt, channel, name);
}
コード例 #2
0
bool fcGraphicsDeviceD3D9::readTexture(void *o_buf, size_t bufsize, void *tex_, int width, int height, fcTextureFormat format)
{
    HRESULT hr;
    IDirect3DTexture9 *tex = (IDirect3DTexture9*)tex_;

    // D3D11 と同様 render target の内容は CPU からはアクセス不可能になっている。
    // staging texture を用意してそれに内容を移し、CPU はそれ経由でデータを読む。
    IDirect3DSurface9 *surf_dst = findOrCreateStagingTexture(width, height, format);
    if (surf_dst == nullptr) { return false; }

    IDirect3DSurface9* surf_src = nullptr;
    hr = tex->GetSurfaceLevel(0, &surf_src);
    if (FAILED(hr)){ return false; }

    bool ret = false;
    hr = m_device->GetRenderTargetData(surf_src, surf_dst);
    if (SUCCEEDED(hr))
    {
        D3DLOCKED_RECT locked;
        hr = surf_dst->LockRect(&locked, nullptr, D3DLOCK_READONLY);
        if (SUCCEEDED(hr))
        {
            char *wpixels = (char*)o_buf;
            int wpitch = width * fcGetPixelSize(format);
            const char *rpixels = (const char*)locked.pBits;
            int rpitch = locked.Pitch;

            // D3D11 と同様表向き解像度と内部解像度が違うケースを考慮
            // (しかし、少なくとも手元の環境では常に wpitch == rpitch っぽい)
            if (wpitch == rpitch)
            {
                memcpy(wpixels, rpixels, bufsize);
            }
            else
            {
                for (int i = 0; i < height; ++i)
                {
                    memcpy(wpixels, rpixels, wpitch);
                    wpixels += wpitch;
                    rpixels += rpitch;
                }
            }
            surf_dst->UnlockRect();

            // D3D9 の ARGB32 のピクセルの並びは BGRA になっているので並べ替える
            if (format == fcTextureFormat_ARGB32) {
                BGRA_RGBA_conversion((RGBA<uint8_t>*)o_buf, bufsize / 4);
            }
            ret = true;
        }
    }

    surf_src->Release();
    return ret;
}
コード例 #3
0
bool fcExrContext::addLayerTexture(void *tex, fcTextureFormat fmt, int channel, const char *name, bool flipY)
{
    std::string *raw_frame = nullptr;

    // フレームバッファの内容取得
    if (tex == m_tex_prev)
    {
        // 前回取得した結果を使い回す
        raw_frame = &m_exr->raw_frames.back();
    }
    else
    {
        m_tex_prev = tex;
        m_exr->raw_frames.push_back(std::string());
        raw_frame = &m_exr->raw_frames.back();
        raw_frame->resize(m_exr->width * m_exr->height * fcGetPixelSize(fmt));
        if (!m_dev->readTexture(&(*raw_frame)[0], raw_frame->size(), tex, m_exr->width, m_exr->height, fmt))
        {
            m_exr->raw_frames.pop_back();
            return false;
        }
        if (flipY) {
            fcImageFlipY(&(*raw_frame)[0], m_exr->width, m_exr->height, m_exr->width * fcGetPixelSize(fmt));
        }
    }

    {
        Imf::PixelType pixel_type = Imf::HALF;
        int channels = 0;
        int tsize = 0;
        switch (fmt)
        {
        case fcTextureFormat_ARGBHalf:  pixel_type = Imf::HALF; channels = 4; tsize = 2; break;
        case fcTextureFormat_RGHalf:    pixel_type = Imf::HALF; channels = 2; tsize = 2; break;
        case fcTextureFormat_RHalf:     pixel_type = Imf::HALF; channels = 1; tsize = 2; break;
        case fcTextureFormat_ARGBFloat: pixel_type = Imf::FLOAT; channels = 4; tsize = 4; break;
        case fcTextureFormat_RGFloat:   pixel_type = Imf::FLOAT; channels = 2; tsize = 4; break;
        case fcTextureFormat_RFloat:    pixel_type = Imf::FLOAT; channels = 1; tsize = 4; break;
        case fcTextureFormat_ARGBInt:   pixel_type = Imf::UINT; channels = 4; tsize = 4; break;
        case fcTextureFormat_RGInt:     pixel_type = Imf::UINT; channels = 2; tsize = 4; break;
        case fcTextureFormat_RInt:      pixel_type = Imf::UINT; channels = 1; tsize = 4; break;
        default:
            m_exr->raw_frames.pop_back();
            return false;
        }
        int psize = tsize * channels;

        char *raw_data = &(*raw_frame)[0];
        m_exr->header.channels().insert(name, Imf::Channel(pixel_type));
        m_exr->frame_buffer.insert(name, Imf::Slice(pixel_type, raw_data + (tsize * channel), psize, psize * m_exr->width));
    }
    return true;
}
コード例 #4
0
ファイル: PixelFormat.cpp プロジェクト: ArieLeo/FrameCapturer
void fcImageFlipY(void *image_, int width, int height, fcPixelFormat fmt)
{
    size_t pitch = width * fcGetPixelSize(fmt);
    Buffer buf_((size_t)pitch);
    char *image = (char*)image_;
    char *buf = &buf_[0];

    for (int y = 0; y < height / 2; ++y) {
        int iy = height - y - 1;
        memcpy(buf, image + (pitch*y), pitch);
        memcpy(image + (pitch*y), image + (pitch*iy), pitch);
        memcpy(image + (pitch*iy), buf, pitch);
    }
}
コード例 #5
0
bool fcGraphicsDeviceD3D9::writeTexture(void *o_tex, int width, int height, fcTextureFormat format, const void *buf, size_t bufsize)
{
    int psize = fcGetPixelSize(format);
    int pitch = psize * width;
    const size_t num_pixels = bufsize / psize;

    HRESULT hr;
    IDirect3DTexture9 *tex = (IDirect3DTexture9*)o_tex;

    // D3D11 と違い、D3D9 では書き込みも staging texture を経由する必要がある。
    IDirect3DSurface9 *surf_src = findOrCreateStagingTexture(width, height, format);
    if (surf_src == nullptr) { return false; }

    IDirect3DSurface9* surf_dst = nullptr;
    hr = tex->GetSurfaceLevel(0, &surf_dst);
    if (FAILED(hr)){ return false; }

    bool ret = false;
    D3DLOCKED_RECT locked;
    hr = surf_src->LockRect(&locked, nullptr, D3DLOCK_DISCARD);
    if (SUCCEEDED(hr))
    {
        const char *rpixels = (const char*)buf;
        int rpitch = psize * width;
        char *wpixels = (char*)locked.pBits;
        int wpitch = locked.Pitch;

        // こちらも ARGB32 の場合 BGRA に並べ替える必要がある
        if (format == fcTextureFormat_ARGB32) {
            copy_with_BGRA_RGBA_conversion((RGBA<uint8_t>*)wpixels, (RGBA<uint8_t>*)rpixels, bufsize / 4);
        }
        else {
            memcpy(wpixels, rpixels, bufsize);
        }
        surf_src->UnlockRect();

        hr = m_device->UpdateSurface(surf_src, nullptr, surf_dst, nullptr);
        if (SUCCEEDED(hr)) {
            ret = true;
        }
    }
    surf_dst->Release();

    return false;
}
コード例 #6
0
bool fcExrContext::addLayerPixels(const void *pixels, fcPixelFormat fmt, int channel, const char *name)
{
    if (m_task == nullptr) {
        fcDebugLog("fcExrContext::addLayerPixels(): maybe beginFrame() is not called.");
        return false;
    }

    Buffer *raw_frame = nullptr;

    if (pixels == m_frame_prev)
    {
        raw_frame = m_src_prev;
        fmt = m_fmt_prev;
    }
    else
    {
        m_frame_prev = pixels;

        m_task->pixels.emplace_back(Buffer());
        raw_frame = &m_task->pixels.back();

        if (m_conf.pixel_format == fcExrPixelFormat::Half) {
            auto src_fmt = fmt;
            int channels = fmt & fcPixelFormat_ChannelMask;
            fmt = fcPixelFormat(fcPixelFormat_Type_f16 | channels);
            raw_frame->resize(m_task->width * m_task->height * fcGetPixelSize(fmt));
            if (src_fmt != fmt) {
                fcConvertPixelFormat(raw_frame->data(), fmt, pixels, src_fmt, m_task->width * m_task->height);
            }
            else {
                memcpy(raw_frame->data(), pixels, raw_frame->size());
            }
        }
        else if (m_conf.pixel_format == fcExrPixelFormat::Float) {
            auto src_fmt = fmt;
            int channels = fmt & fcPixelFormat_ChannelMask;
            fmt = fcPixelFormat(fcPixelFormat_Type_f32 | channels);
            raw_frame->resize(m_task->width * m_task->height * fcGetPixelSize(fmt));
            if (src_fmt != fmt) {
                fcConvertPixelFormat(raw_frame->data(), fmt, pixels, src_fmt, m_task->width * m_task->height);
            }
            else {
                memcpy(raw_frame->data(), pixels, raw_frame->size());
            }

        }
        else if (m_conf.pixel_format == fcExrPixelFormat::Int) {
            auto src_fmt = fmt;
            int channels = fmt & fcPixelFormat_ChannelMask;
            fmt = fcPixelFormat(fcPixelFormat_Type_i32 | channels);
            raw_frame->resize(m_task->width * m_task->height * fcGetPixelSize(fmt));
            if (src_fmt != fmt) {
                fcConvertPixelFormat(raw_frame->data(), fmt, pixels, src_fmt, m_task->width * m_task->height);
            }
            else {
                memcpy(raw_frame->data(), pixels, raw_frame->size());
            }

        }
        else { // adaptive
            // convert pixel format if it is not supported by exr
            if ((fmt & fcPixelFormat_TypeMask) == fcPixelFormat_Type_u8) {
                auto src_fmt = fmt;
                int channels = fmt & fcPixelFormat_ChannelMask;
                fmt = fcPixelFormat(fcPixelFormat_Type_f16 | channels);
                raw_frame->resize(m_task->width * m_task->height * fcGetPixelSize(fmt));
                fcConvertPixelFormat(raw_frame->data(), fmt, pixels, src_fmt, m_task->width * m_task->height);
            }
            else {
                raw_frame->resize(m_task->width * m_task->height * fcGetPixelSize(fmt));
                memcpy(raw_frame->data(), pixels, raw_frame->size());
            }
        }

        m_src_prev = raw_frame;
        m_fmt_prev = fmt;
    }

    return addLayerImpl(raw_frame->data(), fmt, channel, name);
}