C++中图片类型的识别与转换详解方法

目录
  • 1、图片类型的识别
    • 1.1、bmp图片
    • 1.2、jpg图片
    • 1.3、jpg图片
    • 1.4、gif图片
    • 1.5、tiff图片
    • 1.6、使用CreateFile和ReadFile API函数读取内容
  • 2、图片之间的相互转换

1、图片类型的识别

一般情况下,不同类型的图片文件都会有其对应的后缀名,比如.jpg、.bmp、.jpg等。但仅仅通过后缀名,是没法判别文件是不是图片以及图片文件真实类型,必须通过文件内容的起始标记字段才能判断出来。

每种图片文件的类型标识字段存储于文件内容开始的几个字节,读出这几个字节就能判断出图片类型了。下面给出常见的图片类型的判断代码。

以下代码都是调用_tfopen(支持Unicode)打开文件,调用fread读出文件中的类型标记数据。注意,打开文件时必须设置 b - 二进制参数,如果不设置,调用fread时可能读不出指定字节数的内容!

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函数读取内容

上面是使用fopen和fread读取文件中的内容的,下面给出调用CreateFile和ReadFile API函数实现的代码:

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图片。可以选择使用GDI+类实现不同图片类型之间的转换。在使用GDI+之前,要先初始化GDI+库:

ULONG_PTR m_gdiplusToken;

Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup( &m_gdiplusToken, &gdiplusStartupInput, NULL );

在退出程序时,要关闭GDI+库:

Gdiplus::GdiplusShutdown( m_gdiplusToken );

实现图片类型之间相互转换的代码如下:

// 根据目标文件的后缀确定要转换成的目标文件类型
BOOL32 SaveImgFileToAnotherType( const CString& strSrcFile, const CString& strDstFile )
{
	// 使用CImage实现不同格式图片文件的转换
	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++ 图片类型转换的资料请关注我们其它相关文章!

(0)

相关推荐

  • C++使用opencv处理两张图片的帧差

    本文为大家分享了使用opencv处理两张图片帧差的具体代码,供大家参考,具体内容如下 这个程序是两张图片做帧差,用C++实现的,把不同的地方用框框起来,仔细读一下程序,应该还是蛮简单的哈哈,opencv处理图片的基础. opencv配置不用我说了吧,源码cmake编译,然后导入vs即可. #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int mai

  • C++中图片重命名实现代码

    非常简单的小程序,满足自己的需求. #include <iostream> #include <fstream> #include<sstream> using namespace std; int main() { int i=1,j=1; //本人程序中,i 和 j 是介于(0-9之间的数字),为了简单起见,这里给定初始值. string fname1= "C:\\Users\\Administrator\\Desktop\\121.bmp";

  • C++ 设置透明背景图片

    背景: 有两个图片,一个是目标背景图片, 一个是带有自身背景色彩的彩色图片 先将这彩色图片绘制到目标背景图片中, 这一步通过BITBLT就可实现.   但实现后的效果是: 目标图片上,绘制上去的彩色图片带有其本身的背景. 问题就来了, 我们想将彩色图片本身的背景去掉,应该如何解决? 解决方法: 使用API函数:TransparentBlt   此函数将原DC中的图片绘制到目标DC中,并同时设置原图形在目标图形上的透明色. BOOL TransparentBlt( HDC hdcDest, //

  • C++实现单张图片读取和保存

    使用C++实现对单张图片的读取和保存,C语言可以参考,比较简单. #include<iostream> using namespace std; void main(void) { //保存输入图像文件名和输出图像文件名 char InImgName[10]; char OutImgName[10]; //图像数据长度 int length; //文件指针 FILE* fp; //输入要读取的图像名 cout<<"Enter Image name:"; cin&

  • C++实现批量图片拼接

    本文实例为大家分享了C++实现批量图片拼接的具体代码,供大家参考,具体内容如下 /**函数功能:不同图片拼接 * 参数: * vector<string> pic_list : 图片名称列表 * int pic_cols_rows : horizontal==true,pic_cols_rows为生成图片的行数 horizontal==false,pic_cols_rows为生成图片的列数 * bool horizontal : true-先横向后纵向合成图片 false-先纵向后横向合成图片

  • C++实现读取图片长度和宽度

    看到一个用ASP写的读取图片文件的长度.宽度的程序,感觉有点意思,于是用C++也写了一个. #include <iostream> #include <fstream> #include <string> using namespace std; class CImage { private: long m_Width; long m_Height; int get_extension(string fname); public: CImage() { m_Width

  • C++中图片类型的识别与转换详解方法

    目录 1.图片类型的识别 1.1.bmp图片 1.2.jpg图片 1.3.jpg图片 1.4.gif图片 1.5.tiff图片 1.6.使用CreateFile和ReadFile API函数读取内容 2.图片之间的相互转换 1.图片类型的识别 一般情况下,不同类型的图片文件都会有其对应的后缀名,比如.jpg..bmp..jpg等.但仅仅通过后缀名,是没法判别文件是不是图片以及图片文件真实类型,必须通过文件内容的起始标记字段才能判断出来. 每种图片文件的类型标识字段存储于文件内容开始的几个字节,读

  • 对Python3中bytes和HexStr之间的转换详解

    在Python操作数据内容时,多数情况下可能遇到下面3种类型的数据处理: hexstring 如:'1C532145697A8B6F' str 如:'\x1C\x53\x21\x45\x69\x7A\x8B\x6F' list 如:[0x1C, 0x53, 0x21, 0x45, 0x69, 0x7A, 0x8B, 0x6F] 各种第三方模块(如pyDes),或者自己写的接口中,可能存在由于类型不统一需要在这3种数据中来回切换的情况. 需要用到的核心的方法如下: list() 将对象转换为lis

  • JS中对象与字符串的互相转换详解

    在使用 JSON2.JS 文件的 JSON.parse(data) 方法时候,碰到了问题: throw new SyntaxError('JSON.parse'); 查询资料,大概意思如下: JSON.parse方法在遇到不可解析的字符串时,会抛出SyntaxError异常. 即:JSON.parse(text, reviver),This method parses a JSON text to produce an object or array. t can throw a SyntaxE

  • TS 中的类型推断与放宽实例详解

    目录 简介 类型推断与放宽概念 常规类型推断 最佳通用类型 按上下文归类 类型放宽 常规类型放宽 非严格类型检查模式 严格类型检查模式 字面量类型放宽 对象.数组字面量类型的放宽 类字面量类型的放宽 函数返回值字面量类型的放宽 TS 内部类型放宽规则 实例分析 开篇问题解答 简介 我们知道在编码时即使不标注变量类型,TypeScript 编译器也能推断出变量类型,那 TypeScript 编译器是怎么进行类型推断,在类型推断时又是如何判断兼容性的呢? 此文,正好为你解开这个疑惑的,掌握本文讲解的

  • JAVA中list,set,数组之间的转换详解

    JAVA的list,set,数组之间的转换,主要是使用Apache Jakarta Commons Collections,具体的方法如下:import org.apache.commons.collections.CollectionUtils; String[] strArray = {"aaa", "bbb", "ccc"};    List strList = new ArrayList();    Set strSet = new Ha

  • iOS中图片的解压缩到渲染过程详解

    前言 在移动app开发过程中,图片往往是不可或缺的资源.从磁盘上加载一张图片,到显示到屏幕上,中间经过了一些复杂的过程,其中非常重要的一步就是对图片的解压缩.下面来一起看看详细的介绍吧 一.图像从文件到屏幕过程 通常计算机在显示是CPU与GPU协同合作完成一次渲染.接下来我们了解一下CPU/GPU等在这样一次渲染过程中,具体的分工是什么? CPU: 计算视图frame,图片解码,需要绘制纹理图片通过数据总线交给GPU GPU: 纹理混合,顶点变换与计算,像素点的填充计算,渲染到帧缓冲区. 时钟信

  • JavaScript中字符串与Unicode编码互相转换的实现方法

    本文实例讲述了JavaScript中字符串与Unicode编码互相转换的实现方法.分享给大家供大家参考,具体如下: 这段代码演示了JavaScript中字符串与Unicode编码的转换: // 为了控制台的演示方便, 变量没有添加 var 定义 // 实际编程中请避免 // 字符串 str = "中文"; // 获取字符 char0 = str.charAt(0); // "中" // 数字编码值 code = str.charCodeAt(0); // 20013

  • 解决Pycharm中import时无法识别自己写的程序方法

    我们用pycharm打开自己写的代码,当多个文件之间有相互依赖的关系的时候,import无法识别自己写的文件,但是我们写的文件又确实在同一个文件夹中, 这种问题可以用下面的方法解决: 1)打开File-->Setting->打开 Console下的Python Console,把选项(Add source roots to PYTHONPAT)点击勾选上 2)右键点击自己的工作空间,找下面的Mark Directory as 选择Source Root,就可以解决上面的问题了! 以上这篇解决P

  • 在django中图片上传的格式校验及大小方法

    如下所示: Uploadfiles = request.FILES.get('参数', '') for i in Uploadfiles : # 图片大小的属性 i.size suffix = os.path.splitext(i.name)[1] if not suffix: return False elif suffix.lower() == '.jpeg' or suffix.lower() == ".png" or suffix.lower() == ".jpg&q

  • Python用sndhdr模块识别音频格式详解

    本文主要介绍了Python编程中,用sndhdr模块识别音频格式的相关内容,具体如下. sndhdr模块 功能描述:sndhdr模块提供检测音频类型的接口. 唯一一个API sndhdr模块提供了sndhdr.what(filename)和sndhdr.whathdr(filename)两个函数.但实际上它们的功能是一样的.(不知道多写一个的意义何在,what函数在内部调用了whathdr函数并把数据完完整整地返回) 在之前的版本,whathdr函数返回元组类型的数据,在Python3.5版本之

随机推荐