C++中圖片類型的識別與轉換詳解方法
1、圖片類型的識別
一般情況下,不同類型的圖片文件都會有其對應的后綴名,比如.jpg、.bmp、.jpg等。但僅僅通過后綴名,是沒法判別文件是不是圖片以及圖片文件真實類型,必須通過文件內容的起始標記字段才能判斷出來。
每種圖片文件的類型標識字段存儲于文件內容開始的幾個字節(jié),讀出這幾個字節(jié)就能判斷出圖片類型了。下面給出常見的圖片類型的判斷代碼。
以下代碼都是調用_tfopen(支持Unicode)打開文件,調用fread讀出文件中的類型標記數(shù)據(jù)。注意,打開文件時必須設置 b - 二進制參數(shù),如果不設置,調用fread時可能讀不出指定字節(jié)數(shù)的內容!
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ù)讀取內容
上面是使用fopen和fread讀取文件中的內容的,下面給出調用CreateFile和ReadFile API函數(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、圖片之間的相互轉換
有時我們需要進行不同圖片類型之間的相互轉換,比如將占用較大存儲空間的bmp圖片轉換成jpg或者jpg圖片??梢赃x擇使用GDI+類實現(xiàn)不同圖片類型之間的轉換。在使用GDI+之前,要先初始化GDI+庫:
ULONG_PTR m_gdiplusToken; Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup( &m_gdiplusToken, &gdiplusStartupInput, NULL );
在退出程序時,要關閉GDI+庫:
Gdiplus::GdiplusShutdown( m_gdiplusToken );
實現(xiàn)圖片類型之間相互轉換的代碼如下:
// 根據(jù)目標文件的后綴確定要轉換成的目標文件類型 BOOL32 SaveImgFileToAnotherType( const CString& strSrcFile, const CString& strDstFile ) { // 使用CImage實現(xiàn)不同格式圖片文件的轉換 if ( strDstFile.IsEmpty() ) { return FALSE; } CImage img; HRESULT hResult = img.Load( strSrcFile ); // 加載源圖片文件 if ( hResult != S_OK ) { return FALSE; } GUID guidFileType = Gdiplus::ImageFormatPNG; // 默認保存為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 ); // 保存為目標文件 if ( hResult != S_OK ) { return FALSE; } return TRUE; }
以上就是C++中圖片類型的識別與轉換詳解方法的詳細內容,更多關于C++ 圖片類型轉換的資料請關注腳本之家其它相關文章!
相關文章
數(shù)據(jù)結構 C語言實現(xiàn)循環(huán)單鏈表的實例
這篇文章主要介紹了數(shù)據(jù)結構 C語言實現(xiàn)循環(huán)單鏈表的實例的相關資料,需要的朋友可以參考下2017-05-05基于C語言構建一個獨立棧協(xié)程和共享棧協(xié)程的任務調度系統(tǒng)
這篇文章主要為大家詳細介紹了如何基于C語言構建一個獨立棧協(xié)程和共享棧協(xié)程的任務調度系統(tǒng),文中的示例代碼講解詳細,需要的可以參考下2024-02-02C++實現(xiàn)LeetCode(167.兩數(shù)之和之二 - 輸入數(shù)組有序)
這篇文章主要介紹了C++實現(xiàn)LeetCode(167.兩數(shù)之和之二 - 輸入數(shù)組有序),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下2021-08-08