본문 바로가기

Visual C++/Metadata Reader Class using FreeImage

JPEG Metadata Reading with FreeImageReader class

JPEG 이미지 파일에 포함된 Metadata 를 읽어오기 위해 FreeImage 라이브러리를 사용하는 예

여기서는 앞서 작성했던 기능들을 모아서 클래스를 작성하고 프로젝트에서 쉽게 호출하는 예제를 소개한다


앞서 소개한 내용 참조

FreeImage의 다운로드 및 VC++ 프로젝트에 설정

FreeImage를 이용하여 JPEG 이미지의 특정 Metadata를 읽어오는 예제

Exiv2 커맨드라인 유틸리티를 이용하여 JPEG 메타데이타를 변경하는 예제


main.cpp

#include <iostream>


#include "FreeImageReader.h"


using namespace std;

/** 이 프로그램은 FreeImage 바이너리 배포판에 포함된 다음과 같은 3가지 파일을 필요로 합니다

1. FreeImage.h : 아래의 라이브러리 안에 구현된 함수들의 원형이 선언되어 있으므로 Compiler에 의해 참조됩니다

2. FreeImage.dll: 이 코드가 컴파일되어 생성되는 실행파일이 있는 곳에 복사해 두면 Linker에 의해 참조됩니다

3. FreeImage.lib: 프로젝트의 Library Drectories에 이 라이브러리가 있는 디렉토리를 등록하고

   #pragma comment(lib, "FreeImage.lib") 디렉티브를 이용하면 Linker에 의해 참조됩니다

*/

int main(int argc, char *argv[]) {


FreeImageReader freeImageReader;


char* jpgFullPath = "D:\\test\\sample1.jpg";


cout << endl << "*********  UserComment 태그 검색 테스트  **************" << endl;


char* tagName = "UserComment";

char* tagValue =  freeImageReader.GetValue3(jpgFullPath, tagName);

cout << tagName << " : " << tagValue << endl;


cout << "*******************************************************" << endl;


return 0;

}


FreeImageReader.h

#pragma once


#include "FreeImage.h"


class FreeImageReader

{

public:

FreeImageReader(void);

~FreeImageReader(void);


FIBITMAP* LoadImage(const char* lpszPathName, int flag);

static void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char* message);

char* GetValue1(const char* tagName, FIBITMAP* dib, FREE_IMAGE_MDMODEL model);

char* GetValue2(const char* tagName, FIBITMAP* dib, FREE_IMAGE_MDMODEL model);

char* GetValue3(const char* jpgFullPath, const char* tagName);

};


FreeImageReader.cpp

#include <iostream>

#include "FreeImageReader.h"


#pragma comment(lib, "FreeImage.lib")


using namespace std;


FreeImageReader::FreeImageReader(void)

{

// call this ONLY when linking with FreeImage as a static library

FreeImage_Initialise();


// initialize your own FreeImage error handler

FreeImage_SetOutputMessage(FreeImageErrorHandler);


// print version & copyright infos

cout << "FreeImage " << FreeImage_GetVersion() << "\n";

cout << FreeImage_GetCopyrightMessage() << "\n\n";

}



FreeImageReader::~FreeImageReader(void)

{

// call this ONLY when linking with FreeImage as a static library

FreeImage_DeInitialise();

}


/** Generic image loader

@param lpszPathName Pointer to the full file name

@param flag Optional load flag constant

@return Returns the loaded dib if successful, returns NULL otherwise

*/

FIBITMAP* FreeImageReader::LoadImage(const char* lpszPathName, int flag)

{

FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;


// check the file signature and deduce its format

// (the second argument is currently not used by FreeImage)

fif = FreeImage_GetFileType(lpszPathName, 0);

if(fif == FIF_UNKNOWN) {

// no signature ?

// try to guess the file format from the file extension

fif = FreeImage_GetFIFFromFilename(lpszPathName);

}

// check that the plugin has reading capabilities ...

if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {

// ok, let's load the file

FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);

// unless a bad file format, we are done !

return dib;

}

return NULL;

}


/**

FreeImage error handler

@param fif Format / Plugin responsible for the error 

@param message Error message

*/

void FreeImageReader::FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char* message)

{

cout << "\n*** ";

if(fif != FIF_UNKNOWN) {

cout << FreeImage_GetFormatFromFIF(fif) << " Format\n";

}

cout << message;

cout << " ***\n";

}


/**

특정 태그에 대한 순차적 검색 예, 검색된 태그의 이름과 값을 출력함

*/

char* FreeImageReader::GetValue1(const char* tagName, FIBITMAP* dib, FREE_IMAGE_MDMODEL model)

{

FITAG *tag = NULL;

FIMETADATA *mdhandle = NULL;


mdhandle = FreeImage_FindFirstMetadata(model, dib, &tag);

char* _tagValue = NULL;

if(mdhandle) {


do {

char* _tagName = (char*) FreeImage_GetTagKey(tag);

if(strcmp(_tagName, tagName)==0)

{

FREE_IMAGE_MDTYPE tagType = FreeImage_GetTagType(tag);

// 7 = FIDT_UNDEFINED, An 8-bit byte that may contain anything, depending on the definition of the field.

_tagValue = (char*)  FreeImage_TagToString(model, tag);

//cout << _tagName << " : " << _tagValue << " : " << tagType << endl;

break;

}else continue;


} while(FreeImage_FindNextMetadata(mdhandle, &tag));

}

// Unload the bitmap

FreeImage_Unload(dib);

return _tagValue;

}


/**

특정 태그에 대한 비순차적 검색의 예, 검색된 태그의 이름과 값을 출력함

*/

char* FreeImageReader::GetValue2(const char* tagName, FIBITMAP* dib, FREE_IMAGE_MDMODEL model)

{

FITAG *tagUserComment = NULL;

FreeImage_GetMetadata(model, dib, tagName, &tagUserComment);

char* _tagValue = NULL;

if(tagUserComment != NULL) {

char* _tagName = (char*) FreeImage_GetTagKey(tagUserComment);

FREE_IMAGE_MDTYPE tagType = FreeImage_GetTagType(tagUserComment);

// 7 = FIDT_UNDEFINED, An 8-bit byte that may contain anything, depending on the definition of the field.

_tagValue = (char*)  FreeImage_TagToString(model, tagUserComment);

//cout << _tagName << " : " << _tagValue << " : " << tagType << endl;

}

// Unload the bitmap

FreeImage_Unload(dib);

return _tagValue;

}



/**

태그에 대한 비순차적 검색을 제공하며 사용 편의성을 위해 파라미터 수를 줄임

*/

char* FreeImageReader::GetValue3(const char* jpgFullPath, const char* tagName)

{

// Load the bitmap

FIBITMAP *dib = LoadImage(jpgFullPath, 0);

if(!dib) {

cout <<  "이미지 로드 실패" << endl;

return NULL;

}


FITAG *tagUserComment = NULL;

FreeImage_GetMetadata(FIMD_EXIF_EXIF, dib, tagName, &tagUserComment);

char* _tagValue = NULL;

if(tagUserComment != NULL) {

char* _tagName = (char*) FreeImage_GetTagKey(tagUserComment);

FREE_IMAGE_MDTYPE tagType = FreeImage_GetTagType(tagUserComment);

// 7 = FIDT_UNDEFINED, An 8-bit byte that may contain anything, depending on the definition of the field.

_tagValue = (char*)  FreeImage_TagToString(FIMD_EXIF_EXIF, tagUserComment);

//cout << _tagName << " : " << _tagValue << " : " << tagType << endl;

}

// Unload the bitmap

FreeImage_Unload(dib);

return _tagValue;

}