⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imagedecoder.cpp

📁 Evc下的图片解码类
💻 CPP
字号:
/*
ImageDecoder.cpp
  Class ImageDecoder Implementation, base upon imaging com interface.
*/

#include "ImageDecoder.h"
#include "debug.h"

ImageDecoder::ImageDecoder(TCHAR* ImageFileName)
{
	HRESULT hr;
	ImageInfo ii;

	lstrcpy(this->filename, ImageFileName);
	
	if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)))
    {
        DBGMSG(TEXT("CoInitializeEx failed, hr: 0x%08x\n"), hr);
		goto finish;
    }

	hr = CoCreateInstance(CLSID_ImagingFactory, 
                          NULL, 
                          CLSCTX_INPROC_SERVER, 
                          IID_IImagingFactory, 
                          (void**) &pImagingFactory);
    if(FAILED(hr))
    {
		DBGMSG(TEXT("CoCreateInstance failed, hr:0x08x\n"), hr);
		goto finish;
	}
	DBGMSG(TEXT("Opening %s"), filename);

	if(FAILED(hr = CreateStreamOnFile(filename, &pStream)))
	{
		DBGMSG(TEXT("CreateStreamOnFile failed, hr: 0x%08x\n"), hr);
		goto finish;
	}

	GetCodecCLSID(pImagingFactory, NULL, NULL, eDecoder);
	
	if(FAILED(hr = pImagingFactory->CreateImageDecoder(pStream, DecoderInitFlagBuiltIn1st, &pImageDecoder)))
	{
		DBGMSG(TEXT("CreateImageDecoder failed, hr: 0x%08x\n"), hr);
		goto finish;
	}
		
    if (FAILED(hr = pImageDecoder->GetFrameCount(&FrameDimensionTime, &nFrameCount)))
	{
        //DBGMSG(TEXT("GetFrameCount failed, hr: 0x%08x\n"), hr);
        nFrameCount = 0;
        //JPG file will fail this call, just pass it
		//goto finish;
	}

	pImageDecoder->GetImageInfo(&ii);
	
    this->ii = ii;

	if(FAILED(hr = pImagingFactory->CreateNewBitmap(ii.Width, ii.Height, ii.PixelFormat, &pBitmapImage)))
	{
		DBGMSG(TEXT("CreateNewBitmap failed, hr = 0x%08x\n"), hr);
		goto finish;
	}
	
	if(FAILED(hr = pBitmapImage->QueryInterface(IID_IImageSink, (void**)&pImageSink)))
	{
		DBGMSG(TEXT("QueryInterface for ImageSink from BitmapImage failed, hr: 0x%08x\n"), hr);
		goto finish;
	}
	
	if(FAILED(hr = pBitmapImage->QueryInterface(IID_IImage, (void**)&pImage)))
	{
		DBGMSG(TEXT("QueryInterface for Image from BitmapImage failed, hr: 0x%08x\n"), hr);
		goto finish;
	}

	if (FAILED(hr = pBitmapImage->QueryInterface(IID_IBasicBitmapOps, (void**)&pBasicBitmapOps)))
	{
		DBGMSG(TEXT("QueryInterface for BasicBitmapOps from BitmapImage failed, hr: 0x%08x\n"), hr);
		goto finish;
	}
	state = Init;
	goto finish_ok;

finish:
	state = UnInit;
finish_ok:
	Angle = 0;
	pBitmapImageRotate = NULL;
	pImageRotate = NULL;
    nSelectedFrame = 0;
	return;
}

ImageDecoder::ImageDecoder(HRSRC hRes)
{
	HRESULT hr;
	ImageInfo ii;

	//lstrcpy(this->filename, ImageFileName);
	
	if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)))
    {
        DBGMSG(TEXT("CoInitializeEx failed, hr: 0x%08x\n"), hr);
		goto finish;
    }

	hr = CoCreateInstance(CLSID_ImagingFactory, 
                          NULL, 
                          CLSCTX_INPROC_SERVER, 
                          IID_IImagingFactory, 
                          (void**) &pImagingFactory);
    if(FAILED(hr))
    {
		DBGMSG(TEXT("CoCreateInstance failed, hr:0x08x\n"), hr);
		goto finish;
	}
	
	//DBGMSG(TEXT("Opening %s"), filename);

	//if(FAILED(hr = CreateStreamOnFile(filename, &pStream)))
	if(FAILED(hr = CreateStreamOnResource(hRes, &pStream)))
	{
		DBGMSG(TEXT("CreateStreamOnFile failed, hr: 0x%08x\n"), hr);
		goto finish;
	}

	GetCodecCLSID(pImagingFactory, NULL, NULL, eDecoder);
	
	if(FAILED(hr = pImagingFactory->CreateImageDecoder(pStream, DecoderInitFlagBuiltIn1st, &pImageDecoder)))
	{
		DBGMSG(TEXT("CreateImageDecoder failed, hr: 0x%08x\n"), hr);
		goto finish;
	}
		
    if (FAILED(hr = pImageDecoder->GetFrameCount(&FrameDimensionTime, &nFrameCount)))
	{
        //DBGMSG(TEXT("GetFrameCount failed, hr: 0x%08x\n"), hr);
        nFrameCount = 0;
        //JPG file will fail this call, just pass it
		//goto finish;
	}

	pImageDecoder->GetImageInfo(&ii);
	
    this->ii = ii;

	if(FAILED(hr = pImagingFactory->CreateNewBitmap(ii.Width, ii.Height, ii.PixelFormat, &pBitmapImage)))
	{
		DBGMSG(TEXT("CreateNewBitmap failed, hr = 0x%08x\n"), hr);
		goto finish;
	}
	
	if(FAILED(hr = pBitmapImage->QueryInterface(IID_IImageSink, (void**)&pImageSink)))
	{
		DBGMSG(TEXT("QueryInterface for ImageSink from BitmapImage failed, hr: 0x%08x\n"), hr);
		goto finish;
	}
	
	if(FAILED(hr = pBitmapImage->QueryInterface(IID_IImage, (void**)&pImage)))
	{
		DBGMSG(TEXT("QueryInterface for Image from BitmapImage failed, hr: 0x%08x\n"), hr);
		goto finish;
	}

	if (FAILED(hr = pBitmapImage->QueryInterface(IID_IBasicBitmapOps, (void**)&pBasicBitmapOps)))
	{
		DBGMSG(TEXT("QueryInterface for BasicBitmapOps from BitmapImage failed, hr: 0x%08x\n"), hr);
		goto finish;
	}
	state = Init;
	goto finish_ok;

finish:
	state = UnInit;
finish_ok:
	Angle = 0;
	pBitmapImageRotate = NULL;
	pImageRotate = NULL;
    nSelectedFrame = 0;
	return;
}

ImageDecoder::~ImageDecoder()
{
    if(pImageRotate)
	{
		pImageRotate->Release();
		pImageRotate = NULL;
	}

	if(pBitmapImageRotate)
	{
		pBitmapImageRotate->Release();
		pBitmapImageRotate = NULL;
	}
	if(pBasicBitmapOps)
	{
		pBasicBitmapOps->Release();
		pBasicBitmapOps = NULL;
	}
    if(pImage)
	{
		pImage->Release();
        pImage = NULL;
	}
	if(pImageSink)	
	{
		pImageSink->Release();
		pImageSink = NULL;
	}
	if(pBitmapImage)
	{
		pBitmapImage->Release();
        pBitmapImage = NULL;
	}
    if(pImageDecoder)
	{
		pImageDecoder->Release();
		pImageDecoder = NULL;
	}
    if(pStream)
	{
		pStream->Release();
        pStream = NULL;
	}
    if(pImagingFactory)
	{
		pImagingFactory->Release();
		pImagingFactory = NULL;
	}

	CoUninitialize();
	return;
}

void ImageDecoder::Decode() //decode the image
{
	HRESULT hr;
	if (FAILED(hr = pImageDecoder->BeginDecode(pImageSink, NULL)))
	{
		DBGMSG(TEXT("BeginDecode into Bitmap Image failed, hr = 0x%08d\n"), hr);
		goto finish;
	}
	
	while (E_PENDING == (hr = pImageDecoder->Decode()))
	{
		Sleep(0);
	}

	hr = pImageDecoder->EndDecode(hr);
	
	if (FAILED(hr))
	{
		DBGMSG(TEXT("Decoding failed, hr = 0x%08x\n"), hr);
		goto finish;
	}
	state = Decoded;
finish:
	return;
}

void ImageDecoder::Rotate(int Angle)
{
	this->Angle = Angle;
}

StateType ImageDecoder::State()
{
	return state;
}

#if 0
TCHAR* ImageDecoder::FileName()
{
	//return filename;
}
#endif

int ImageDecoder::Width()
{
	return ii.Width;
}

int ImageDecoder::Height()
{
	return ii.Height;
}

UINT ImageDecoder::FrameCount()
{
    return nFrameCount;
}

void ImageDecoder::SelectNextFrame()
{
    HRESULT hr;
    nSelectedFrame++;
    if(nSelectedFrame > (nFrameCount - 1))
    {
        nSelectedFrame = 0;
    }

    ASSERT(pBitmapImage);
    pBitmapImage->Release();

    ASSERT(pImageSink);    
    pImageSink->Release();

    ASSERT(pImage);
    pImage->Release();
    
    if (FAILED(hr = pImageDecoder->SelectActiveFrame(&FrameDimensionTime, nSelectedFrame)))
    {
        ASSERT(0);
    }
    if (FAILED(hr = pImagingFactory->CreateNewBitmap(ii.Width, ii.Height, ii.PixelFormat, &pBitmapImage)))
	{
		DBGMSG(TEXT("CreateNewBitmap failed, hr = 0x%08x\n"), hr);
	    ASSERT(0);
	}
	
    if (FAILED(hr = pBitmapImage->QueryInterface(IID_IImageSink, (void**)&pImageSink)))
    {
        DBGMSG(TEXT("QueryInterface for ImageSink from BitmapImage failed, hr: 0x%08x\n"), hr);
        ASSERT(0);
    }
    
    if (FAILED(hr = pBitmapImage->QueryInterface(IID_IImage, (void**)&pImage)))
    {
        DBGMSG(TEXT("QueryInterface for Image from BitmapImage failed, hr: 0x%08x\n"), hr);
        ASSERT(0);
    }
}
void ImageDecoder::Draw(HDC hdc, RECT &dstRect)
{
	RECT rc;
	HRESULT hr;
	float fAngle = (float)Angle;
	
	GetDestRect(ii.Width, ii.Height, dstRect.right, dstRect.bottom, rc);
	
	if(Angle != 0)
	{
		if(pImageRotate)
		{
			pImageRotate->Release();
			pImageRotate = NULL;
		}
		if(pBitmapImageRotate)
		{
			pBitmapImageRotate->Release();
			pBitmapImageRotate = NULL;
		}

		if(FAILED(hr = pBasicBitmapOps->Rotate(fAngle, InterpolationHintDefault, &pBitmapImageRotate)))
		{
			DBGMSG(TEXT("Rotate Image failed, hr: 0x%08x\n"), hr);
		}
		
		if(FAILED(hr = pBitmapImageRotate->QueryInterface(IID_IImage, (void**)&pImageRotate)))
		{
			DBGMSG(TEXT("QueryInterface for Image from BitmapImage failed, hr: 0x%08x\n"), hr);
		}

		pImageRotate->Draw(hdc, &rc, NULL);
	}
	else
	{
		pImage->Draw(hdc, &rc, NULL);
	}

}

void ImageDecoder::Flip()
{
}

void ImageDecoder::Resize()
{
}

void ImageDecoder::AdjustBrightness()
{
}

void ImageDecoder::AdjustContrast()
{
}

void ImageDecoder::AdjustGamma()
{
}


BOOL ImageDecoder::GetCodecCLSID(IImagingFactory* pImagingFactory, CLSID * pclsid, WCHAR * wszMimeType, CodecType ctCodec)
{
    UINT uiCount;
    ImageCodecInfo * codecs;
    HRESULT hr;
    BOOL fRet = FALSE;
    TCHAR * tszCodec;

    if(eEncoder == ctCodec)
    {
        hr = pImagingFactory->GetInstalledEncoders(&uiCount, &codecs);
        tszCodec = TEXT("Encoder");
    }
    else
    {
        hr = pImagingFactory->GetInstalledDecoders(&uiCount, &codecs);
        tszCodec = TEXT("Decoder");
    }
    if(FAILED(hr))
    {
        DBGMSG(TEXT("GetInstalled%ss returned 0x%08x\n"), tszCodec, hr);
        return FALSE;
    }

    for(UINT i = 0; i < uiCount; i++)
    {
        //DBGMSG(TEXT("%s %d of %d: MimeType = %s\n"), tszCodec, i + 1, uiCount, codecs[i].MimeType);
        if (wszMimeType && !wcscmp(wszMimeType, codecs[i].MimeType))
        {
            *pclsid = codecs[i].Clsid;
            fRet = TRUE;
            break;
        }
    }
    CoTaskMemFree(codecs);
    return fRet;
}

HRESULT ImageDecoder::CreateStreamOnFile(const TCHAR * tszFilename, IStream ** ppStream)
{
    HRESULT hrRet = S_OK;
    HGLOBAL hg = NULL;
    HANDLE hFile = NULL;
    DWORD dwSize, dwRead;
    BYTE* pbLocked = NULL;

    // Open the file
    hFile = CreateFile(tszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
    if(INVALID_HANDLE_VALUE == hFile)
    {
        DBGMSG(TEXT("CreateFile failed with GLE = %d\n"), GetLastError());
        hrRet = 0x80000000 + GetLastError();
        goto error;
    }

    dwSize = GetFileSize(hFile, NULL);
    if(0xffffffff == dwSize)
    {
        DBGMSG(TEXT("GetFileSize failed with GLE = %d\n"), GetLastError());
        hrRet = 0x80000000 + GetLastError();
        goto error;
    }

    // Open a memory object
    hg = GlobalAlloc(GMEM_MOVEABLE, dwSize);
    if(NULL == hg)
    {
        DBGMSG(TEXT("GlobalAlloc failed with GLE = %d\n"), GetLastError());
        hrRet = 0x80000000 + GetLastError();
        goto error;
    }

    // Ge a pointer to the memory we just allocated
    pbLocked = (BYTE*) GlobalLock(hg);
    if(NULL == pbLocked)
    {
        DBGMSG(TEXT("GlobalLock failed with GLE = %d\n"), GetLastError());
        hrRet = 0x80000000 + GetLastError();
        goto error;
    }

    // copy the file
    if(!ReadFile(hFile, pbLocked, dwSize, &dwRead, NULL))
    {
        DBGMSG(TEXT("ReadFile failed with GLE = %d\n"), GetLastError());
        hrRet = 0x80000000 + GetLastError();
        goto error;
    }

    GlobalUnlock(hg);
    
    // Create the stream
    hrRet = CreateStreamOnHGlobal(hg, TRUE, ppStream);

    CloseHandle(hFile);
    return hrRet;
error:
    if(pbLocked)
        GlobalUnlock(hg);
    if(hg)
        GlobalFree(hg);
    if(hFile)
        CloseHandle(hFile);
    return hrRet;
}


HRESULT ImageDecoder::CreateStreamOnResource(HRSRC hRes, IStream ** ppStream)
{
    HRESULT hrRet = S_OK;
    HGLOBAL hg = NULL;
    //HANDLE hFile = NULL;
    DWORD dwSize; //dwRead;
    BYTE* pbLocked = NULL;

    // Open the file
	#if 0
	hFile = CreateFile(tszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
    if(INVALID_HANDLE_VALUE == hFile)
    {
        DBGMSG(TEXT("CreateFile failed with GLE = %d"), GetLastError());
        hrRet = 0x80000000 + GetLastError();
        goto error;
    }

    dwSize = GetFileSize(hFile, NULL);
    if(0xffffffff == dwSize)
    {
        DBGMSG(TEXT("GetFileSize failed with GLE = %d"), GetLastError());
        hrRet = 0x80000000 + GetLastError();
        goto error;
    }
	#endif
	
	HGLOBAL hGbl = LoadResource(GetModuleHandle(NULL), hRes);
	BYTE* pbData = (BYTE*)LockResource(hGbl);
	dwSize = SizeofResource(GetModuleHandle(NULL), hRes);

	
    // Open a memory object
    hg = GlobalAlloc(GMEM_MOVEABLE, dwSize);
    if(NULL == hg)
    {
        DBGMSG(TEXT("GlobalAlloc failed with GLE = %d\n"), GetLastError());
        hrRet = 0x80000000 + GetLastError();
        goto error;
    }

    // Ge a pointer to the memory we just allocated
    pbLocked = (BYTE*) GlobalLock(hg);
    if(NULL == pbLocked)
    {
        DBGMSG(TEXT("GlobalLock failed with GLE = %d\n"), GetLastError());
        hrRet = 0x80000000 + GetLastError();
        goto error;
    }

    // copy the file
    memcpy(pbLocked, pbData, dwSize);
    #if 0
    if(!ReadFile(hFile, pbLocked, dwSize, &dwRead, NULL))
    {
        DBGMSG(TEXT("ReadFile failed with GLE = %d"), GetLastError());
        hrRet = 0x80000000 + GetLastError();
        goto error;
    }
	#endif

    GlobalUnlock(hg);
    
    // Create the stream
    hrRet = CreateStreamOnHGlobal(hg, TRUE, ppStream);

    //CloseHandle(hFile);
    return hrRet;
error:
    if(pbLocked)
        GlobalUnlock(hg);
    if(hg)
        GlobalFree(hg);
//    if(hFile)
//        CloseHandle(hFile);
    return hrRet;
}


void ImageDecoder::
GetDestRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight, RECT &out)
{
	int x, y, width, height;
	float XRatio, YRatio;
	x = 0;
    y = 0;
	if(Angle == 0 || Angle == 360 || Angle == 180)
	{
		width = srcWidth;
		height = srcHeight;
	}
	else
	{
		width = srcHeight;
		height = srcWidth;
	}
	XRatio = (float)dstWidth/(float)width;
	YRatio = (float)dstHeight/(float)height;

	if(XRatio < YRatio)
	{
		height = (int)((float)height * XRatio);
		width = dstWidth;
		y = (dstHeight - height)/2;
		
	}
	else
	{
		height = dstHeight;
		width = (int)((float)width * YRatio);
		x = (dstWidth - width)/2;
	}

	out.left = x;
	out.right = x + width;
	out.top = y;
	out.bottom = y + height;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -