0

I came across this example and couldn't figure out how to change stream->InitializeFromFilename to something that outputs to STDOUT, inside the HRESULT SavePixelsToFile32bppPBGRA(UINT width, UINT height, UINT stride, LPBYTE pixels, LPWSTR filePath, const GUID &format) function. Tried using stream->InitializeFromMemory but hit a wall due to minimal C++ experience.

Reasons behind this is that i'm building something and would like to pipe the stdout of the example using something else.

Regards in advance

hawaii
  • 328
  • 4
  • 12
  • Does this answer your question? [How to display an image using C++ right in console window?](https://stackoverflow.com/questions/38322397/how-to-display-an-image-using-c-right-in-console-window) Well it's less than 10 line code if you are willing to use some framework like [Qt](https://stackoverflow.com/questions/1357960/qt-jpg-image-display). But I don't think you'll be outputting it on `stdout`. It will be a different screen. – brc-dd Sep 08 '20 at 05:37
  • What do you mean by "outputs to STDOUT" in the Windows context? Do you want to "display" the image in the console or output its bits? – Simon Mourier Sep 09 '20 at 06:20
  • would like to do something like cout << stream (or byte array); but just cant figure out how to do this with wic. the png image generated appears to only contain header information when trying to use the memory method from wic. must be doing something wrong – hawaii Sep 09 '20 at 09:29
  • You can't stream out WIC decoding to the output. But you can build a memory buffer using CreateStreamOnHGlobal, then InitializeFromIStream then write using WIC as in sample, then convert IStream to std::osstream: http://www.cplusplus.com/forum/windows/193777/ – Simon Mourier Sep 09 '20 at 12:54
  • thanks @SimonMourier ill attempt that – hawaii Sep 09 '20 at 13:56
  • hi @SimonMourier! I was able to update your snippet to output the generated image to the required ostream. Thanks for the help. Will try using desktop duplication api now, since the performance still isn't enough. But at least this is already doing what was needed. – hawaii Sep 09 '20 at 19:39

1 Answers1

0

Thanks to @SimonMourier, I was able to update his code to achieve what was needed.

SavePixelsToFile32bppPBGRA now writes the data to an IStream pointer, streamOut. It also invokes a new function at the end, to output data.

HRESULT SavePixelsToFile32bppPBGRA(UINT width, UINT height, UINT stride, LPBYTE pixels, const GUID& format)
{
    if (!pixels)
        return E_INVALIDARG;

    HRESULT hr = S_OK;
    IWICImagingFactory* factory = nullptr;
    IWICBitmapEncoder* encoder = nullptr;
    IWICBitmapFrameEncode* frame = nullptr;
    IWICStream* streamOut = nullptr;
    IStream * streamIn = nullptr;
    GUID pf = GUID_WICPixelFormat32bppPBGRA;
    BOOL coInit = CoInitialize(nullptr);

    HRCHECK(CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory)));
    HRCHECK(factory->CreateStream(&streamOut));
    HRCHECK(CreateStreamOnHGlobal(NULL, true, &streamIn));
    HRCHECK(streamOut->InitializeFromIStream(streamIn));
    HRCHECK(factory->CreateEncoder(format, nullptr, &encoder));
    HRCHECK(encoder->Initialize(streamOut, WICBitmapEncoderNoCache));
    HRCHECK(encoder->CreateNewFrame(&frame, nullptr)); // we don't use options here
    HRCHECK(frame->Initialize(nullptr)); // we dont' use any options here
    HRCHECK(frame->SetSize(width, height));
    HRCHECK(frame->SetPixelFormat(&pf));
    HRCHECK(frame->WritePixels(height, stride, stride * height, pixels));
    HRCHECK(frame->Commit());
    HRCHECK(encoder->Commit());

    sendIStreamToOutput(streamOut);

cleanup:
    RELEASE(streamIn);
    RELEASE(streamOut);
    RELEASE(frame);
    RELEASE(encoder);
    RELEASE(factory);
    if (coInit) CoUninitialize();
    return hr;
}

sendIStreamToOutput reads the data from the IStream and writes it to std::cout (with binary mode active).

void sendIStreamToOutput (IStream * pIStream) {

    STATSTG sts;
    pIStream->Stat(&sts, STATFLAG_DEFAULT);
    ULARGE_INTEGER uli = sts.cbSize;
    LARGE_INTEGER zero;
    zero.QuadPart = 0;
    ULONG size = (ULONG)uli.QuadPart;
    char* bits = new char[size];
    ULONG written;
    pIStream->Seek(zero, STREAM_SEEK_SET, NULL);
    pIStream->Read(bits, size, &written);
    
    std::ostream& lhs = std::cout;

    _setmode(_fileno(stdout), _O_BINARY);

    lhs.write(bits, size);

    fflush(stdout);

    delete[] bits;
 }
hawaii
  • 328
  • 4
  • 12