?? mjpeg2bmp.cpp
字號:
#define INITGUID
#include <windows.h> // For all that Windows stuff
#include <stdlib.h>
#include <stdio.h>
#include <imaging.h>
#if _WIN32_WCE >= 500
#include <GdiPlusEnums.h>
#endif
#define GETZONESONLY
#include "CameraCode.h" // Only needed for ZONE_ constants
#include "StreamFrame.h"
enum CodecType {eDecoder, eEncoder};
#define NAMEVALENTRY(x) { (LONG)(x), TEXT(#x) }
struct NameValuePair {
LONG pValue;
TCHAR *szName;
};
//void info (const TCHAR* tszFormat, ...);
IImagingFactory *pImagingFactory = NULL;
//----------------------------------------------------------------------
// InitDisplayFrame
//
HRESULT InitDisplayFrame (LPCWSTR pszExt)
{
HRESULT hr;
BOOL fFound = FALSE;
// Get length of search extension
int nLen = pszExt ? lstrlen (pszExt) : 0;
if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)))
{
DEBUGMSG (ZONE_ERROR, (TEXT("CoInitializeEx failed, hr: 0x%08x\r\n"), hr));
return 1;
}
hr = CoCreateInstance(CLSID_ImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IImagingFactory,
(void**) &pImagingFactory);
if (FAILED(hr))
return hr;
//
// Query current installed codecs
//
ImageCodecInfo *pCodecInfo;
UINT uCnt = 0;
hr = pImagingFactory->GetInstalledDecoders (&uCnt, &pCodecInfo);
if (SUCCEEDED(hr))
{
DEBUGMSG (ZONE_INIT, (TEXT ("Detected %d decoders\r\n"), uCnt));
for (UINT i = 0; i < uCnt; i++)
{
if (nLen &&
(_wcsnicmp(pCodecInfo[i].FormatDescription, pszExt, nLen) == 0))
fFound = TRUE;
DEBUGMSG (ZONE_INIT, (TEXT("Name >%S<\r\n"), pCodecInfo[i].CodecName));
DEBUGMSG (ZONE_INIT, (TEXT("Desc >%S<\r\n\r\n"), pCodecInfo[i].FormatDescription));
}
CoTaskMemFree ((PVOID)pCodecInfo);
}
// See if we were supposed to find specific support and didn't find it
if (!hr && nLen && !fFound)
{
pImagingFactory->Release();
hr = ERROR_NOT_SUPPORTED;
}
return hr;
}
//----------------------------------------------------------------------
// Frees the imaging library
//
HRESULT ReleaseDisplayFrame ()
{
HRESULT hr = 0;
if (pImagingFactory)
{
pImagingFactory->Release();
pImagingFactory = NULL;
}
return hr;
}
BYTE MJPG2JPGHdr[440] = {
// JPEG file header
0xff,0xd8, // SOI
0xff,0xe0, // APP0
0x00,0x10, // APP0 Hdr size
0x4a,0x46,0x49,0x46,0x00, // ID string
0x01,0x01, // Version
0x00, // Bits per type
0x00, 0x00, // X density
0x00, 0x00, // Y density
0x00, // X Thumbnail size
0x00, // Y Thumbnail size
/* JPEG DHT Segment for YCrCb omitted from MJPG data */
0xFF,0xC4,0x01,0xA2,
0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x01,0x00,0x03,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x0B,0x10,0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,
0x00,0x01,0x7D,0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,
0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24,
0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,0x2A,0x34,
0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,
0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,
0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,
0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,
0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,
0xDA,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
0xF8,0xF9,0xFA,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,
0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,0x15,0x62,
0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,0x27,0x28,0x29,0x2A,
0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,
0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,
0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,
0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,
0xD9,0xDA,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
0xF9,0xFA
};
//----------------------------------------------------------------------
// DisplayFrame
//
HRESULT DisplayFrame (PBYTE pData, DWORD dwPreBuff, DWORD dwSize, HDC hdc, RECT *pRect)
{
HRESULT hr;
IImageSink *pImageSink = NULL;
IImage *pImage = NULL;
IImageDecoder *pImageDecoder = NULL;
IImageEncoder *pImageEncoder = NULL;
IBitmapImage *pBitmapImage = NULL;
IStream *pStream = NULL;
ImageInfo ii;
LPBYTE pLocal = 0;
if (pImagingFactory == NULL)
return E_NOINTERFACE;
if (*pData == 0)
return 0;
int MjpegHdrSize = *(pData+4);
MjpegHdrSize = MjpegHdrSize << 8;
MjpegHdrSize += *(pData+5)+4;
if (MjpegHdrSize > 100)
return -2;
#if 1
// Slow way copies the data to a seperate heap allocation. This seems to be needed for the
// CreateStreamOnHGlobal method because that method looks at the heap block header to determine
// the size of the data.
// Data is in big endian format
pLocal = (LPBYTE)LocalAlloc (LPTR, dwSize+512);
if (!pLocal)
return -1;
memcpy (pLocal, MJPG2JPGHdr, sizeof (MJPG2JPGHdr));
memcpy (pLocal + sizeof (MJPG2JPGHdr), pData + MjpegHdrSize, dwSize - MjpegHdrSize);
// Create the stream
hr = CreateStreamOnHGlobal(pLocal, TRUE, &pStream);
#endif
#if 0
// This way also copies the data but then uses an custom stream
// interface to expose the data.
pLocal = (LPBYTE)LocalAlloc (LPTR, dwSize+512);
if (!pLocal)
return -1;
memcpy (pLocal, MJPG2JPGHdr, sizeof (MJPG2JPGHdr));
memcpy (pLocal + sizeof (MJPG2JPGHdr), pData + MjpegHdrSize, dwSize - MjpegHdrSize);
// Create the stream
FrameStream *pfs = new FrameStream (pLocal, dwSize + 512);
hr = pfs->QueryInterface (__uuidof(IStream)/*IID_IStream*/, (void **)&pStream);
#endif
#if 0
// Add JPEG header to MJPEG frame data. We need to also remove the MJPEG info at the start of the frame
// Data is in big endian format.
// Expose the data in custom stream interface.
PBYTE pPreBuff = pData + MjpegHdrSize - sizeof (MJPG2JPGHdr);
memcpy (pPreBuff, MJPG2JPGHdr, sizeof (MJPG2JPGHdr));
FrameStream *pfs = new FrameStream (pPreBuff, dwSize + sizeof (MJPG2JPGHdr) - MjpegHdrSize);
hr = pfs->QueryInterface (__uuidof(IStream)/*IID_IStream*/, (void **)&pStream);
#endif
__try
{
if (FAILED(hr))
{
DEBUGMSG (ZONE_ERROR, (TEXT("Create stream failed, hr: 0x%08x\r\n"), hr));
goto finish;
}
// Get the decoder. The system chooses the proper decoder
// from the format of the data in the buffer.
if (FAILED(hr = pImagingFactory->CreateImageDecoder(pStream, DecoderInitFlagBuiltIn1st, &pImageDecoder)))
{
DEBUGMSG (ZONE_ERROR, (TEXT("CreateImageDecoder failed, hr: 0x%08x\r\n"), hr));
goto finish;
}
// Query image info
if (FAILED(hr = pImageDecoder->GetImageInfo(&ii)))
{
DEBUGMSG (ZONE_ERROR, (TEXT("GetImageInfo failed, hr: 0x%08x\r\n"), hr));
goto finish;
}
// Create bitmap of the same size
if (FAILED(hr = pImagingFactory->CreateNewBitmap(ii.Width, ii.Height, ii.PixelFormat, &pBitmapImage)))
{
DEBUGMSG (ZONE_ERROR, (TEXT("CreateNewBitmap failed, hr = 0x%08x\r\n"), hr));
goto finish;
}
// Get the "sink" which is needed by the decoder so it can write the data to the bitmap
if (FAILED(hr = pBitmapImage->QueryInterface(IID_IImageSink, (void**)&pImageSink)))
{
DEBUGMSG (ZONE_ERROR, (TEXT("QueryInterface for ImageSink from BitmapImage failed, hr: 0x%08x\r\n"), hr));
goto finish;
}
// Finally, start the conversion
if (FAILED(hr = pImageDecoder->BeginDecode(pImageSink, NULL)))
{
DEBUGMSG (ZONE_ERROR, (TEXT("BeginDecode into Bitmap Image failed, hr = 0x%08d\r\n"), hr));
goto finish;
}
// Loop as necessary
while (E_PENDING == (hr = pImageDecoder->Decode()))
Sleep(100);
if (hr != S_OK)
{
DEBUGCHK ((TEXT("Bad decode hr = %08x\r\n"), hr));
}
// Clean up
hr = pImageDecoder->EndDecode(hr);
if (FAILED(hr))
{
DEBUGMSG (ZONE_DECODING, (TEXT("Decoding failed, hr = 0x%08x\r\n"), hr));
// If fail to decode, release block
if (pLocal)
LocalFree (pLocal);
goto finish;
}
// DEBUGMSG (ZONE_DECODING, (TEXT("img size %d\r\n"), dwSize));
DEBUGMSG (1, (TEXT("img size %d\r\n"), dwSize));
//
// We have a bitmap at this point. Get Image interface and draw
//
if (FAILED(hr = pBitmapImage->QueryInterface(IID_IImage, (void**)&pImage)))
{
DEBUGMSG (ZONE_ERROR, (TEXT("QueryInterface for Image from BitmapImage failed, hr: 0x%08x\r\n"), hr));
goto finish;
}
hr = pImage->Draw (hdc, pRect, NULL);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG (ZONE_ERROR, (TEXT ("Exception decoding image \r\n")));
}
finish:
if (pImage)
pImage->Release();
pImage = NULL; // This is already deleted above, but just to make sure...
if (pImageSink)
pImageSink->Release();
pImageSink = NULL;
if (pBitmapImage)
pBitmapImage->Release();
pBitmapImage = NULL;
if (pImageSink)
pImageSink->Release();
pImageSink = NULL;
if (pImageDecoder)
pImageDecoder->Release();
pImageDecoder = NULL;
if (pStream)
pStream->Release();
pStream = NULL;
if (pImageEncoder)
pImageEncoder->Release();
pImageEncoder = NULL;
// LocalFree (pLocal); Seems to be released by the ImageDecoder object
return hr;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -