山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他コマンドプロンプト上でjpegファイルをクリッピング(多角形,楕円,曲線)して保存するプログラム(GDI+)(32/64bit)
概要
コマンドプロンプト上で保存jpegファイルをリージョンでクリッピングして保存するプログラムです。
入力ファイルはtest.jpg、クリッピング結果はtest_cut.jpgに保存されます。
プログラムソースの#ifディレクティブの評価値を変更しリコンパイルし実行することにより多角形、楕円、スプラインの3種類のクリッピングを試すことができます。
以下に入力ファイルとそれぞれのクリッピング結果を示します。
入力ファイルはtest.jpg、クリッピング結果はtest_cut.jpgに保存されます。
プログラムソースの#ifディレクティブの評価値を変更しリコンパイルし実行することにより多角形、楕円、スプラインの3種類のクリッピングを試すことができます。
以下に入力ファイルとそれぞれのクリッピング結果を示します。
テスト環境
コンパイラ
Visual C++ 2008/2013 Express 32/64bit マルチバイト/UNICODE実行環境
Windows 10 Home(32bit/64bit)Windows 7 Enterprise Service Pack 1 64bit
プログラムソースの概要
jpegcut2.cpp
_tmain
GdiplusStartupによりGDI+の初期化をします。
GetEncoderClsidによりjpegエンコーダを取得します。
imgtrim関数を呼び出しクリッピングを実行します。
GdiplusShutdownにより終了処理を実行します。
imgtrim
jpegファイルの読み込み等
jpegファイルよりGdiplus::Imageオブジェクトを作成します。GDI+はunicodeしかサポートしないのでマルチバイトでコンパイルした場合は、unicodeに変換するコードを有効にします。
GetHorizontalResolution,
GetVerticalResolution関数によりソースファイルの解像度(DPI)を取得します。
new Bitmapにより保存用のBitmapオブジェクトを作成します。
SetResolutionでBitmapオブジェクトの解像度を設定します。
Bitmapオブジェクトを元にGraphicsオブジェクトを作成します。
クリッピングを実施すると背景が真っ黒になるので、Clear関数により背景色を設定します。色はColorクラスのコンストラクタで指定します。
パスの作成
#ifディレクティブの評価値(0の場合#if~#endがコンパイル対象とならない)により以下の3つのリージョンのいずれかを適用します。多角形(Polygon)
Pointの配列でクリッピングしたい領域の各座標を指定します。ここではひし形としています。AddPolygonに上記の配列と要素数を引数として渡すとポリゴンのパスとして設定します。
要素数はsizeof演算子で計算させます。
Point po[] = { Point(width / 2, 0), Point(width, height / 2), Point(width / 2, height), Point(0, height / 2) };
gp->AddPolygon(po, sizeof(po) / sizeof(po[0]));
楕円(Ellipse)
AddEllipseで楕円をパスとして設定します。この関数では、楕円に外接する長方形の左上座標と右下座標を指定します。
gp->AddEllipse(width * 2 / 10, height * 2 / 10, width * 6 / 10, height * 6 / 10);
スプライン(Curve)
スプライン曲線の各点の座標をPointの配列で指定します。この座標列が猫のシルエットとなります。AddCurveに上記の配列と要素数を引数として渡すしパスとして設定します。
要素数はsizeof演算子で計算させます。
Point po[] = {
Point(152, 179), Point(159, 175), Point(160, 154), Point(143, 134), Point(138, 127), Point(123, 115), Point(122, 102),
Point(120, 95), Point(126, 94), Point(138, 93), Point(148, 90), Point(154, 86), Point(157, 94), Point(168, 98), Point(178, 104),
Point(206, 112), Point(224, 134), Point(228, 149), Point(228, 161), Point(226, 166), Point(235, 168), Point(247, 166), Point(265, 166),
Point(286, 162), Point(292, 167), Point(288, 173), Point(228, 180), Point(218, 181), Point(205, 184), Point(197, 183), Point(156, 186) };
gp->AddCurve(po, sizeof(po) / sizeof(po[0]));
リージョンの作成・設定
Regionクラスのコンストラクタにより先ほど作成したパスを元にリージョンを作成します。SetClip関数によりリージョンをクリッピングとしてGraphicsとして設定します。
描画・保存・各オブジェクトの解放
DrawImage関数によりImageオブジェクトの指定領域をGraphicsオブジェクトに描画します。
DrawImage関数には沢山のオーバーロードされた形式があります。
描画が終了すればImageオブジェクトは不要なのでデストラクタでImageオブジェクトを解放します。
Save関数によりBitmapオブジェクトをファイルに保存します。マルチバイトでコンパイルした場合は、unicodeに変換するコードを有効にします。
リージョン,パス,Bitmap,Graphicsオブジェクトを解放します。
ソースコード
jpegcut2.cpp
// jpegをリージョンでクリッピング
// コマンドプロンプトで動作
// GDI+ランタイムが必要
// 使い方
// jpegcut2
#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
#include <tchar.h>
#include <locale.h>
#pragma comment(lib,"gdiplus.lib")
using namespace Gdiplus;
GdiplusStartupInput gdiSI;
ULONG_PTR gdiToken;
CLSID encoderClsid;
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid); // エンコーダーの取得
int imgtrim(TCHAR* dtc, TCHAR* src, int wdith, int height);
int _tmain(int argc, TCHAR** argv){
// UNICODE文字を標準出力に正しく表示させるためにロケールを設定
_tsetlocale(LC_ALL, _TEXT(""));
GdiplusStartup(&gdiToken, &gdiSI, NULL);
if (GetEncoderClsid(L"image/jpeg", &encoderClsid) < 0){
_tprintf(_TEXT("jpegエンコーダーが取得できませんでした。¥n"));
return (int)0;
}
if (imgtrim(_TEXT("test_cut.jpg"), _TEXT("test.jpg"), 320, 240))
_tprintf(_TEXT("jpegトリミングに失敗しました¥n"));
else
_tprintf(_TEXT("jpegトリミングソフト¥n¥n使い方¥n¥njpegcut1 保存ファイル 入力ファイル 切り取り位置x 切り取り位置y 切り取り横幅 切り取り高さ¥n"));
GdiplusShutdown(gdiToken);
return 0;
}
int imgtrim(TCHAR* dtc, TCHAR* src, int width, int height){
Image* srcImage = 0;
#ifdef UNICODE
srcImage = Bitmap::FromFile(src);
#else
WCHAR srcFile[MAX_PATH];
MultiByteToWideChar(932, 0, src, -1, srcFile, sizeof(srcFile) / sizeof(WCHAR));
srcImage = Bitmap::FromFile(srcFile);
#endif
if (srcImage == 0 || srcImage->GetLastStatus() != Gdiplus::Ok){
srcImage->~Image();
return -1;
}
float px_res = srcImage->GetHorizontalResolution(); // jpgファイルの解像度DPI(横)
float py_res = srcImage->GetVerticalResolution(); // jpgファイルの解像度DPI(縦)
Bitmap* bmp = new Bitmap(width, height); // 保存用
bmp->SetResolution(px_res, py_res);
Graphics* MyGraphics = Graphics::FromImage(bmp);
Color orgColor(170, 163, 155);
MyGraphics->Clear(orgColor);
GraphicsPath* gp = new GraphicsPath();
#if 0 // ひし形のリージョン
Point po[] = { Point(width / 2, 0), Point(width, height / 2), Point(width / 2, height), Point(0, height / 2) };
gp->AddPolygon(po, sizeof(po) / sizeof(po[0]));
#endif
#if 0 // 楕円のリージョン
gp->AddEllipse(width * 2 / 10, height * 2 / 10, width * 6 / 10, height * 6 / 10);
#endif
#if 1 // スプラインのリージョン
Point po[] = {
Point(152, 179), Point(159, 175), Point(160, 154), Point(143, 134), Point(138, 127), Point(123, 115), Point(122, 102),
Point(120, 95), Point(126, 94), Point(138, 93), Point(148, 90), Point(154, 86), Point(157, 94), Point(168, 98), Point(178, 104),
Point(206, 112), Point(224, 134), Point(228, 149), Point(228, 161), Point(226, 166), Point(235, 168), Point(247, 166), Point(265, 166),
Point(286, 162), Point(292, 167), Point(288, 173), Point(228, 180), Point(218, 181), Point(205, 184), Point(197, 183), Point(156, 186) };
gp->AddCurve(po, sizeof(po) / sizeof(po[0]));
#endif
Region* rgn = new Region(gp);
MyGraphics->SetClip(rgn);
MyGraphics->DrawImage(srcImage, 0, 0);
srcImage->~Image();
#ifdef UNICODE
bmp->Save(dtc, &encoderClsid);
#else
WCHAR dtcFile[MAX_PATH];
MultiByteToWideChar(932, 0, dtc, -1, dtcFile, sizeof(dtcFile) / sizeof(WCHAR));
bmp->Save(dtcFile, &encoderClsid);
#endif
delete rgn;
delete gp;
delete bmp;
delete MyGraphics;
return 0;
}
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid){
UINT num = 0;
UINT size = 0;
ImageCodecInfo* pImageCodecInfo;
GetImageEncodersSize(&num, &size);
if (size == 0)
return -1;
pImageCodecInfo = (ImageCodecInfo*)new char[size];
if (pImageCodecInfo == NULL)
return -1;
GetImageEncoders(num, size, pImageCodecInfo);
for (UINT n = 0; n<num; ++n) {
if (wcscmp(pImageCodecInfo[n].MimeType, format) == 0) {
*pClsid = pImageCodecInfo[n].Clsid;
delete pImageCodecInfo;
return n;
}
}
delete pImageCodecInfo;
return -1;
}
ソースコードと実行ファイルのダウンロード
ダウンロード jpegcut2.zip(91.9kB)
jpegcut2.cpp jpegcut2.exe test.jpg
Copyright (C) 2012 山本ワールド All Rights Reserved.