mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-15 12:33:21 +08:00
303 lines
7.8 KiB
C++
303 lines
7.8 KiB
C++
/*! \file ImageRaw3.cpp
|
|
* \brief Implementation of CImageRaw3
|
|
*
|
|
* \author Nikolay.Pogorskiy@avsmedia.net
|
|
*/
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "gdiplus.h"
|
|
#include "ImageRaw3.h"
|
|
#include "ImageRawATLError.h"
|
|
#include "..\..\..\..\AVSVideoStudio3\Common\ImageStudioUtils.h"
|
|
#include "ImageRawCommon.h"
|
|
|
|
#define _RET_ERROR_IR3(HR) return CImageRawATLError::Error(hr = (HR),__uuidof(IImageRaw3))
|
|
|
|
#define _RET_IR3(HR) if (FAILED(hr = (HR))) \
|
|
_RET_ERROR_IR3(hr); \
|
|
else \
|
|
return hr;
|
|
|
|
#define _CHECK_RET_IR3(HR) do {_CHECK_HR(hr = (HR)); if (FAILED(hr)){ _RET_IR3(hr);}} while(0);
|
|
|
|
|
|
|
|
void CImageRaw3::_ExtractImage()
|
|
{
|
|
|
|
}
|
|
|
|
STDMETHODIMP CImageRaw3::OpenFile(BSTR fileName)
|
|
{
|
|
_HR;
|
|
_CHECK_RET_IR3(m_imageraw_core._open(fileName));
|
|
_CHECK_RET_IR3(m_imageraw_core._load(&m_OptionsSimple));
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CImageRaw3::ApplyXML(BSTR bsSettingXML,LONG lMode)
|
|
{
|
|
return m_OptionsSimple.OpenXML(bsSettingXML);
|
|
}
|
|
|
|
STDMETHODIMP CImageRaw3::GetXML(BSTR * bsSettingXML, LONG lMode)
|
|
{
|
|
if (!bsSettingXML)
|
|
return E_POINTER;
|
|
|
|
return m_OptionsSimple.CopyXMLTo(bsSettingXML);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CImageRaw3::GetMetaData(BSTR * bsMetaDataXML)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CImageRaw3::GetPreviewImage(IUnknown** piUncFrame)
|
|
{
|
|
_HR;
|
|
unsigned char * ppm = NULL;
|
|
CComQIPtr<MediaCore::IAVSUncompressedVideoFrame> pMediaData;
|
|
UINT nWidth,nHeight,nColors;
|
|
|
|
/*m_OptionsSimple.UseTemperature = true;
|
|
m_OptionsSimple.Temperature.temperature = 5000;
|
|
m_OptionsSimple.Temperature.green = 1.0;*/
|
|
|
|
_CHECK_RET_IR3(m_imageraw_core._get_preview(&m_OptionsSimple,(void **)&ppm,&nWidth,&nHeight,&nColors));
|
|
|
|
CAutoMemPtr_<unsigned char> auto_data(ppm);
|
|
|
|
// ñîçäàåì ýêçåìïëÿð ìåäèàäàòû
|
|
if FAILED(hr = pMediaData.CoCreateInstance(MediaCore::CLSID_CAVSUncompressedVideoFrame))
|
|
return hr;
|
|
|
|
int nBufferSize = 3*nWidth*nHeight;
|
|
pMediaData->put_ColorSpace(CSP_BGR);
|
|
pMediaData->put_Width(nWidth);
|
|
pMediaData->put_Height(nHeight);
|
|
pMediaData->put_AspectRatioX(nWidth);
|
|
pMediaData->put_AspectRatioY(nHeight);
|
|
pMediaData->put_Interlaced(VARIANT_FALSE);
|
|
pMediaData->put_Stride(0, 3*nWidth);
|
|
if FAILED(hr = pMediaData->AllocateBuffer(nBufferSize))
|
|
return hr;
|
|
|
|
long nCreatedBufferSize = 0;
|
|
BYTE * pBufferPtr = NULL;
|
|
pMediaData->get_Buffer(&pBufferPtr);
|
|
pMediaData->get_BufferSize(&nCreatedBufferSize);
|
|
if (nCreatedBufferSize != nBufferSize)
|
|
return E_IMAGERAW(IMAGERAW_MEMORY_ERROR);
|
|
|
|
//pMediaData->put_Plane(0, pBufferPtr);
|
|
|
|
|
|
memcpy_s(pBufferPtr,nCreatedBufferSize,ppm,3*nWidth*nHeight);
|
|
|
|
hr = pMediaData.CopyTo((MediaCore::IAVSUncompressedVideoFrame**)piUncFrame);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CImageRaw3::LoadPPMThumbnail(BYTE * thumb_data, size_t thumb_size, IUnknown** piUnkFrame)
|
|
{
|
|
/*FILE * f = fopen("c:\\ppm_thumb.ppm","w");
|
|
fwrite(thumb_data, thumb_size, 1, f);
|
|
fclose(f);*/
|
|
return E_IMAGERAW(IMAGERAW_UNSUPPORTEDTHUMBFORMAT_ERROR);
|
|
}
|
|
|
|
HRESULT CImageRaw3::LoadGdiplusThumbnail(BYTE * thumb_data, size_t thumb_size, IUnknown** piUnkFrame)
|
|
{
|
|
_HR;
|
|
INT flip,tmpI;
|
|
Bitmap * bitmap;
|
|
CComQIPtr<MediaCore::IAVSUncompressedVideoFrame> pMediaData;
|
|
UINT nWidth,nHeight;
|
|
Gdiplus::Status gdi_state;
|
|
void * pMem = NULL;
|
|
|
|
if (!piUnkFrame)
|
|
return E_POINTER;
|
|
|
|
*piUnkFrame = NULL;
|
|
|
|
CAutoMemPtr_<BYTE> auto_thumb_data(thumb_data);
|
|
|
|
// thumbnail íå çàãðóæåí
|
|
if (!thumb_data || !thumb_size)
|
|
return E_IMAGERAW(IMAGERAW_LOAD_THUMBNAIL_ERROR);
|
|
|
|
// ñîçäàåì stream, ÷òîáû ïîòîì ïðî÷èòàòü èç íåãî èçîáðàæåíèå ÷åðåç Gdi+
|
|
// âûäåëÿåì ïîä stream ãëîáàëüíóþ ïàìÿòü
|
|
HGLOBAL hgMem = ::GlobalAlloc(GHND,thumb_size);
|
|
if (!hgMem)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// äëÿ àâòîìàòè÷åñêîãî îñâîáîæäåíèÿ
|
|
CAutoHGLOBALFree auto_hgMem(hgMem);
|
|
|
|
// çàïîëíÿåì ïàìÿòü
|
|
if (!(pMem = ::GlobalLock(hgMem)))
|
|
return E_IMAGERAW(IMAGERAW_MEMORY_ERROR);
|
|
|
|
if (memcpy_s(pMem,thumb_size,auto_thumb_data,thumb_size))
|
|
return E_IMAGERAW(IMAGERAW_MEMORY_ERROR);
|
|
|
|
if (::GlobalUnlock(hgMem))
|
|
return E_IMAGERAW(IMAGERAW_MEMORY_ERROR);
|
|
|
|
CComPtr<IStream> spStream;
|
|
// ñîçäàåì stream, êîòîðûé àâòîìàòè÷åñêè îñîâîáîäèò ïàìÿòü hgMem íà Release
|
|
if FAILED(hr = ::CreateStreamOnHGlobal(hgMem,TRUE,&spStream))
|
|
return E_IMAGERAW(IMAGERAW_UNEXPECTED_ERROR);
|
|
|
|
// áîëüøå íå òðåáóåòñÿ ñîïðîâîæäàòü ïàìÿòü, òàê êàê òåïåðü ñîïðîâîæäàåòñÿ îáúåêòîì stream
|
|
auto_hgMem.Detach();
|
|
|
|
// ñîçäàåì áèòìàï è ïûòàåìñÿ ïðî÷èòàòü â íåãî èç ñòðèìà
|
|
bitmap = new Bitmap(spStream);
|
|
std::auto_ptr<Bitmap> _bitmap_ptr(bitmap);
|
|
|
|
if (!bitmap)
|
|
return E_IMAGERAW(IMAGERAW_UNEXPECTED_ERROR);
|
|
|
|
if ((gdi_state = bitmap->GetLastStatus() )!= Gdiplus::Status::Ok)
|
|
return E_IMAGERAW(IMAGERAW_DECODE_THUMBNAIL_ERROR);
|
|
|
|
// ñîçäàåì ýêçåìïëÿð ìåäèàäàòû
|
|
if FAILED(hr = pMediaData.CoCreateInstance(MediaCore::CLSID_CAVSUncompressedVideoFrame))
|
|
return hr;
|
|
|
|
// çàïîëíÿåì ïîëÿ ìåäèàäàòû
|
|
nWidth = bitmap->GetWidth();
|
|
nHeight = bitmap->GetHeight();
|
|
|
|
// ó÷èòûâàåì îðèåíòàöèþ êàìåðû
|
|
// todo: âîçìîæíî, íåêîòîðûå êàìåðû çàïèñûâàþò thumbnail â óæå ñêîððåêòèðîâàíîé îðèåíòàöèè
|
|
switch(flip = m_imageraw_core._get_dcraw()->flip)
|
|
{
|
|
case 1:/* Flip horizontal */
|
|
bitmap->RotateFlip(RotateNoneFlipX);
|
|
break;
|
|
case 2: /* Flip vertical */
|
|
bitmap->RotateFlip(RotateNoneFlipY);
|
|
break;
|
|
case 3: /* Rotate 180 */
|
|
bitmap->RotateFlip(Rotate180FlipNone);
|
|
break;
|
|
|
|
// \todo Flip over diagonal "\"
|
|
case 4:
|
|
break;
|
|
|
|
case 5: /* Rotate 270 */
|
|
tmpI = nWidth; nWidth = nHeight; nHeight = tmpI;
|
|
bitmap->RotateFlip(Rotate270FlipNone);
|
|
break;
|
|
|
|
case 6: /* Rotate 90 */
|
|
tmpI = nWidth; nWidth = nHeight; nHeight = tmpI;
|
|
bitmap->RotateFlip(Rotate90FlipNone);
|
|
break;
|
|
|
|
// \todo Flip over diagonal "/"
|
|
case 7:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
int nBufferSize = 4*nWidth*nHeight;
|
|
pMediaData->put_ColorSpace(CSP_BGRA | CSP_VFLIP);
|
|
pMediaData->put_Width(nWidth);
|
|
pMediaData->put_Height(nHeight);
|
|
pMediaData->put_AspectRatioX(nWidth);
|
|
pMediaData->put_AspectRatioY(nHeight);
|
|
pMediaData->put_Interlaced(VARIANT_FALSE);
|
|
pMediaData->put_Stride(0, 4*nWidth);
|
|
if FAILED(hr = pMediaData->AllocateBuffer(nBufferSize))
|
|
return hr;
|
|
|
|
long nCreatedBufferSize = 0;
|
|
BYTE * pBufferPtr = NULL;
|
|
pMediaData->get_Buffer(&pBufferPtr);
|
|
pMediaData->get_BufferSize(&nCreatedBufferSize);
|
|
if (nCreatedBufferSize != nBufferSize)
|
|
return E_IMAGERAW(IMAGERAW_MEMORY_ERROR);
|
|
|
|
pMediaData->put_Plane(0, pBufferPtr);
|
|
|
|
if FAILED(hr = ImageRaw3::ImageToMemory(bitmap,pBufferPtr))
|
|
return hr;
|
|
|
|
// êîïèðóåì èçîáðàæåíèå èç bitmap-à
|
|
return pMediaData.CopyTo((MediaCore::IAVSUncompressedVideoFrame**)piUnkFrame);
|
|
|
|
}
|
|
|
|
STDMETHODIMP CImageRaw3::GetThumbnailImage(IUnknown** piUnkFrame)
|
|
{
|
|
_HR;
|
|
BYTE * thumb_data;
|
|
size_t thumb_size;
|
|
|
|
if (!piUnkFrame)
|
|
return E_POINTER;
|
|
|
|
*piUnkFrame = NULL;
|
|
|
|
_CHECK_RET_IR3(m_imageraw_core._get_thumbnail((void**)&thumb_data, &thumb_size));
|
|
|
|
bool isPPMThumbnail = false;
|
|
_CHECK_RET_IR3(m_imageraw_core._is_ppm_thumbnail(&isPPMThumbnail));
|
|
|
|
if (!isPPMThumbnail)
|
|
return LoadGdiplusThumbnail(thumb_data, thumb_size, piUnkFrame);
|
|
else
|
|
return LoadPPMThumbnail(thumb_data, thumb_size, piUnkFrame);
|
|
|
|
}
|
|
|
|
STDMETHODIMP CImageRaw3::RenderImage(IUnknown** piUncFrame)
|
|
{
|
|
piVideoFrame->AddRef();
|
|
*piUncFrame = piVideoFrame;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CImageRaw3::SetAdditionalParam(BSTR ParamName, VARIANT ParamValue)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CImageRaw3::GetAdditionalParam(BSTR ParamName, VARIANT* ParamValue)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CImageRaw3::CloseFile(void)
|
|
{
|
|
HRESULT hr;
|
|
_CHECK_RET_IR3(m_imageraw_core._close());
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CImageRaw3::LoadThumbnail(BSTR fileName, IUnknown** piUncFrame)
|
|
{
|
|
_HR;
|
|
|
|
if (!piUncFrame)
|
|
return E_POINTER;
|
|
|
|
_CHECK_RET_IR3(m_imageraw_core._open(fileName));
|
|
hr = GetThumbnailImage(piUncFrame);
|
|
_CHECK_RET_IR3(m_imageraw_core._close());
|
|
return hr;
|
|
}
|