MFC读写EXIF信息
读取有类库可以直接调用,网络上有直接可以用的;但是写Exif的资料非常少,我花了一点时间研究收集,终于成功。
将相关的资料共享。主要是借助gdi+,需要注意的地方很多
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> #include <gdiplus.h> #include <stdio.h> using namespace Gdiplus; #pragma comment(lib, "gdiplus.lib") 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; } 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) 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的文件 { // 将图片文件读到内存后,再从内存创建Bitmap unsigned char* buffer = new unsigned char[file_size]; if (ReadFile(file_handle, buffer, file_size, &temp, NULL)) bmp = LoadBitmapFromMemory(buffer, temp); delete [] buffer; } CloseHandle(file_handle); } return bmp; } int _tmain(int argc, _TCHAR* argv[]) { GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); Status stat; CLSID clsid; char propertyValue[] = "Fake Photograph"; Bitmap* bitmap = LoadBitmapFromFile(L"E:/sandbox/stone.jpg"); PropertyItem* propertyItem = new PropertyItem; // Get the CLSID of the JPEG encoder. GetEncoderClsid(L"image/jpeg", &clsid); propertyItem->id = PropertyTagCopyright; propertyItem->length = 16; // string length including NULL terminator propertyItem->type = PropertyTagTypeASCII; propertyItem->value = propertyValue; bitmap->SetPropertyItem(propertyItem); stat = bitmap->Save(L"E:/sandbox/stone.jpg", &clsid, NULL); if(stat == Ok) printf("FakePhoto2.jpg saved successfully.\n"); delete propertyItem; delete bitmap; GdiplusShutdown(gdiplusToken); return 0; return 0; }
这段console代码共4个函数。main函数,
GetEncoderClsid
LoadBitmapFromMemory和
LoadBitmapFromFile函数。
其中
GetEncoderClsid
函数是GDI+自己用于获得图片格式的。之所以要使用非占用的方式打开图片,是因为写入EXIF的信息也是图片自己信息的一部分,如果采用直接打开的方法,那么原始资源被占用,造成EXIF信息写不进去。
main函数中,就是主要过程。采用GDI+写入
SetPropertyItem
的方法进行写入。函数中
E:/sandbox/stone.jpg
是文件名,按照自己需要修改。
在本例中,我改写的EXIF项目
PropertyTagCopyright
这个是GDI+自己提供的,如果需要修改其他项目,跟到原始文件中,有一个长长的定义,从中选择自己需要的项目就可以。这个过程可能是需要查阅一些文件和进行对比的。
感谢
阅读至此,希望有所收获。