1 /*
2 Sample usage of GD on windows. This little program opens a window, fetch its DIB
3 and assigns to a GD truecolor image.
4
5 Thanks to Mateusz Loskot (http://mateusz.loskot.net) for the AttachBuffer function!
6 */
7 #include <windows.h>
8 #include <gd.h>
9 #include <gdfontg.h>
10 #include <gdfontl.h>
11
12
gdImageTrueColorAttachBuffer(int * buffer,int sx,int sy,int stride)13 gdImagePtr gdImageTrueColorAttachBuffer(int* buffer, int sx, int sy, int stride)
14 {
15 int i;
16 int height;
17 int* rowptr;
18 gdImagePtr im;
19 im = (gdImage *) malloc (sizeof (gdImage));
20 if (!im) {
21 return 0;
22 }
23 memset (im, 0, sizeof (gdImage));
24
25 #if 0
26 if (overflow2(sizeof (int *), sy)) {
27 return 0;
28 }
29 #endif
30
31 im->tpixels = (int **) malloc (sizeof (int *) * sy);
32 if (!im->tpixels) {
33 free(im);
34 return 0;
35 }
36
37 im->polyInts = 0;
38 im->polyAllocated = 0;
39 im->brush = 0;
40 im->tile = 0;
41 im->style = 0;
42
43 height = sy;
44 rowptr = buffer;
45 if (stride < 0) {
46 int startoff = (height - 1) * stride;
47 rowptr = buffer - startoff;
48 }
49
50 i = 0;
51 while (height--) {
52 im->tpixels[i] = rowptr;
53 rowptr += stride;
54 i++;
55 }
56
57 im->sx = sx;
58 im->sy = sy;
59 im->transparent = (-1);
60 im->interlace = 0;
61 im->trueColor = 1;
62 im->saveAlphaFlag = 0;
63 im->alphaBlendingFlag = 1;
64 im->thick = 1;
65 im->AA = 0;
66 im->cx1 = 0;
67 im->cy1 = 0;
68 im->cx2 = im->sx - 1;
69 im->cy2 = im->sy - 1;
70 return im;
71 }
72
gdImageDetachBuffer(gdImagePtr im)73 void gdImageDetachBuffer(gdImagePtr im)
74 {
75 free(im->tpixels);
76 free(im);
77 }
78
79
gdCreateBmp(int width,int height)80 BITMAPINFO gdCreateBmp(int width, int height)
81 {
82 BITMAPINFO bmp_info;
83
84 // Configure bitmap properties
85
86 ZeroMemory(&bmp_info, sizeof(BITMAPINFO));
87 bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
88 bmp_info.bmiHeader.biWidth = width;
89 bmp_info.bmiHeader.biHeight = height;
90 bmp_info.bmiHeader.biPlanes = 1;
91 bmp_info.bmiHeader.biBitCount = 32;
92 bmp_info.bmiHeader.biCompression = BI_RGB;
93 bmp_info.bmiHeader.biSizeImage = 0;
94 bmp_info.bmiHeader.biXPelsPerMeter = 0;
95 bmp_info.bmiHeader.biYPelsPerMeter = 0;
96 bmp_info.bmiHeader.biClrUsed = 0;
97 bmp_info.bmiHeader.biClrImportant = 0;
98 return bmp_info;
99 }
100
101 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
102
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)103 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
104 PSTR szCmdLine, int iCmdShow)
105 {
106 static TCHAR szAppName[] = TEXT ("Bezier") ;
107 HWND hwnd ;
108 MSG msg ;
109 WNDCLASS wndclass ;
110
111 wndclass.style = CS_HREDRAW | CS_VREDRAW ;
112 wndclass.lpfnWndProc = WndProc ;
113 wndclass.cbClsExtra = 0 ;
114 wndclass.cbWndExtra = 0 ;
115 wndclass.hInstance = hInstance ;
116 wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
117 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
118 wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
119 wndclass.lpszMenuName = NULL ;
120 wndclass.lpszClassName = szAppName ;
121
122 if (!RegisterClass (&wndclass)) {
123 // UNICODE-Compilierung ist die einzige realistische Fehlermöglichkeit
124 MessageBox (NULL, TEXT ("Programm arbeitet mit Unicode und setzt Windows NT voraus!"),
125 szAppName, MB_ICONERROR) ;
126 return 0 ;
127 }
128
129 hwnd = CreateWindow (szAppName, TEXT ("Bezierkurven"),
130 WS_OVERLAPPEDWINDOW,
131 CW_USEDEFAULT, CW_USEDEFAULT,
132 CW_USEDEFAULT, CW_USEDEFAULT,
133 NULL, NULL, hInstance, NULL) ;
134
135 ShowWindow (hwnd, iCmdShow) ;
136 UpdateWindow (hwnd) ;
137
138 while (GetMessage (&msg, NULL, 0, 0)) {
139 TranslateMessage (&msg) ;
140 DispatchMessage (&msg) ;
141 }
142 return msg.wParam ;
143 }
144
DrawBezier(HDC hdc,POINT apt[])145 void DrawBezier (HDC hdc, POINT apt[])
146 {
147 PolyBezier (hdc, apt, 4) ;
148
149 MoveToEx (hdc, apt[0].x, apt[0].y, NULL) ;
150 LineTo (hdc, apt[1].x, apt[1].y) ;
151
152 MoveToEx (hdc, apt[2].x, apt[2].y, NULL) ;
153 LineTo (hdc, apt[3].x, apt[3].y) ;
154 }
155
156
gdDrawImage(HDC hdc,RECT * rc)157 void gdDrawImage(HDC hdc, RECT *rc)
158 {
159 HDC mem_dc;
160 BITMAPINFO bmp_info;
161 void* bits;
162 HBITMAP bmp, temp;
163 gdImagePtr im;
164 int width, height, stride;
165 int white, black, blue, red;
166 char *s = "Hello world!";
167 gdFontPtr lfont, gfont;
168
169 width = rc->right - rc->left;
170 height = rc->bottom - rc->top;
171
172 bmp_info = gdCreateBmp(width, height);
173
174 // Create memory device context
175 mem_dc = CreateCompatibleDC(hdc);
176 if (!mem_dc) {
177 MessageBox(NULL, "Can't create a compatible DC!", "Error!", MB_ICONEXCLAMATION | MB_OK);
178 return;
179 }
180
181 // bits points to a shared buffer of pixels
182 bits = NULL;
183 bmp = CreateDIBSection(mem_dc, &bmp_info, DIB_RGB_COLORS, (void**)&bits, 0, 0);
184
185 // Selecting the object before doing anything allows you to use libgd
186 // together with native Windows GDI.
187 temp = (HBITMAP)SelectObject(mem_dc, bmp);
188
189 /*stride = ((width * 1 + 3) >> 2) << 2;*/
190 // always uses 32bit in BMPINFO
191 stride = width;
192 im = NULL;
193
194 // Attach shared buffer of pixels to GD image
195 // Negative stride places 0,0 in upper-left corner
196 im = gdImageTrueColorAttachBuffer((int*)bits, width, height, -stride);
197 if (!im) {
198 MessageBox(NULL, "GD image creation failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
199 return;
200 }
201
202 // Start of GD drawing
203 white = gdImageColorAllocate(im, 255, 255, 255);
204 black = gdImageColorAllocate(im, 0, 0, 0);
205 blue = gdImageColorAllocate(im, 0, 0, 255);
206
207 // Allocate the color red, 50% transparent.
208 red = gdImageColorAllocateAlpha(im, 255, 0, 0, 64);
209
210 // Erase background with white color
211 gdImageFilledRectangle(im, 0, 0, width, height, 0xFF0000);
212
213 lfont = gdFontGetLarge();
214 gfont = gdFontGetGiant();
215
216 // Draw a dashed line from the upper left corner to the lower right corner.
217 gdImageFilledRectangle(im, 25, 25, 100, 100, blue);
218
219 gdImageChar(im, gfont, 35, 35, 'Q', white);
220 gdImageFilledRectangle(im, 50, 50, 75, 175, red);
221 gdImageLine(im, 0, 0, 150, 150, black);
222
223 gdImageString(im, gdFontGetLarge(),
224 im->sx / 2 - (strlen(s) * lfont->w / 2),
225 im->sy / 2 - lfont->h / 2,
226 (unsigned char*)s, black);
227
228 // Copy drawing from memory context (shared bitmap buffer) to screen DC.
229 BitBlt(hdc, rc->left, rc->top, width, height, mem_dc, 0, 0, SRCCOPY);
230
231 // Free
232 gdImageDetachBuffer(im);
233 SelectObject(mem_dc, temp);
234 DeleteObject(bmp);
235 DeleteObject(mem_dc);
236 }
237
WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)238 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
239 {
240 static POINT apt[4] ;
241 HDC hdc ;
242 int cxClient, cyClient ;
243 PAINTSTRUCT ps ;
244 RECT rc;
245
246 GetClientRect(hwnd, &rc);
247
248 switch (message) {
249 case WM_SIZE:
250 cxClient = LOWORD (lParam) ;
251 cyClient = HIWORD (lParam) ;
252
253 apt[0].x = cxClient / 4 ;
254 apt[0].y = cyClient / 2 ;
255
256 apt[1].x = cxClient / 2 ;
257 apt[1].y = cyClient / 4 ;
258
259 apt[2].x = cxClient / 2 ;
260 apt[2].y = 3 * cyClient / 4 ;
261
262 apt[3].x = 3 * cxClient / 4 ;
263 apt[3].y = cyClient / 2 ;
264 return 0 ;
265
266 case WM_LBUTTONDOWN:
267 case WM_RBUTTONDOWN:
268 case WM_MOUSEMOVE:
269 if (wParam & MK_LBUTTON || wParam & MK_RBUTTON) {
270 hdc = GetDC (hwnd) ;
271
272 // alte Kurve löschen (mit Weiß übermalen)
273 SelectObject (hdc, GetStockObject (WHITE_PEN)) ;
274 DrawBezier (hdc, apt) ;
275
276 if (wParam & MK_LBUTTON) {
277 apt[1].x = LOWORD (lParam) ;
278 apt[1].y = HIWORD (lParam) ;
279 }
280
281 if (wParam & MK_RBUTTON) {
282 apt[2].x = LOWORD (lParam) ;
283 apt[2].y = HIWORD (lParam) ;
284 }
285
286 // neue Kurve (mit Schwarz) zeichnen
287 SelectObject (hdc, GetStockObject (BLACK_PEN)) ;
288 gdDrawImage(hdc, &rc);
289 DrawBezier (hdc, apt) ;
290 ReleaseDC (hwnd, hdc) ;
291 }
292 return 0 ;
293
294
295 case WM_PAINT:
296 hdc = BeginPaint (hwnd, &ps) ;
297
298 GetClientRect(hwnd, &rc);
299 gdDrawImage(hdc, &rc);
300 DrawBezier (hdc, apt) ;
301
302 EndPaint (hwnd, &ps) ;
303 return 0 ;
304
305 case WM_DESTROY:
306 PostQuitMessage (0) ;
307 return 0 ;
308 }
309 return DefWindowProc (hwnd, message, wParam, lParam) ;
310 }
311