MFC读写EXIF信息,图片非占用

简介: MFC读写EXIF信息读取有类库可以直接调用,网络上有直接可以用的;但是写Exif的资料非常少,我花了一点时间研究收集,终于成功。将相关的资料共享。主要是借助gdi+,需要注意的地方很多 // ConsoleApplication2.cpp : 定义控制台应用程序的入口点。

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+自己提供的,如果需要修改其他项目,跟到原始文件中,有一个长长的定义,从中选择自己需要的项目就可以。这个过程可能是需要查阅一些文件和进行对比的。
感谢 阅读至此,希望有所收获。
 
目前方向:图像拼接融合、图像识别 联系方式:jsxyhelu@foxmail.com
目录
相关文章
无需cad,从dwg文件中读取缩略图
无需cad,从dwg文件中读取缩略图
|
3月前
|
JSON Java 数据处理
Unity 数据读取|(二)多种方式读取文本文件
Unity 数据读取|(二)多种方式读取文本文件
|
4月前
|
计算机视觉 C++
win7系统OpenCV读取图片内存位置异常
win7系统OpenCV读取图片内存位置异常
30 0
Qt实用技巧:测试QImage加载解码、QImage使用原数据、QImage格式转换等等的时间消耗
Qt实用技巧:测试QImage加载解码、QImage使用原数据、QImage格式转换等等的时间消耗
|
C++
CxImage内存方式转换图像
最近,处于项目需要,需要将Bmp转换为JPEG格式。以前做过,采用的是GDI+的方式,该方式有一个极大地缺陷为无法实现跨平台处理。闲话少说,进入正题。 [cpp] view plain copy   CxImage cxImageBmp(pRGBBuffer, dwRGBSize, CXIMAGE_FORMAT_BMP);      cxImageBmp.Save("D:\\ttt.jpg",CXIMAGE_FORMAT_JPG);   该方式很正常,顺利将RGB格式24位BMP图像转化为本地JPG文件并保存下来。
1159 0
|
测试技术 图形学
Unity读取AssetBundle资源全教程(所有读取方式)
读取/加载 AssetBundle 资源的多种方式 本文提供全流程,中文翻译。 Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) ...
2281 0
|
C++
CxImage动态加载图片(判断图片文件类型)
1、打开一张图可以通过创建一个新的CxImage对象来完成,通过构造函数来打开一张图CxImage::CxImage(const char * filename, DWORD imagetype)其中filename是需要打开的文件路径,imagetype是文件类型,支持的类型有: [c...
1572 0