VC++ 修改JPEG

#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")

// 获取JPEG图像编码器CLSID
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
	UINT num = 0;
	UINT size = 0;
	ImageCodecInfo* pImageCodecInfo = NULL;
	//获取含有可用图像编码器的数目
	GetImageEncodersSize(&num, &size);
	if (size == 0)
	{
		return -1;
	}

	pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
	if (pImageCodecInfo == NULL)
	{
		return -1;
	}

	// 获取含有可用图像编码器信息的ImageCodecInfo对象数组,根据图像类型名称做对比,取出图像编码器CLSID
	GetImageEncoders(num, size, pImageCodecInfo);
	for (UINT j = 0; j < num; ++j)
	{
		if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
		{
			*pClsid = pImageCodecInfo[j].Clsid;
			free(pImageCodecInfo);
			return j;
		}
	}

	free(pImageCodecInfo);
	return -1;
}
// 从内存加载图片,失败返回NULL
Bitmap* LoadBitmapFromMemory(const void* memory, DWORD size)
{
	Bitmap* bmp = NULL;
	IStream* stream = NULL;
	// 从内存创建流对象
	if (CreateStreamOnHGlobal(NULL, TRUE, &stream) == S_OK)
	{
		ULARGE_INTEGER uli;
		uli.QuadPart = size;
		// 设置流大小
		stream->SetSize(uli);
		// 将流数据写入内存
		if (stream->Write(memory, size, NULL) == S_OK)
			// 从内存创建Bitmap图片
			bmp = new Bitmap(stream);
		stream->Release();
	}

	return bmp;
}
// 从文件加载图片,不独占文件,失败返回NULL
Bitmap* LoadBitmapFromFile(const TCHAR* file_name)
{
	Bitmap* bmp = NULL;
	// 打开图片文件
	HANDLE file_handle = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (file_handle != INVALID_HANDLE_VALUE)
	{
		DWORD temp = 0;
		// 获取文件总大小
		DWORD file_size = GetFileSize(file_handle, &temp);
		if (file_size && !temp)  // 不处理大于4G的文件
		{
			//申请存放图片数据的内存空间
			unsigned char* buffer = new unsigned char[file_size];
			// 将图片文件读到内存后,再从内存创建Bitmap
			if (ReadFile(file_handle, buffer, file_size, &temp, NULL))
				bmp = LoadBitmapFromMemory(buffer, temp);
			delete[] buffer;
		}

		// 关闭文件句柄
		CloseHandle(file_handle);
	}
	else
	{
		DWORD dwErrorCode = GetLastError();
		std::cout << "CreateFile fail.ErrorCode=" << dwErrorCode << endl;
	}

	return bmp;
}

// 更新文件版权信息
BOOL UpdataJpegExifCopyRightInfo(const wchar_t* filename, const char* exifCopyrightInfo)
{
	BOOL bResult = FALSE;
	// GDI+接口初始化
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	// 从文件名获取图片信息,
	Bitmap* image = LoadBitmapFromFile(filename);// Bitmap::FromFile(filename);//Bitmap::FromFile这种方式文件是已独占方式打开,无法修改EXIF属性信息
	if (image == NULL){
		// 清理GDI+资源
		GdiplusShutdown(gdiplusToken);
		return bResult;
	}

	image->GetPropertyItemSize(PropertyTagCopyright);

	// 给EXIF属性申请内存空间
	PropertyItem* propertyItem = (PropertyItem*)malloc(sizeof(PropertyItem));
	memset(propertyItem, 0, sizeof(PropertyItem));
	// 设置EXIF版本属性值
	propertyItem->id = PropertyTagCopyright;							//版权信息对应的Tag值
	propertyItem->type = PropertyTagTypeASCII;							//版权信息值类型
	propertyItem->value = (void*)exifCopyrightInfo;
	// 设置属性字符串长度
	propertyItem->length = strlen(exifCopyrightInfo) + 1;

	// 获取JPEG图像编码器CLSID
	CLSID  clsid;
	GetEncoderClsid(L"image/jpeg", &clsid);

	// 设置属性值
	image->SetPropertyItem(propertyItem);
	// 保存图片
	Status status = image->Save(filename, &clsid, NULL);
	if (status == Ok)
		bResult = TRUE;

	// 删除申请的内存空间
	free(propertyItem);
	delete image;

	// 清理GDI+资源
	GdiplusShutdown(gdiplusToken);

	return bResult;
}

程序中调用的是GDI+接口来实现修改JPG图片的EXIF属性信息,切记打开文件不要用Bitmap::FromFile方式,此方式文件将会被占用,导致修改属性失败。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值