EDN Admin
Well-known member
Hi All,
Im have a need to create a PNG image within a plugin of a specified size (passed at time called) from scratch. The image will ideally be transparent and consist of a mix of boxes / text / etc. (no images).
After the image is created, I need to pass it back to the host environment as a byte / char string with the size of the buffer.
Ive spent the last couple of days trying to work this out. Im using the Windows Imaging Factory as thats used by the host environment also.
Below is my efforts so far - but to be honest I feel Ive taken a wrong path somewhere along the lines.
Id appreciate any help you could give to:
1) Create an image
2) Draw text / boxes in it
3) Convert it to a PNG stream
4) Return it with size and buffer
Thanks in advance
Kent
---------------------------------------------------------------------------------------------------------------unsigned char * returnPNGImage( long width, long height, long *outSize )
{
UINT cbBufferSize = 0;
BYTE *pv = NULL;
// Initialize COM
CoInitialize(NULL);
// The factory pointer
IWICImagingFactory *pFactory = NULL;
IWICBitmap *pBitmap = NULL;
UINT uiWidth = width;
UINT uiHeight = height;
WICPixelFormatGUID formatGUID = GUID_WICPixelFormat32bppBGRA;
WICRect rcLock = { 0, 0, uiWidth, uiHeight };
IWICBitmapLock *pLock = NULL;
// Create the COM imaging factory
HRESULT hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pFactory );
if (SUCCEEDED(hr))
{
hr = pFactory->CreateBitmap(uiWidth, uiHeight, formatGUID, WICBitmapCacheOnDemand, &pBitmap);
}
if (SUCCEEDED(hr))
{
hr = pBitmap->Lock(&rcLock, WICBitmapLockWrite, &pLock);
if (SUCCEEDED(hr))
{
UINT cbStride = 0;
hr = pLock->GetStride(&cbStride);
if (SUCCEEDED(hr))
{
hr = pLock->GetDataPointer(&cbBufferSize, &pv);
}
// Clear the image data
ZeroMemory(pv, cbBufferSize);
// Release the bitmap lock.
pLock->Release();
}
}
IWICStream *pStream;
if (SUCCEEDED(hr)) hr = pFactory->CreateStream(&pStream);
debugAppend("CreateStream", (long)SUCCEEDED(hr));
BYTE * outStream = new BYTE(cbBufferSize);
debugAppend("Out Stream", (long)outStream);
if (SUCCEEDED(hr)) hr = pStream->InitializeFromMemory(outStream, cbBufferSize);
debugAppend("InitializeFromMemory", (long)SUCCEEDED(hr));
IWICBitmapEncoder *pEncoder = NULL;
if (SUCCEEDED(hr)) hr = pFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &pEncoder);
debugAppend("CreateEncoder", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr)) hr = pEncoder->Initialize(pStream, WICBitmapEncoderNoCache);
debugAppend("Initialize", (long)SUCCEEDED(hr));
IWICBitmapFrameEncode * pFrame;
if (SUCCEEDED(hr)) hr = pEncoder->CreateNewFrame(&pFrame, nullptr);
debugAppend("CreateNewFrame", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr)) hr = pFrame->Initialize(nullptr);
debugAppend("Initialize", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr)) hr = pFrame->SetSize(width, height);
debugAppend("SetSize", (long)SUCCEEDED(hr));
GUID pixelFormat = GUID_WICPixelFormat32bppPBGRA;
if (SUCCEEDED(hr)) hr = pFrame->SetPixelFormat(&pixelFormat);
debugAppend("SetPixelFormat", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
BYTE* pByteData(new BYTE[4*width*height]);
BYTE* pData = pByteData.get();
memcpy(pData, pImageData->pByteData, 4*width*height);
// Loop through the bytes and convert from BGRA -> RGBA
for (UINT i = 0; i < width*height; i++) {
BYTE temp = pData[0];
pData[0] = pData[2];
pData[2] = temp;
pData += 4;
}
}
if (SUCCEEDED(hr)) hr = pFrame->WritePixels(height, 4*width, 4*width*height, pv);
debugAppend("WritePixels", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr)) hr = pFrame->Commit();
debugAppend("Commit", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr)) hr = pEncoder->Commit();
debugAppend("Commit", (long)SUCCEEDED(hr));
// --------------
if (pBitmap)
{
pBitmap->Release();
}
if (pFactory)
{
pFactory->Release();
}
unsigned char * outImage = pFactory->QueryInterface
*outSize = cbBufferSize;// return the size of our created buffer
return pv; // and the buffer itself
}
View the full article
Im have a need to create a PNG image within a plugin of a specified size (passed at time called) from scratch. The image will ideally be transparent and consist of a mix of boxes / text / etc. (no images).
After the image is created, I need to pass it back to the host environment as a byte / char string with the size of the buffer.
Ive spent the last couple of days trying to work this out. Im using the Windows Imaging Factory as thats used by the host environment also.
Below is my efforts so far - but to be honest I feel Ive taken a wrong path somewhere along the lines.
Id appreciate any help you could give to:
1) Create an image
2) Draw text / boxes in it
3) Convert it to a PNG stream
4) Return it with size and buffer
Thanks in advance
Kent
---------------------------------------------------------------------------------------------------------------unsigned char * returnPNGImage( long width, long height, long *outSize )
{
UINT cbBufferSize = 0;
BYTE *pv = NULL;
// Initialize COM
CoInitialize(NULL);
// The factory pointer
IWICImagingFactory *pFactory = NULL;
IWICBitmap *pBitmap = NULL;
UINT uiWidth = width;
UINT uiHeight = height;
WICPixelFormatGUID formatGUID = GUID_WICPixelFormat32bppBGRA;
WICRect rcLock = { 0, 0, uiWidth, uiHeight };
IWICBitmapLock *pLock = NULL;
// Create the COM imaging factory
HRESULT hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pFactory );
if (SUCCEEDED(hr))
{
hr = pFactory->CreateBitmap(uiWidth, uiHeight, formatGUID, WICBitmapCacheOnDemand, &pBitmap);
}
if (SUCCEEDED(hr))
{
hr = pBitmap->Lock(&rcLock, WICBitmapLockWrite, &pLock);
if (SUCCEEDED(hr))
{
UINT cbStride = 0;
hr = pLock->GetStride(&cbStride);
if (SUCCEEDED(hr))
{
hr = pLock->GetDataPointer(&cbBufferSize, &pv);
}
// Clear the image data
ZeroMemory(pv, cbBufferSize);
// Release the bitmap lock.
pLock->Release();
}
}
IWICStream *pStream;
if (SUCCEEDED(hr)) hr = pFactory->CreateStream(&pStream);
debugAppend("CreateStream", (long)SUCCEEDED(hr));
BYTE * outStream = new BYTE(cbBufferSize);
debugAppend("Out Stream", (long)outStream);
if (SUCCEEDED(hr)) hr = pStream->InitializeFromMemory(outStream, cbBufferSize);
debugAppend("InitializeFromMemory", (long)SUCCEEDED(hr));
IWICBitmapEncoder *pEncoder = NULL;
if (SUCCEEDED(hr)) hr = pFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &pEncoder);
debugAppend("CreateEncoder", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr)) hr = pEncoder->Initialize(pStream, WICBitmapEncoderNoCache);
debugAppend("Initialize", (long)SUCCEEDED(hr));
IWICBitmapFrameEncode * pFrame;
if (SUCCEEDED(hr)) hr = pEncoder->CreateNewFrame(&pFrame, nullptr);
debugAppend("CreateNewFrame", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr)) hr = pFrame->Initialize(nullptr);
debugAppend("Initialize", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr)) hr = pFrame->SetSize(width, height);
debugAppend("SetSize", (long)SUCCEEDED(hr));
GUID pixelFormat = GUID_WICPixelFormat32bppPBGRA;
if (SUCCEEDED(hr)) hr = pFrame->SetPixelFormat(&pixelFormat);
debugAppend("SetPixelFormat", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
BYTE* pByteData(new BYTE[4*width*height]);
BYTE* pData = pByteData.get();
memcpy(pData, pImageData->pByteData, 4*width*height);
// Loop through the bytes and convert from BGRA -> RGBA
for (UINT i = 0; i < width*height; i++) {
BYTE temp = pData[0];
pData[0] = pData[2];
pData[2] = temp;
pData += 4;
}
}
if (SUCCEEDED(hr)) hr = pFrame->WritePixels(height, 4*width, 4*width*height, pv);
debugAppend("WritePixels", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr)) hr = pFrame->Commit();
debugAppend("Commit", (long)SUCCEEDED(hr));
if (SUCCEEDED(hr)) hr = pEncoder->Commit();
debugAppend("Commit", (long)SUCCEEDED(hr));
// --------------
if (pBitmap)
{
pBitmap->Release();
}
if (pFactory)
{
pFactory->Release();
}
unsigned char * outImage = pFactory->QueryInterface
*outSize = cbBufferSize;// return the size of our created buffer
return pv; // and the buffer itself
}
View the full article