コマンドプロンプト上でjpegファイルをトリムして保存するプログラム(GDI+)(32/64bit)

icon 項目のみ表示/展開表示の切り替え

概要

コマンドプロンプト上で保存jpegファイル トリムするjpegファイル 選択する矩形の左上座標と幅と高さを指定して実行するトリムしたファイルが作成されます。

テスト環境

コンパイラ

Visual C++ 2008/2013 Express 32/64bit マルチバイト/UNICODE

実行環境

Windows 10 Home(32bit/64bit)
Windows 7 Enterprise Service Pack 1 64bit

動作例

以下にコマンドプロンプト上でimage1.jpgをトリミングしてimage2.jpgに保存する例を示す。
jpegcut1 image2.jpg image1.jpg 100 50 150 100
image1.jpgの座標100,50を左上とし幅150、高さ100の矩形領域の外をトリミングしてimage2.jpgに保存している。
image1.jpg 0 50 100 150 200 250 300 320 50 100 150 200 240 image2.jpg 0 50 100 150 50 100 SVGの代替画像
あらかじめ画像サイズがわかっていればバッチファイルを使用して例えば4分割等が簡単にできる。以下に4分割の例を示す。
複数のファイルを分割する場合は、バッチファイルからcall文を使用して4cut.batを呼び出す必要がある。
以下のバッチファイルは、引数で指定されたピクセル数をsetコマンドにより2分の1の値を求め、jpegcut1にその値を渡している。

バッチファイルのソース 4cut.bat

set /a "A=%3 / 2"
set /a "H=%4 / 2"
jpegcut1 %1_1.jpg %2 0 0 %A% %H%
jpegcut1 %1_2.jpg %2 %A% 0 %A% %H%
jpegcut1 %1_3.jpg %2 0 %H% %A% %H%
jpegcut1 %1_4.jpg %2 %A% %H% %A% %H%

バッチファイルの呼び出し例

第1引数に保存ファイルの拡張子を除いた名称、第2引数にトリムするファイル、第3引数にトリムするファイルの横幅、第4引数に縦幅を指定する。以下に実行例を示す。
4cut image3 image1.jpg 320 200
image3_1.jpg 0 50 100 150 160 50 100 120 image3_2.jpg 0 50 100 150 160 50 100 120 image3_3.jpg 50 100 150 160 0 50 100 120 image3_4.jpg 50 100 150 160 0 50 100 120 SVGの代替画像
複数のjpegファイルを4分割した場合は以下のようにバッチファイルを記述する。
call 4cut image_cut1 image1.jpg 320 200
call 4cut image_cut2 image2.jpg 320 200
call 4cut image_cut3 image3.jpg 320 200

プログラムソースの概要

jpegcut1.cpp

_tmain

GdiplusStartupによりGDI+の初期化をします。
GetEncoderClsidによりjpegエンコーダを取得します。
コマンドラインの引数の個数をチェックし7個(自分自身のプログラム名を含む)の場合、imgcut関数を呼び出しトリミングを実行します。
GdiplusShutdownにより終了処理を実行します。

imgcut

jpegファイルよりGdiplus::Imageオブジェクトを作成します。
GDI+はunicodeしかサポートしないのでマルチバイトでコンパイルした場合は、unicodeに変換するコードを有効にします。
GetHorizontalResolution,GetVerticalResolution関数によりソースファイルの解像度(DPI)を取得します。
new Bitmapにより保存用のBitmapオブジェクトを作成します。
SetResolutionでBitmapオブジェクトの解像度を設定します。
Bitmapオブジェクトを元にGraphicsオブジェクトを作成します。
DrawImage関数によりImageオブジェクトの指定領域をGraphicsオブジェクトに描画します。
DrawImage関数には沢山のオーバーロードされた形式があります。
描画が終了すればImageオブジェクトは不要なのでデストラクタでImageオブジェクトを解放します。
Save関数によりBitmapオブジェクトをファイルに保存します。マルチバイトでコンパイルした場合は、unicodeに変換するコードを有効にします。
Bitmapオブジェクト,Graphicsオブジェクトを解放します。

ソースコード

jpegcut1.cpp

// jpegトリミングソフト
// コマンドプロンプトで動作
// GDI+ランタイムが必要
// 使い方
//   jpegcut1 保存ファイル 入力ファイル 切り取り位置x 切り取り位置y 切り取り横幅 切り取り高さ

#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); //     エンコーダーの取得
// srcで指定するjpegファイルの矩形領域(左上sx,sy 幅 width 高さ height)でトリミングしdtcで指定するjpegファイルに保存
int imgcut(TCHAR* dtc, TCHAR* src, int sx,int sy,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(argc == 7){
                int sx = _ttoi(argv[3]);
                int sy = _ttoi(argv[4]);
                int width = _ttoi(argv[5]);
                int height = _ttoi(argv[6]);
                if(imgcut(argv[1], argv[2], sx, sy, width, height)){
                   _tprintf(_TEXT("jpegトリミングに失敗しました¥n"));
                }
        }else{
           _tprintf(_TEXT("jpegトリミングソフト¥n¥n使い方¥n¥njpegcut1 保存ファイル 入力ファイル 切り取り位置x 切り取り位置y 切り取り横幅 切り取り高さ¥n"));
        }
        GdiplusShutdown(gdiToken);
        return 0;
}

int imgcut(TCHAR* dtc, TCHAR* src, int sx, int sy,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);

        MyGraphics->DrawImage(srcImage, 0,0,sx,sy,width,height,UnitPixel);
        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 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;
}

ソースコードと実行ファイルのダウンロード

ダウンロード jpegcut1.zip(51.7kB)
jpegcut1.cpp
jpegcut1.exe
4cut.bat