C++中圖片類型的識別與轉(zhuǎn)換詳解方法
1、圖片類型的識別
一般情況下,不同類型的圖片文件都會有其對應(yīng)的后綴名,比如.jpg、.bmp、.jpg等。但僅僅通過后綴名,是沒法判別文件是不是圖片以及圖片文件真實(shí)類型,必須通過文件內(nèi)容的起始標(biāo)記字段才能判斷出來。
每種圖片文件的類型標(biāo)識字段存儲于文件內(nèi)容開始的幾個字節(jié),讀出這幾個字節(jié)就能判斷出圖片類型了。下面給出常見的圖片類型的判斷代碼。
以下代碼都是調(diào)用_tfopen(支持Unicode)打開文件,調(diào)用fread讀出文件中的類型標(biāo)記數(shù)據(jù)。注意,打開文件時必須設(shè)置 b - 二進(jìn)制參數(shù),如果不設(shè)置,調(diào)用fread時可能讀不出指定字節(jié)數(shù)的內(nèi)容!
1.1、bmp圖片
BOOL32 IsBmpFile( LPCTSTR lpStrFilePath ) { FILE* pFile = _tfopen( lpStrFilePath, _T("rb") ); if ( pFile == NULL ) { return FALSE; } char szData[2] = {0}; int nReadNum = fread( szData, sizeof(char), 2, pFile ); if ( nReadNum < 2 ) { fclose( pFile ); return FALSE; } fclose( pFile ); // bmp: 0x42, 0x4d unsigned char szBmpFlag = { 0x42, 0x4d }; if ( !memcmp( szBmpFlag, szData, 2 ) ) { return TRUE; } return FALSE; }
1.2、jpg圖片
BOOL32 IsJpgFile( LPCTSTR lpStrFilePath ) { FILE* pFile = _tfopen( lpStrFilePath, _T("rb") ); if ( pFile == NULL ) { return FALSE; } char szData[2] = {0}; int nReadNum = fread( szData, sizeof(char), 2, pFile ); if ( nReadNum < 2 ) { fclose( pFile ); return FALSE; } fclose( pFile ); // jpg: 0xFF, 0xD8 unsigned char szJpgFlag[] = { 0xFF, 0xD8 }; if ( !memcmp( szJpgFlag, szData, 2 ) ) { return TRUE; } return FALSE; }
1.3、jpg圖片
BOOL32 IsPngFile( LPCTSTR lpStrFilePath ) { FILE* pFile = _tfopen( lpStrFilePath, _T("rb") ); if ( pFile == NULL ) { return FALSE; } char szData[8] = {0}; int nReadNum = fread( szData, sizeof(char), 8, pFile ); if ( nReadNum < 8 ) { fclose( pFile ); return FALSE; } fclose( pFile ); // png: 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A unsigned char szPngFlag[] = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; if ( !memcmp( szPngFlag, szData, 8 ) ) { return TRUE; } return FALSE; }
1.4、gif圖片
BOOL32 IsGifFile( LPCTSTR lpStrFilePath ) { FILE* pFile = _tfopen( lpStrFilePath, _T("rb") ); if ( pFile == NULL ) { return FALSE; } char szData[6+1] = {0}; int nReadNum = fread( szData, sizeof(char), 6, pFile ); if ( nReadNum < 6 ) { fclose( pFile ); return FALSE; } fclose(pFile); // 使用字符串判斷更直觀 if ( strcmp( szData, "GIF89a" ) == 0 || strcmp( szData, "GIF87a" ) == 0 ) { return TRUE; } return FALSE; }
1.5、tiff圖片
BOOL32 IsTiffFile( LPCTSTR lpStrFilePath ) { FILE* pFile = _tfopen( lpStrFilePath, _T("rb") ); if ( pFile == NULL ) { return FALSE; } char szData[4] = {0}; int nReadNum = fread( szData, sizeof(char), 4, pFile ); if ( nReadNum < 4 ) { fclose( pFile ); return FALSE; } fclose( pFile ); // jpg: 0x49, 0x49, 0x2A, 0x00 unsigned char szTiffFlag[] = { 0x49, 0x49, 0x2A, 0x00 }; if ( !memcmp( szTiffFlag, szData, 2 ) ) { return TRUE; } return FALSE; }
1.6、使用CreateFile和ReadFile API函數(shù)讀取內(nèi)容
上面是使用fopen和fread讀取文件中的內(nèi)容的,下面給出調(diào)用CreateFile和ReadFile API函數(shù)實(shí)現(xiàn)的代碼:
BOOL32 IsJpgFile( LPCTSTR lpStrFilePath ) { HANDLE hFile = ::CreateFile(lpStrFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return FALSE; } unsigned char szData[4] = { 0 }; DWORD dwReadNum; if (!::ReadFile((HANDLE)hFile, szData, 4, &dwReadNum, NULL)) { CloseHandle(hFile); return FALSE; } if ( dwReadNum< 4 ) { CloseHandle(hFile); return FALSE; } CloseHandle(hFile); unsigned char szJpgFlag[] = { 0xFF, 0xD8 }; // 0xFF,0xD8 if ( !memcmp( szJpgFlag, szData, 2 ) ) { return TRUE; } return FALSE; }
2、圖片之間的相互轉(zhuǎn)換
有時我們需要進(jìn)行不同圖片類型之間的相互轉(zhuǎn)換,比如將占用較大存儲空間的bmp圖片轉(zhuǎn)換成jpg或者jpg圖片。可以選擇使用GDI+類實(shí)現(xiàn)不同圖片類型之間的轉(zhuǎn)換。在使用GDI+之前,要先初始化GDI+庫:
ULONG_PTR m_gdiplusToken; Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup( &m_gdiplusToken, &gdiplusStartupInput, NULL );
在退出程序時,要關(guān)閉GDI+庫:
Gdiplus::GdiplusShutdown( m_gdiplusToken );
實(shí)現(xiàn)圖片類型之間相互轉(zhuǎn)換的代碼如下:
// 根據(jù)目標(biāo)文件的后綴確定要轉(zhuǎn)換成的目標(biāo)文件類型 BOOL32 SaveImgFileToAnotherType( const CString& strSrcFile, const CString& strDstFile ) { // 使用CImage實(shí)現(xiàn)不同格式圖片文件的轉(zhuǎn)換 if ( strDstFile.IsEmpty() ) { return FALSE; } CImage img; HRESULT hResult = img.Load( strSrcFile ); // 加載源圖片文件 if ( hResult != S_OK ) { return FALSE; } GUID guidFileType = Gdiplus::ImageFormatPNG; // 默認(rèn)保存為png圖片 CString strExt; s32 nIndex = strDstFile.ReverseFind( _T('.') ); if ( nIndex != -1 ) { strExt = strDstFile.Right( strDstFile.GetLength() - nIndex - 1 ); if ( strExt == _T("png") ) { guidFileType = Gdiplus::ImageFormatPNG; } else if ( strExt == _T("jpg")) { guidFileType = Gdiplus::ImageFormatJPEG; } else if ( strExt == _T("bmp") ) { guidFileType = Gdiplus::ImageFormatBMP; } else if ( strExt == _T("gif") ) { guidFileType = Gdiplus::ImageFormatGIF; } else { guidFileType = Gdiplus::ImageFormatPNG; } } hResult = img.Save( strDstFile, guidFileType ); // 保存為目標(biāo)文件 if ( hResult != S_OK ) { return FALSE; } return TRUE; }
以上就是C++中圖片類型的識別與轉(zhuǎn)換詳解方法的詳細(xì)內(nèi)容,更多關(guān)于C++ 圖片類型轉(zhuǎn)換的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
數(shù)據(jù)結(jié)構(gòu) C語言實(shí)現(xiàn)循環(huán)單鏈表的實(shí)例
這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu) C語言實(shí)現(xiàn)循環(huán)單鏈表的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-05-05基于C語言構(gòu)建一個獨(dú)立棧協(xié)程和共享?xiàng)f(xié)程的任務(wù)調(diào)度系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了如何基于C語言構(gòu)建一個獨(dú)立棧協(xié)程和共享?xiàng)f(xié)程的任務(wù)調(diào)度系統(tǒng),文中的示例代碼講解詳細(xì),需要的可以參考下2024-02-02C++實(shí)現(xiàn)LeetCode(167.兩數(shù)之和之二 - 輸入數(shù)組有序)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(167.兩數(shù)之和之二 - 輸入數(shù)組有序),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08