반응형

GDI Plus Bitmap을 OpenCV Mat으로, 다시 OpenCV Mat을 GDI Plus Bitmap으로 변환해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <windows.h>
#include <gdiplus.h>
#include <opencv2/opencv.hpp>
 
#pragma comment(lib, "gdiplus")
 
using namespace cv;
using namespace Gdiplus;
 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCSTR lpszClass = "Mat and Bitmap";
 
Mat originalImage;
Mat bitmapToMat;
 
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    WNDCLASS WndClass;
    g_hInst = hInstance;
 
    ULONG_PTR gpToken;
    GdiplusStartupInput gpsi;
    if (GdiplusStartup(&gpToken, &gpsi, NULL!= Ok) {
        MessageBox(NULL, TEXT("GDI+ start-up error."), TEXT("GDI+ Error"), MB_OK);
 
        return 0;
    }
 
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); //(HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hInstance = hInstance;
    WndClass.lpfnWndProc = (WNDPROC)WndProc;
    WndClass.lpszClassName = lpszClass;
    WndClass.lpszMenuName = NULL;
    WndClass.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&WndClass);
 
    hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        630960NULL, (HMENU)NULL, hInstance, NULL);
    ShowWindow(hWnd, nCmdShow);
 
    while (GetMessage(&Message, 000)) {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
 
    GdiplusShutdown(gpToken);
 
    return (int)Message.wParam;
}
 
Mat BitmapToMat(Bitmap* bitmap)
{
    PixelFormat pixelFormat = bitmap->GetPixelFormat();
    if (pixelFormat != PixelFormat32bppARGB) // PixelFormat24bppRGB
        return Mat();
 
    int width = bitmap->GetWidth();
    int height = bitmap->GetHeight();
    Gdiplus::Rect rectLock(00, width, height);
    Gdiplus::BitmapData bitmapData;
 
    if (bitmap->LockBits(&rectLock, Gdiplus::ImageLockModeRead, pixelFormat, &bitmapData) != Gdiplus::Ok)
        return Mat();
 
    Mat mat = Mat(height, width, CV_8UC4, // CV_8UC3
        static_cast<unsigned char*>(bitmapData.Scan0), bitmapData.Stride).clone();
 
    bitmap->UnlockBits(&bitmapData);
 
    return mat;
}
 
void OnPaint(HDC hdc)
{
    Graphics G(hdc);
 
    // Mat to Bitmap
    cvtColor(originalImage, originalImage, COLOR_BGR2BGRA);
    Bitmap bitmap((INT)originalImage.size().width, (INT)originalImage.size().height, (INT)originalImage.step,
        PixelFormat32bppARGB, originalImage.data);
    G.DrawImage(&bitmap, 00, bitmap.GetWidth(), bitmap.GetHeight());
 
    // Bitmap to Mat
    bitmapToMat = BitmapToMat(&bitmap);
 
    imshow("BitmapToMat", bitmapToMat);
}
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
 
    switch (iMessage) {
    case WM_CREATE:
        originalImage = imread("Barbara.jpg");
 
        return 0;
 
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        OnPaint(hdc);
        EndPaint(hWnd, &ps);
 
        return 0;
 
    case WM_DESTROY:
        PostQuitMessage(0);
 
        return 0;
    }
 
    return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
 

 

소스를 입력하고 빌드한다.

 

실행하면 Bitmap과 Mat 포맷의 이미지가 출력된다.

 

Mat to Bitmap 주석 부분이 Mat에서 Bitmap으로 변환의 핵심이다.

 

위 함수가 Bitmap에서 Mat으로 변환의 핵심이다.

 

반응형

'OpenCV' 카테고리의 다른 글

Compiling and Running OpenPose from Source  (2) 2022.05.15
OpenCV with C# and Camera  (0) 2021.12.29
OpenCvSharp for Network  (0) 2021.12.28
OpenCV with C#  (0) 2021.11.20
OpenCV with Qt and MSVC in Windows  (0) 2021.09.26
Posted by J-sean
:
반응형

TcpListener, TcpClient, NetworkStream, MemoryStream등을 이용해 클라이언트의 화면을 서버로 전송하는 프로그램을 만들어 보자. (이 예제는 thread를 사용하지 않기 때문에 상황에 따라 프로그램이 freeze될 수 있다)

 

서버 폼에 PictureBox, ListBlox, Button을 적당히 배치한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
using System.Net;
using System.Net.Sockets;
using System.IO;
 
namespace Server
{
    public partial class Form1 : Form
    {
        TcpListener listener;
        TcpClient client;
        NetworkStream networkStream;
        MemoryStream memoryStream;
        Bitmap bitmap;
        IPHostEntry ipHostEntry;
 
        string serverIP;
        int serverPort;
        byte[] data = new byte[1048576]; // 1MB
        byte[] dataSizeFromClient;
        int receivedDataSize;
        int expectedDataSize;
 
        public Form1()
        {
            InitializeComponent();
 
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
 
            serverPort = 7000;
            // 호스트 이름으로 검색되는 첫 번째 IP4 주소 확인
            string hostName = Dns.GetHostName();
            ipHostEntry = Dns.GetHostEntry(hostName);
            foreach (IPAddress address in ipHostEntry.AddressList)
            {
                if (address.AddressFamily == AddressFamily.InterNetwork)
                {
                    serverIP = address.ToString();
                    break;
                }
            }
            listBox1.Items.Add("Server IP: " + serverIP);
 
            listener = new TcpListener(IPAddress.Any, serverPort);
            //listener = new TcpListener(IPAddress.Parse("127.0.0.1"), serverPort);            
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            listener.Start();
 
            client = listener.AcceptTcpClient();
            listBox1.Items.Add("Client IP: " + client.Client.RemoteEndPoint.ToString().Split(':')[0]);
 
            networkStream = client.GetStream();
 
            receivedDataSize = 0;
            dataSizeFromClient = new byte[sizeof(int)];
 
            if (networkStream.CanRead)
            {
                // 클라이언트로 부터 받아야 할 데이터 사이즈 정보 확인.
                networkStream.Read(dataSizeFromClient, 0, dataSizeFromClient.Length);
                expectedDataSize = BitConverter.ToInt32(dataSizeFromClient, 0);
                listBox1.Items.Add("Expected data size: " + (expectedDataSize / 1024).ToString() + "KB");
 
                // 데이터 송신
                do
                {
                    receivedDataSize += networkStream.Read(data, receivedDataSize, data.Length - receivedDataSize);
                    // Reads data from the NetworkStream and stores it to a byte array.                    
                } while (networkStream.DataAvailable);
                // while (expectedDataSize > receivedDataSize);
            }
 
            listBox1.Items.Add("Data received: " + (receivedDataSize / 1024).ToString() + "KB");
            memoryStream = new MemoryStream(data, 0, receivedDataSize);
            // Initializes a new non-resizable instance of the MemoryStream class
            // based on the specified region (index) of a byte array.            
            bitmap = new Bitmap(memoryStream);
            pictureBox1.Image = bitmap;
 
            listener.Stop();
            client.Close();
            networkStream.Close();
            memoryStream.Close();
        }
    }
}
 

 

서버 소스를 입력하고 빌드한다.

 

클라이언트 폼에 PictureBox, ListBox, Label, TextBox, Button을 적당히 배치한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
using System.Net;
using System.Net.Sockets;
using System.IO;
 
namespace Client
{
    public partial class Form1 : Form
    {
        TcpClient client;
        NetworkStream networkStream;
        MemoryStream memoryStream;
        Bitmap screen;
 
        string serverIP;
        int serverPort;
        byte[] data;
        byte[] dataSizeForServer;
 
        public Form1()
        {
            InitializeComponent();
 
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
            textBox1.Text = "192.168.0.100";
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            memoryStream = new MemoryStream();
            screen = GetScreen();
            pictureBox1.Image = screen;
            screen.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
            data = memoryStream.ToArray();
 
            serverIP = textBox1.Text;
            serverPort = 7000;
            client = new TcpClient(serverIP, serverPort);
            listBox1.Items.Add("Connected to: " + client.Client.RemoteEndPoint.ToString().Split(':')[0]);
 
            networkStream = client.GetStream();
 
            if (networkStream.CanWrite)
            {
                // 보낼 데이터 사이즈를 서버에 미리 공유
                dataSizeForServer = BitConverter.GetBytes(data.Length);
                networkStream.Write(dataSizeForServer, 0, dataSizeForServer.Length);
 
                // 데이터 전송
                networkStream.Write(data, 0, data.Length);
                listBox1.Items.Add("Data sent: " + (data.Length / 1024).ToString() + "KB");
            }
 
            client.Close();
            networkStream.Close();
            memoryStream.Close();
        }
 
        private Bitmap GetScreen()
        {
            Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Graphics g = Graphics.FromImage(bitmap);
            g.CopyFromScreen(0000, bitmap.Size);
            g.Dispose();
 
            return bitmap;
        }
    }
}
 

 

클라이언트 소스를 입력하고 빌드한다.

 

 

서버를 실행하면 IP주소가 표시된다.

 

클라이언트를 실행하고 서버 IP주소를 입력한다.

 

서버의 'Start Server' 버튼을 클릭하면 보안 경고가 나타난다. '액세스 허용' 버튼을 클릭한다.

 

클라이언트의 'Start Client' 버튼을 클릭한다.

 

서버 프로그램에는 접속된 클라이언트의 화면과 함께 클라이언트 IP주소, 전송될 데이터 사이즈, 실제 전송된 데이터 사이즈가 표시된다.

같은 컴퓨터에서 서버와 클라이언트를 동시에 실행했기 때문에 같은 IP주소가 표시된다.

 

 

클라이언트 프로그램에는 캡쳐한 화면과 함께 접속한 서버의 IP주소, 전송된 데이터 사이즈가 표시된다.

 

※ 참고

2021.12.24 - [C#] - C# TCP/IP Image transfer - 이미지(파일) 전송 2

2021.12.25 - [C#] - C# TCP/IP Image transfer - 이미지(파일) 전송 3

 

반응형
Posted by J-sean
:
반응형

Screen capture with Windows API and OpenCV.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <Windows.h>
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
 
using namespace std;
using namespace cv;
 
class hWnd2Mat
{
public:
    hWnd2Mat(HWND hWindow, float scale = 1);
    virtual ~hWnd2Mat();
    virtual void Read();
    Mat capture;
 
private:
    HWND hWnd;
    HDC hWindowDC, hWindowCompatibleDC;
    int height, width, srcHeight, srcWidth;
    HBITMAP hBitmap;
    BITMAPINFOHEADER bi;
};
 
hWnd2Mat::hWnd2Mat(HWND hWindow, float scale)
{
    hWnd = hWindow;
    hWindowDC = GetDC(hWnd);
    hWindowCompatibleDC = CreateCompatibleDC(hWindowDC);
    SetStretchBltMode(hWindowCompatibleDC, COLORONCOLOR);
 
    RECT windowsize;    // get the height and width of the screen
    GetClientRect(hWnd, &windowsize);
 
    srcHeight = windowsize.bottom;
    srcWidth = windowsize.right;
    height = (int)(windowsize.bottom * scale);
    width = (int)(windowsize.right * scale);
 
    capture.create(height, width, CV_8UC4);
 
    // create a bitmap
    hBitmap = CreateCompatibleBitmap(hWindowDC, width, height);
    bi.biSize = sizeof(BITMAPINFOHEADER);    // http://msdn.microsoft.com/en-us/library/windows/window/dd183402%28v=vs.85%29.aspx
    bi.biWidth = width;
    bi.biHeight = -height;  //this is the line that makes it draw upside down or not
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;
 
    // use the previously created device context with the bitmap
    SelectObject(hWindowCompatibleDC, hBitmap);
};
 
void hWnd2Mat::Read()
{
    // copy from the window device context to the bitmap device context
    StretchBlt(hWindowCompatibleDC, 00, width, height, hWindowDC, 00, srcWidth, srcHeight, SRCCOPY);
    //change SRCCOPY to NOTSRCCOPY for wacky colors!
    GetDIBits(hWindowCompatibleDC, hBitmap, 0, height, capture.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
    //copy from hWindowCompatibleDC to hBitmap
};
 
hWnd2Mat::~hWnd2Mat()
{
    DeleteObject(hBitmap);
    DeleteDC(hWindowCompatibleDC);
    ReleaseDC(hWnd, hWindowDC);
};
 
int main()
{
    HWND hWndDesktop = GetDesktopWindow();
    hWnd2Mat desktop(hWndDesktop, 1);    // scale = 1
 
    cout << "Screen capure in 3 seconds." << endl;
    
    for (int i = 3; i > 0; i--)
    {
        cout << i << ".." << endl;
        Sleep(1000);
    }
 
    desktop.Read();
    imshow("Capture", desktop.capture);
 
    waitKey();
 
    return 0;
}



It captures your desktop image in 3 seconds.


반응형
Posted by J-sean
:
반응형

GDI+ Bitmap class inherits from the Image class. The Image class provides methods for loading and saving vector images (metafiles) and raster images (bitmaps). You can build Windows applications with GDI+ and OpenCV.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <windows.h>
#include <gdiplus.h>
#include <opencv2/opencv.hpp>
 
#pragma comment(lib, "gdiplus")
 
using namespace cv;
using namespace Gdiplus;
 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCSTR lpszClass = "MatToBitmap";
 
Mat src;    // source image
Mat org;    // original image
Mat dst;    // processed image
 

Prepare necessities.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    WNDCLASS WndClass;
    g_hInst = hInstance;
 
    ULONG_PTR gpToken;
    GdiplusStartupInput gpsi;
    if (GdiplusStartup(&gpToken, &gpsi, NULL!= Ok) {
        MessageBox(NULL, TEXT("GDI+ start-up error."), TEXT("GDI+ Error"), MB_OK);
 
        return 0;
    }
 
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); //(HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hInstance = hInstance;
    WndClass.lpfnWndProc = (WNDPROC)WndProc;
    WndClass.lpszClassName = lpszClass;
    WndClass.lpszMenuName = NULL;
    WndClass.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&WndClass);
 
    hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,
        670340NULL, (HMENU)NULL, hInstance, NULL);
    ShowWindow(hWnd, nCmdShow);
 
    while (GetMessage(&Message, 000)) {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
 
    GdiplusShutdown(gpToken);
 
    return (int)Message.wParam;
}
 
 

Start GDI+ and change the background color to the radio button color and Window size.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool getFile(PTCHAR filename)
{
    OPENFILENAME ofn;
    memset(&ofn, 0sizeof(OPENFILENAME));
    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = NULL;
    ofn.lpstrFilter = TEXT("all(*.*)\0*.*\0jpg(*.jpg)\0*.jpg\0png(*.png)\0*.png\0bmp(*.bmp)\0*.bmp\0");
    ofn.lpstrFile = filename;
    ofn.nMaxFile = MAX_PATH;
 
    if (GetOpenFileName(&ofn) != 0) {
        //MessageBox(NULL, filename, TEXT("File opened."), MB_OK);
 
        return true;
    }
    else {
        MessageBox(NULL, TEXT("File open failed"), TEXT("No file selected"), MB_OK);
 
        return false;
    }
}
 
 

Retrieve an image file name.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool ImageLoad()
{
    TCHAR filename[MAX_PATH] = "";
 
    if (getFile(filename)) {
        src = imread(filename);
        if (src.empty()) {
            MessageBox(NULL, TEXT("Image load failed"), TEXT("No image loaded"), MB_OK);
 
            return false;
        }
 
        return true;
    }
    else {
        return false;
    }
}
 
 

Read the image from the file.

 

1
2
3
4
5
6
7
8
void ImageResize()
{
    // maximum image display size: 320 X 240 with original ratio
    double ratio = min((double)320 / (double)src.size().width, (double)240 / (double)src.size().height);
    resize(src, src, cv::Size(), ratio, ratio);
    org = src.clone();
    cvtColor(org, org, COLOR_BGR2BGRA);
}
 
 

Resize an image.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
void ImageProcess(int direction)
{
    cvtColor(src, dst, COLOR_BGR2GRAY);
 
    float vertical[] = {
        -202,
        -202,
        -202
    };
 
    float horizontal[] = {
        -2-2-2,
        000,
        222
    };
 
    float diagonal[] = {
        -2-20,
        -202,
        022
    };
    
    Mat emboss;
    switch (direction)
    {
    case 0:
        emboss = Mat(33, CV_32FC1, vertical);
 
        break;
 
    case 1:
        emboss = Mat(33, CV_32FC1, horizontal);
 
        break;
 
    case 2:
        emboss = Mat(33, CV_32FC1, diagonal);
 
        break;
 
    default:
        emboss = Mat(33, CV_32FC1, vertical);
    }
    filter2D(dst, dst, -1, emboss, cv::Point(-1-1), 128);
    
    cvtColor(dst, dst, COLOR_GRAY2BGRA);
}
 
 

Process an image with embossing filter.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void OnPaint(HDC hdc)
{
    if (!dst.empty()) {
        Graphics G(hdc);
 
        Bitmap bitmapDst(dst.size().width, dst.size().height, dst.step, PixelFormat32bppARGB, dst.data);
        Bitmap bitmapOrg(org.size().width, org.size().height, org.step, PixelFormat32bppARGB, org.data);
        // stride(src.step): Integer that specifies the byte offset between the beginning of one scan line and
        // the next. This is usually(but not necessarily) the number of bytes in the pixel format(for example,
        // 2 for 16 bits per pixel) multiplied by the width of the bitmap. The value passed to this parameter
        // must be a multiple of four.
 
        G.DrawImage(&bitmapDst, 00, bitmapDst.GetWidth(), bitmapDst.GetHeight());
        G.DrawImage(&bitmapOrg, bitmapOrg.GetWidth() + 100, bitmapOrg.GetWidth(), bitmapOrg.GetHeight());
    }
    else {
        TextOut(hdc, 270110, TEXT("No image to display"), 19);
    }
}
 
 

Draw original and processed images.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
enum { ID_R1 = 101, ID_R2, ID_R3 };
HWND r1, r2, r3;
int x = 10;
int y = 270;
int w = 90;
int h = 20;
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;    
 
    switch (iMessage) {
    case WM_CREATE:
        if (ImageLoad()) {
            ImageResize();
            ImageProcess(0);
        }
        
        CreateWindow(TEXT("button"), TEXT("Filter type"), WS_CHILD | WS_VISIBLE |
            BS_GROUPBOX, 525029050, hWnd, (HMENU)0, g_hInst, NULL);
 
        r1 = CreateWindow(TEXT("button"), TEXT("Vertical"), WS_CHILD | WS_VISIBLE |
            BS_AUTORADIOBUTTON | WS_GROUP, x, y, w, h, hWnd, (HMENU)ID_R1, g_hInst, NULL);
 
        r2 = CreateWindow(TEXT("button"), TEXT("Horizontal"), WS_CHILD | WS_VISIBLE |
            BS_AUTORADIOBUTTON, x + 90, y, w, h, hWnd, (HMENU)ID_R2, g_hInst, NULL);
 
        r3 = CreateWindow(TEXT("button"), TEXT("Diagonal"), WS_CHILD | WS_VISIBLE |
            BS_AUTORADIOBUTTON, x + 180, y, w, h, hWnd, (HMENU)ID_R3, g_hInst, NULL);
 
        CheckRadioButton(hWnd, ID_R1, ID_R3, ID_R1);
 
        return 0;
 
    case WM_COMMAND:
        if (!dst.empty()) {
            switch (LOWORD(wParam)) {
            case ID_R1:
                ImageProcess(0);
                break;
 
            case ID_R2:
                ImageProcess(1);
                break;
 
            case ID_R3:
                ImageProcess(2);
                break;
            }
 
            InvalidateRect(hWnd, NULL, TRUE);
        }
 
        return 0;
 
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        OnPaint(hdc);
        EndPaint(hWnd, &ps);
 
        return 0;
 
    case WM_DESTROY:
        PostQuitMessage(0);
 
        return 0;
    }
 
    return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
 
 

Define the necessary variables and handle window messages.

 

 

Run the application and select an image file.

 

Processed and original image with a vertical filter.

 

Processed and original image with a horizontal filter.

 

Processed and original image with a diagonal filter.

 

 

반응형
Posted by J-sean
: