mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-04-07 13:55:33 +08:00
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@62364 954022d7-b5bf-4e40-9824-e11837661b57
846 lines
24 KiB
C++
846 lines
24 KiB
C++
#include "Common.h"
|
|
|
|
#include "../../raster/ImageFileFormatChecker.h"
|
|
#include "../../raster/BgraFrame.h"
|
|
|
|
namespace MetaFile
|
|
{
|
|
unsigned char GetLowestBit(unsigned int ulValue)
|
|
{
|
|
if (0 == ulValue)
|
|
return 0;
|
|
|
|
unsigned char unOffset = 0;
|
|
unsigned int ulBit = 1;
|
|
while (!(ulValue & ulBit))
|
|
{
|
|
ulBit = ulBit << 1;
|
|
unOffset++;
|
|
|
|
// îãðàíè÷èâàåìñÿ 32-áèòàìè
|
|
if (ulBit & 0x80000000)
|
|
return 0;
|
|
}
|
|
|
|
return unOffset;
|
|
}
|
|
bool ReadImageCoreHeader(BYTE* pHeaderBuffer, unsigned int ulHeaderBufferLen, BYTE* pImageBuffer, unsigned int ulImageBufferLen, BYTE** ppDstBuffer, unsigned int* pulWidth, unsigned int* pulHeight)
|
|
{
|
|
CDataStream oHeaderStream;
|
|
oHeaderStream.SetStream(pHeaderBuffer, ulHeaderBufferLen);
|
|
|
|
unsigned short ushWidth;
|
|
unsigned short ushHeight;
|
|
unsigned short ushPlanes;
|
|
unsigned short ushBitCount;
|
|
|
|
oHeaderStream >> ushWidth;
|
|
oHeaderStream >> ushHeight;
|
|
oHeaderStream >> ushPlanes;
|
|
oHeaderStream >> ushBitCount;
|
|
|
|
if (0x0001 != ushPlanes)
|
|
return false;
|
|
|
|
return false;
|
|
}
|
|
bool ReadImageInfoHeader(BYTE* pHeaderBuffer, unsigned int ulHeaderBufferLen, BYTE* pImageBuffer, unsigned int ulImageBufferLen, BYTE** ppDstBuffer, unsigned int* pulWidth, unsigned int* pulHeight)
|
|
{
|
|
CDataStream oHeaderStream;
|
|
oHeaderStream.SetStream(pHeaderBuffer, ulHeaderBufferLen);
|
|
|
|
int nWidth;
|
|
int nHeight;
|
|
|
|
unsigned short ushPlanes;
|
|
unsigned short ushBitCount;
|
|
|
|
unsigned int unCompression;
|
|
unsigned int unImageSize;
|
|
unsigned int unXPelsPerMeter;
|
|
unsigned int unYPelsPerMeter;
|
|
unsigned int unColorUsed;
|
|
unsigned int unColorImportant;
|
|
|
|
oHeaderStream >> nWidth;
|
|
oHeaderStream >> nHeight;
|
|
oHeaderStream >> ushPlanes;
|
|
oHeaderStream >> ushBitCount;
|
|
oHeaderStream >> unCompression;
|
|
oHeaderStream >> unImageSize;
|
|
oHeaderStream >> unXPelsPerMeter;
|
|
oHeaderStream >> unYPelsPerMeter;
|
|
oHeaderStream >> unColorUsed;
|
|
oHeaderStream >> unColorImportant;
|
|
|
|
if (0x0001 != ushPlanes)
|
|
return false;
|
|
|
|
if (nHeight < 0x00000000 && (BI_RGB != unCompression))
|
|
return false;
|
|
|
|
if (nWidth < 0)
|
|
return false;
|
|
|
|
BYTE* pBgraBuffer = NULL;
|
|
unsigned int ulWidth = 0;
|
|
unsigned int ulHeight = 0;
|
|
|
|
BYTE* pBuffer = pImageBuffer;
|
|
int lBufLen = ulImageBufferLen;
|
|
|
|
*ppDstBuffer = NULL;
|
|
*pulWidth = 0;
|
|
*pulHeight = 0;
|
|
|
|
if (BI_BITCOUNT_0 == ushBitCount) // Çíà÷èò êîìïðåññèÿ ëèáî PNG, ëèáî JPEG
|
|
{
|
|
if (BI_JPEG != unCompression || BI_PNG != unCompression)
|
|
return false;
|
|
|
|
std::wstring wsTempFileName;
|
|
FILE* pTempFile = NULL;
|
|
if (!WmfOpenTempFile(&wsTempFileName, &pTempFile, L"wb", L".wmf0", NULL))
|
|
return false;
|
|
|
|
::fwrite(pBuffer, 1, unImageSize, pTempFile);
|
|
::fclose(pTempFile);
|
|
|
|
CBgraFrame oFrame;
|
|
oFrame.OpenFile(wsTempFileName);
|
|
|
|
// TODO: Êàê áóäóò ôàéëû ñäåëàòü ÷òåíèå.
|
|
NSFile::CFileBinary::Remove(wsTempFileName);
|
|
return false;
|
|
}
|
|
else if (BI_BITCOUNT_1 == ushBitCount)
|
|
{
|
|
// Äâóöâåòíàÿ êàðòèíêà, çíà÷èò ïàëèòðà ñîñòîèò èç 2-õ öâåòîâ
|
|
TRgbQuad oColor1, oColor2;
|
|
oHeaderStream >> oColor1 >> oColor2;
|
|
|
|
// Ñ÷èòûâàåì ñàìó êàðòèíêó
|
|
int lCalcLen = (((nWidth * ushPlanes * ushBitCount + 31) & ~31) / 8) * abs(nHeight);
|
|
if (lCalcLen > lBufLen)
|
|
return false;
|
|
|
|
pBgraBuffer = new BYTE[nWidth * abs(nHeight) * 4 * sizeof(BYTE)];
|
|
if (NULL == pBgraBuffer)
|
|
return false;
|
|
|
|
ulHeight = (unsigned short)abs(nHeight);
|
|
ulWidth = (unsigned short)nWidth;
|
|
|
|
int nWidthBytes = (nWidth + 7) / 8;
|
|
int nAdditBytes = 4 - div_t(div(((nWidth + 7) / 8), 4)).rem;
|
|
if (4 == nAdditBytes)
|
|
nAdditBytes = 0;
|
|
|
|
int nLastBitCount = div_t(div(nWidth, 8)).rem - 1;
|
|
if (-1 == nLastBitCount)
|
|
nLastBitCount = 7;
|
|
|
|
nLastBitCount = (int)pow((double)2, (double)nLastBitCount);
|
|
|
|
if (nHeight < 0)
|
|
{
|
|
for (int nY = 0; nY < abs(nHeight); nY++)
|
|
{
|
|
int nIndex = 4 * nWidth * nY;
|
|
for (int nX = 0; nX < nWidthBytes; nX++)
|
|
{
|
|
int nByte = *pBuffer; pBuffer++; lBufLen--;
|
|
int nBitCount = 128;
|
|
if (nX == nWidthBytes - 1)
|
|
nBitCount = nLastBitCount;
|
|
|
|
for (int nBitIndex = nBitCount; nBitIndex > 0; nBitIndex /= 2)
|
|
{
|
|
int nBit = (nByte & nBitIndex);
|
|
TRgbQuad* pColor = (nBit ? &oColor2 : &oColor1);
|
|
pBgraBuffer[nIndex + 0] = pColor->b;
|
|
pBgraBuffer[nIndex + 1] = pColor->g;
|
|
pBgraBuffer[nIndex + 2] = pColor->r;
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
nIndex += 4;
|
|
}
|
|
}
|
|
for (int nAddIndex = 0; nAddIndex < nAdditBytes; nAddIndex++)
|
|
{
|
|
int nByte = *pBuffer; pBuffer++; lBufLen--;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int nY = abs(nHeight) - 1; nY >= 0; nY--)
|
|
{
|
|
int nIndex = 4 * nWidth * nY;
|
|
for (int nX = 0; nX < nWidthBytes; nX++)
|
|
{
|
|
int nByte = *pBuffer; pBuffer++; lBufLen--;
|
|
int nBitCount = 128;
|
|
if (nX == nWidthBytes - 1)
|
|
nBitCount = nLastBitCount;
|
|
|
|
for (int nBitIndex = nBitCount; nBitIndex > 0; nBitIndex /= 2)
|
|
{
|
|
int nBit = (nByte & nBitIndex);
|
|
TRgbQuad* pColor = (nBit ? &oColor2 : &oColor1);
|
|
pBgraBuffer[nIndex + 0] = pColor->b;
|
|
pBgraBuffer[nIndex + 1] = pColor->g;
|
|
pBgraBuffer[nIndex + 2] = pColor->r;
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
nIndex += 4;
|
|
}
|
|
}
|
|
for (int nAddIndex = 0; nAddIndex < nAdditBytes; nAddIndex++)
|
|
{
|
|
int nByte = *pBuffer; pBuffer++; lBufLen--;
|
|
}
|
|
}
|
|
}
|
|
|
|
*ppDstBuffer = pBgraBuffer;
|
|
*pulWidth = ulWidth;
|
|
*pulHeight = ulHeight;
|
|
|
|
return true;
|
|
}
|
|
else if (BI_BITCOUNT_2 == ushBitCount)
|
|
{
|
|
unsigned char unColorTableLen = 16;
|
|
if (0 != unColorUsed)
|
|
unColorTableLen = (std::min)((unsigned char)16, (unsigned char)unColorUsed);
|
|
|
|
TRgbQuad oColorTable[16];
|
|
if (oHeaderStream.CanRead() < unColorTableLen * 4)
|
|
return false;
|
|
|
|
// Ñ÷èòûâàåì ïàëèòðó
|
|
for (unsigned short ushIndex = 0; ushIndex < unColorTableLen; ushIndex++)
|
|
{
|
|
oHeaderStream >> oColorTable[ushIndex];
|
|
}
|
|
|
|
// 4 áèòà - 1 ïèêñåë
|
|
|
|
// Ñ÷èòûâàåì ñàìó êàðòèíêó
|
|
int lCalcLen = (((nWidth * ushPlanes * ushBitCount + 31) & ~31) / 8) * abs(nHeight);
|
|
if (lCalcLen != lBufLen)
|
|
return false;
|
|
|
|
// Øèðèíà â áàéòàõ äîëæíà áûòü êðàòíà 4, çíà÷èò ñàìà øèðèíà äîëæíà áûòü êðàòíà 8
|
|
int nAdd = 0;
|
|
while (0 != div_t(div(nWidth + nAdd, 8)).rem)
|
|
{
|
|
nAdd++;
|
|
}
|
|
|
|
int nScanLineBytes = (nWidth + nAdd) / 2;
|
|
if (lBufLen < (nScanLineBytes * abs(nHeight)))
|
|
return false;
|
|
|
|
pBgraBuffer = new BYTE[nWidth * abs(nHeight) * 4 * sizeof(BYTE)];
|
|
if (NULL == pBgraBuffer)
|
|
return false;
|
|
|
|
ulHeight = (unsigned short)abs(nHeight);
|
|
ulWidth = (unsigned short)nWidth;
|
|
|
|
if (nHeight < 0)
|
|
{
|
|
for (int nY = 0; nY < abs(nHeight); nY++)
|
|
{
|
|
for (int nLineIndex = 0; nLineIndex < nScanLineBytes; nLineIndex++)
|
|
{
|
|
BYTE nByte = *pBuffer; pBuffer++;
|
|
|
|
int nX = nLineIndex * 2;
|
|
int nIndex = 4 * (nWidth * nY + nX);
|
|
BYTE nColorIndex = (nByte & 0xf0) >> 4;
|
|
|
|
if (nX < nWidth)
|
|
{
|
|
pBgraBuffer[nIndex + 0] = oColorTable[nColorIndex].b;
|
|
pBgraBuffer[nIndex + 1] = oColorTable[nColorIndex].g;
|
|
pBgraBuffer[nIndex + 2] = oColorTable[nColorIndex].r;
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
}
|
|
|
|
nX = nLineIndex * 2 + 1;
|
|
nIndex = 4 * (nWidth * nY + nX);
|
|
nColorIndex = nByte & 0x0f;
|
|
|
|
if (nX < nWidth)
|
|
{
|
|
pBgraBuffer[nIndex + 0] = oColorTable[nColorIndex].b;
|
|
pBgraBuffer[nIndex + 1] = oColorTable[nColorIndex].g;
|
|
pBgraBuffer[nIndex + 2] = oColorTable[nColorIndex].r;
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int nY = abs(nHeight) - 1; nY >= 0; nY--)
|
|
{
|
|
for (int nLineIndex = 0; nLineIndex < nScanLineBytes; nLineIndex++)
|
|
{
|
|
BYTE nByte = *pBuffer; pBuffer++;
|
|
|
|
int nX = nLineIndex * 2;
|
|
int nIndex = 4 * (nWidth * nY + nX);
|
|
BYTE nColorIndex = (nByte & 0xf0) >> 4;
|
|
|
|
if (nX < nWidth)
|
|
{
|
|
pBgraBuffer[nIndex + 0] = oColorTable[nColorIndex].b;
|
|
pBgraBuffer[nIndex + 1] = oColorTable[nColorIndex].g;
|
|
pBgraBuffer[nIndex + 2] = oColorTable[nColorIndex].r;
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
}
|
|
|
|
nX = nLineIndex * 2 + 1;
|
|
nIndex = 4 * (nWidth * nY + nX);
|
|
nColorIndex = nByte & 0x0f;
|
|
|
|
if (nX < nWidth)
|
|
{
|
|
pBgraBuffer[nIndex + 0] = oColorTable[nColorIndex].b;
|
|
pBgraBuffer[nIndex + 1] = oColorTable[nColorIndex].g;
|
|
pBgraBuffer[nIndex + 2] = oColorTable[nColorIndex].r;
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
*ppDstBuffer = pBgraBuffer;
|
|
*pulWidth = ulWidth;
|
|
*pulHeight = ulHeight;
|
|
|
|
return true;
|
|
}
|
|
else if (BI_BITCOUNT_3 == ushBitCount)
|
|
{
|
|
unsigned short ushColorTableLen = 256;
|
|
|
|
if (0 != unColorUsed)
|
|
ushColorTableLen = (std::min)((unsigned short)256, (unsigned short)unColorUsed);
|
|
|
|
TRgbQuad oColorTable[256];
|
|
if (oHeaderStream.CanRead() < ushColorTableLen * 4)
|
|
return false;
|
|
|
|
// Ñ÷èòûâàåì ïàëèòðó
|
|
for (unsigned short ushIndex = 0; ushIndex < ushColorTableLen; ushIndex++)
|
|
{
|
|
oHeaderStream >> oColorTable[ushIndex];
|
|
}
|
|
|
|
// 1 áàéò - 1 ïèêñåë
|
|
// Øèðèíà äîëæíà áûòü êðàòíà 4.
|
|
int nAdd = 0;
|
|
while (0 != div_t(div(nWidth + nAdd, 4)).rem)
|
|
{
|
|
nAdd++;
|
|
}
|
|
|
|
if (lBufLen < (nWidth + nAdd) * abs(nHeight))
|
|
return false;
|
|
|
|
pBgraBuffer = new BYTE[nWidth * abs(nHeight) * 4 * sizeof(BYTE)];
|
|
if (NULL == pBgraBuffer)
|
|
return false;
|
|
|
|
ulHeight = (unsigned short)abs(nHeight);
|
|
ulWidth = (unsigned short)nWidth;
|
|
|
|
if (nHeight < 0)
|
|
{
|
|
for (int nY = 0; nY < abs(nHeight); nY++)
|
|
{
|
|
for (int nX = 0; nX < nWidth; nX++)
|
|
{
|
|
int nIndex = 4 * (nWidth * nY + nX);
|
|
|
|
BYTE nByte = *pBuffer; pBuffer++; lBufLen--;
|
|
|
|
pBgraBuffer[nIndex + 0] = oColorTable[nByte].b;
|
|
pBgraBuffer[nIndex + 1] = oColorTable[nByte].g;
|
|
pBgraBuffer[nIndex + 2] = oColorTable[nByte].r;
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
}
|
|
pBuffer += nAdd; lBufLen -= nAdd;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int nY = abs(nHeight) - 1; nY >= 0; nY--)
|
|
{
|
|
for (int nX = 0; nX < nWidth; nX++)
|
|
{
|
|
int nIndex = 4 * (nWidth * nY + nX);
|
|
|
|
BYTE nByte = *pBuffer; pBuffer++; lBufLen--;
|
|
|
|
pBgraBuffer[nIndex + 0] = oColorTable[nByte].b;
|
|
pBgraBuffer[nIndex + 1] = oColorTable[nByte].g;
|
|
pBgraBuffer[nIndex + 2] = oColorTable[nByte].r;
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
}
|
|
pBuffer += nAdd; lBufLen -= nAdd;
|
|
}
|
|
}
|
|
|
|
*ppDstBuffer = pBgraBuffer;
|
|
*pulWidth = ulWidth;
|
|
*pulHeight = ulHeight;
|
|
|
|
return true;
|
|
}
|
|
else if (BI_BITCOUNT_4 == ushBitCount)
|
|
{
|
|
unsigned int ulMaskR = 0x1f, ulMaskB = 0x7C00, ulMaskG = 0x3E0;
|
|
unsigned int ulShiftR = 0, ulShiftB = 10, ulShiftG = 5;
|
|
double dKoefR = 255 / 31.0, dKoefB = 255 / 31.0, dKoefG = 255 / 31.0;
|
|
|
|
if (BI_RGB == unCompression)
|
|
{
|
|
// Ìàñêè, ñäâèãè è êîýôôèöèåíòû óæå çàïîëíåíû ñòàíäàðòíûìè çíà÷åíèÿìè äëÿ ìàñîê
|
|
// 000000000011111 - Red
|
|
// 000001111100000 - Green
|
|
// 111110000000000 - Blue
|
|
}
|
|
else if (BI_BITFIELDS == unCompression)
|
|
{
|
|
oHeaderStream >> ulMaskB;
|
|
oHeaderStream >> ulMaskG;
|
|
oHeaderStream >> ulMaskR;
|
|
|
|
ulShiftR = GetLowestBit(ulMaskR);
|
|
ulShiftB = GetLowestBit(ulMaskB);
|
|
ulShiftG = GetLowestBit(ulMaskG);
|
|
|
|
dKoefR = 255.0 / (ulMaskR >> ulShiftR);
|
|
dKoefG = 255.0 / (ulMaskG >> ulShiftG);
|
|
dKoefB = 255.0 / (ulMaskB >> ulShiftB);
|
|
}
|
|
else
|
|
return false;
|
|
|
|
// Ñ÷èòûâàåì ñàìó êàðòèíêó
|
|
int lCalcLen = (((nWidth * ushPlanes * ushBitCount + 31) & ~31) / 8) * abs(nHeight);
|
|
if (lCalcLen != lBufLen)
|
|
return false;
|
|
|
|
// 2 áàéò íà âñå êàíàëû êàíàë
|
|
// (Øèðèíà * 3) äîëæíà áûòü êðàòíà 4.
|
|
int nAdd = 0;
|
|
while (0 != div_t(div(2 * nWidth + nAdd, 4)).rem)
|
|
{
|
|
nAdd++;
|
|
}
|
|
|
|
pBgraBuffer = new BYTE[nWidth * abs(nHeight) * 4 * sizeof(BYTE)];
|
|
if (NULL == pBgraBuffer)
|
|
return false;
|
|
|
|
ulHeight = (unsigned short)abs(nHeight);
|
|
ulWidth = (unsigned short)nWidth;
|
|
|
|
if (nHeight < 0)
|
|
{
|
|
for (int nY = 0; nY < abs(nHeight); nY++)
|
|
{
|
|
for (int nX = 0; nX < nWidth; nX++)
|
|
{
|
|
int nIndex = 4 * (nWidth * nY + nX);
|
|
|
|
unsigned short ushValue = ((pBuffer[1] << 8) | pBuffer[0]) & 0xFFFF; pBuffer += 2; lBufLen -= 2;
|
|
|
|
unsigned char unR = (ushValue & ulMaskR) >> ulShiftR;
|
|
unsigned char unG = (ushValue & ulMaskG) >> ulShiftG;
|
|
unsigned char unB = (ushValue & ulMaskB) >> ulShiftB;
|
|
|
|
pBgraBuffer[nIndex + 0] = (unsigned char)(unR * dKoefR);
|
|
pBgraBuffer[nIndex + 1] = (unsigned char)(unG * dKoefG);
|
|
pBgraBuffer[nIndex + 2] = (unsigned char)(unB * dKoefB);
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
}
|
|
pBuffer += nAdd; lBufLen -= nAdd;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int nY = abs(nHeight) - 1; nY >= 0; nY--)
|
|
{
|
|
for (int nX = 0; nX < nWidth; nX++)
|
|
{
|
|
int nIndex = 4 * (nWidth * nY + nX);
|
|
|
|
unsigned short ushValue = ((pBuffer[1] << 8) | pBuffer[0]) & 0xFFFF; pBuffer += 2; lBufLen -= 2;
|
|
unsigned char unR = (ushValue & ulMaskR) >> ulShiftR;
|
|
unsigned char unG = (ushValue & ulMaskG) >> ulShiftG;
|
|
unsigned char unB = (ushValue & ulMaskB) >> ulShiftB;
|
|
|
|
pBgraBuffer[nIndex + 0] = (unsigned char)(unR * dKoefR);
|
|
pBgraBuffer[nIndex + 1] = (unsigned char)(unG * dKoefG);
|
|
pBgraBuffer[nIndex + 2] = (unsigned char)(unB * dKoefB);
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
}
|
|
pBuffer += nAdd; lBufLen -= nAdd;
|
|
}
|
|
}
|
|
|
|
*ppDstBuffer = pBgraBuffer;
|
|
*pulWidth = ulWidth;
|
|
*pulHeight = ulHeight;
|
|
|
|
return false;
|
|
}
|
|
else if (BI_BITCOUNT_5 == ushBitCount)
|
|
{
|
|
if (BI_RGB != unCompression)
|
|
return false; // TODO: Ñäåëàòü äàííûé âàðèàíò, êàê òîëüêî áóäåò ôàéëû ñ äàííûì òèïîì
|
|
|
|
// Ñ÷èòûâàåì ñàìó êàðòèíêó
|
|
int lCalcLen = (((nWidth * ushPlanes * ushBitCount + 31) & ~31) / 8) * abs(nHeight);
|
|
if (lCalcLen != lBufLen)
|
|
return false;
|
|
|
|
// 1 áàéò íà êàæäûé êàíàë
|
|
// (Øèðèíà * 3) äîëæíà áûòü êðàòíà 4.
|
|
int nAdd = 0;
|
|
while (0 != div_t(div(3 * nWidth + nAdd, 4)).rem)
|
|
{
|
|
nAdd++;
|
|
}
|
|
|
|
int nSize = nWidth * nHeight * 4;
|
|
|
|
pBgraBuffer = new BYTE[nWidth * abs(nHeight) * 4 * sizeof(BYTE)];
|
|
if (NULL == pBgraBuffer)
|
|
return false;
|
|
|
|
ulHeight = (unsigned short)abs(nHeight);
|
|
ulWidth = (unsigned short)nWidth;
|
|
|
|
if (nHeight < 0)
|
|
{
|
|
for (int nY = 0; nY < abs(nHeight); nY++)
|
|
{
|
|
for (int nX = 0; nX < nWidth; nX++)
|
|
{
|
|
int nIndex = 4 * (nWidth * nY + nX);
|
|
|
|
pBgraBuffer[nIndex + 0] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 1] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 2] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
}
|
|
pBuffer += nAdd; lBufLen -= nAdd;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int nY = abs(nHeight) - 1; nY >= 0; nY--)
|
|
{
|
|
for (int nX = 0; nX < nWidth; nX++)
|
|
{
|
|
int nIndex = 4 * (nWidth * nY + nX);
|
|
pBgraBuffer[nIndex + 0] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 1] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 2] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 3] = 255;
|
|
}
|
|
pBuffer += nAdd; lBufLen -= nAdd;
|
|
}
|
|
}
|
|
|
|
*ppDstBuffer = pBgraBuffer;
|
|
*pulWidth = ulWidth;
|
|
*pulHeight = ulHeight;
|
|
|
|
return true;
|
|
}
|
|
else if (BI_BITCOUNT_6 == ushBitCount)
|
|
{
|
|
unsigned int ulMaskR = 0xff000000, ulMaskB = 0x00ff0000, ulMaskG = 0x0000ff00;
|
|
unsigned int ulShiftR = 24, ulShiftB = 16, ulShiftG = 8;
|
|
double dKoefR = 1.0, dKoefB = 1.0, dKoefG = 1.0;
|
|
bool bMask = false;
|
|
|
|
if (BI_RGB == unCompression)
|
|
{
|
|
// Ìàñêè, ñäâèãè è êîýôôèöèåíòû óæå çàïîëíåíû ñòàíäàðòíûìè çíà÷åíèÿìè äëÿ ìàñîê
|
|
}
|
|
else if (BI_BITFIELDS == unCompression)
|
|
{
|
|
if (oHeaderStream.CanRead() < 12)
|
|
return false;
|
|
|
|
oHeaderStream >> ulMaskB;
|
|
oHeaderStream >> ulMaskG;
|
|
oHeaderStream >> ulMaskR;
|
|
|
|
ulShiftR = GetLowestBit(ulMaskR);
|
|
ulShiftB = GetLowestBit(ulMaskB);
|
|
ulShiftG = GetLowestBit(ulMaskG);
|
|
|
|
dKoefR = 255.0 / (ulMaskR >> ulShiftR);
|
|
dKoefG = 255.0 / (ulMaskG >> ulShiftG);
|
|
dKoefB = 255.0 / (ulMaskB >> ulShiftB);
|
|
|
|
bMask = true;
|
|
}
|
|
else
|
|
return false;
|
|
|
|
// Ñ÷èòûâàåì ñàìó êàðòèíêó
|
|
int lCalcLen = (((nWidth * ushPlanes * ushBitCount + 31) & ~31) / 8) * abs(nHeight);
|
|
if (lCalcLen != lBufLen)
|
|
return false;
|
|
|
|
// 1 áàéò íà êàæäûé êàíàë
|
|
// Øèðèíà äîëæíà áûòü êðàòíà 4.
|
|
int nAdd = 0;
|
|
while (0 != div_t(div(nWidth + nAdd, 4)).rem)
|
|
{
|
|
nAdd++;
|
|
}
|
|
|
|
int nSize = nWidth * nHeight * 4;
|
|
|
|
pBgraBuffer = new BYTE[(nWidth + nAdd) * abs(nHeight) * 4 * sizeof(BYTE)];
|
|
if (NULL == pBgraBuffer)
|
|
return false;
|
|
|
|
ulHeight = (unsigned short)abs(nHeight);
|
|
ulWidth = (unsigned short)(nWidth + nAdd);
|
|
|
|
if (nHeight < 0)
|
|
{
|
|
for (int nY = 0; nY < abs(nHeight); nY++)
|
|
{
|
|
for (int nX = 0; nX < nWidth; nX++)
|
|
{
|
|
int nIndex = 4 * ((nWidth + nAdd) * nY + nX);
|
|
|
|
if (bMask)
|
|
{
|
|
unsigned int unValue = ((pBuffer[3] << 24) | (pBuffer[2] << 16) | (pBuffer[1] << 8) | pBuffer[0]) & 0xFFFFFFFF; pBuffer += 4; lBufLen -= 4;
|
|
|
|
unsigned char unR = (unValue & ulMaskR) >> ulShiftR;
|
|
unsigned char unG = (unValue & ulMaskG) >> ulShiftG;
|
|
unsigned char unB = (unValue & ulMaskB) >> ulShiftB;
|
|
|
|
pBgraBuffer[nIndex + 0] = (unsigned char)(unR * dKoefR);
|
|
pBgraBuffer[nIndex + 1] = (unsigned char)(unG * dKoefG);
|
|
pBgraBuffer[nIndex + 2] = (unsigned char)(unB * dKoefB);
|
|
pBgraBuffer[nIndex + 3] = pBuffer[3];
|
|
}
|
|
else
|
|
{
|
|
pBgraBuffer[nIndex + 0] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 1] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 2] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 3] = 255; pBuffer++; lBufLen--; // Åñëè áðàòü çíà÷åíèå èç êàðòèíêè, òîãäà îíà ïîëó÷àåòñÿ âñåãäà ïðîçðà÷íîé
|
|
}
|
|
}
|
|
for (int nX = nWidth; nX < nWidth + nAdd; nX++)
|
|
{
|
|
int nIndex = 4 * ((nWidth + nAdd) * nY + nX);
|
|
|
|
pBgraBuffer[nIndex + 0] = 255;
|
|
pBgraBuffer[nIndex + 1] = 255;
|
|
pBgraBuffer[nIndex + 2] = 255;
|
|
pBgraBuffer[nIndex + 3] = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int nY = abs(nHeight) - 1; nY >= 0; nY--)
|
|
{
|
|
for (int nX = 0; nX < nWidth; nX++)
|
|
{
|
|
int nIndex = 4 * ((nWidth + nAdd) * nY + nX);
|
|
if (bMask)
|
|
{
|
|
unsigned int unValue = ((pBuffer[3] << 24) | (pBuffer[2] << 16) | (pBuffer[1] << 8) | pBuffer[0]) & 0xFFFFFFFF; pBuffer += 4; lBufLen -= 4;
|
|
|
|
unsigned char unR = (unValue & ulMaskR) >> ulShiftR;
|
|
unsigned char unG = (unValue & ulMaskG) >> ulShiftG;
|
|
unsigned char unB = (unValue & ulMaskB) >> ulShiftB;
|
|
|
|
pBgraBuffer[nIndex + 0] = (unsigned char)(unR * dKoefR);
|
|
pBgraBuffer[nIndex + 1] = (unsigned char)(unG * dKoefG);
|
|
pBgraBuffer[nIndex + 2] = (unsigned char)(unB * dKoefB);
|
|
pBgraBuffer[nIndex + 3] = pBuffer[3];
|
|
}
|
|
else
|
|
{
|
|
pBgraBuffer[nIndex + 0] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 1] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 2] = pBuffer[0]; pBuffer++; lBufLen--;
|
|
pBgraBuffer[nIndex + 3] = 255; pBuffer++; lBufLen--; // Åñëè áðàòü çíà÷åíèå èç êàðòèíêè, òîãäà îíà ïîëó÷àåòñÿ âñåãäà ïðîçðà÷íîé
|
|
}
|
|
}
|
|
|
|
for (int nX = nWidth; nX < nWidth + nAdd; nX++)
|
|
{
|
|
int nIndex = 4 * ((nWidth + nAdd) * nY + nX);
|
|
|
|
pBgraBuffer[nIndex + 0] = 255;
|
|
pBgraBuffer[nIndex + 1] = 255;
|
|
pBgraBuffer[nIndex + 2] = 255;
|
|
pBgraBuffer[nIndex + 3] = 0;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
*ppDstBuffer = pBgraBuffer;
|
|
*pulWidth = ulWidth;
|
|
*pulHeight = ulHeight;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
void ReadImage(BYTE* pHeaderBuffer, unsigned int ulHeaderBufferLen, BYTE* pImageBuffer, unsigned int ulImageBufferLen, BYTE** ppDstBuffer, unsigned int* pulWidth, unsigned int* pulHeight)
|
|
{
|
|
if (ulHeaderBufferLen <= 0 || NULL == pHeaderBuffer || NULL == pImageBuffer || ulImageBufferLen < 0)
|
|
return;
|
|
|
|
CDataStream oHeaderStream;
|
|
oHeaderStream.SetStream(pHeaderBuffer, ulHeaderBufferLen);
|
|
|
|
// Ñ÷èòûâàåì çàãîëîâîê
|
|
unsigned int ulHeaderSize;
|
|
oHeaderStream >> ulHeaderSize;
|
|
|
|
if (ulHeaderSize < 0x0000000C)
|
|
return;
|
|
else if (0x0000000C == ulHeaderSize) // BitmapCoreHeader
|
|
ReadImageCoreHeader(pHeaderBuffer + 4, ulHeaderBufferLen - 4, pImageBuffer, ulImageBufferLen, ppDstBuffer, pulWidth, pulHeight);
|
|
else // BitmapInfoHeader
|
|
ReadImageInfoHeader(pHeaderBuffer + 4, ulHeaderBufferLen - 4, pImageBuffer, ulImageBufferLen, ppDstBuffer, pulWidth, pulHeight);
|
|
}
|
|
void ReadImage(BYTE* pImageBuffer, unsigned int unBufferLen, unsigned int unColorUsage, BYTE** ppDstBuffer, unsigned int* punWidth, unsigned int* punHeight)
|
|
{
|
|
if (unBufferLen <= 0 || NULL == pImageBuffer)
|
|
return;
|
|
|
|
CDataStream oHeaderStream;
|
|
oHeaderStream.SetStream(pImageBuffer, unBufferLen);
|
|
|
|
// Ñ÷èòûâàåì çàãîëîâîê
|
|
unsigned int unHeaderSize;
|
|
oHeaderStream >> unHeaderSize;
|
|
|
|
if (unHeaderSize > unBufferLen)
|
|
return;
|
|
else if (unHeaderSize < 0x0000000C)
|
|
return;
|
|
else if (0x0000000C == unHeaderSize) // BitmapCoreHeader
|
|
ReadImageCoreHeader(pImageBuffer + 4, unHeaderSize - 4, pImageBuffer + unHeaderSize, unBufferLen - unHeaderSize, ppDstBuffer, punWidth, punHeight);
|
|
else // BitmapInfoHeader
|
|
{
|
|
unsigned short ushBitCount;
|
|
unsigned int unColorUsed;
|
|
oHeaderStream.Skip(10);
|
|
oHeaderStream >> ushBitCount;
|
|
oHeaderStream.Skip(16);
|
|
oHeaderStream >> unColorUsed;
|
|
|
|
if (DIB_RGB_COLORS == unColorUsage)
|
|
{
|
|
if (0 == unColorUsed && BI_BITCOUNT_1 == ushBitCount)
|
|
unColorUsed = 2;
|
|
else if (0 == unColorUsed && BI_BITCOUNT_3 == ushBitCount)
|
|
unColorUsed = 256;
|
|
|
|
unHeaderSize += 4 * unColorUsed; // RGBQuad
|
|
ReadImageInfoHeader(pImageBuffer + 4, unHeaderSize - 4, pImageBuffer + unHeaderSize, unBufferLen - unHeaderSize, ppDstBuffer, punWidth, punHeight);
|
|
}
|
|
else
|
|
{
|
|
// TODO: ðåàëèçîâàòü äðóãèå òèïû öâåòîâ
|
|
}
|
|
}
|
|
}
|
|
double GetEllipseAngle(int nL, int nT, int nR, int nB, int nX, int nY)
|
|
{
|
|
double dX0 = (nL + nR) / 2.0;
|
|
double dY0 = (nT + nB) / 2.0;
|
|
|
|
// Îïðåäåëèì êâàäðàíò
|
|
int nQuarter = -1;
|
|
if (nX >= dX0)
|
|
{
|
|
if (nY <= dY0)
|
|
nQuarter = 3;
|
|
else
|
|
nQuarter = 0;
|
|
}
|
|
else
|
|
{
|
|
if (nY <= dY0)
|
|
nQuarter = 2;
|
|
else
|
|
nQuarter = 1;
|
|
}
|
|
|
|
double dDist = sqrt((double)(nX - dX0) * (nX - dX0) + (nY - dY0) * (nY - dY0));
|
|
double dRadAngle = asin(abs(nY - dY0) / dDist);
|
|
|
|
double dAngle = dRadAngle * 180 / 3.1415926;
|
|
switch (nQuarter)
|
|
{
|
|
case 1: dAngle = 180 - dAngle; break;
|
|
case 2: dAngle = 180 + dAngle; break;
|
|
case 3: dAngle = 360 - dAngle; break;
|
|
}
|
|
|
|
return dAngle;
|
|
}
|
|
void ProcessRasterOperation(unsigned int unRasterOperation, BYTE** ppBgra, unsigned int unWidth, unsigned int unHeight)
|
|
{
|
|
BYTE* pBgra = *ppBgra;
|
|
// Äëÿ áèòîâûõ îïåðàöèé SRCPAINT è SRCAND ñäåëàåì, êàê áóäòî ôîí ÷èñòî áåëûé.
|
|
if (0x008800C6 == unRasterOperation) // SRCPAINT
|
|
{
|
|
BYTE* pCur = pBgra;
|
|
for (unsigned int unY = 0; unY < unHeight; unY++)
|
|
{
|
|
for (unsigned int unX = 0; unX < unWidth; unX++)
|
|
{
|
|
unsigned int unIndex = (unY * unWidth + unX) * 4;
|
|
|
|
if (0xff == pCur[unIndex + 0] && 0xff == pCur[unIndex + 1] && 0xff == pCur[unIndex + 2])
|
|
pCur[unIndex + 3] = 0;
|
|
}
|
|
}
|
|
}
|
|
else if (0x00EE0086 == unRasterOperation) // SRCAND
|
|
{
|
|
BYTE* pCur = pBgra;
|
|
for (unsigned int unY = 0; unY < unHeight; unY++)
|
|
{
|
|
for (unsigned int unX = 0; unX < unWidth; unX++)
|
|
{
|
|
unsigned int unIndex = (unY * unWidth + unX) * 4;
|
|
|
|
if (0 == pCur[unIndex + 0] && 0 == pCur[unIndex + 1] && 0 == pCur[unIndex + 2])
|
|
pCur[unIndex + 3] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|