/*	
 *	GdiplusHelper.cpp
 *
 *	GDI+ヘルパー関数
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2016 Naoyuki Sawa
 *
 *	* Fri Mar 11 21:58:48 JST 2016 Naoyuki Sawa
 *	- 1st リリース。
 *	- 現在の所、当モジュールの目的は、以下の二点です。
 *	  │①GDI+を使うアプリケーションで、頻繁に使う共通処理を、このモジュールにまとめる事にしました。
 *	  │  特に、GetEncoderClsid()は使用頻度が高いと思います。
 *	  │②GDI+自体は、C++ソースからしか利用出来ませんが、Cソースからも利用出来るようにしたいです。
 *	  │  厳密にはGdiPlusFlat.hがCバインドですが、依存するインクルードファイルのため、Cソースからインルードできないようです。
 *	  │  そんなわけで、本来GDI+はC++用なのでずか、当モジュールを介して、Cソースからも利用出来るようにしたいと思っています。
 *	  目的②は可能かどうか、まだ目途が立っていません。
 *	  しばらくは目的①に注力し、しばらくして当モジュールが完成して来たら、②も検討しようと思っています。
 *	* Sat Mar 12 21:11:01 JST 2016 Naoyuki Sawa
 *	- GetEncoderClsid()に指定するMIMEタイプの、"image/"を省略する事も出来るようにしました。
 *	  詳細は、GetEncoderClsid()の実装部のコメントを参照して下さい。
 *	* Fri Jun 17 22:27:15 JST 2016 Naoyuki Sawa
 *	- clipstd.hの「using namespace Gdiplus;」を削除した事に伴い、明示的に'Gdiplus::'を指定するように変更しました。
 *	  詳細は、clipstd.hの同日のコメントを参照して下さい。
 */
#include "clip.h"
/****************************************************************************
 *	初期化、終了
 ****************************************************************************/
static ULONG_PTR Gdiplus_Token;
/*--------------------------------------------------------------------------*/
void Gdiplus_Init() {
	Gdiplus::GdiplusStartupInput Input;
	if(Gdiplus::GdiplusStartup(&Gdiplus_Token, &Input, NULL)) { DIE(); }
}
/*--------------------------------------------------------------------------*/
void Gdiplus_Exit() {
	Gdiplus::GdiplusShutdown(Gdiplus_Token);
}
/****************************************************************************
 *	イメージエンコーダ
 ****************************************************************************/
//□参考資料
//│「Microsoft Developer Network - チュートリアル: イメージ処理ネットワークの作成」
//│(https://msdn.microsoft.com/ja-jp/library/ff398050.aspx)
//上記の記事のサンプルソースを元に、以下の変更を行って作成しました。
//・MIMEタイプの文字列引数を、UnicodeでなくシフトJISで指定出来るようにしました。
//・MIMEタイプの文字列の比較を、大文字小文字を区別せずに比較するようにしました。
void GetEncoderClsid(const char* sMimeType, CLSID* pClsid) {
	unsigned i, num, size;
	Gdiplus::ImageCodecInfo* aImageCodecInfo;
	//イメージエンコーダの数と、イメージエンコーダ情報の配列のトータルバイト数を取得する。
	if(Gdiplus::GetImageEncodersSize(&num, &size)) { DIE(); }	//エラー
	//イメージエンコーダ情報の配列を取得するための、メモリを確保する。
	aImageCodecInfo = (Gdiplus::ImageCodecInfo*)malloc(size);
	if(!aImageCodecInfo) { DIE(); }	//メモリ不足
	//イメージエンコーダ情報の配列を取得する。
	if(Gdiplus::GetImageEncoders(num, size, aImageCodecInfo)) { DIE(); }	//エラー
	//各イメージエンコーダ情報について…
	for(i = 0; i < (int)num; i++) {
		//このイメージエンコーダ情報のMIMEタイプを、Unicode⇒シフトJISに変換する。
		char* tMimeType = strdup_UnicodeToShiftJis(aImageCodecInfo[i].MimeType);
		//このイメージエンコーダ情報のMIMEタイプと、指定されたMIMEタイプを、大文字小文字を区別せずに比較する。
		int cmp = strcasecmp(tMimeType, sMimeType);
		//このイメージエンコーダ情報のMIMEタイプを、Unicode⇒シフトJISに変換した、メモリを開放する。
		free(tMimeType);
		//このイメージエンコーダ情報のMIMEタイプと、指定されたMIMEタイプが、大文字小文字を区別せずに一致したら…
		if(!cmp) {
			//クラスIDを格納する。
			*pClsid = aImageCodecInfo[i].Clsid;
			//イメージエンコーダ情報の配列の、メモリを開放する。
			free(aImageCodecInfo);
			return;	//ここまで
		}
	}
	//イメージエンコーダ情報の配列の、メモリを開放する。
	free(aImageCodecInfo);
//{{サービス
	// * Sat Mar 12 21:11:01 JST 2016 Naoyuki Sawa
	// - GetEncoderClsid()に指定するMIMEタイプの、"image/"を省略する事も出来るようにしました。
	// - GDI+のビルトインエンコーダのMIMEタイプは全て"image/"で始まっており、常に"image/"を指定しなければいけないのは面倒です。
	//   そこで、当関数が検索に失敗した場合、アプリケーションが"image/"を省略していたら、当関数が自動的に"image/"を補って、もう一度検索するようにしました。
	//   これはサービスであり、本質的な変更ではありません。
	//   <例>
	//   │GetEncoderClsid("image/gif", &clsid); //┬どちらでも同じ結果になります。
	//   │GetEncoderClsid("gif", &clsid);       //┘
	//当関数が検索に失敗した場合、アプリケーションが"image/"を省略していたら、当関数が自動的に"image/"を補って、もう一度検索する。
	if(strncasecmp(sMimeType, "image/", 6)) {	//この条件判断を行わないと、"image/"を補っても検索に失敗した場合に、無限に再帰してしまうので注意せよ。
		sMimeType = strconcat("image/", sMimeType, NULL);
		GetEncoderClsid(sMimeType, pClsid);
		free((void*)sMimeType);
		return;	//ここまで
	}
//}}サービス
	DIE();	//指定されたMIMEタイプに一致する、イメージエンコーダ情報が無かった。
}
