mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-15 15:20:04 +08:00
179 lines
5.0 KiB
C++
179 lines
5.0 KiB
C++
/*! \file ImageRawRoutines.cpp
|
|
*
|
|
* \brief Âñïîìîãàòåëüíûå ôóíêöèè
|
|
*/
|
|
#include "stdafx.h"
|
|
#include "gdiplus.h"
|
|
using namespace Gdiplus;
|
|
|
|
namespace ImageRaw3{
|
|
|
|
HRESULT ImageToMemory(Bitmap* pBitmap, BYTE* pPixels)
|
|
{
|
|
HRESULT hr;
|
|
BOOL Flipped;
|
|
if (!pBitmap || !pPixels)
|
|
return E_POINTER;
|
|
|
|
// pre-flip the image
|
|
|
|
|
|
|
|
Flipped = (pBitmap->RotateFlip(RotateNoneFlipY) == Ok);
|
|
|
|
// create locking settings
|
|
Rect rectLock(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
|
|
BitmapData* pBitmapData = new BitmapData();
|
|
|
|
if (!pBitmapData)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// variables
|
|
BOOL Success = FALSE;
|
|
int nX, nY, nIndex = 0;
|
|
int nOffset = 0;
|
|
|
|
// try to process 24bpp image first
|
|
|
|
// lock the bitmap bits
|
|
if ((pBitmap->GetPixelFormat() == PixelFormat1bppIndexed ||
|
|
pBitmap->GetPixelFormat() == PixelFormat4bppIndexed ||
|
|
pBitmap->GetPixelFormat() == PixelFormat16bppGrayScale ||
|
|
pBitmap->GetPixelFormat() == PixelFormat16bppRGB555 ||
|
|
pBitmap->GetPixelFormat() == PixelFormat16bppRGB565 ||
|
|
pBitmap->GetPixelFormat() == PixelFormat24bppRGB ||
|
|
pBitmap->GetPixelFormat() == PixelFormat32bppRGB ) &&
|
|
pBitmap->LockBits(&rectLock, ImageLockModeRead, PixelFormat24bppRGB, pBitmapData) == Ok)
|
|
{
|
|
// compute stride value
|
|
int nStride = pBitmapData->Stride;
|
|
if (!Flipped) nStride *= -1;
|
|
|
|
// retrieve pointer to the locked bits
|
|
BYTE* pBitmapPixels = (BYTE*)pBitmapData->Scan0;
|
|
|
|
// copy pixel info
|
|
long lH = (int)pBitmap->GetHeight();
|
|
long lW = (int)pBitmap->GetWidth();
|
|
for (nY = 0; nY < lH; ++nY)
|
|
{
|
|
nOffset = (nStride < 0) ? (lH - 1 - nY)*(-nStride) : nY*nStride;
|
|
|
|
for (nX = 0; nX < lW; ++nX, nIndex += 4, nOffset += 3)
|
|
{
|
|
pPixels[nIndex + 0] = pBitmapPixels[nOffset + 0];
|
|
pPixels[nIndex + 1] = pBitmapPixels[nOffset + 1];
|
|
pPixels[nIndex + 2] = pBitmapPixels[nOffset + 2];
|
|
pPixels[nIndex + 3] = 255;
|
|
}
|
|
}
|
|
|
|
// unlock the bits
|
|
pBitmap->UnlockBits(pBitmapData);
|
|
|
|
// update output flag
|
|
Success = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// lock the bitmap bits
|
|
if (pBitmap->LockBits(&rectLock, ImageLockModeRead, PixelFormat32bppARGB, pBitmapData) == Ok)
|
|
{
|
|
// compute stride value
|
|
int nStride = pBitmapData->Stride; if (!Flipped) nStride *= -1;
|
|
|
|
// retrieve pointer to the locked bits
|
|
BYTE* pBitmapPixels = (BYTE*)pBitmapData->Scan0;
|
|
|
|
// copy pixel info
|
|
long lH = (int)pBitmap->GetHeight();
|
|
long lW = (int)pBitmap->GetWidth();
|
|
// copy pixel info
|
|
for (nY = 0; nY < (int)lH; ++nY)
|
|
{
|
|
nOffset = (nStride < 0) ? (lH - 1 - nY)*(-nStride) : nY*nStride;
|
|
|
|
for (nX = 0; nX < (int)lW; ++nX, nIndex += 4, nOffset += 4)
|
|
{
|
|
pPixels[nIndex + 0] = pBitmapPixels[nOffset + 0];
|
|
pPixels[nIndex + 1] = pBitmapPixels[nOffset + 1];
|
|
pPixels[nIndex + 2] = pBitmapPixels[nOffset + 2];
|
|
pPixels[nIndex + 3] = pBitmapPixels[nOffset + 3];
|
|
}
|
|
}
|
|
|
|
// unlock the bits
|
|
pBitmap->UnlockBits(pBitmapData);
|
|
|
|
// update output flag
|
|
Success = TRUE;
|
|
}
|
|
}
|
|
|
|
// delete unnecessary bitmap data pointer
|
|
if (pBitmapData)
|
|
delete pBitmapData;
|
|
|
|
// raise error (if necessary)
|
|
return Success?S_OK:E_FAIL;
|
|
}
|
|
|
|
|
|
static const double XYZ_to_RGB[3][3] = {{ 3.24071, -0.969258, 0.0556352 },{-1.53726, 1.87599, -0.203996 },{-0.498571, 0.0415557, 1.05707 } };
|
|
/*! \brief Convert between Temperature and RGB.
|
|
*
|
|
* \details Base on information from http://www.brucelindbloom.com/
|
|
* The fit for D-illuminant between 4000K and 15000K are from CIE
|
|
* The generalization to 2000K < T < 4000K and the blackbody fits
|
|
* are my own and should be taken with a grain of salt.
|
|
*/
|
|
void Temperature_to_RGB(double T, double RGB[3])
|
|
{
|
|
int c;
|
|
double xD, yD, X, Y, Z, max;
|
|
// Fit for CIE Daylight illuminant
|
|
if (T<= 4000) {
|
|
xD = 0.27475e9/(T*T*T) - 0.98598e6/(T*T) + 1.17444e3/T + 0.145986;
|
|
} else if (T<= 7000) {
|
|
xD = -4.6070e9/(T*T*T) + 2.9678e6/(T*T) + 0.09911e3/T + 0.244063;
|
|
} else {
|
|
xD = -2.0064e9/(T*T*T) + 1.9018e6/(T*T) + 0.24748e3/T + 0.237040;
|
|
}
|
|
yD = -3*xD*xD + 2.87*xD - 0.275;
|
|
|
|
// Fit for Blackbody using CIE standard observer function at 2 degrees
|
|
//xD = -1.8596e9/(T*T*T) + 1.37686e6/(T*T) + 0.360496e3/T + 0.232632;
|
|
//yD = -2.6046*xD*xD + 2.6106*xD - 0.239156;
|
|
|
|
// Fit for Blackbody using CIE standard observer function at 10 degrees
|
|
//xD = -1.98883e9/(T*T*T) + 1.45155e6/(T*T) + 0.364774e3/T + 0.231136;
|
|
//yD = -2.35563*xD*xD + 2.39688*xD - 0.196035;
|
|
|
|
X = xD/yD;
|
|
Y = 1;
|
|
Z = (1-xD-yD)/yD;
|
|
max = 0;
|
|
for (c=0; c<3; c++) {
|
|
RGB[c] = X*XYZ_to_RGB[0][c] + Y*XYZ_to_RGB[1][c] + Z*XYZ_to_RGB[2][c];
|
|
if (RGB[c]>max) max = RGB[c];
|
|
}
|
|
for (c=0; c<3; c++) RGB[c] = RGB[c]/max;
|
|
}
|
|
|
|
void RGB_to_Temperature(double RGB[3], float *T, float *Green)
|
|
{
|
|
double Tmax, Tmin, testRGB[3];
|
|
Tmin = 2000;
|
|
Tmax = 15000;
|
|
for (*T=(Tmax+Tmin)/2; Tmax-Tmin>10; *T=(Tmax+Tmin)/2)
|
|
{
|
|
Temperature_to_RGB(*T, testRGB);
|
|
if (testRGB[2]/testRGB[0] > RGB[2]/RGB[0])
|
|
Tmax = *T;
|
|
else
|
|
Tmin = *T;
|
|
}
|
|
*Green = (testRGB[1]/testRGB[0]) / (RGB[1]/RGB[0]);
|
|
}
|
|
|
|
}; |