C++GDI+を使用して画像を切り取る
4227 ワード
概要
現在、C#は画像を切り取るケースが多いが、C++を使うケースは少ない.しかし、現在のプロジェクトは画像をカットする必要があります.私もOpenCVを使うのが簡単だと知っていますが、プロジェクトの中にOpenCVのものをたくさん配置したくありません.プロジェクトはあまり必要ありませんから.
このブログには、ピクチャカット、バイト配列、IStreamの変換、StreamとImageクラスの変換の2つの知識点が含まれています.
画像の切り取り
まず自分でネット上のC++の画像を切り取る方法を探して、それからGDI+の中のDrawImageという関数が画像を切り取ることができることを発見しました.
Status DrawImage(IN Image* image, IN const RectF& destRect, IN REAL srcx, IN REAL srcy, IN REAL srcwidth, IN REAL srcheight, IN Unit srcUnit, IN const ImageAttributes* imageAttributes = NULL, IN DrawImageAbort callback = NULL, IN VOID* callbackData = NULL)
バイト配列とIStreamの変換
1.グローバル領域にメモリハンドルを作成し、ターゲットストリームに使用する. HGLOBAL hDesMem = GlobalAlloc(GMEM_MOVEABLE, ImageSize); IStream *pDesStream = NULL; CreateStreamOnHGlobal(hDesMem, TRUE, &pDesStream); BYTE *pDesData = (BYTE *)GlobalLock(hDesMem); 2、.メモリを、購買依頼のグローバルスペースにコピーします. CopyMemory(pDesData, imgSrc, ImageSize); GlobalUnlock(hDesMem);
3、最後にグローバル空間を解放し、ストリームを解放することを忘れないでください.
GlobalFree(hDesMem);//グローバルスペースpDesStream->Release(); pOutStream->Release();
IStreamとImageクラスの変換
2時間かけてImageクラスを表示した後、IStreamでインスタンスを作成できるImageのコンストラクション関数が入っていることに気づきました.
Image( IN IStream* stream, IN BOOL useEmbeddedColorManagement = FALSE );
その後、FromStreamの関数もImageポインタに変換できることが分かった.
inline Image* Image::FromStream( IN IStream* stream, IN BOOL useEmbeddedColorManagement )
まとめ
初めてブログを出しましたが、間違ったところがあれば、牛さんの包容と指摘をお願いします.
現在、C#は画像を切り取るケースが多いが、C++を使うケースは少ない.しかし、現在のプロジェクトは画像をカットする必要があります.私もOpenCVを使うのが簡単だと知っていますが、プロジェクトの中にOpenCVのものをたくさん配置したくありません.プロジェクトはあまり必要ありませんから.
このブログには、ピクチャカット、バイト配列、IStreamの変換、StreamとImageクラスの変換の2つの知識点が含まれています.
画像の切り取り
まず自分でネット上のC++の画像を切り取る方法を探して、それからGDI+の中のDrawImageという関数が画像を切り取ることができることを発見しました.
Status DrawImage(IN Image* image, IN const RectF& destRect, IN REAL srcx, IN REAL srcy, IN REAL srcwidth, IN REAL srcheight, IN Unit srcUnit, IN const ImageAttributes* imageAttributes = NULL, IN DrawImageAbort callback = NULL, IN VOID* callbackData = NULL)
バイト配列とIStreamの変換
1.グローバル領域にメモリハンドルを作成し、ターゲットストリームに使用する. HGLOBAL hDesMem = GlobalAlloc(GMEM_MOVEABLE, ImageSize); IStream *pDesStream = NULL; CreateStreamOnHGlobal(hDesMem, TRUE, &pDesStream); BYTE *pDesData = (BYTE *)GlobalLock(hDesMem); 2、.メモリを、購買依頼のグローバルスペースにコピーします. CopyMemory(pDesData, imgSrc, ImageSize); GlobalUnlock(hDesMem);
3、最後にグローバル空間を解放し、ストリームを解放することを忘れないでください.
GlobalFree(hDesMem);//グローバルスペースpDesStream->Release(); pOutStream->Release();
IStreamとImageクラスの変換
2時間かけてImageクラスを表示した後、IStreamでインスタンスを作成できるImageのコンストラクション関数が入っていることに気づきました.
Image( IN IStream* stream, IN BOOL useEmbeddedColorManagement = FALSE );
その後、FromStreamの関数もImageポインタに変換できることが分かった.
inline Image* Image::FromStream( IN IStream* stream, IN BOOL useEmbeddedColorManagement )
include
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;
// : ,
// :imgSrc, ,
// ImageSize:
// imgDst:
// xPos: x
// yPos: y
// Width:
// Height:
// : 0,
DWORD CutPicture(BYTE *imgSrc, int ImageSize, BYTE* imgDst, int xPos, int yPos, int Width, int Height)
{
int nRet = -1;
if (Width<=0 || Height <=0 || imgSrc==nullptr || ImageSize<=0)
{
return 0;
}
GdiplusStartupInput gdiplusstartupinput;
ULONG_PTR gdiplustoken;
DWORD nDstSize = 0;
GdiplusStartup(&gdiplustoken, &gdiplusstartupinput, NULL);
{
CLSID clsid;
nRet = GetCodecClsid(L"image/jpeg", &clsid);
if (nRet == -1)
{
GdiplusShutdown(gdiplustoken);
return 0;
}
// ,
HGLOBAL hDesMem = GlobalAlloc(GMEM_MOVEABLE, ImageSize);
IStream *pDesStream = NULL;
CreateStreamOnHGlobal(hDesMem, TRUE, &pDesStream);
BYTE *pDesData = (BYTE *)GlobalLock(hDesMem);
//3. , 。
CopyMemory(pDesData, imgSrc, ImageSize);
GlobalUnlock(hDesMem);
// 4. Image
Image *bmSrc = Image::FromStream(pDesStream);
// bmSrc->Save(L"E:\\test3.jpg", &clsid, NULL);
int w = 0, h = 0;
w = bmSrc->GetWidth();
h = bmSrc->GetHeight();
if (w < h) // Width Height
{
int nTemp = Width;
Width = Height;
Height = nTemp;
}
Bitmap *bmPhoto = new Bitmap(Width, Height); // elvsi
bmPhoto->SetResolution(bmSrc->GetHorizontalResolution(), bmSrc->GetVerticalResolution());
//bmPhoto->SetResolution(Width, Height);
Graphics grPhoto(bmPhoto);
grPhoto.Clear((ARGB)Color::White);
grPhoto.SetInterpolationMode(InterpolationModeHighQualityBicubic);
Rect dest(0, 0, w, h);
grPhoto.DrawImage((Image*)bmSrc, dest, xPos, yPos, Width, Height, UnitPixel);
// bmPhoto->Save(L"E:\\test4.jpg", &clsid, NULL);
//2.
IStream *pOutStream = NULL;
ULARGE_INTEGER pSeek;
LARGE_INTEGER dlibMove = { 0 };
CreateStreamOnHGlobal(NULL, TRUE, &pOutStream);
// JPEG
bmPhoto->Save(pOutStream, &clsid, NULL);
pOutStream->Seek(dlibMove, STREAM_SEEK_SET, &pSeek);
pOutStream->Read(imgDst, ImageSize, &nDstSize);
GlobalFree(hDesMem); //
delete bmSrc;
delete bmPhoto;
pDesStream->Release();
pOutStream->Release();
}
GdiplusShutdown(gdiplustoken);
return nDstSize;
}
まとめ
初めてブログを出しましたが、間違ったところがあれば、牛さんの包容と指摘をお願いします.