반응형

 

graphics 기초

w,h크기로 버퍼를 만들었으면, 유효한 좌표는 (0,0)부터 (w-1, h-1)까지다.

RECT에 있어서도 마찬가지인데, rect.left = 0, rect.right=2이면, rect.width는 3이 아니라 2가된다.

right 및 bottom은 exclusive 되는것.

여기를 참조하자.

resize 할때 ratio 유지하기

아래 코드를 참조하자.


Gdiplus::Bitmap* GDIPlusImageProcessor::ResizeClone(Bitmap *bmp, INT width, INT height)
{
    UINT o_height = bmp->GetHeight();
    UINT o_width = bmp->GetWidth();
    INT n_width = width;
    INT n_height = height;
    double ratio = ((double)o_width) / ((double)o_height);
    if (o_width > o_height) {
        // Resize down by width
        n_height = static_cast<UINT>(((double)n_width) / ratio);
    } else {
        n_width = static_cast<UINT>(n_height * ratio);
    }
    Gdiplus::Bitmap* newBitmap = new Gdiplus::Bitmap(n_width, n_height, bmp->GetPixelFormat());
    Gdiplus::Graphics graphics(newBitmap);
    graphics.DrawImage(bmp, 0, 0, n_width, n_height);
    return newBitmap;
}

이미지관련

GDI+로 stc에 이미지 찍기

물론 직접 디코딩하는게 SevityWare정신(?)에도 맞고, 포터블 하겠지만(?)

jpg,png,bmp등 너무 많은 파일이 있고, 픽셀포맷도 너무 다양해서 시작하기에 부담이 된다.

게다가 jpg 하나에도 jpg2000등 여러가지 종류가 있지 않나..

직접 디코딩은 나중에 시간이 많으면 도전하자.

아래 코드들에서 delete pImg; 빠진듯??

pixel단위 GetPixel이용


#pragma once

#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

#include "SvAssert.h"
#include "stc.h"

int main(void)
{
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR           gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	Bitmap* pImg = Bitmap::FromFile(L"c:\\a.jpg");

	unsigned int h = pImg->GetHeight();
	unsigned int w = pImg->GetWidth();
	Gdiplus::PixelFormat pf = pImg->GetPixelFormat();

	for (int y = 0; y < (int)h; y++)
	{
		for (int x = 0; x < (int)w; x++)
		{
			Color c;
			pImg->GetPixel(x, y, &c);
			SetPixel(x, y, (unsigned int)c.GetValue());
		}
	}

	GdiplusShutdown(gdiplusToken);
	return 0;
}

이미지 버퍼에 직접 접근하여 복사

여기를 보면 버퍼에 접근하는 법 나옴


#pragma once

#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

#include "SvAssert.h"
#include "stc.h"

int main(void)
{
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR           gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	Bitmap* pImg = Bitmap::FromFile(L"a.jpg");

	unsigned int h = min(STC_HEIGHT, pImg->GetHeight());
	unsigned int w = min(STC_WIDTH,pImg->GetWidth());
	PixelFormat pf = pImg->GetPixelFormat();

	BitmapData bitmapData;
	pImg->LockBits(&Rect(0, 0, w, h), ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData);
	unsigned int *pRaw = (unsigned int*)bitmapData.Scan0;   // for easy access and indexing

	for (int y = 0; y < (int)h; y++)
	{
		memcpy(&VGS::buf[y*STC_WIDTH], &pRaw[y*bitmapData.Stride/4], w*4);
	}
	Invalidate();
	pImg->UnlockBits(&bitmapData);

	GdiplusShutdown(gdiplusToken);
	return 0;
}

BitBlt()함수를 stc.h에 추가해 보았다. (Resize해서 찍는건 안된다.)


#pragma once

#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

#include "SvAssert.h"
#include "stc.h"

int main(void)
{
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR           gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	Bitmap* pImg = Bitmap::FromFile(L"a.jpg");

	BitmapData bitmapData;
	pImg->LockBits(&Rect(0, 0, pImg->GetWidth(), pImg->GetHeight()), ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData);
	unsigned int *pRaw = (unsigned int*)bitmapData.Scan0;   // for easy access and indexing

	BitBlt(10, 10, pRaw, 100, 100, bitmapData.Stride);

	pImg->UnlockBits(&bitmapData);

	GdiplusShutdown(gdiplusToken);
	return 0;
}

VGS 버퍼에 직접 그리기

아마도 가장 빠를 듯하다. 공유 메모리에 전달하기 위해 Invalidate()라는 함수를 stc.h에 추가해야 했다.


#pragma once

#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

#include "SvAssert.h"
#include "stc.h"

int main(void)
{
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR           gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	Bitmap* pImg = Bitmap::FromFile(L"a.jpg");

	Bitmap stcBitmap(STC_WIDTH, STC_HEIGHT, STC_WIDTH * 4, PixelFormat32bppRGB, (BYTE*)VGS::buf);
	Graphics g(&stcBitmap);
	
        //원할경우 아래 좌표및 크기를 조정하면 된다. 
        g.DrawImage(pImg, 0, 0, stcBitmap.GetWidth(), stcBitmap.GetHeight());
        
	Invalidate();
	return 0;
}

SvGC로 이미지 출력

위 내용을 종합해서 SvGC를 구현했다. 그 사용법은 아래를 참조하자.


#include "SvCommon.h"

int main(void)
{
	SvGC gc(SvGC::GC_TYPE_WIN32_VGS);
	SvGC::image_handle img1 = gc.CreateImage("a.jpg", SvGC::GC_IMAGE_TYPE_FILE, 100, 100);
	gc.DrawImage(img1, 10, 10);
	gc.DestroyImage(img1);
	return 0;
}
반응형

'비트코인' 카테고리의 다른 글

DID  (1) 2025.06.01
NFT  (3) 2023.06.24
나만의 ERC-20 토큰 만들기 실습편  (2) 2023.05.21
Solidity  (0) 2023.05.17
나만의 ERC-20 토큰 만들기  (0) 2023.05.09

+ Recent posts