4 * Copyright (c) 2003 Alexandre Pigolkine
6 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
7 * and associated documentation files (the "Software"), to deal in the Software without restriction,
8 * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all copies or substantial
13 * portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
16 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
19 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * Alexandre Pigolkine(pigolkine@gmx.de)
27 #include "gdip_win32.h"
31 #include <sys/types.h>
36 gdip_bitmap_init (GpBitmap *bitmap)
38 gdip_image_init (&bitmap->image);
39 bitmap->image.type = imageBitmap;
40 bitmap->cairo_format = 0;
41 bitmap->data.Width = 0;
42 bitmap->data.Height = 0;
43 bitmap->data.Stride = 0;
44 bitmap->data.PixelFormat = 0;
45 bitmap->data.Scan0 = 0;
46 bitmap->data.Reserved = 0;
48 bitmap->hBitmapDC = 0;
49 bitmap->hInitialBitmap = 0;
56 GpBitmap *result = (GpBitmap *) GdipAlloc (sizeof(GpBitmap));
57 gdip_bitmap_init (result);
62 * This should only be called from GdipDisposeImage, and it should *not* free
63 * the structure, that one is freed by GdipDisposeImage
66 gdip_bitmap_dispose (GpBitmap *bitmap)
68 GdipFree (bitmap->data.Scan0);
72 gdip_bitmap_fill_info_header (GpBitmap *bitmap, PBITMAPINFOHEADER bmi)
74 int bitmapLen = bitmap->data.Stride * bitmap->data.Height;
76 bmi->biSize = sizeof (BITMAPINFOHEADER);
77 bmi->biWidth = bitmap->data.Width;
78 bmi->biHeight = -bitmap->data.Height;
81 bmi->biCompression = BI_RGB;
82 bmi->biSizeImage = bitmapLen;
86 gdip_bitmap_save_bmp (const char *name, GpBitmap *bitmap)
88 BITMAPFILEHEADER bmfh;
90 int bitmapLen = bitmap->data.Stride * bitmap->data.Height;
93 bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
94 bmfh.bfType = BFT_BITMAP;
95 bmfh.bfOffBits = (14 + 40 + 0 * 4);
96 bmfh.bfSize = (bmfh.bfOffBits + bitmapLen);
97 fp = fopen (name, "w+b");
98 fwrite (&bmfh, 1, sizeof (bmfh), fp);
99 gdip_bitmap_fill_info_header (bitmap, &bmi);
100 bmi.biHeight = -bmi.biHeight;
101 fwrite (&bmi, 1, sizeof (bmi), fp);
102 fwrite (bitmap->data.Scan0, 1, bitmapLen, fp);
107 gdip_bitmap_create_Win32_HDC (GpBitmap *bitmap)
110 void * hdc = CreateCompatibleDC_pfn (0);
111 void * hbitmap = 0, * holdbitmap = 0;
112 void * hdcDesc = GetDC_pfn (0);
114 hbitmap = CreateCompatibleBitmap_pfn (hdcDesc, bitmap->data.Width, bitmap->data.Height);
117 gdip_bitmap_fill_info_header (bitmap, &bmi.bmiHeader);
118 /* _saveBmp ("file1.bmp", bitmap); */
119 SetDIBits_pfn (hdc, hbitmap, 0, bitmap->data.Height, bitmap->data.Scan0, &bmi, 0);
120 holdbitmap = SelectObject_pfn (hdc, hbitmap);
121 bitmap->hBitmapDC = hdc;
122 bitmap->hInitialBitmap = holdbitmap;
123 bitmap->hBitmap = hbitmap;
129 ReleaseDC_pfn (0, hdcDesc);
134 gdip_bitmap_destroy_Win32_HDC (GpBitmap *bitmap, void *hdc)
136 if (bitmap->hBitmapDC == hdc) {
140 unsigned long *array, *end;
142 SelectObject_pfn (bitmap->hBitmapDC, bitmap->hInitialBitmap);
144 gdip_bitmap_fill_info_header (bitmap, &bmi.bmiHeader);
145 res = GetDIBits_pfn (bitmap->hBitmapDC, bitmap->hBitmap, 0, bitmap->data.Height, bitmap->data.Scan0, &bmi, 0);
146 if (bitmap->cairo_format == CAIRO_FORMAT_ARGB32) {
147 array = bitmap->data.Scan0;
148 end = array + (bmi.bmiHeader.biSizeImage >> 2);
149 while (array < end) {
150 *array |= 0xff000000;
154 /* _saveBmp ("file2.bmp", bitmap); */
156 DeleteObject_pfn (bitmap->hBitmap);
157 DeleteDC_pfn (bitmap->hBitmapDC);
158 bitmap->hBitmapDC = 0;
159 bitmap->hInitialBitmap = 0;
165 GdipCreateBitmapFromScan0 (int width, int height, int stride, int format, void *scan0, GpBitmap **bitmap)
167 GpBitmap *result = 0;
168 int cairo_format = 0;
171 return InvalidParameter;
174 scan0 = GdipAlloc (stride*height);
178 cairo_format = CAIRO_FORMAT_RGB24;
180 case Format32bppArgb:
181 cairo_format = CAIRO_FORMAT_ARGB32;
185 return NotImplemented;
187 result = gdip_bitmap_new ();
188 result->cairo_format = cairo_format;
189 result->data.Width = width;
190 result->data.Height = height;
191 result->data.Stride = stride;
192 result->data.PixelFormat = format;
193 result->data.Scan0 = scan0;
200 GdipCreateBitmapFromGraphics (int width, int height, GpGraphics *graphics, GpBitmap **bitmap)
202 GpBitmap *result = 0;
204 int cairo_format = 0;
208 * FIXME: should get the stride based on the format of the graphics object.
210 fprintf (stderr, "GdipCreateBitmapFromGraphics: This routine has not been checked for stride size\n");
215 cairo_format = CAIRO_FORMAT_ARGB32;
216 bmpSize = stride * height;
217 result = gdip_bitmap_new ();
218 result->cairo_format = cairo_format;
219 result->data.Width = width;
220 result->data.Height = height;
221 result->data.Stride = stride;
222 result->data.PixelFormat = Format32bppArgb;
223 result->data.Scan0 = GdipAlloc (bmpSize);
224 result->data.Reserved = 1;
230 GdipCloneBitmapAreaI (int x, int y, int width, int height, int format, GpBitmap *original, GpBitmap **bitmap)
232 GpBitmap *result = 0;
233 int bmpSize = original->data.Height * original->data.Stride;
236 * FIXME: Convert format if needed and copy only specified rectangle
238 result = gdip_bitmap_new ();
239 result->cairo_format = original->cairo_format;
240 result->data.Width = original->data.Width;
241 result->data.Height = original->data.Height;
242 result->data.Stride = original->data.Stride;
243 result->data.PixelFormat = original->data.PixelFormat;
244 result->data.Scan0 = GdipAlloc (bmpSize);
245 memmove (result->data.Scan0, original->data.Scan0, bmpSize);
246 result->data.Reserved = 1;
253 ChangePixelFormat (GpBitmap *bitmap, GdipBitmapData *destData)
255 int sourcePixelIncrement = (bitmap->data.PixelFormat == Format32bppArgb) ? 1 : 0;
256 int destinationPixelIncrement = (destData->PixelFormat == Format32bppArgb) ? 1 : 0;
257 char * curSrc = bitmap->data.Scan0;
262 printf("ChangePixelFormat to %d. Src inc %d, Dest Inc %d\n",
263 destData->PixelFormat, sourcePixelIncrement, destinationPixelIncrement);
265 if (bitmap->data.PixelFormat == destData->PixelFormat) return 0;
267 if (destData->PixelFormat != Format32bppArgb && destData->PixelFormat != Format24bppRgb) {
268 fprintf (stderr, "This pixel format is not supported %d\n", destData->PixelFormat);
271 destData->Width = bitmap->data.Width;
272 destData->Height = bitmap->data.Height;
273 destData->Stride = ((destData->PixelFormat == Format32bppArgb ) ? 4 : 3 ) * bitmap->data.Width;
274 destData->Scan0 = GdipAlloc (destData->Stride * bitmap->data.Height);
275 destData->Reserved = 1;
276 curSrc = bitmap->data.Scan0;
277 curDst = (char *)destData->Scan0;
278 for ( i = 0; i < bitmap->data.Height; i++) {
279 for( j = 0; j < bitmap->data.Width; j++) {
280 *curDst++ = *curSrc++;
281 *curDst++ = *curSrc++;
282 *curDst++ = *curSrc++;
283 curSrc += sourcePixelIncrement;
284 curDst += destinationPixelIncrement;
291 GdipBitmapLockBits (GpBitmap *bitmap, Rect *rc, int flags, int format, GdipBitmapData *result)
294 printf ("Bitmap is null\n");
295 return InvalidParameter;
298 /* Special case: the entire image is requested */
299 if (rc->left == 0 && rc->right == bitmap->data.Width &&
300 rc->top == 0 && rc->bottom == bitmap->data.Height &&
301 format == bitmap->data.PixelFormat){
302 *result = bitmap->data;
303 result->Reserved = result->Reserved & ~1;
307 if (bitmap->data.PixelFormat != format) {
308 GdipBitmapData convert;
309 convert.PixelFormat = format;
310 if (!ChangePixelFormat (bitmap, &convert)) {
311 printf ("Requesting format change, not supported yet %d %d\n", bitmap->data.PixelFormat, format);
312 return InvalidParameter;
314 result->Width = convert.Width;
315 result->Height = convert.Height;
316 result->Stride = convert.Stride;
317 result->PixelFormat = convert.PixelFormat;
318 result->Reserved = convert.Reserved;
319 result->Scan0 = convert.Scan0;
322 result->Width = bitmap->data.Width;
323 result->Height = bitmap->data.Height;
324 result->Stride = bitmap->data.Stride;
325 result->PixelFormat = bitmap->data.PixelFormat;
326 result->Reserved = bitmap->data.Reserved;
327 result->Scan0 = bitmap->data.Scan0;
334 ____BitmapLockBits (GpBitmap *bitmap, Rect *rc, int flags, int format, int *width, int *height, int *stride, int *fptr, int *res, int *scan0)
339 s = GdipBitmapLockBits (bitmap, rc, flags, format, &d);
343 *fptr = d.PixelFormat;
345 *scan0 = (int)d.Scan0;
351 GdipBitmapUnlockBits (GpBitmap *bitmap, GdipBitmapData *bitmap_data)
353 if (bitmap_data->Reserved & 1)
354 GdipFree (bitmap_data->Scan0);