Decoding Images¶
Decoding¶
Unpack the compressed image data as described below.
UINT32 nWidth, nHeight, nLineBytes;
USHORT q[PUC_Q_COUNT];
UINT8* pDecodeBuf;
result = PUC_GetResolution(hDevice, &nWidth, &nHeight);
if (PUC_CHK_FAILED(result))
{
return;
}
for (UINT32 i = 0; i < PUC_Q_COUNT; i++)
{
result = PUC_GetQuantization(hDevice, i, &q[i]);
if (PUC_CHK_FAILED(result))
{
return;
}
}
nLineBytes = nWidth % 4 == 0 ? nWidth : nWidth + (4 - nWidth % 4);
pDecodeBuf = new UINT8[nLineBytes * nHeight];
result = PUC_DecodeData(pDecodeBuf, 0, 0, nWidth, nHeight, nLineBytes, xferData.pData, q);
if (PUC_CHK_FAILED(result))
{
return;
}
The decoded image can be saved as a bitmap as shown below.
UINT32 nInfoBytes;
BITMAPINFO* pBitmapInfo;
DWORD nPixelBytes;
BITMAPFILEHEADER fileHeader;
FILE* fp;
nInfoBytes = sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 256);
pBitmapInfo = (BITMAPINFO*)new BYTE[nInfoBytes];
nPixelBytes = nLineBytes * nHeight;
memset(pBitmapInfo, 0, nInfoBytes);
pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pBitmapInfo->bmiHeader.biWidth = nWidth;
pBitmapInfo->bmiHeader.biHeight = -(INT32)nHeight;
pBitmapInfo->bmiHeader.biPlanes = 1;
pBitmapInfo->bmiHeader.biBitCount = 8;
pBitmapInfo->bmiHeader.biCompression = BI_RGB;
pBitmapInfo->bmiHeader.biSizeImage = nPixelBytes;
pBitmapInfo->bmiHeader.biClrUsed = 256;
for (int i = 0; i < 256; i++)
{
pBitmapInfo->bmiColors[i].rgbRed = (BYTE)i;
pBitmapInfo->bmiColors[i].rgbGreen = (BYTE)i;
pBitmapInfo->bmiColors[i].rgbBlue = (BYTE)i;
}
memset(&fileHeader, 0, sizeof(fileHeader));
fileHeader.bfType = ('M' << 8) + 'B';
fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + nInfoBytes + nPixelBytes;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + nInfoBytes;
_tfopen_s(&fp, _T("test.bmp"), _T("wb"));
fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(pBitmapInfo, nInfoBytes, 1, fp);
fwrite(pDecodeBuf, nPixelBytes, 1, fp);
fclose(fp);
delete[] pBitmapInfo;
Note
As pixels are arranged top to bottom, the height of the “BITMAPINFOHEADER” is specified with a minus.
The width of the image must be a multiple of 4.
Fast decoding with multi-threading¶
The PUC_DecodeDataMultiThread function is provided to decode the specified range in block units in parallel. The arguments are almost the same as for the PUC_DecodeData function, but the number of threads can be specified at the end. Specify the appropriate number of threads according to the performance of the CPU.
The maximum number of threads is PUC_MAX_DECODE_THREAD_COUNT. You cannot specify more than that.
It is also possible to execute the PUC_DecodeDataMultiThread function in parallel, but since the SDK’s internal thread limit is PUC_MAX_DECODE_THREAD_COUNT, so if this limit is exceeded, the function will wait until there is room in the thread.”
Note
For smaller resolutions, specify the appropriate number of threads, as decoding may be slower than normal decoding.
Decode only DC data¶
Unpack DC data from the compressed image data as described below. The image data is divided into 8 x 8 pixels blocks. Specify the decode range with block number in the X and Y directions and execute.
UINT32 nBlockCountX, nBlockCountY, nLineBytes;
UINT8* pDecodeDCBuf;
nLineBytes = nWidth % 4 == 0 ? nWidth : nWidth + (4 - nWidth % 4);
nBlockCountX = nLineBytes % 8 == 0 ? nLineBytes / 8 : (nLineBytes + 7) / 8;
nBlockCountY = nHeight % 8 == 0 ? nHeight / 8 : (nHeight + 7) / 8;
pDecodeDCBuf = new UINT8[nBlockCountX * nBlockCountY];
result = PUC_DecodeDCData(pDecodeDCBuf, 0, 0, nBlockCountX, nBlockCountY, xferData.pData);
if (PUC_CHK_FAILED(result))
{
return;
}
Note
The image data is divided into 8x8 pixel blocks, and the decoding range is executed by specifying the block numbers in the X and Y directions.