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)
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;
173 return InvalidParameter;
177 cairo_format = CAIRO_FORMAT_RGB24;
179 case Format32bppArgb:
180 cairo_format = CAIRO_FORMAT_ARGB32;
184 return NotImplemented;
186 result = gdip_bitmap_new ();
187 result->cairo_format = cairo_format;
188 result->data.Width = width;
189 result->data.Height = height;
190 result->data.Stride = stride;
191 result->data.PixelFormat = format;
192 result->data.Scan0 = scan0;
199 GdipCreateBitmapFromGraphics (int width, int height, GpGraphics *graphics, GpBitmap **bitmap)
201 GpBitmap *result = 0;
203 int cairo_format = 0;
207 * FIXME: should get the stride based on the format of the graphics object.
209 fprintf (stderr, "GdipCreateBitmapFromGraphics: This routine has not been checked for stride size\n");
214 cairo_format = CAIRO_FORMAT_ARGB32;
215 bmpSize = stride * height;
216 result = gdip_bitmap_new ();
217 result->cairo_format = cairo_format;
218 result->data.Width = width;
219 result->data.Height = height;
220 result->data.Stride = stride;
221 result->data.PixelFormat = Format32bppArgb;
222 result->data.Scan0 = GdipAlloc (bmpSize);
223 result->data.Reserved = 1;
229 GdipCloneBitmapAreaI (int x, int y, int width, int height, int format, GpBitmap *original, GpBitmap **bitmap)
231 GpBitmap *result = 0;
232 int bmpSize = original->data.Height * original->data.Stride;
235 * FIXME: Convert format if needed and copy only specified rectangle
237 result = gdip_bitmap_new ();
238 result->cairo_format = original->cairo_format;
239 result->data.Width = original->data.Width;
240 result->data.Height = original->data.Height;
241 result->data.Stride = original->data.Stride;
242 result->data.PixelFormat = original->data.PixelFormat;
243 result->data.Scan0 = GdipAlloc (bmpSize);
244 memmove (result->data.Scan0, original->data.Scan0, bmpSize);
245 result->data.Reserved = 1;
252 ChangePixelFormat (GpBitmap *bitmap, GdipBitmapData *destData)
254 int sourcePixelIncrement = (bitmap->data.PixelFormat == Format32bppArgb) ? 1 : 0;
255 int destinationPixelIncrement = (destData->PixelFormat == Format32bppArgb) ? 1 : 0;
256 char * curSrc = bitmap->data.Scan0;
261 printf("ChangePixelFormat to %d. Src inc %d, Dest Inc %d\n",
262 destData->PixelFormat, sourcePixelIncrement, destinationPixelIncrement);
264 if (bitmap->data.PixelFormat == destData->PixelFormat) return 0;
266 if (destData->PixelFormat != Format32bppArgb && destData->PixelFormat != Format24bppRgb) {
267 fprintf (stderr, "This pixel format is not supported %d\n", destData->PixelFormat);
270 destData->Width = bitmap->data.Width;
271 destData->Height = bitmap->data.Height;
272 destData->Stride = ((destData->PixelFormat == Format32bppArgb ) ? 4 : 3 ) * bitmap->data.Width;
273 destData->Scan0 = GdipAlloc (destData->Stride * bitmap->data.Height);
274 destData->Reserved = 1;
275 curSrc = bitmap->data.Scan0;
276 curDst = (char *)destData->Scan0;
277 for ( i = 0; i < bitmap->data.Height; i++) {
278 for( j = 0; j < bitmap->data.Width; j++) {
279 *curDst++ = *curSrc++;
280 *curDst++ = *curSrc++;
281 *curDst++ = *curSrc++;
282 curSrc += sourcePixelIncrement;
283 curDst += destinationPixelIncrement;
290 GdipBitmapLockBits (GpBitmap *bitmap, Rect *rc, int flags, int format, GdipBitmapData *result)
293 printf ("Bitmap is null\n");
294 return InvalidParameter;
297 /* Special case: the entire image is requested */
298 if (rc->left == 0 && rc->right == bitmap->data.Width &&
299 rc->top == 0 && rc->bottom == bitmap->data.Height &&
300 format == bitmap->data.PixelFormat){
301 *result = bitmap->data;
302 result->Reserved = result->Reserved & ~1;
306 if (bitmap->data.PixelFormat != format) {
307 GdipBitmapData convert;
308 convert.PixelFormat = format;
309 if (!ChangePixelFormat (bitmap, &convert)) {
310 printf ("Requesting format change, not supported yet %d %d\n", bitmap->data.PixelFormat, format);
311 return InvalidParameter;
313 result->Width = convert.Width;
314 result->Height = convert.Height;
315 result->Stride = convert.Stride;
316 result->PixelFormat = convert.PixelFormat;
317 result->Reserved = convert.Reserved;
318 result->Scan0 = convert.Scan0;
321 result->Width = bitmap->data.Width;
322 result->Height = bitmap->data.Height;
323 result->Stride = bitmap->data.Stride;
324 result->PixelFormat = bitmap->data.PixelFormat;
325 result->Reserved = bitmap->data.Reserved;
326 result->Scan0 = bitmap->data.Scan0;
333 ____BitmapLockBits (GpBitmap *bitmap, Rect *rc, int flags, int format, int *width, int *height, int *stride, int *fptr, int *res, int *scan0)
338 s = GdipBitmapLockBits (bitmap, rc, flags, format, &d);
342 *fptr = d.PixelFormat;
344 *scan0 = (int)d.Scan0;
350 GdipBitmapUnlockBits (GpBitmap *bitmap, GdipBitmapData *bitmap_data)
352 if (bitmap_data->Reserved & 1)
353 GdipFree (bitmap_data->Scan0);