Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenimage.c
Go to the documentation of this file.
00001 /* 00002 * Copyright (C) 2007 Google (Evan Stade) 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include <stdarg.h> 00020 00021 #define NONAMELESSUNION 00022 00023 #include "windef.h" 00024 #include "winbase.h" 00025 #include "winuser.h" 00026 #include "wingdi.h" 00027 00028 #define COBJMACROS 00029 #include "objbase.h" 00030 #include "olectl.h" 00031 #include "ole2.h" 00032 00033 #include "initguid.h" 00034 #include "wincodec.h" 00035 #include "gdiplus.h" 00036 #include "gdiplus_private.h" 00037 #include "wine/debug.h" 00038 00039 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus); 00040 00041 #define PIXELFORMATBPP(x) ((x) ? ((x) >> 8) & 255 : 24) 00042 00043 static INT ipicture_pixel_height(IPicture *pic) 00044 { 00045 HDC hdcref; 00046 OLE_YSIZE_HIMETRIC y; 00047 00048 IPicture_get_Height(pic, &y); 00049 00050 hdcref = GetDC(0); 00051 00052 y = MulDiv(y, GetDeviceCaps(hdcref, LOGPIXELSY), INCH_HIMETRIC); 00053 ReleaseDC(0, hdcref); 00054 00055 return y; 00056 } 00057 00058 static INT ipicture_pixel_width(IPicture *pic) 00059 { 00060 HDC hdcref; 00061 OLE_XSIZE_HIMETRIC x; 00062 00063 IPicture_get_Width(pic, &x); 00064 00065 hdcref = GetDC(0); 00066 00067 x = MulDiv(x, GetDeviceCaps(hdcref, LOGPIXELSX), INCH_HIMETRIC); 00068 00069 ReleaseDC(0, hdcref); 00070 00071 return x; 00072 } 00073 00074 GpStatus WINGDIPAPI GdipBitmapApplyEffect(GpBitmap* bitmap, CGpEffect* effect, 00075 RECT* roi, BOOL useAuxData, VOID** auxData, INT* auxDataSize) 00076 { 00077 FIXME("(%p %p %p %d %p %p): stub\n", bitmap, effect, roi, useAuxData, auxData, auxDataSize); 00078 /* 00079 * Note: According to Jose Roca's GDI+ docs, this function is not 00080 * implemented in Windows's GDI+. 00081 */ 00082 return NotImplemented; 00083 } 00084 00085 GpStatus WINGDIPAPI GdipBitmapCreateApplyEffect(GpBitmap** inputBitmaps, 00086 INT numInputs, CGpEffect* effect, RECT* roi, RECT* outputRect, 00087 GpBitmap** outputBitmap, BOOL useAuxData, VOID** auxData, INT* auxDataSize) 00088 { 00089 FIXME("(%p %d %p %p %p %p %d %p %p): stub\n", inputBitmaps, numInputs, effect, roi, outputRect, outputBitmap, useAuxData, auxData, auxDataSize); 00090 /* 00091 * Note: According to Jose Roca's GDI+ docs, this function is not 00092 * implemented in Windows's GDI+. 00093 */ 00094 return NotImplemented; 00095 } 00096 00097 static inline void getpixel_1bppIndexed(BYTE *index, const BYTE *row, UINT x) 00098 { 00099 *index = (row[x/8]>>(7-x%8)) & 1; 00100 } 00101 00102 static inline void getpixel_4bppIndexed(BYTE *index, const BYTE *row, UINT x) 00103 { 00104 if (x & 1) 00105 *index = row[x/2]&0xf; 00106 else 00107 *index = row[x/2]>>4; 00108 } 00109 00110 static inline void getpixel_8bppIndexed(BYTE *index, const BYTE *row, UINT x) 00111 { 00112 *index = row[x]; 00113 } 00114 00115 static inline void getpixel_16bppGrayScale(BYTE *r, BYTE *g, BYTE *b, BYTE *a, 00116 const BYTE *row, UINT x) 00117 { 00118 *r = *g = *b = row[x*2+1]; 00119 *a = 255; 00120 } 00121 00122 static inline void getpixel_16bppRGB555(BYTE *r, BYTE *g, BYTE *b, BYTE *a, 00123 const BYTE *row, UINT x) 00124 { 00125 WORD pixel = *((const WORD*)(row)+x); 00126 *r = (pixel>>7&0xf8)|(pixel>>12&0x7); 00127 *g = (pixel>>2&0xf8)|(pixel>>6&0x7); 00128 *b = (pixel<<3&0xf8)|(pixel>>2&0x7); 00129 *a = 255; 00130 } 00131 00132 static inline void getpixel_16bppRGB565(BYTE *r, BYTE *g, BYTE *b, BYTE *a, 00133 const BYTE *row, UINT x) 00134 { 00135 WORD pixel = *((const WORD*)(row)+x); 00136 *r = (pixel>>8&0xf8)|(pixel>>13&0x7); 00137 *g = (pixel>>3&0xfc)|(pixel>>9&0x3); 00138 *b = (pixel<<3&0xf8)|(pixel>>2&0x7); 00139 *a = 255; 00140 } 00141 00142 static inline void getpixel_16bppARGB1555(BYTE *r, BYTE *g, BYTE *b, BYTE *a, 00143 const BYTE *row, UINT x) 00144 { 00145 WORD pixel = *((const WORD*)(row)+x); 00146 *r = (pixel>>7&0xf8)|(pixel>>12&0x7); 00147 *g = (pixel>>2&0xf8)|(pixel>>6&0x7); 00148 *b = (pixel<<3&0xf8)|(pixel>>2&0x7); 00149 if ((pixel&0x8000) == 0x8000) 00150 *a = 255; 00151 else 00152 *a = 0; 00153 } 00154 00155 static inline void getpixel_24bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, 00156 const BYTE *row, UINT x) 00157 { 00158 *r = row[x*3+2]; 00159 *g = row[x*3+1]; 00160 *b = row[x*3]; 00161 *a = 255; 00162 } 00163 00164 static inline void getpixel_32bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, 00165 const BYTE *row, UINT x) 00166 { 00167 *r = row[x*4+2]; 00168 *g = row[x*4+1]; 00169 *b = row[x*4]; 00170 *a = 255; 00171 } 00172 00173 static inline void getpixel_32bppARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, 00174 const BYTE *row, UINT x) 00175 { 00176 *r = row[x*4+2]; 00177 *g = row[x*4+1]; 00178 *b = row[x*4]; 00179 *a = row[x*4+3]; 00180 } 00181 00182 static inline void getpixel_32bppPARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, 00183 const BYTE *row, UINT x) 00184 { 00185 *a = row[x*4+3]; 00186 if (*a == 0) 00187 *r = *g = *b = 0; 00188 else 00189 { 00190 *r = row[x*4+2] * 255 / *a; 00191 *g = row[x*4+1] * 255 / *a; 00192 *b = row[x*4] * 255 / *a; 00193 } 00194 } 00195 00196 static inline void getpixel_48bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, 00197 const BYTE *row, UINT x) 00198 { 00199 *r = row[x*6+5]; 00200 *g = row[x*6+3]; 00201 *b = row[x*6+1]; 00202 *a = 255; 00203 } 00204 00205 static inline void getpixel_64bppARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, 00206 const BYTE *row, UINT x) 00207 { 00208 *r = row[x*8+5]; 00209 *g = row[x*8+3]; 00210 *b = row[x*8+1]; 00211 *a = row[x*8+7]; 00212 } 00213 00214 static inline void getpixel_64bppPARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, 00215 const BYTE *row, UINT x) 00216 { 00217 *a = row[x*8+7]; 00218 if (*a == 0) 00219 *r = *g = *b = 0; 00220 else 00221 { 00222 *r = row[x*8+5] * 255 / *a; 00223 *g = row[x*8+3] * 255 / *a; 00224 *b = row[x*8+1] * 255 / *a; 00225 } 00226 } 00227 00228 GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap* bitmap, INT x, INT y, 00229 ARGB *color) 00230 { 00231 BYTE r, g, b, a; 00232 BYTE index; 00233 BYTE *row; 00234 TRACE("%p %d %d %p\n", bitmap, x, y, color); 00235 00236 if(!bitmap || !color || 00237 x < 0 || y < 0 || x >= bitmap->width || y >= bitmap->height) 00238 return InvalidParameter; 00239 00240 row = bitmap->bits+bitmap->stride*y; 00241 00242 switch (bitmap->format) 00243 { 00244 case PixelFormat1bppIndexed: 00245 getpixel_1bppIndexed(&index,row,x); 00246 break; 00247 case PixelFormat4bppIndexed: 00248 getpixel_4bppIndexed(&index,row,x); 00249 break; 00250 case PixelFormat8bppIndexed: 00251 getpixel_8bppIndexed(&index,row,x); 00252 break; 00253 case PixelFormat16bppGrayScale: 00254 getpixel_16bppGrayScale(&r,&g,&b,&a,row,x); 00255 break; 00256 case PixelFormat16bppRGB555: 00257 getpixel_16bppRGB555(&r,&g,&b,&a,row,x); 00258 break; 00259 case PixelFormat16bppRGB565: 00260 getpixel_16bppRGB565(&r,&g,&b,&a,row,x); 00261 break; 00262 case PixelFormat16bppARGB1555: 00263 getpixel_16bppARGB1555(&r,&g,&b,&a,row,x); 00264 break; 00265 case PixelFormat24bppRGB: 00266 getpixel_24bppRGB(&r,&g,&b,&a,row,x); 00267 break; 00268 case PixelFormat32bppRGB: 00269 getpixel_32bppRGB(&r,&g,&b,&a,row,x); 00270 break; 00271 case PixelFormat32bppARGB: 00272 getpixel_32bppARGB(&r,&g,&b,&a,row,x); 00273 break; 00274 case PixelFormat32bppPARGB: 00275 getpixel_32bppPARGB(&r,&g,&b,&a,row,x); 00276 break; 00277 case PixelFormat48bppRGB: 00278 getpixel_48bppRGB(&r,&g,&b,&a,row,x); 00279 break; 00280 case PixelFormat64bppARGB: 00281 getpixel_64bppARGB(&r,&g,&b,&a,row,x); 00282 break; 00283 case PixelFormat64bppPARGB: 00284 getpixel_64bppPARGB(&r,&g,&b,&a,row,x); 00285 break; 00286 default: 00287 FIXME("not implemented for format 0x%x\n", bitmap->format); 00288 return NotImplemented; 00289 } 00290 00291 if (bitmap->format & PixelFormatIndexed) 00292 *color = bitmap->image.palette_entries[index]; 00293 else 00294 *color = a<<24|r<<16|g<<8|b; 00295 00296 return Ok; 00297 } 00298 00299 static inline UINT get_palette_index(BYTE r, BYTE g, BYTE b, BYTE a, GpBitmap* bitmap) { 00300 BYTE index = 0; 00301 int best_distance = 0x7fff; 00302 int distance; 00303 int i; 00304 /* This algorithm scans entire palette, 00305 computes difference from desired color (all color components have equal weight) 00306 and returns the index of color with least difference. 00307 00308 Note: Maybe it could be replaced with a better algorithm for better image quality 00309 and performance, though better algorithm would probably need some pre-built lookup 00310 tables and thus may actually be slower if this method is called only few times per 00311 every image. 00312 */ 00313 for(i=0;i<bitmap->image.palette_size;i++) { 00314 ARGB color=bitmap->image.palette_entries[i]; 00315 distance=abs(b-(color & 0xff)) + abs(g-(color>>8 & 0xff)) + abs(r-(color>>16 & 0xff)) + abs(a-(color>>24 & 0xff)); 00316 if (distance<best_distance) { 00317 best_distance=distance; 00318 index=i; 00319 } 00320 } 00321 return index; 00322 } 00323 00324 static inline void setpixel_8bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, 00325 BYTE *row, UINT x, GpBitmap* bitmap) 00326 { 00327 BYTE index = get_palette_index(r,g,b,a,bitmap); 00328 row[x]=index; 00329 } 00330 00331 static inline void setpixel_1bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, 00332 BYTE *row, UINT x, GpBitmap* bitmap) 00333 { 00334 row[x/8] = (row[x/8] & ~(1<<(7-x%8))) | (get_palette_index(r,g,b,a,bitmap)<<(7-x%8)); 00335 } 00336 00337 static inline void setpixel_4bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, 00338 BYTE *row, UINT x, GpBitmap* bitmap) 00339 { 00340 if (x & 1) 00341 row[x/2] = (row[x/2] & 0xf0) | get_palette_index(r,g,b,a,bitmap); 00342 else 00343 row[x/2] = (row[x/2] & 0x0f) | get_palette_index(r,g,b,a,bitmap)<<4; 00344 } 00345 00346 static inline void setpixel_16bppGrayScale(BYTE r, BYTE g, BYTE b, BYTE a, 00347 BYTE *row, UINT x) 00348 { 00349 *((WORD*)(row)+x) = (r+g+b)*85; 00350 } 00351 00352 static inline void setpixel_16bppRGB555(BYTE r, BYTE g, BYTE b, BYTE a, 00353 BYTE *row, UINT x) 00354 { 00355 *((WORD*)(row)+x) = (r<<7&0x7c00)| 00356 (g<<2&0x03e0)| 00357 (b>>3&0x001f); 00358 } 00359 00360 static inline void setpixel_16bppRGB565(BYTE r, BYTE g, BYTE b, BYTE a, 00361 BYTE *row, UINT x) 00362 { 00363 *((WORD*)(row)+x) = (r<<8&0xf800)| 00364 (g<<3&0x07e0)| 00365 (b>>3&0x001f); 00366 } 00367 00368 static inline void setpixel_16bppARGB1555(BYTE r, BYTE g, BYTE b, BYTE a, 00369 BYTE *row, UINT x) 00370 { 00371 *((WORD*)(row)+x) = (a<<8&0x8000)| 00372 (r<<7&0x7c00)| 00373 (g<<2&0x03e0)| 00374 (b>>3&0x001f); 00375 } 00376 00377 static inline void setpixel_24bppRGB(BYTE r, BYTE g, BYTE b, BYTE a, 00378 BYTE *row, UINT x) 00379 { 00380 row[x*3+2] = r; 00381 row[x*3+1] = g; 00382 row[x*3] = b; 00383 } 00384 00385 static inline void setpixel_32bppRGB(BYTE r, BYTE g, BYTE b, BYTE a, 00386 BYTE *row, UINT x) 00387 { 00388 *((DWORD*)(row)+x) = (r<<16)|(g<<8)|b; 00389 } 00390 00391 static inline void setpixel_32bppARGB(BYTE r, BYTE g, BYTE b, BYTE a, 00392 BYTE *row, UINT x) 00393 { 00394 *((DWORD*)(row)+x) = (a<<24)|(r<<16)|(g<<8)|b; 00395 } 00396 00397 static inline void setpixel_32bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a, 00398 BYTE *row, UINT x) 00399 { 00400 r = r * a / 255; 00401 g = g * a / 255; 00402 b = b * a / 255; 00403 *((DWORD*)(row)+x) = (a<<24)|(r<<16)|(g<<8)|b; 00404 } 00405 00406 static inline void setpixel_48bppRGB(BYTE r, BYTE g, BYTE b, BYTE a, 00407 BYTE *row, UINT x) 00408 { 00409 row[x*6+5] = row[x*6+4] = r; 00410 row[x*6+3] = row[x*6+2] = g; 00411 row[x*6+1] = row[x*6] = b; 00412 } 00413 00414 static inline void setpixel_64bppARGB(BYTE r, BYTE g, BYTE b, BYTE a, 00415 BYTE *row, UINT x) 00416 { 00417 UINT64 a64=a, r64=r, g64=g, b64=b; 00418 *((UINT64*)(row)+x) = (a64<<56)|(a64<<48)|(r64<<40)|(r64<<32)|(g64<<24)|(g64<<16)|(b64<<8)|b64; 00419 } 00420 00421 static inline void setpixel_64bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a, 00422 BYTE *row, UINT x) 00423 { 00424 UINT64 a64, r64, g64, b64; 00425 a64 = a * 257; 00426 r64 = r * a / 255; 00427 g64 = g * a / 255; 00428 b64 = b * a / 255; 00429 *((UINT64*)(row)+x) = (a64<<48)|(r64<<32)|(g64<<16)|b64; 00430 } 00431 00432 GpStatus WINGDIPAPI GdipBitmapSetPixel(GpBitmap* bitmap, INT x, INT y, 00433 ARGB color) 00434 { 00435 BYTE a, r, g, b; 00436 BYTE *row; 00437 TRACE("bitmap:%p, x:%d, y:%d, color:%08x\n", bitmap, x, y, color); 00438 00439 if(!bitmap || x < 0 || y < 0 || x >= bitmap->width || y >= bitmap->height) 00440 return InvalidParameter; 00441 00442 a = color>>24; 00443 r = color>>16; 00444 g = color>>8; 00445 b = color; 00446 00447 row = bitmap->bits + bitmap->stride * y; 00448 00449 switch (bitmap->format) 00450 { 00451 case PixelFormat16bppGrayScale: 00452 setpixel_16bppGrayScale(r,g,b,a,row,x); 00453 break; 00454 case PixelFormat16bppRGB555: 00455 setpixel_16bppRGB555(r,g,b,a,row,x); 00456 break; 00457 case PixelFormat16bppRGB565: 00458 setpixel_16bppRGB565(r,g,b,a,row,x); 00459 break; 00460 case PixelFormat16bppARGB1555: 00461 setpixel_16bppARGB1555(r,g,b,a,row,x); 00462 break; 00463 case PixelFormat24bppRGB: 00464 setpixel_24bppRGB(r,g,b,a,row,x); 00465 break; 00466 case PixelFormat32bppRGB: 00467 setpixel_32bppRGB(r,g,b,a,row,x); 00468 break; 00469 case PixelFormat32bppARGB: 00470 setpixel_32bppARGB(r,g,b,a,row,x); 00471 break; 00472 case PixelFormat32bppPARGB: 00473 setpixel_32bppPARGB(r,g,b,a,row,x); 00474 break; 00475 case PixelFormat48bppRGB: 00476 setpixel_48bppRGB(r,g,b,a,row,x); 00477 break; 00478 case PixelFormat64bppARGB: 00479 setpixel_64bppARGB(r,g,b,a,row,x); 00480 break; 00481 case PixelFormat64bppPARGB: 00482 setpixel_64bppPARGB(r,g,b,a,row,x); 00483 break; 00484 case PixelFormat8bppIndexed: 00485 setpixel_8bppIndexed(r,g,b,a,row,x,bitmap); 00486 break; 00487 case PixelFormat4bppIndexed: 00488 setpixel_4bppIndexed(r,g,b,a,row,x,bitmap); 00489 break; 00490 case PixelFormat1bppIndexed: 00491 setpixel_1bppIndexed(r,g,b,a,row,x,bitmap); 00492 break; 00493 default: 00494 FIXME("not implemented for format 0x%x\n", bitmap->format); 00495 return NotImplemented; 00496 } 00497 00498 return Ok; 00499 } 00500 00501 GpStatus convert_pixels(INT width, INT height, 00502 INT dst_stride, BYTE *dst_bits, PixelFormat dst_format, 00503 INT src_stride, const BYTE *src_bits, PixelFormat src_format, ARGB *src_palette) 00504 { 00505 INT x, y; 00506 00507 if (src_format == dst_format || 00508 (dst_format == PixelFormat32bppRGB && PIXELFORMATBPP(src_format) == 32)) 00509 { 00510 UINT widthbytes = PIXELFORMATBPP(src_format) * width / 8; 00511 for (y=0; y<height; y++) 00512 memcpy(dst_bits+dst_stride*y, src_bits+src_stride*y, widthbytes); 00513 return Ok; 00514 } 00515 00516 #define convert_indexed_to_rgb(getpixel_function, setpixel_function) do { \ 00517 for (x=0; x<width; x++) \ 00518 for (y=0; y<height; y++) { \ 00519 BYTE index; \ 00520 BYTE *color; \ 00521 getpixel_function(&index, src_bits+src_stride*y, x); \ 00522 color = (BYTE*)(&src_palette[index]); \ 00523 setpixel_function(color[2], color[1], color[0], color[3], dst_bits+dst_stride*y, x); \ 00524 } \ 00525 return Ok; \ 00526 } while (0); 00527 00528 #define convert_rgb_to_rgb(getpixel_function, setpixel_function) do { \ 00529 for (x=0; x<width; x++) \ 00530 for (y=0; y<height; y++) { \ 00531 BYTE r, g, b, a; \ 00532 getpixel_function(&r, &g, &b, &a, src_bits+src_stride*y, x); \ 00533 setpixel_function(r, g, b, a, dst_bits+dst_stride*y, x); \ 00534 } \ 00535 return Ok; \ 00536 } while (0); 00537 00538 switch (src_format) 00539 { 00540 case PixelFormat1bppIndexed: 00541 switch (dst_format) 00542 { 00543 case PixelFormat16bppGrayScale: 00544 convert_indexed_to_rgb(getpixel_1bppIndexed, setpixel_16bppGrayScale); 00545 case PixelFormat16bppRGB555: 00546 convert_indexed_to_rgb(getpixel_1bppIndexed, setpixel_16bppRGB555); 00547 case PixelFormat16bppRGB565: 00548 convert_indexed_to_rgb(getpixel_1bppIndexed, setpixel_16bppRGB565); 00549 case PixelFormat16bppARGB1555: 00550 convert_indexed_to_rgb(getpixel_1bppIndexed, setpixel_16bppARGB1555); 00551 case PixelFormat24bppRGB: 00552 convert_indexed_to_rgb(getpixel_1bppIndexed, setpixel_24bppRGB); 00553 case PixelFormat32bppRGB: 00554 convert_indexed_to_rgb(getpixel_1bppIndexed, setpixel_32bppRGB); 00555 case PixelFormat32bppARGB: 00556 convert_indexed_to_rgb(getpixel_1bppIndexed, setpixel_32bppARGB); 00557 case PixelFormat32bppPARGB: 00558 convert_indexed_to_rgb(getpixel_1bppIndexed, setpixel_32bppPARGB); 00559 case PixelFormat48bppRGB: 00560 convert_indexed_to_rgb(getpixel_1bppIndexed, setpixel_48bppRGB); 00561 case PixelFormat64bppARGB: 00562 convert_indexed_to_rgb(getpixel_1bppIndexed, setpixel_64bppARGB); 00563 default: 00564 break; 00565 } 00566 break; 00567 case PixelFormat4bppIndexed: 00568 switch (dst_format) 00569 { 00570 case PixelFormat16bppGrayScale: 00571 convert_indexed_to_rgb(getpixel_4bppIndexed, setpixel_16bppGrayScale); 00572 case PixelFormat16bppRGB555: 00573 convert_indexed_to_rgb(getpixel_4bppIndexed, setpixel_16bppRGB555); 00574 case PixelFormat16bppRGB565: 00575 convert_indexed_to_rgb(getpixel_4bppIndexed, setpixel_16bppRGB565); 00576 case PixelFormat16bppARGB1555: 00577 convert_indexed_to_rgb(getpixel_4bppIndexed, setpixel_16bppARGB1555); 00578 case PixelFormat24bppRGB: 00579 convert_indexed_to_rgb(getpixel_4bppIndexed, setpixel_24bppRGB); 00580 case PixelFormat32bppRGB: 00581 convert_indexed_to_rgb(getpixel_4bppIndexed, setpixel_32bppRGB); 00582 case PixelFormat32bppARGB: 00583 convert_indexed_to_rgb(getpixel_4bppIndexed, setpixel_32bppARGB); 00584 case PixelFormat32bppPARGB: 00585 convert_indexed_to_rgb(getpixel_4bppIndexed, setpixel_32bppPARGB); 00586 case PixelFormat48bppRGB: 00587 convert_indexed_to_rgb(getpixel_4bppIndexed, setpixel_48bppRGB); 00588 case PixelFormat64bppARGB: 00589 convert_indexed_to_rgb(getpixel_4bppIndexed, setpixel_64bppARGB); 00590 default: 00591 break; 00592 } 00593 break; 00594 case PixelFormat8bppIndexed: 00595 switch (dst_format) 00596 { 00597 case PixelFormat16bppGrayScale: 00598 convert_indexed_to_rgb(getpixel_8bppIndexed, setpixel_16bppGrayScale); 00599 case PixelFormat16bppRGB555: 00600 convert_indexed_to_rgb(getpixel_8bppIndexed, setpixel_16bppRGB555); 00601 case PixelFormat16bppRGB565: 00602 convert_indexed_to_rgb(getpixel_8bppIndexed, setpixel_16bppRGB565); 00603 case PixelFormat16bppARGB1555: 00604 convert_indexed_to_rgb(getpixel_8bppIndexed, setpixel_16bppARGB1555); 00605 case PixelFormat24bppRGB: 00606 convert_indexed_to_rgb(getpixel_8bppIndexed, setpixel_24bppRGB); 00607 case PixelFormat32bppRGB: 00608 convert_indexed_to_rgb(getpixel_8bppIndexed, setpixel_32bppRGB); 00609 case PixelFormat32bppARGB: 00610 convert_indexed_to_rgb(getpixel_8bppIndexed, setpixel_32bppARGB); 00611 case PixelFormat32bppPARGB: 00612 convert_indexed_to_rgb(getpixel_8bppIndexed, setpixel_32bppPARGB); 00613 case PixelFormat48bppRGB: 00614 convert_indexed_to_rgb(getpixel_8bppIndexed, setpixel_48bppRGB); 00615 case PixelFormat64bppARGB: 00616 convert_indexed_to_rgb(getpixel_8bppIndexed, setpixel_64bppARGB); 00617 default: 00618 break; 00619 } 00620 break; 00621 case PixelFormat16bppGrayScale: 00622 switch (dst_format) 00623 { 00624 case PixelFormat16bppRGB555: 00625 convert_rgb_to_rgb(getpixel_16bppGrayScale, setpixel_16bppRGB555); 00626 case PixelFormat16bppRGB565: 00627 convert_rgb_to_rgb(getpixel_16bppGrayScale, setpixel_16bppRGB565); 00628 case PixelFormat16bppARGB1555: 00629 convert_rgb_to_rgb(getpixel_16bppGrayScale, setpixel_16bppARGB1555); 00630 case PixelFormat24bppRGB: 00631 convert_rgb_to_rgb(getpixel_16bppGrayScale, setpixel_24bppRGB); 00632 case PixelFormat32bppRGB: 00633 convert_rgb_to_rgb(getpixel_16bppGrayScale, setpixel_32bppRGB); 00634 case PixelFormat32bppARGB: 00635 convert_rgb_to_rgb(getpixel_16bppGrayScale, setpixel_32bppARGB); 00636 case PixelFormat32bppPARGB: 00637 convert_rgb_to_rgb(getpixel_16bppGrayScale, setpixel_32bppPARGB); 00638 case PixelFormat48bppRGB: 00639 convert_rgb_to_rgb(getpixel_16bppGrayScale, setpixel_48bppRGB); 00640 case PixelFormat64bppARGB: 00641 convert_rgb_to_rgb(getpixel_16bppGrayScale, setpixel_64bppARGB); 00642 default: 00643 break; 00644 } 00645 break; 00646 case PixelFormat16bppRGB555: 00647 switch (dst_format) 00648 { 00649 case PixelFormat16bppGrayScale: 00650 convert_rgb_to_rgb(getpixel_16bppRGB555, setpixel_16bppGrayScale); 00651 case PixelFormat16bppRGB565: 00652 convert_rgb_to_rgb(getpixel_16bppRGB555, setpixel_16bppRGB565); 00653 case PixelFormat16bppARGB1555: 00654 convert_rgb_to_rgb(getpixel_16bppRGB555, setpixel_16bppARGB1555); 00655 case PixelFormat24bppRGB: 00656 convert_rgb_to_rgb(getpixel_16bppRGB555, setpixel_24bppRGB); 00657 case PixelFormat32bppRGB: 00658 convert_rgb_to_rgb(getpixel_16bppRGB555, setpixel_32bppRGB); 00659 case PixelFormat32bppARGB: 00660 convert_rgb_to_rgb(getpixel_16bppRGB555, setpixel_32bppARGB); 00661 case PixelFormat32bppPARGB: 00662 convert_rgb_to_rgb(getpixel_16bppRGB555, setpixel_32bppPARGB); 00663 case PixelFormat48bppRGB: 00664 convert_rgb_to_rgb(getpixel_16bppRGB555, setpixel_48bppRGB); 00665 case PixelFormat64bppARGB: 00666 convert_rgb_to_rgb(getpixel_16bppRGB555, setpixel_64bppARGB); 00667 default: 00668 break; 00669 } 00670 break; 00671 case PixelFormat16bppRGB565: 00672 switch (dst_format) 00673 { 00674 case PixelFormat16bppGrayScale: 00675 convert_rgb_to_rgb(getpixel_16bppRGB565, setpixel_16bppGrayScale); 00676 case PixelFormat16bppRGB555: 00677 convert_rgb_to_rgb(getpixel_16bppRGB565, setpixel_16bppRGB555); 00678 case PixelFormat16bppARGB1555: 00679 convert_rgb_to_rgb(getpixel_16bppRGB565, setpixel_16bppARGB1555); 00680 case PixelFormat24bppRGB: 00681 convert_rgb_to_rgb(getpixel_16bppRGB565, setpixel_24bppRGB); 00682 case PixelFormat32bppRGB: 00683 convert_rgb_to_rgb(getpixel_16bppRGB565, setpixel_32bppRGB); 00684 case PixelFormat32bppARGB: 00685 convert_rgb_to_rgb(getpixel_16bppRGB565, setpixel_32bppARGB); 00686 case PixelFormat32bppPARGB: 00687 convert_rgb_to_rgb(getpixel_16bppRGB565, setpixel_32bppPARGB); 00688 case PixelFormat48bppRGB: 00689 convert_rgb_to_rgb(getpixel_16bppRGB565, setpixel_48bppRGB); 00690 case PixelFormat64bppARGB: 00691 convert_rgb_to_rgb(getpixel_16bppRGB565, setpixel_64bppARGB); 00692 default: 00693 break; 00694 } 00695 break; 00696 case PixelFormat16bppARGB1555: 00697 switch (dst_format) 00698 { 00699 case PixelFormat16bppGrayScale: 00700 convert_rgb_to_rgb(getpixel_16bppARGB1555, setpixel_16bppGrayScale); 00701 case PixelFormat16bppRGB555: 00702 convert_rgb_to_rgb(getpixel_16bppARGB1555, setpixel_16bppRGB555); 00703 case PixelFormat16bppRGB565: 00704 convert_rgb_to_rgb(getpixel_16bppARGB1555, setpixel_16bppRGB565); 00705 case PixelFormat24bppRGB: 00706 convert_rgb_to_rgb(getpixel_16bppARGB1555, setpixel_24bppRGB); 00707 case PixelFormat32bppRGB: 00708 convert_rgb_to_rgb(getpixel_16bppARGB1555, setpixel_32bppRGB); 00709 case PixelFormat32bppARGB: 00710 convert_rgb_to_rgb(getpixel_16bppARGB1555, setpixel_32bppARGB); 00711 case PixelFormat32bppPARGB: 00712 convert_rgb_to_rgb(getpixel_16bppARGB1555, setpixel_32bppPARGB); 00713 case PixelFormat48bppRGB: 00714 convert_rgb_to_rgb(getpixel_16bppARGB1555, setpixel_48bppRGB); 00715 case PixelFormat64bppARGB: 00716 convert_rgb_to_rgb(getpixel_16bppARGB1555, setpixel_64bppARGB); 00717 default: 00718 break; 00719 } 00720 break; 00721 case PixelFormat24bppRGB: 00722 switch (dst_format) 00723 { 00724 case PixelFormat16bppGrayScale: 00725 convert_rgb_to_rgb(getpixel_24bppRGB, setpixel_16bppGrayScale); 00726 case PixelFormat16bppRGB555: 00727 convert_rgb_to_rgb(getpixel_24bppRGB, setpixel_16bppRGB555); 00728 case PixelFormat16bppRGB565: 00729 convert_rgb_to_rgb(getpixel_24bppRGB, setpixel_16bppRGB565); 00730 case PixelFormat16bppARGB1555: 00731 convert_rgb_to_rgb(getpixel_24bppRGB, setpixel_16bppARGB1555); 00732 case PixelFormat32bppRGB: 00733 convert_rgb_to_rgb(getpixel_24bppRGB, setpixel_32bppRGB); 00734 case PixelFormat32bppARGB: 00735 convert_rgb_to_rgb(getpixel_24bppRGB, setpixel_32bppARGB); 00736 case PixelFormat32bppPARGB: 00737 convert_rgb_to_rgb(getpixel_24bppRGB, setpixel_32bppPARGB); 00738 case PixelFormat48bppRGB: 00739 convert_rgb_to_rgb(getpixel_24bppRGB, setpixel_48bppRGB); 00740 case PixelFormat64bppARGB: 00741 convert_rgb_to_rgb(getpixel_24bppRGB, setpixel_64bppARGB); 00742 default: 00743 break; 00744 } 00745 break; 00746 case PixelFormat32bppRGB: 00747 switch (dst_format) 00748 { 00749 case PixelFormat16bppGrayScale: 00750 convert_rgb_to_rgb(getpixel_32bppRGB, setpixel_16bppGrayScale); 00751 case PixelFormat16bppRGB555: 00752 convert_rgb_to_rgb(getpixel_32bppRGB, setpixel_16bppRGB555); 00753 case PixelFormat16bppRGB565: 00754 convert_rgb_to_rgb(getpixel_32bppRGB, setpixel_16bppRGB565); 00755 case PixelFormat16bppARGB1555: 00756 convert_rgb_to_rgb(getpixel_32bppRGB, setpixel_16bppARGB1555); 00757 case PixelFormat24bppRGB: 00758 convert_rgb_to_rgb(getpixel_32bppRGB, setpixel_24bppRGB); 00759 case PixelFormat32bppARGB: 00760 convert_rgb_to_rgb(getpixel_32bppRGB, setpixel_32bppARGB); 00761 case PixelFormat32bppPARGB: 00762 convert_rgb_to_rgb(getpixel_32bppRGB, setpixel_32bppPARGB); 00763 case PixelFormat48bppRGB: 00764 convert_rgb_to_rgb(getpixel_32bppRGB, setpixel_48bppRGB); 00765 case PixelFormat64bppARGB: 00766 convert_rgb_to_rgb(getpixel_32bppRGB, setpixel_64bppARGB); 00767 default: 00768 break; 00769 } 00770 break; 00771 case PixelFormat32bppARGB: 00772 switch (dst_format) 00773 { 00774 case PixelFormat16bppGrayScale: 00775 convert_rgb_to_rgb(getpixel_32bppARGB, setpixel_16bppGrayScale); 00776 case PixelFormat16bppRGB555: 00777 convert_rgb_to_rgb(getpixel_32bppARGB, setpixel_16bppRGB555); 00778 case PixelFormat16bppRGB565: 00779 convert_rgb_to_rgb(getpixel_32bppARGB, setpixel_16bppRGB565); 00780 case PixelFormat16bppARGB1555: 00781 convert_rgb_to_rgb(getpixel_32bppARGB, setpixel_16bppARGB1555); 00782 case PixelFormat24bppRGB: 00783 convert_rgb_to_rgb(getpixel_32bppARGB, setpixel_24bppRGB); 00784 case PixelFormat32bppPARGB: 00785 convert_32bppARGB_to_32bppPARGB(width, height, dst_bits, dst_stride, src_bits, src_stride); 00786 return Ok; 00787 case PixelFormat48bppRGB: 00788 convert_rgb_to_rgb(getpixel_32bppARGB, setpixel_48bppRGB); 00789 case PixelFormat64bppARGB: 00790 convert_rgb_to_rgb(getpixel_32bppARGB, setpixel_64bppARGB); 00791 default: 00792 break; 00793 } 00794 break; 00795 case PixelFormat32bppPARGB: 00796 switch (dst_format) 00797 { 00798 case PixelFormat16bppGrayScale: 00799 convert_rgb_to_rgb(getpixel_32bppPARGB, setpixel_16bppGrayScale); 00800 case PixelFormat16bppRGB555: 00801 convert_rgb_to_rgb(getpixel_32bppPARGB, setpixel_16bppRGB555); 00802 case PixelFormat16bppRGB565: 00803 convert_rgb_to_rgb(getpixel_32bppPARGB, setpixel_16bppRGB565); 00804 case PixelFormat16bppARGB1555: 00805 convert_rgb_to_rgb(getpixel_32bppPARGB, setpixel_16bppARGB1555); 00806 case PixelFormat24bppRGB: 00807 convert_rgb_to_rgb(getpixel_32bppPARGB, setpixel_24bppRGB); 00808 case PixelFormat32bppRGB: 00809 convert_rgb_to_rgb(getpixel_32bppPARGB, setpixel_32bppRGB); 00810 case PixelFormat32bppARGB: 00811 convert_rgb_to_rgb(getpixel_32bppPARGB, setpixel_32bppARGB); 00812 case PixelFormat48bppRGB: 00813 convert_rgb_to_rgb(getpixel_32bppPARGB, setpixel_48bppRGB); 00814 case PixelFormat64bppARGB: 00815 convert_rgb_to_rgb(getpixel_32bppPARGB, setpixel_64bppARGB); 00816 default: 00817 break; 00818 } 00819 break; 00820 case PixelFormat48bppRGB: 00821 switch (dst_format) 00822 { 00823 case PixelFormat16bppGrayScale: 00824 convert_rgb_to_rgb(getpixel_48bppRGB, setpixel_16bppGrayScale); 00825 case PixelFormat16bppRGB555: 00826 convert_rgb_to_rgb(getpixel_48bppRGB, setpixel_16bppRGB555); 00827 case PixelFormat16bppRGB565: 00828 convert_rgb_to_rgb(getpixel_48bppRGB, setpixel_16bppRGB565); 00829 case PixelFormat16bppARGB1555: 00830 convert_rgb_to_rgb(getpixel_48bppRGB, setpixel_16bppARGB1555); 00831 case PixelFormat24bppRGB: 00832 convert_rgb_to_rgb(getpixel_48bppRGB, setpixel_24bppRGB); 00833 case PixelFormat32bppRGB: 00834 convert_rgb_to_rgb(getpixel_48bppRGB, setpixel_32bppRGB); 00835 case PixelFormat32bppARGB: 00836 convert_rgb_to_rgb(getpixel_48bppRGB, setpixel_32bppARGB); 00837 case PixelFormat32bppPARGB: 00838 convert_rgb_to_rgb(getpixel_48bppRGB, setpixel_32bppPARGB); 00839 case PixelFormat64bppARGB: 00840 convert_rgb_to_rgb(getpixel_48bppRGB, setpixel_64bppARGB); 00841 default: 00842 break; 00843 } 00844 break; 00845 case PixelFormat64bppARGB: 00846 switch (dst_format) 00847 { 00848 case PixelFormat16bppGrayScale: 00849 convert_rgb_to_rgb(getpixel_64bppARGB, setpixel_16bppGrayScale); 00850 case PixelFormat16bppRGB555: 00851 convert_rgb_to_rgb(getpixel_64bppARGB, setpixel_16bppRGB555); 00852 case PixelFormat16bppRGB565: 00853 convert_rgb_to_rgb(getpixel_64bppARGB, setpixel_16bppRGB565); 00854 case PixelFormat16bppARGB1555: 00855 convert_rgb_to_rgb(getpixel_64bppARGB, setpixel_16bppARGB1555); 00856 case PixelFormat24bppRGB: 00857 convert_rgb_to_rgb(getpixel_64bppARGB, setpixel_24bppRGB); 00858 case PixelFormat32bppRGB: 00859 convert_rgb_to_rgb(getpixel_64bppARGB, setpixel_32bppRGB); 00860 case PixelFormat32bppARGB: 00861 convert_rgb_to_rgb(getpixel_64bppARGB, setpixel_32bppARGB); 00862 case PixelFormat32bppPARGB: 00863 convert_rgb_to_rgb(getpixel_64bppARGB, setpixel_32bppPARGB); 00864 case PixelFormat48bppRGB: 00865 convert_rgb_to_rgb(getpixel_64bppARGB, setpixel_48bppRGB); 00866 default: 00867 break; 00868 } 00869 break; 00870 case PixelFormat64bppPARGB: 00871 switch (dst_format) 00872 { 00873 case PixelFormat16bppGrayScale: 00874 convert_rgb_to_rgb(getpixel_64bppPARGB, setpixel_16bppGrayScale); 00875 case PixelFormat16bppRGB555: 00876 convert_rgb_to_rgb(getpixel_64bppPARGB, setpixel_16bppRGB555); 00877 case PixelFormat16bppRGB565: 00878 convert_rgb_to_rgb(getpixel_64bppPARGB, setpixel_16bppRGB565); 00879 case PixelFormat16bppARGB1555: 00880 convert_rgb_to_rgb(getpixel_64bppPARGB, setpixel_16bppARGB1555); 00881 case PixelFormat24bppRGB: 00882 convert_rgb_to_rgb(getpixel_64bppPARGB, setpixel_24bppRGB); 00883 case PixelFormat32bppRGB: 00884 convert_rgb_to_rgb(getpixel_64bppPARGB, setpixel_32bppRGB); 00885 case PixelFormat32bppARGB: 00886 convert_rgb_to_rgb(getpixel_64bppPARGB, setpixel_32bppARGB); 00887 case PixelFormat32bppPARGB: 00888 convert_rgb_to_rgb(getpixel_64bppPARGB, setpixel_32bppPARGB); 00889 case PixelFormat48bppRGB: 00890 convert_rgb_to_rgb(getpixel_64bppPARGB, setpixel_48bppRGB); 00891 case PixelFormat64bppARGB: 00892 convert_rgb_to_rgb(getpixel_64bppPARGB, setpixel_64bppARGB); 00893 default: 00894 break; 00895 } 00896 break; 00897 default: 00898 break; 00899 } 00900 00901 #undef convert_indexed_to_rgb 00902 #undef convert_rgb_to_rgb 00903 00904 return NotImplemented; 00905 } 00906 00907 /* This function returns a pointer to an array of pixels that represents the 00908 * bitmap. The *entire* bitmap is locked according to the lock mode specified by 00909 * flags. It is correct behavior that a user who calls this function with write 00910 * privileges can write to the whole bitmap (not just the area in rect). 00911 * 00912 * FIXME: only used portion of format is bits per pixel. */ 00913 GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, 00914 UINT flags, PixelFormat format, BitmapData* lockeddata) 00915 { 00916 INT bitspp = PIXELFORMATBPP(format); 00917 GpRect act_rect; /* actual rect to be used */ 00918 GpStatus stat; 00919 00920 TRACE("%p %p %d 0x%x %p\n", bitmap, rect, flags, format, lockeddata); 00921 00922 if(!lockeddata || !bitmap) 00923 return InvalidParameter; 00924 00925 if(rect){ 00926 if(rect->X < 0 || rect->Y < 0 || (rect->X + rect->Width > bitmap->width) || 00927 (rect->Y + rect->Height > bitmap->height) || !flags) 00928 return InvalidParameter; 00929 00930 act_rect = *rect; 00931 } 00932 else{ 00933 act_rect.X = act_rect.Y = 0; 00934 act_rect.Width = bitmap->width; 00935 act_rect.Height = bitmap->height; 00936 } 00937 00938 if(bitmap->lockmode) 00939 { 00940 WARN("bitmap is already locked and cannot be locked again\n"); 00941 return WrongState; 00942 } 00943 00944 if (bitmap->bits && bitmap->format == format && !(flags & ImageLockModeUserInputBuf)) 00945 { 00946 /* no conversion is necessary; just use the bits directly */ 00947 lockeddata->Width = act_rect.Width; 00948 lockeddata->Height = act_rect.Height; 00949 lockeddata->PixelFormat = format; 00950 lockeddata->Reserved = flags; 00951 lockeddata->Stride = bitmap->stride; 00952 lockeddata->Scan0 = bitmap->bits + (bitspp / 8) * act_rect.X + 00953 bitmap->stride * act_rect.Y; 00954 00955 bitmap->lockmode = flags; 00956 bitmap->numlocks++; 00957 00958 return Ok; 00959 } 00960 00961 /* Make sure we can convert to the requested format. */ 00962 if (flags & ImageLockModeRead) 00963 { 00964 stat = convert_pixels(0, 0, 0, NULL, format, 0, NULL, bitmap->format, NULL); 00965 if (stat == NotImplemented) 00966 { 00967 FIXME("cannot read bitmap from %x to %x\n", bitmap->format, format); 00968 return NotImplemented; 00969 } 00970 } 00971 00972 /* If we're opening for writing, make sure we'll be able to write back in 00973 * the original format. */ 00974 if (flags & ImageLockModeWrite) 00975 { 00976 stat = convert_pixels(0, 0, 0, NULL, bitmap->format, 0, NULL, format, NULL); 00977 if (stat == NotImplemented) 00978 { 00979 FIXME("cannot write bitmap from %x to %x\n", format, bitmap->format); 00980 return NotImplemented; 00981 } 00982 } 00983 00984 lockeddata->Width = act_rect.Width; 00985 lockeddata->Height = act_rect.Height; 00986 lockeddata->PixelFormat = format; 00987 lockeddata->Reserved = flags; 00988 00989 if(!(flags & ImageLockModeUserInputBuf)) 00990 { 00991 lockeddata->Stride = (((act_rect.Width * bitspp + 7) / 8) + 3) & ~3; 00992 00993 bitmap->bitmapbits = GdipAlloc(lockeddata->Stride * act_rect.Height); 00994 00995 if (!bitmap->bitmapbits) return OutOfMemory; 00996 00997 lockeddata->Scan0 = bitmap->bitmapbits; 00998 } 00999 01000 if (flags & ImageLockModeRead) 01001 { 01002 static int fixme=0; 01003 01004 if (!fixme && (PIXELFORMATBPP(bitmap->format) * act_rect.X) % 8 != 0) 01005 { 01006 FIXME("Cannot copy rows that don't start at a whole byte.\n"); 01007 fixme = 1; 01008 } 01009 01010 stat = convert_pixels(act_rect.Width, act_rect.Height, 01011 lockeddata->Stride, lockeddata->Scan0, format, 01012 bitmap->stride, 01013 bitmap->bits + bitmap->stride * act_rect.Y + PIXELFORMATBPP(bitmap->format) * act_rect.X / 8, 01014 bitmap->format, bitmap->image.palette_entries); 01015 01016 if (stat != Ok) 01017 { 01018 GdipFree(bitmap->bitmapbits); 01019 bitmap->bitmapbits = NULL; 01020 return stat; 01021 } 01022 } 01023 01024 bitmap->lockmode = flags; 01025 bitmap->numlocks++; 01026 bitmap->lockx = act_rect.X; 01027 bitmap->locky = act_rect.Y; 01028 01029 return Ok; 01030 } 01031 01032 GpStatus WINGDIPAPI GdipBitmapSetResolution(GpBitmap* bitmap, REAL xdpi, REAL ydpi) 01033 { 01034 TRACE("(%p, %.2f, %.2f)\n", bitmap, xdpi, ydpi); 01035 01036 if (!bitmap || xdpi == 0.0 || ydpi == 0.0) 01037 return InvalidParameter; 01038 01039 bitmap->image.xres = xdpi; 01040 bitmap->image.yres = ydpi; 01041 01042 return Ok; 01043 } 01044 01045 GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap, 01046 BitmapData* lockeddata) 01047 { 01048 GpStatus stat; 01049 static int fixme=0; 01050 01051 TRACE("(%p,%p)\n", bitmap, lockeddata); 01052 01053 if(!bitmap || !lockeddata) 01054 return InvalidParameter; 01055 01056 if(!bitmap->lockmode) 01057 return WrongState; 01058 01059 if(!(lockeddata->Reserved & ImageLockModeWrite)){ 01060 if(!(--bitmap->numlocks)) 01061 bitmap->lockmode = 0; 01062 01063 GdipFree(bitmap->bitmapbits); 01064 bitmap->bitmapbits = NULL; 01065 return Ok; 01066 } 01067 01068 if (!bitmap->bitmapbits && !(lockeddata->Reserved & ImageLockModeUserInputBuf)) 01069 { 01070 /* we passed a direct reference; no need to do anything */ 01071 bitmap->lockmode = 0; 01072 bitmap->numlocks = 0; 01073 return Ok; 01074 } 01075 01076 if (!fixme && (PIXELFORMATBPP(bitmap->format) * bitmap->lockx) % 8 != 0) 01077 { 01078 FIXME("Cannot copy rows that don't start at a whole byte.\n"); 01079 fixme = 1; 01080 } 01081 01082 stat = convert_pixels(lockeddata->Width, lockeddata->Height, 01083 bitmap->stride, 01084 bitmap->bits + bitmap->stride * bitmap->locky + PIXELFORMATBPP(bitmap->format) * bitmap->lockx / 8, 01085 bitmap->format, 01086 lockeddata->Stride, lockeddata->Scan0, lockeddata->PixelFormat, NULL); 01087 01088 if (stat != Ok) 01089 { 01090 ERR("failed to convert pixels; this should never happen\n"); 01091 } 01092 01093 GdipFree(bitmap->bitmapbits); 01094 bitmap->bitmapbits = NULL; 01095 bitmap->lockmode = 0; 01096 bitmap->numlocks = 0; 01097 01098 return stat; 01099 } 01100 01101 GpStatus WINGDIPAPI GdipCloneBitmapArea(REAL x, REAL y, REAL width, REAL height, 01102 PixelFormat format, GpBitmap* srcBitmap, GpBitmap** dstBitmap) 01103 { 01104 BitmapData lockeddata_src, lockeddata_dst; 01105 int i; 01106 UINT row_size; 01107 Rect area; 01108 GpStatus stat; 01109 01110 TRACE("(%f,%f,%f,%f,0x%x,%p,%p)\n", x, y, width, height, format, srcBitmap, dstBitmap); 01111 01112 if (!srcBitmap || !dstBitmap || srcBitmap->image.type != ImageTypeBitmap || 01113 x < 0 || y < 0 || 01114 x + width > srcBitmap->width || y + height > srcBitmap->height) 01115 { 01116 TRACE("<-- InvalidParameter\n"); 01117 return InvalidParameter; 01118 } 01119 01120 if (format == PixelFormatDontCare) 01121 format = srcBitmap->format; 01122 01123 area.X = roundr(x); 01124 area.Y = roundr(y); 01125 area.Width = roundr(width); 01126 area.Height = roundr(height); 01127 01128 stat = GdipBitmapLockBits(srcBitmap, &area, ImageLockModeRead, format, 01129 &lockeddata_src); 01130 if (stat != Ok) return stat; 01131 01132 stat = GdipCreateBitmapFromScan0(lockeddata_src.Width, lockeddata_src.Height, 01133 0, lockeddata_src.PixelFormat, NULL, dstBitmap); 01134 if (stat == Ok) 01135 { 01136 stat = GdipBitmapLockBits(*dstBitmap, NULL, ImageLockModeWrite, 01137 lockeddata_src.PixelFormat, &lockeddata_dst); 01138 01139 if (stat == Ok) 01140 { 01141 /* copy the image data */ 01142 row_size = (lockeddata_src.Width * PIXELFORMATBPP(lockeddata_src.PixelFormat) +7)/8; 01143 for (i=0; i<lockeddata_src.Height; i++) 01144 memcpy((BYTE*)lockeddata_dst.Scan0+lockeddata_dst.Stride*i, 01145 (BYTE*)lockeddata_src.Scan0+lockeddata_src.Stride*i, 01146 row_size); 01147 01148 GdipBitmapUnlockBits(*dstBitmap, &lockeddata_dst); 01149 } 01150 01151 if (stat != Ok) 01152 GdipDisposeImage((GpImage*)*dstBitmap); 01153 } 01154 01155 GdipBitmapUnlockBits(srcBitmap, &lockeddata_src); 01156 01157 if (stat != Ok) 01158 { 01159 *dstBitmap = NULL; 01160 } 01161 01162 return stat; 01163 } 01164 01165 GpStatus WINGDIPAPI GdipCloneBitmapAreaI(INT x, INT y, INT width, INT height, 01166 PixelFormat format, GpBitmap* srcBitmap, GpBitmap** dstBitmap) 01167 { 01168 TRACE("(%i,%i,%i,%i,0x%x,%p,%p)\n", x, y, width, height, format, srcBitmap, dstBitmap); 01169 01170 return GdipCloneBitmapArea(x, y, width, height, format, srcBitmap, dstBitmap); 01171 } 01172 01173 GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage) 01174 { 01175 GpStatus stat = GenericError; 01176 01177 TRACE("%p, %p\n", image, cloneImage); 01178 01179 if (!image || !cloneImage) 01180 return InvalidParameter; 01181 01182 if (image->picture) 01183 { 01184 IStream* stream; 01185 HRESULT hr; 01186 INT size; 01187 LARGE_INTEGER move; 01188 01189 hr = CreateStreamOnHGlobal(0, TRUE, &stream); 01190 if (FAILED(hr)) 01191 return GenericError; 01192 01193 hr = IPicture_SaveAsFile(image->picture, stream, FALSE, &size); 01194 if(FAILED(hr)) 01195 { 01196 WARN("Failed to save image on stream\n"); 01197 goto out; 01198 } 01199 01200 /* Set seek pointer back to the beginning of the picture */ 01201 move.QuadPart = 0; 01202 hr = IStream_Seek(stream, move, STREAM_SEEK_SET, NULL); 01203 if (FAILED(hr)) 01204 goto out; 01205 01206 stat = GdipLoadImageFromStream(stream, cloneImage); 01207 if (stat != Ok) WARN("Failed to load image from stream\n"); 01208 01209 out: 01210 IStream_Release(stream); 01211 return stat; 01212 } 01213 else if (image->type == ImageTypeBitmap) 01214 { 01215 GpBitmap *bitmap = (GpBitmap*)image; 01216 BitmapData lockeddata_src, lockeddata_dst; 01217 int i; 01218 UINT row_size; 01219 01220 stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, bitmap->format, 01221 &lockeddata_src); 01222 if (stat != Ok) return stat; 01223 01224 stat = GdipCreateBitmapFromScan0(lockeddata_src.Width, lockeddata_src.Height, 01225 0, lockeddata_src.PixelFormat, NULL, (GpBitmap**)cloneImage); 01226 if (stat == Ok) 01227 { 01228 stat = GdipBitmapLockBits((GpBitmap*)*cloneImage, NULL, ImageLockModeWrite, 01229 lockeddata_src.PixelFormat, &lockeddata_dst); 01230 01231 if (stat == Ok) 01232 { 01233 /* copy the image data */ 01234 row_size = (lockeddata_src.Width * PIXELFORMATBPP(lockeddata_src.PixelFormat) +7)/8; 01235 for (i=0; i<lockeddata_src.Height; i++) 01236 memcpy((BYTE*)lockeddata_dst.Scan0+lockeddata_dst.Stride*i, 01237 (BYTE*)lockeddata_src.Scan0+lockeddata_src.Stride*i, 01238 row_size); 01239 01240 GdipBitmapUnlockBits((GpBitmap*)*cloneImage, &lockeddata_dst); 01241 } 01242 01243 if (stat != Ok) 01244 GdipDisposeImage(*cloneImage); 01245 } 01246 01247 GdipBitmapUnlockBits(bitmap, &lockeddata_src); 01248 01249 if (stat != Ok) 01250 { 01251 *cloneImage = NULL; 01252 } 01253 else memcpy(&(*cloneImage)->format, &image->format, sizeof(GUID)); 01254 01255 return stat; 01256 } 01257 else 01258 { 01259 ERR("GpImage with no IPicture or bitmap?!\n"); 01260 return NotImplemented; 01261 } 01262 } 01263 01264 GpStatus WINGDIPAPI GdipCreateBitmapFromFile(GDIPCONST WCHAR* filename, 01265 GpBitmap **bitmap) 01266 { 01267 GpStatus stat; 01268 IStream *stream; 01269 01270 TRACE("(%s) %p\n", debugstr_w(filename), bitmap); 01271 01272 if(!filename || !bitmap) 01273 return InvalidParameter; 01274 01275 stat = GdipCreateStreamOnFile(filename, GENERIC_READ, &stream); 01276 01277 if(stat != Ok) 01278 return stat; 01279 01280 stat = GdipCreateBitmapFromStream(stream, bitmap); 01281 01282 IStream_Release(stream); 01283 01284 return stat; 01285 } 01286 01287 GpStatus WINGDIPAPI GdipCreateBitmapFromGdiDib(GDIPCONST BITMAPINFO* info, 01288 VOID *bits, GpBitmap **bitmap) 01289 { 01290 DWORD height, stride; 01291 PixelFormat format; 01292 01293 FIXME("(%p, %p, %p) - partially implemented\n", info, bits, bitmap); 01294 01295 if (!info || !bits || !bitmap) 01296 return InvalidParameter; 01297 01298 height = abs(info->bmiHeader.biHeight); 01299 stride = ((info->bmiHeader.biWidth * info->bmiHeader.biBitCount + 31) >> 3) & ~3; 01300 01301 if(info->bmiHeader.biHeight > 0) /* bottom-up */ 01302 { 01303 bits = (BYTE*)bits + (height - 1) * stride; 01304 stride = -stride; 01305 } 01306 01307 switch(info->bmiHeader.biBitCount) { 01308 case 1: 01309 format = PixelFormat1bppIndexed; 01310 break; 01311 case 4: 01312 format = PixelFormat4bppIndexed; 01313 break; 01314 case 8: 01315 format = PixelFormat8bppIndexed; 01316 break; 01317 case 16: 01318 format = PixelFormat16bppRGB555; 01319 break; 01320 case 24: 01321 format = PixelFormat24bppRGB; 01322 break; 01323 case 32: 01324 format = PixelFormat32bppRGB; 01325 break; 01326 default: 01327 FIXME("don't know how to handle %d bpp\n", info->bmiHeader.biBitCount); 01328 *bitmap = NULL; 01329 return InvalidParameter; 01330 } 01331 01332 return GdipCreateBitmapFromScan0(info->bmiHeader.biWidth, height, stride, format, 01333 bits, bitmap); 01334 01335 } 01336 01337 /* FIXME: no icm */ 01338 GpStatus WINGDIPAPI GdipCreateBitmapFromFileICM(GDIPCONST WCHAR* filename, 01339 GpBitmap **bitmap) 01340 { 01341 TRACE("(%s) %p\n", debugstr_w(filename), bitmap); 01342 01343 return GdipCreateBitmapFromFile(filename, bitmap); 01344 } 01345 01346 GpStatus WINGDIPAPI GdipCreateBitmapFromResource(HINSTANCE hInstance, 01347 GDIPCONST WCHAR* lpBitmapName, GpBitmap** bitmap) 01348 { 01349 HBITMAP hbm; 01350 GpStatus stat = InvalidParameter; 01351 01352 TRACE("%p (%s) %p\n", hInstance, debugstr_w(lpBitmapName), bitmap); 01353 01354 if(!lpBitmapName || !bitmap) 01355 return InvalidParameter; 01356 01357 /* load DIB */ 01358 hbm = LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 01359 LR_CREATEDIBSECTION); 01360 01361 if(hbm){ 01362 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, bitmap); 01363 DeleteObject(hbm); 01364 } 01365 01366 return stat; 01367 } 01368 01369 GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap, 01370 HBITMAP* hbmReturn, ARGB background) 01371 { 01372 GpStatus stat; 01373 HBITMAP result; 01374 UINT width, height; 01375 BITMAPINFOHEADER bih; 01376 LPBYTE bits; 01377 BitmapData lockeddata; 01378 TRACE("(%p,%p,%x)\n", bitmap, hbmReturn, background); 01379 01380 if (!bitmap || !hbmReturn) return InvalidParameter; 01381 01382 GdipGetImageWidth((GpImage*)bitmap, &width); 01383 GdipGetImageHeight((GpImage*)bitmap, &height); 01384 01385 bih.biSize = sizeof(bih); 01386 bih.biWidth = width; 01387 bih.biHeight = height; 01388 bih.biPlanes = 1; 01389 bih.biBitCount = 32; 01390 bih.biCompression = BI_RGB; 01391 bih.biSizeImage = 0; 01392 bih.biXPelsPerMeter = 0; 01393 bih.biYPelsPerMeter = 0; 01394 bih.biClrUsed = 0; 01395 bih.biClrImportant = 0; 01396 01397 result = CreateDIBSection(0, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&bits, NULL, 0); 01398 01399 if (result) 01400 { 01401 lockeddata.Stride = -width * 4; 01402 lockeddata.Scan0 = bits + (width * 4 * (height - 1)); 01403 01404 stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead|ImageLockModeUserInputBuf, 01405 PixelFormat32bppPARGB, &lockeddata); 01406 01407 if (stat == Ok) 01408 stat = GdipBitmapUnlockBits(bitmap, &lockeddata); 01409 } 01410 else 01411 stat = GenericError; 01412 01413 if (stat != Ok && result) 01414 { 01415 DeleteObject(result); 01416 result = NULL; 01417 } 01418 01419 *hbmReturn = result; 01420 01421 return stat; 01422 } 01423 01424 GpStatus WINGDIPAPI GdipConvertToEmfPlus(const GpGraphics* ref, 01425 GpMetafile* metafile, BOOL* succ, EmfType emfType, 01426 const WCHAR* description, GpMetafile** out_metafile) 01427 { 01428 static int calls; 01429 01430 TRACE("(%p,%p,%p,%u,%s,%p)\n", ref, metafile, succ, emfType, 01431 debugstr_w(description), out_metafile); 01432 01433 if(!ref || !metafile || !out_metafile) 01434 return InvalidParameter; 01435 01436 *succ = FALSE; 01437 *out_metafile = NULL; 01438 01439 if(!(calls++)) 01440 FIXME("not implemented\n"); 01441 01442 return NotImplemented; 01443 } 01444 01445 /* FIXME: this should create a bitmap in the given size with the attributes 01446 * (resolution etc.) of the graphics object */ 01447 GpStatus WINGDIPAPI GdipCreateBitmapFromGraphics(INT width, INT height, 01448 GpGraphics* target, GpBitmap** bitmap) 01449 { 01450 static int calls; 01451 GpStatus ret; 01452 01453 TRACE("(%d, %d, %p, %p)\n", width, height, target, bitmap); 01454 01455 if(!target || !bitmap) 01456 return InvalidParameter; 01457 01458 if(!(calls++)) 01459 FIXME("hacked stub\n"); 01460 01461 ret = GdipCreateBitmapFromScan0(width, height, 0, PixelFormat24bppRGB, 01462 NULL, bitmap); 01463 01464 return ret; 01465 } 01466 01467 GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap) 01468 { 01469 GpStatus stat; 01470 ICONINFO iinfo; 01471 BITMAP bm; 01472 int ret; 01473 UINT width, height; 01474 GpRect rect; 01475 BitmapData lockeddata; 01476 HDC screendc; 01477 BOOL has_alpha; 01478 int x, y; 01479 BYTE *bits; 01480 BITMAPINFOHEADER bih; 01481 DWORD *src; 01482 BYTE *dst_row; 01483 DWORD *dst; 01484 01485 TRACE("%p, %p\n", hicon, bitmap); 01486 01487 if(!bitmap || !GetIconInfo(hicon, &iinfo)) 01488 return InvalidParameter; 01489 01490 /* get the size of the icon */ 01491 ret = GetObjectA(iinfo.hbmColor ? iinfo.hbmColor : iinfo.hbmMask, sizeof(bm), &bm); 01492 if (ret == 0) { 01493 DeleteObject(iinfo.hbmColor); 01494 DeleteObject(iinfo.hbmMask); 01495 return GenericError; 01496 } 01497 01498 width = bm.bmWidth; 01499 01500 if (iinfo.hbmColor) 01501 height = abs(bm.bmHeight); 01502 else /* combined bitmap + mask */ 01503 height = abs(bm.bmHeight) / 2; 01504 01505 bits = HeapAlloc(GetProcessHeap(), 0, 4*width*height); 01506 if (!bits) { 01507 DeleteObject(iinfo.hbmColor); 01508 DeleteObject(iinfo.hbmMask); 01509 return OutOfMemory; 01510 } 01511 01512 stat = GdipCreateBitmapFromScan0(width, height, 0, PixelFormat32bppARGB, NULL, bitmap); 01513 if (stat != Ok) { 01514 DeleteObject(iinfo.hbmColor); 01515 DeleteObject(iinfo.hbmMask); 01516 HeapFree(GetProcessHeap(), 0, bits); 01517 return stat; 01518 } 01519 01520 rect.X = 0; 01521 rect.Y = 0; 01522 rect.Width = width; 01523 rect.Height = height; 01524 01525 stat = GdipBitmapLockBits(*bitmap, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &lockeddata); 01526 if (stat != Ok) { 01527 DeleteObject(iinfo.hbmColor); 01528 DeleteObject(iinfo.hbmMask); 01529 HeapFree(GetProcessHeap(), 0, bits); 01530 GdipDisposeImage((GpImage*)*bitmap); 01531 return stat; 01532 } 01533 01534 bih.biSize = sizeof(bih); 01535 bih.biWidth = width; 01536 bih.biHeight = -height; 01537 bih.biPlanes = 1; 01538 bih.biBitCount = 32; 01539 bih.biCompression = BI_RGB; 01540 bih.biSizeImage = 0; 01541 bih.biXPelsPerMeter = 0; 01542 bih.biYPelsPerMeter = 0; 01543 bih.biClrUsed = 0; 01544 bih.biClrImportant = 0; 01545 01546 screendc = GetDC(0); 01547 if (iinfo.hbmColor) 01548 { 01549 GetDIBits(screendc, iinfo.hbmColor, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS); 01550 01551 if (bm.bmBitsPixel == 32) 01552 { 01553 has_alpha = FALSE; 01554 01555 /* If any pixel has a non-zero alpha, ignore hbmMask */ 01556 src = (DWORD*)bits; 01557 for (x=0; x<width && !has_alpha; x++) 01558 for (y=0; y<height && !has_alpha; y++) 01559 if ((*src++ & 0xff000000) != 0) 01560 has_alpha = TRUE; 01561 } 01562 else has_alpha = FALSE; 01563 } 01564 else 01565 { 01566 GetDIBits(screendc, iinfo.hbmMask, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS); 01567 has_alpha = FALSE; 01568 } 01569 01570 /* copy the image data to the Bitmap */ 01571 src = (DWORD*)bits; 01572 dst_row = lockeddata.Scan0; 01573 for (y=0; y<height; y++) 01574 { 01575 memcpy(dst_row, src, width*4); 01576 src += width; 01577 dst_row += lockeddata.Stride; 01578 } 01579 01580 if (!has_alpha) 01581 { 01582 if (iinfo.hbmMask) 01583 { 01584 /* read alpha data from the mask */ 01585 if (iinfo.hbmColor) 01586 GetDIBits(screendc, iinfo.hbmMask, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS); 01587 else 01588 GetDIBits(screendc, iinfo.hbmMask, height, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS); 01589 01590 src = (DWORD*)bits; 01591 dst_row = lockeddata.Scan0; 01592 for (y=0; y<height; y++) 01593 { 01594 dst = (DWORD*)dst_row; 01595 for (x=0; x<height; x++) 01596 { 01597 DWORD src_value = *src++; 01598 if (src_value) 01599 *dst++ = 0; 01600 else 01601 *dst++ |= 0xff000000; 01602 } 01603 dst_row += lockeddata.Stride; 01604 } 01605 } 01606 else 01607 { 01608 /* set constant alpha of 255 */ 01609 dst_row = bits; 01610 for (y=0; y<height; y++) 01611 { 01612 dst = (DWORD*)dst_row; 01613 for (x=0; x<height; x++) 01614 *dst++ |= 0xff000000; 01615 dst_row += lockeddata.Stride; 01616 } 01617 } 01618 } 01619 01620 ReleaseDC(0, screendc); 01621 01622 DeleteObject(iinfo.hbmColor); 01623 DeleteObject(iinfo.hbmMask); 01624 01625 GdipBitmapUnlockBits(*bitmap, &lockeddata); 01626 01627 HeapFree(GetProcessHeap(), 0, bits); 01628 01629 return Ok; 01630 } 01631 01632 static void generate_halftone_palette(ARGB *entries, UINT count) 01633 { 01634 static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff}; 01635 UINT i; 01636 01637 for (i=0; i<8 && i<count; i++) 01638 { 01639 entries[i] = 0xff000000; 01640 if (i&1) entries[i] |= 0x800000; 01641 if (i&2) entries[i] |= 0x8000; 01642 if (i&4) entries[i] |= 0x80; 01643 } 01644 01645 if (8 < count) 01646 entries[i] = 0xffc0c0c0; 01647 01648 for (i=9; i<16 && i<count; i++) 01649 { 01650 entries[i] = 0xff000000; 01651 if (i&1) entries[i] |= 0xff0000; 01652 if (i&2) entries[i] |= 0xff00; 01653 if (i&4) entries[i] |= 0xff; 01654 } 01655 01656 for (i=16; i<40 && i<count; i++) 01657 { 01658 entries[i] = 0; 01659 } 01660 01661 for (i=40; i<256 && i<count; i++) 01662 { 01663 entries[i] = 0xff000000; 01664 entries[i] |= halftone_values[(i-40)%6]; 01665 entries[i] |= halftone_values[((i-40)/6)%6] << 8; 01666 entries[i] |= halftone_values[((i-40)/36)%6] << 16; 01667 } 01668 } 01669 01670 static GpStatus get_screen_resolution(REAL *xres, REAL *yres) 01671 { 01672 HDC screendc = GetDC(0); 01673 01674 if (!screendc) return GenericError; 01675 01676 *xres = (REAL)GetDeviceCaps(screendc, LOGPIXELSX); 01677 *yres = (REAL)GetDeviceCaps(screendc, LOGPIXELSY); 01678 01679 ReleaseDC(0, screendc); 01680 01681 return Ok; 01682 } 01683 01684 GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, 01685 PixelFormat format, BYTE* scan0, GpBitmap** bitmap) 01686 { 01687 BITMAPINFO* pbmi; 01688 HBITMAP hbitmap=NULL; 01689 INT row_size, dib_stride; 01690 BYTE *bits=NULL, *own_bits=NULL; 01691 REAL xres, yres; 01692 GpStatus stat; 01693 01694 TRACE("%d %d %d 0x%x %p %p\n", width, height, stride, format, scan0, bitmap); 01695 01696 if (!bitmap) return InvalidParameter; 01697 01698 if(width <= 0 || height <= 0 || (scan0 && (stride % 4))){ 01699 *bitmap = NULL; 01700 return InvalidParameter; 01701 } 01702 01703 if(scan0 && !stride) 01704 return InvalidParameter; 01705 01706 stat = get_screen_resolution(&xres, &yres); 01707 if (stat != Ok) return stat; 01708 01709 row_size = (width * PIXELFORMATBPP(format)+7) / 8; 01710 dib_stride = (row_size + 3) & ~3; 01711 01712 if(stride == 0) 01713 stride = dib_stride; 01714 01715 if (format & PixelFormatGDI && !(format & (PixelFormatAlpha|PixelFormatIndexed)) && !scan0) 01716 { 01717 pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); 01718 if (!pbmi) 01719 return OutOfMemory; 01720 01721 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 01722 pbmi->bmiHeader.biWidth = width; 01723 pbmi->bmiHeader.biHeight = -height; 01724 pbmi->bmiHeader.biPlanes = 1; 01725 /* FIXME: use the rest of the data from format */ 01726 pbmi->bmiHeader.biBitCount = PIXELFORMATBPP(format); 01727 pbmi->bmiHeader.biCompression = BI_RGB; 01728 pbmi->bmiHeader.biSizeImage = 0; 01729 pbmi->bmiHeader.biXPelsPerMeter = 0; 01730 pbmi->bmiHeader.biYPelsPerMeter = 0; 01731 pbmi->bmiHeader.biClrUsed = 0; 01732 pbmi->bmiHeader.biClrImportant = 0; 01733 01734 hbitmap = CreateDIBSection(0, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); 01735 01736 GdipFree(pbmi); 01737 01738 if (!hbitmap) return GenericError; 01739 01740 stride = dib_stride; 01741 } 01742 else 01743 { 01744 /* Not a GDI format; don't try to make an HBITMAP. */ 01745 if (scan0) 01746 bits = scan0; 01747 else 01748 { 01749 INT size = abs(stride) * height; 01750 01751 own_bits = bits = GdipAlloc(size); 01752 if (!own_bits) return OutOfMemory; 01753 01754 if (stride < 0) 01755 bits += stride * (1 - height); 01756 } 01757 } 01758 01759 *bitmap = GdipAlloc(sizeof(GpBitmap)); 01760 if(!*bitmap) 01761 { 01762 DeleteObject(hbitmap); 01763 GdipFree(own_bits); 01764 return OutOfMemory; 01765 } 01766 01767 (*bitmap)->image.type = ImageTypeBitmap; 01768 memcpy(&(*bitmap)->image.format, &ImageFormatMemoryBMP, sizeof(GUID)); 01769 (*bitmap)->image.flags = ImageFlagsNone; 01770 (*bitmap)->image.palette_flags = 0; 01771 (*bitmap)->image.palette_count = 0; 01772 (*bitmap)->image.palette_size = 0; 01773 (*bitmap)->image.palette_entries = NULL; 01774 (*bitmap)->image.xres = xres; 01775 (*bitmap)->image.yres = yres; 01776 (*bitmap)->width = width; 01777 (*bitmap)->height = height; 01778 (*bitmap)->format = format; 01779 (*bitmap)->image.picture = NULL; 01780 (*bitmap)->hbitmap = hbitmap; 01781 (*bitmap)->hdc = NULL; 01782 (*bitmap)->bits = bits; 01783 (*bitmap)->stride = stride; 01784 (*bitmap)->own_bits = own_bits; 01785 01786 /* set format-related flags */ 01787 if (format & (PixelFormatAlpha|PixelFormatPAlpha|PixelFormatIndexed)) 01788 (*bitmap)->image.flags |= ImageFlagsHasAlpha; 01789 01790 if (format == PixelFormat1bppIndexed || 01791 format == PixelFormat4bppIndexed || 01792 format == PixelFormat8bppIndexed) 01793 { 01794 (*bitmap)->image.palette_size = (*bitmap)->image.palette_count = 1 << PIXELFORMATBPP(format); 01795 (*bitmap)->image.palette_entries = GdipAlloc(sizeof(ARGB) * ((*bitmap)->image.palette_size)); 01796 01797 if (!(*bitmap)->image.palette_entries) 01798 { 01799 GdipDisposeImage(&(*bitmap)->image); 01800 *bitmap = NULL; 01801 return OutOfMemory; 01802 } 01803 01804 if (format == PixelFormat1bppIndexed) 01805 { 01806 (*bitmap)->image.palette_flags = PaletteFlagsGrayScale; 01807 (*bitmap)->image.palette_entries[0] = 0xff000000; 01808 (*bitmap)->image.palette_entries[1] = 0xffffffff; 01809 } 01810 else 01811 { 01812 if (format == PixelFormat8bppIndexed) 01813 (*bitmap)->image.palette_flags = PaletteFlagsHalftone; 01814 01815 generate_halftone_palette((*bitmap)->image.palette_entries, 01816 (*bitmap)->image.palette_count); 01817 } 01818 } 01819 01820 TRACE("<-- %p\n", *bitmap); 01821 01822 return Ok; 01823 } 01824 01825 GpStatus WINGDIPAPI GdipCreateBitmapFromStream(IStream* stream, 01826 GpBitmap **bitmap) 01827 { 01828 GpStatus stat; 01829 01830 TRACE("%p %p\n", stream, bitmap); 01831 01832 stat = GdipLoadImageFromStream(stream, (GpImage**) bitmap); 01833 01834 if(stat != Ok) 01835 return stat; 01836 01837 if((*bitmap)->image.type != ImageTypeBitmap){ 01838 GdipDisposeImage(&(*bitmap)->image); 01839 *bitmap = NULL; 01840 return GenericError; /* FIXME: what error to return? */ 01841 } 01842 01843 return Ok; 01844 } 01845 01846 /* FIXME: no icm */ 01847 GpStatus WINGDIPAPI GdipCreateBitmapFromStreamICM(IStream* stream, 01848 GpBitmap **bitmap) 01849 { 01850 TRACE("%p %p\n", stream, bitmap); 01851 01852 return GdipCreateBitmapFromStream(stream, bitmap); 01853 } 01854 01855 GpStatus WINGDIPAPI GdipCreateCachedBitmap(GpBitmap *bitmap, GpGraphics *graphics, 01856 GpCachedBitmap **cachedbmp) 01857 { 01858 GpStatus stat; 01859 01860 TRACE("%p %p %p\n", bitmap, graphics, cachedbmp); 01861 01862 if(!bitmap || !graphics || !cachedbmp) 01863 return InvalidParameter; 01864 01865 *cachedbmp = GdipAlloc(sizeof(GpCachedBitmap)); 01866 if(!*cachedbmp) 01867 return OutOfMemory; 01868 01869 stat = GdipCloneImage(&(bitmap->image), &(*cachedbmp)->image); 01870 if(stat != Ok){ 01871 GdipFree(*cachedbmp); 01872 return stat; 01873 } 01874 01875 return Ok; 01876 } 01877 01878 GpStatus WINGDIPAPI GdipCreateHICONFromBitmap(GpBitmap *bitmap, HICON *hicon) 01879 { 01880 GpStatus stat; 01881 BitmapData lockeddata; 01882 ULONG andstride, xorstride, bitssize; 01883 LPBYTE andbits, xorbits, androw, xorrow, srcrow; 01884 UINT x, y; 01885 01886 TRACE("(%p, %p)\n", bitmap, hicon); 01887 01888 if (!bitmap || !hicon) 01889 return InvalidParameter; 01890 01891 stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, 01892 PixelFormat32bppPARGB, &lockeddata); 01893 if (stat == Ok) 01894 { 01895 andstride = ((lockeddata.Width+31)/32)*4; 01896 xorstride = lockeddata.Width*4; 01897 bitssize = (andstride + xorstride) * lockeddata.Height; 01898 01899 andbits = GdipAlloc(bitssize); 01900 01901 if (andbits) 01902 { 01903 xorbits = andbits + andstride * lockeddata.Height; 01904 01905 for (y=0; y<lockeddata.Height; y++) 01906 { 01907 srcrow = ((LPBYTE)lockeddata.Scan0) + lockeddata.Stride * y; 01908 01909 androw = andbits + andstride * y; 01910 for (x=0; x<lockeddata.Width; x++) 01911 if (srcrow[3+4*x] >= 128) 01912 androw[x/8] |= 1 << (7-x%8); 01913 01914 xorrow = xorbits + xorstride * y; 01915 memcpy(xorrow, srcrow, xorstride); 01916 } 01917 01918 *hicon = CreateIcon(NULL, lockeddata.Width, lockeddata.Height, 1, 32, 01919 andbits, xorbits); 01920 01921 GdipFree(andbits); 01922 } 01923 else 01924 stat = OutOfMemory; 01925 01926 GdipBitmapUnlockBits(bitmap, &lockeddata); 01927 } 01928 01929 return stat; 01930 } 01931 01932 GpStatus WINGDIPAPI GdipDeleteCachedBitmap(GpCachedBitmap *cachedbmp) 01933 { 01934 TRACE("%p\n", cachedbmp); 01935 01936 if(!cachedbmp) 01937 return InvalidParameter; 01938 01939 GdipDisposeImage(cachedbmp->image); 01940 GdipFree(cachedbmp); 01941 01942 return Ok; 01943 } 01944 01945 GpStatus WINGDIPAPI GdipDrawCachedBitmap(GpGraphics *graphics, 01946 GpCachedBitmap *cachedbmp, INT x, INT y) 01947 { 01948 TRACE("%p %p %d %d\n", graphics, cachedbmp, x, y); 01949 01950 if(!graphics || !cachedbmp) 01951 return InvalidParameter; 01952 01953 return GdipDrawImage(graphics, cachedbmp->image, (REAL)x, (REAL)y); 01954 } 01955 01956 GpStatus WINGDIPAPI GdipEmfToWmfBits(HENHMETAFILE hemf, UINT cbData16, 01957 LPBYTE pData16, INT iMapMode, INT eFlags) 01958 { 01959 FIXME("(%p, %d, %p, %d, %d): stub\n", hemf, cbData16, pData16, iMapMode, eFlags); 01960 return NotImplemented; 01961 } 01962 01963 /* Internal utility function: Replace the image data of dst with that of src, 01964 * and free src. */ 01965 static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette) 01966 { 01967 GdipFree(dst->bitmapbits); 01968 DeleteDC(dst->hdc); 01969 DeleteObject(dst->hbitmap); 01970 01971 if (clobber_palette) 01972 { 01973 GdipFree(dst->image.palette_entries); 01974 dst->image.palette_flags = src->image.palette_flags; 01975 dst->image.palette_count = src->image.palette_count; 01976 dst->image.palette_entries = src->image.palette_entries; 01977 } 01978 else 01979 GdipFree(src->image.palette_entries); 01980 01981 dst->image.xres = src->image.xres; 01982 dst->image.yres = src->image.yres; 01983 dst->width = src->width; 01984 dst->height = src->height; 01985 dst->format = src->format; 01986 dst->hbitmap = src->hbitmap; 01987 dst->hdc = src->hdc; 01988 dst->bits = src->bits; 01989 dst->stride = src->stride; 01990 dst->own_bits = src->own_bits; 01991 01992 GdipFree(src); 01993 } 01994 01995 GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image) 01996 { 01997 TRACE("%p\n", image); 01998 01999 if(!image) 02000 return InvalidParameter; 02001 02002 if (image->type == ImageTypeBitmap) 02003 { 02004 GdipFree(((GpBitmap*)image)->bitmapbits); 02005 GdipFree(((GpBitmap*)image)->own_bits); 02006 DeleteDC(((GpBitmap*)image)->hdc); 02007 DeleteObject(((GpBitmap*)image)->hbitmap); 02008 } 02009 else if (image->type == ImageTypeMetafile) 02010 { 02011 GpMetafile *metafile = (GpMetafile*)image; 02012 GdipFree(metafile->comment_data); 02013 DeleteEnhMetaFile(CloseEnhMetaFile(metafile->record_dc)); 02014 DeleteEnhMetaFile(metafile->hemf); 02015 if (metafile->record_graphics) 02016 { 02017 WARN("metafile closed while recording\n"); 02018 /* not sure what to do here; for now just prevent the graphics from functioning or using this object */ 02019 metafile->record_graphics->image = NULL; 02020 metafile->record_graphics->busy = TRUE; 02021 } 02022 } 02023 else 02024 { 02025 WARN("invalid image: %p\n", image); 02026 return ObjectBusy; 02027 } 02028 if (image->picture) 02029 IPicture_Release(image->picture); 02030 GdipFree(image->palette_entries); 02031 image->type = ~0; 02032 GdipFree(image); 02033 02034 return Ok; 02035 } 02036 02037 GpStatus WINGDIPAPI GdipFindFirstImageItem(GpImage *image, ImageItemData* item) 02038 { 02039 static int calls; 02040 02041 TRACE("(%p,%p)\n", image, item); 02042 02043 if(!image || !item) 02044 return InvalidParameter; 02045 02046 if (!(calls++)) 02047 FIXME("not implemented\n"); 02048 02049 return NotImplemented; 02050 } 02051 02052 GpStatus WINGDIPAPI GdipGetImageItemData(GpImage *image, ImageItemData *item) 02053 { 02054 static int calls; 02055 02056 TRACE("(%p,%p)\n", image, item); 02057 02058 if (!(calls++)) 02059 FIXME("not implemented\n"); 02060 02061 return NotImplemented; 02062 } 02063 02064 GpStatus WINGDIPAPI GdipGetImageBounds(GpImage *image, GpRectF *srcRect, 02065 GpUnit *srcUnit) 02066 { 02067 TRACE("%p %p %p\n", image, srcRect, srcUnit); 02068 02069 if(!image || !srcRect || !srcUnit) 02070 return InvalidParameter; 02071 if(image->type == ImageTypeMetafile){ 02072 *srcRect = ((GpMetafile*)image)->bounds; 02073 *srcUnit = ((GpMetafile*)image)->unit; 02074 } 02075 else if(image->type == ImageTypeBitmap){ 02076 srcRect->X = srcRect->Y = 0.0; 02077 srcRect->Width = (REAL) ((GpBitmap*)image)->width; 02078 srcRect->Height = (REAL) ((GpBitmap*)image)->height; 02079 *srcUnit = UnitPixel; 02080 } 02081 else{ 02082 srcRect->X = srcRect->Y = 0.0; 02083 srcRect->Width = ipicture_pixel_width(image->picture); 02084 srcRect->Height = ipicture_pixel_height(image->picture); 02085 *srcUnit = UnitPixel; 02086 } 02087 02088 TRACE("returning (%f, %f) (%f, %f) unit type %d\n", srcRect->X, srcRect->Y, 02089 srcRect->Width, srcRect->Height, *srcUnit); 02090 02091 return Ok; 02092 } 02093 02094 GpStatus WINGDIPAPI GdipGetImageDimension(GpImage *image, REAL *width, 02095 REAL *height) 02096 { 02097 TRACE("%p %p %p\n", image, width, height); 02098 02099 if(!image || !height || !width) 02100 return InvalidParameter; 02101 02102 if(image->type == ImageTypeMetafile){ 02103 HDC hdc = GetDC(0); 02104 REAL res = (REAL)GetDeviceCaps(hdc, LOGPIXELSX); 02105 02106 ReleaseDC(0, hdc); 02107 02108 *height = convert_unit(res, ((GpMetafile*)image)->unit) * 02109 ((GpMetafile*)image)->bounds.Height; 02110 02111 *width = convert_unit(res, ((GpMetafile*)image)->unit) * 02112 ((GpMetafile*)image)->bounds.Width; 02113 } 02114 02115 else if(image->type == ImageTypeBitmap){ 02116 *height = ((GpBitmap*)image)->height; 02117 *width = ((GpBitmap*)image)->width; 02118 } 02119 else{ 02120 *height = ipicture_pixel_height(image->picture); 02121 *width = ipicture_pixel_width(image->picture); 02122 } 02123 02124 TRACE("returning (%f, %f)\n", *height, *width); 02125 return Ok; 02126 } 02127 02128 GpStatus WINGDIPAPI GdipGetImageGraphicsContext(GpImage *image, 02129 GpGraphics **graphics) 02130 { 02131 HDC hdc; 02132 GpStatus stat; 02133 02134 TRACE("%p %p\n", image, graphics); 02135 02136 if(!image || !graphics) 02137 return InvalidParameter; 02138 02139 if (image->type == ImageTypeBitmap && ((GpBitmap*)image)->hbitmap) 02140 { 02141 hdc = ((GpBitmap*)image)->hdc; 02142 02143 if(!hdc){ 02144 hdc = CreateCompatibleDC(0); 02145 SelectObject(hdc, ((GpBitmap*)image)->hbitmap); 02146 ((GpBitmap*)image)->hdc = hdc; 02147 } 02148 02149 stat = GdipCreateFromHDC(hdc, graphics); 02150 02151 if (stat == Ok) 02152 (*graphics)->image = image; 02153 } 02154 else if (image->type == ImageTypeMetafile) 02155 stat = METAFILE_GetGraphicsContext((GpMetafile*)image, graphics); 02156 else 02157 stat = graphics_from_image(image, graphics); 02158 02159 return stat; 02160 } 02161 02162 GpStatus WINGDIPAPI GdipGetImageHeight(GpImage *image, UINT *height) 02163 { 02164 TRACE("%p %p\n", image, height); 02165 02166 if(!image || !height) 02167 return InvalidParameter; 02168 02169 if(image->type == ImageTypeMetafile){ 02170 HDC hdc = GetDC(0); 02171 REAL res = (REAL)GetDeviceCaps(hdc, LOGPIXELSX); 02172 02173 ReleaseDC(0, hdc); 02174 02175 *height = roundr(convert_unit(res, ((GpMetafile*)image)->unit) * 02176 ((GpMetafile*)image)->bounds.Height); 02177 } 02178 else if(image->type == ImageTypeBitmap) 02179 *height = ((GpBitmap*)image)->height; 02180 else 02181 *height = ipicture_pixel_height(image->picture); 02182 02183 TRACE("returning %d\n", *height); 02184 02185 return Ok; 02186 } 02187 02188 GpStatus WINGDIPAPI GdipGetImageHorizontalResolution(GpImage *image, REAL *res) 02189 { 02190 if(!image || !res) 02191 return InvalidParameter; 02192 02193 *res = image->xres; 02194 02195 TRACE("(%p) <-- %0.2f\n", image, *res); 02196 02197 return Ok; 02198 } 02199 02200 GpStatus WINGDIPAPI GdipGetImagePaletteSize(GpImage *image, INT *size) 02201 { 02202 TRACE("%p %p\n", image, size); 02203 02204 if(!image || !size) 02205 return InvalidParameter; 02206 02207 if (image->palette_count == 0) 02208 *size = sizeof(ColorPalette); 02209 else 02210 *size = sizeof(UINT)*2 + sizeof(ARGB)*image->palette_count; 02211 02212 TRACE("<-- %u\n", *size); 02213 02214 return Ok; 02215 } 02216 02217 /* FIXME: test this function for non-bitmap types */ 02218 GpStatus WINGDIPAPI GdipGetImagePixelFormat(GpImage *image, PixelFormat *format) 02219 { 02220 TRACE("%p %p\n", image, format); 02221 02222 if(!image || !format) 02223 return InvalidParameter; 02224 02225 if(image->type != ImageTypeBitmap) 02226 *format = PixelFormat24bppRGB; 02227 else 02228 *format = ((GpBitmap*) image)->format; 02229 02230 return Ok; 02231 } 02232 02233 GpStatus WINGDIPAPI GdipGetImageRawFormat(GpImage *image, GUID *format) 02234 { 02235 TRACE("(%p, %p)\n", image, format); 02236 02237 if(!image || !format) 02238 return InvalidParameter; 02239 02240 memcpy(format, &image->format, sizeof(GUID)); 02241 02242 return Ok; 02243 } 02244 02245 GpStatus WINGDIPAPI GdipGetImageType(GpImage *image, ImageType *type) 02246 { 02247 TRACE("%p %p\n", image, type); 02248 02249 if(!image || !type) 02250 return InvalidParameter; 02251 02252 *type = image->type; 02253 02254 return Ok; 02255 } 02256 02257 GpStatus WINGDIPAPI GdipGetImageVerticalResolution(GpImage *image, REAL *res) 02258 { 02259 if(!image || !res) 02260 return InvalidParameter; 02261 02262 *res = image->yres; 02263 02264 TRACE("(%p) <-- %0.2f\n", image, *res); 02265 02266 return Ok; 02267 } 02268 02269 GpStatus WINGDIPAPI GdipGetImageWidth(GpImage *image, UINT *width) 02270 { 02271 TRACE("%p %p\n", image, width); 02272 02273 if(!image || !width) 02274 return InvalidParameter; 02275 02276 if(image->type == ImageTypeMetafile){ 02277 HDC hdc = GetDC(0); 02278 REAL res = (REAL)GetDeviceCaps(hdc, LOGPIXELSX); 02279 02280 ReleaseDC(0, hdc); 02281 02282 *width = roundr(convert_unit(res, ((GpMetafile*)image)->unit) * 02283 ((GpMetafile*)image)->bounds.Width); 02284 } 02285 else if(image->type == ImageTypeBitmap) 02286 *width = ((GpBitmap*)image)->width; 02287 else 02288 *width = ipicture_pixel_width(image->picture); 02289 02290 TRACE("returning %d\n", *width); 02291 02292 return Ok; 02293 } 02294 02295 GpStatus WINGDIPAPI GdipGetMetafileHeaderFromMetafile(GpMetafile * metafile, 02296 MetafileHeader * header) 02297 { 02298 static int calls; 02299 02300 TRACE("(%p, %p)\n", metafile, header); 02301 02302 if(!metafile || !header) 02303 return InvalidParameter; 02304 02305 if(!(calls++)) 02306 FIXME("not implemented\n"); 02307 02308 memset(header, 0, sizeof(MetafileHeader)); 02309 02310 return Ok; 02311 } 02312 02313 GpStatus WINGDIPAPI GdipGetMetafileHeaderFromEmf(HENHMETAFILE hEmf, 02314 MetafileHeader *header) 02315 { 02316 static int calls; 02317 02318 if(!hEmf || !header) 02319 return InvalidParameter; 02320 02321 if(!(calls++)) 02322 FIXME("not implemented\n"); 02323 02324 memset(header, 0, sizeof(MetafileHeader)); 02325 02326 return Ok; 02327 } 02328 02329 GpStatus WINGDIPAPI GdipGetMetafileHeaderFromFile(GDIPCONST WCHAR *filename, 02330 MetafileHeader *header) 02331 { 02332 static int calls; 02333 02334 TRACE("(%s,%p)\n", debugstr_w(filename), header); 02335 02336 if(!filename || !header) 02337 return InvalidParameter; 02338 02339 if(!(calls++)) 02340 FIXME("not implemented\n"); 02341 02342 memset(header, 0, sizeof(MetafileHeader)); 02343 02344 return Ok; 02345 } 02346 02347 GpStatus WINGDIPAPI GdipGetMetafileHeaderFromStream(IStream *stream, 02348 MetafileHeader *header) 02349 { 02350 static int calls; 02351 02352 TRACE("(%p,%p)\n", stream, header); 02353 02354 if(!stream || !header) 02355 return InvalidParameter; 02356 02357 if(!(calls++)) 02358 FIXME("not implemented\n"); 02359 02360 memset(header, 0, sizeof(MetafileHeader)); 02361 02362 return Ok; 02363 } 02364 02365 GpStatus WINGDIPAPI GdipGetAllPropertyItems(GpImage *image, UINT size, 02366 UINT num, PropertyItem* items) 02367 { 02368 static int calls; 02369 02370 TRACE("(%p, %u, %u, %p)\n", image, size, num, items); 02371 02372 if(!(calls++)) 02373 FIXME("not implemented\n"); 02374 02375 return InvalidParameter; 02376 } 02377 02378 GpStatus WINGDIPAPI GdipGetPropertyCount(GpImage *image, UINT* num) 02379 { 02380 static int calls; 02381 02382 TRACE("(%p, %p)\n", image, num); 02383 02384 if(!(calls++)) 02385 FIXME("not implemented\n"); 02386 02387 *num = 0; 02388 return Ok; 02389 } 02390 02391 GpStatus WINGDIPAPI GdipGetPropertyIdList(GpImage *image, UINT num, PROPID* list) 02392 { 02393 static int calls; 02394 02395 TRACE("(%p, %u, %p)\n", image, num, list); 02396 02397 if(!(calls++)) 02398 FIXME("not implemented\n"); 02399 02400 return InvalidParameter; 02401 } 02402 02403 GpStatus WINGDIPAPI GdipGetPropertyItem(GpImage *image, PROPID id, UINT size, 02404 PropertyItem* buffer) 02405 { 02406 static int calls; 02407 02408 TRACE("(%p, %u, %u, %p)\n", image, id, size, buffer); 02409 02410 if(!(calls++)) 02411 FIXME("not implemented\n"); 02412 02413 return InvalidParameter; 02414 } 02415 02416 GpStatus WINGDIPAPI GdipGetPropertyItemSize(GpImage *image, PROPID pid, 02417 UINT* size) 02418 { 02419 static int calls; 02420 02421 TRACE("%p %x %p\n", image, pid, size); 02422 02423 if(!size || !image) 02424 return InvalidParameter; 02425 02426 if(!(calls++)) 02427 FIXME("not implemented\n"); 02428 02429 return NotImplemented; 02430 } 02431 02432 GpStatus WINGDIPAPI GdipGetPropertySize(GpImage *image, UINT* size, UINT* num) 02433 { 02434 static int calls; 02435 02436 TRACE("(%p,%p,%p)\n", image, size, num); 02437 02438 if(!(calls++)) 02439 FIXME("not implemented\n"); 02440 02441 return InvalidParameter; 02442 } 02443 02444 struct image_format_dimension 02445 { 02446 const GUID *format; 02447 const GUID *dimension; 02448 }; 02449 02450 static struct image_format_dimension image_format_dimensions[] = 02451 { 02452 {&ImageFormatGIF, &FrameDimensionTime}, 02453 {&ImageFormatIcon, &FrameDimensionResolution}, 02454 {NULL} 02455 }; 02456 02457 /* FIXME: Need to handle multi-framed images */ 02458 GpStatus WINGDIPAPI GdipImageGetFrameCount(GpImage *image, 02459 GDIPCONST GUID* dimensionID, UINT* count) 02460 { 02461 static int calls; 02462 02463 TRACE("(%p,%s,%p)\n", image, debugstr_guid(dimensionID), count); 02464 02465 if(!image || !count) 02466 return InvalidParameter; 02467 02468 if(!(calls++)) 02469 FIXME("returning frame count of 1\n"); 02470 02471 *count = 1; 02472 02473 return Ok; 02474 } 02475 02476 GpStatus WINGDIPAPI GdipImageGetFrameDimensionsCount(GpImage *image, 02477 UINT* count) 02478 { 02479 TRACE("(%p, %p)\n", image, count); 02480 02481 /* Native gdiplus 1.1 does not yet support multiple frame dimensions. */ 02482 02483 if(!image || !count) 02484 return InvalidParameter; 02485 02486 *count = 1; 02487 02488 return Ok; 02489 } 02490 02491 GpStatus WINGDIPAPI GdipImageGetFrameDimensionsList(GpImage* image, 02492 GUID* dimensionIDs, UINT count) 02493 { 02494 int i; 02495 const GUID *result=NULL; 02496 02497 TRACE("(%p,%p,%u)\n", image, dimensionIDs, count); 02498 02499 if(!image || !dimensionIDs || count != 1) 02500 return InvalidParameter; 02501 02502 for (i=0; image_format_dimensions[i].format; i++) 02503 { 02504 if (IsEqualGUID(&image->format, image_format_dimensions[i].format)) 02505 { 02506 result = image_format_dimensions[i].dimension; 02507 break; 02508 } 02509 } 02510 02511 if (!result) 02512 result = &FrameDimensionPage; 02513 02514 memcpy(dimensionIDs, result, sizeof(GUID)); 02515 02516 return Ok; 02517 } 02518 02519 GpStatus WINGDIPAPI GdipImageSelectActiveFrame(GpImage *image, 02520 GDIPCONST GUID* dimensionID, UINT frameidx) 02521 { 02522 static int calls; 02523 02524 TRACE("(%p, %s, %u)\n", image, debugstr_guid(dimensionID), frameidx); 02525 02526 if(!image || !dimensionID) 02527 return InvalidParameter; 02528 02529 if(!(calls++)) 02530 FIXME("not implemented\n"); 02531 02532 return Ok; 02533 } 02534 02535 GpStatus WINGDIPAPI GdipLoadImageFromFile(GDIPCONST WCHAR* filename, 02536 GpImage **image) 02537 { 02538 GpStatus stat; 02539 IStream *stream; 02540 02541 TRACE("(%s) %p\n", debugstr_w(filename), image); 02542 02543 if (!filename || !image) 02544 return InvalidParameter; 02545 02546 stat = GdipCreateStreamOnFile(filename, GENERIC_READ, &stream); 02547 02548 if (stat != Ok) 02549 return stat; 02550 02551 stat = GdipLoadImageFromStream(stream, image); 02552 02553 IStream_Release(stream); 02554 02555 return stat; 02556 } 02557 02558 /* FIXME: no icm handling */ 02559 GpStatus WINGDIPAPI GdipLoadImageFromFileICM(GDIPCONST WCHAR* filename,GpImage **image) 02560 { 02561 TRACE("(%s) %p\n", debugstr_w(filename), image); 02562 02563 return GdipLoadImageFromFile(filename, image); 02564 } 02565 02566 static const WICPixelFormatGUID *wic_pixel_formats[] = { 02567 &GUID_WICPixelFormat16bppBGR555, 02568 &GUID_WICPixelFormat24bppBGR, 02569 &GUID_WICPixelFormat32bppBGR, 02570 &GUID_WICPixelFormat32bppBGRA, 02571 &GUID_WICPixelFormat32bppPBGRA, 02572 NULL 02573 }; 02574 02575 static const PixelFormat wic_gdip_formats[] = { 02576 PixelFormat16bppRGB555, 02577 PixelFormat24bppRGB, 02578 PixelFormat32bppRGB, 02579 PixelFormat32bppARGB, 02580 PixelFormat32bppPARGB, 02581 }; 02582 02583 static GpStatus decode_image_wic(IStream* stream, REFCLSID clsid, GpImage **image) 02584 { 02585 GpStatus status=Ok; 02586 GpBitmap *bitmap; 02587 HRESULT hr; 02588 IWICBitmapDecoder *decoder; 02589 IWICBitmapFrameDecode *frame; 02590 IWICBitmapSource *source=NULL; 02591 WICPixelFormatGUID wic_format; 02592 PixelFormat gdip_format=0; 02593 int i; 02594 UINT width, height; 02595 BitmapData lockeddata; 02596 WICRect wrc; 02597 HRESULT initresult; 02598 02599 initresult = CoInitialize(NULL); 02600 02601 hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, 02602 &IID_IWICBitmapDecoder, (void**)&decoder); 02603 if (FAILED(hr)) goto end; 02604 02605 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad); 02606 if (SUCCEEDED(hr)) 02607 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); 02608 02609 if (SUCCEEDED(hr)) /* got frame */ 02610 { 02611 hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &wic_format); 02612 02613 if (SUCCEEDED(hr)) 02614 { 02615 for (i=0; wic_pixel_formats[i]; i++) 02616 { 02617 if (IsEqualGUID(&wic_format, wic_pixel_formats[i])) 02618 { 02619 source = (IWICBitmapSource*)frame; 02620 IWICBitmapSource_AddRef(source); 02621 gdip_format = wic_gdip_formats[i]; 02622 break; 02623 } 02624 } 02625 if (!source) 02626 { 02627 /* unknown format; fall back on 32bppARGB */ 02628 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, (IWICBitmapSource*)frame, &source); 02629 gdip_format = PixelFormat32bppARGB; 02630 } 02631 } 02632 02633 if (SUCCEEDED(hr)) /* got source */ 02634 { 02635 hr = IWICBitmapSource_GetSize(source, &width, &height); 02636 02637 if (SUCCEEDED(hr)) 02638 status = GdipCreateBitmapFromScan0(width, height, 0, gdip_format, 02639 NULL, &bitmap); 02640 02641 if (SUCCEEDED(hr) && status == Ok) /* created bitmap */ 02642 { 02643 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeWrite, 02644 gdip_format, &lockeddata); 02645 if (status == Ok) /* locked bitmap */ 02646 { 02647 wrc.X = 0; 02648 wrc.Width = width; 02649 wrc.Height = 1; 02650 for (i=0; i<height; i++) 02651 { 02652 wrc.Y = i; 02653 hr = IWICBitmapSource_CopyPixels(source, &wrc, abs(lockeddata.Stride), 02654 abs(lockeddata.Stride), (BYTE*)lockeddata.Scan0+lockeddata.Stride*i); 02655 if (FAILED(hr)) break; 02656 } 02657 02658 GdipBitmapUnlockBits(bitmap, &lockeddata); 02659 } 02660 02661 if (SUCCEEDED(hr) && status == Ok) 02662 *image = (GpImage*)bitmap; 02663 else 02664 { 02665 *image = NULL; 02666 GdipDisposeImage((GpImage*)bitmap); 02667 } 02668 02669 if (SUCCEEDED(hr) && status == Ok) 02670 { 02671 double dpix, dpiy; 02672 hr = IWICBitmapSource_GetResolution(source, &dpix, &dpiy); 02673 if (SUCCEEDED(hr)) 02674 { 02675 bitmap->image.xres = dpix; 02676 bitmap->image.yres = dpiy; 02677 } 02678 hr = S_OK; 02679 } 02680 } 02681 02682 IWICBitmapSource_Release(source); 02683 } 02684 02685 IWICBitmapFrameDecode_Release(frame); 02686 } 02687 02688 IWICBitmapDecoder_Release(decoder); 02689 02690 end: 02691 if (SUCCEEDED(initresult)) CoUninitialize(); 02692 02693 if (FAILED(hr) && status == Ok) status = hresult_to_status(hr); 02694 02695 if (status == Ok) 02696 { 02697 /* Native GDI+ used to be smarter, but since Win7 it just sets these flags. */ 02698 bitmap->image.flags |= ImageFlagsReadOnly|ImageFlagsHasRealPixelSize|ImageFlagsHasRealDPI|ImageFlagsColorSpaceRGB; 02699 } 02700 02701 return status; 02702 } 02703 02704 static GpStatus decode_image_icon(IStream* stream, REFCLSID clsid, GpImage **image) 02705 { 02706 return decode_image_wic(stream, &CLSID_WICIcoDecoder, image); 02707 } 02708 02709 static GpStatus decode_image_bmp(IStream* stream, REFCLSID clsid, GpImage **image) 02710 { 02711 GpStatus status; 02712 GpBitmap* bitmap; 02713 02714 status = decode_image_wic(stream, &CLSID_WICBmpDecoder, image); 02715 02716 bitmap = (GpBitmap*)*image; 02717 02718 if (status == Ok && bitmap->format == PixelFormat32bppARGB) 02719 { 02720 /* WIC supports bmp files with alpha, but gdiplus does not */ 02721 bitmap->format = PixelFormat32bppRGB; 02722 } 02723 02724 return status; 02725 } 02726 02727 static GpStatus decode_image_jpeg(IStream* stream, REFCLSID clsid, GpImage **image) 02728 { 02729 return decode_image_wic(stream, &CLSID_WICJpegDecoder, image); 02730 } 02731 02732 static GpStatus decode_image_png(IStream* stream, REFCLSID clsid, GpImage **image) 02733 { 02734 return decode_image_wic(stream, &CLSID_WICPngDecoder, image); 02735 } 02736 02737 static GpStatus decode_image_gif(IStream* stream, REFCLSID clsid, GpImage **image) 02738 { 02739 return decode_image_wic(stream, &CLSID_WICGifDecoder, image); 02740 } 02741 02742 static GpStatus decode_image_tiff(IStream* stream, REFCLSID clsid, GpImage **image) 02743 { 02744 return decode_image_wic(stream, &CLSID_WICTiffDecoder, image); 02745 } 02746 02747 static GpStatus decode_image_olepicture_metafile(IStream* stream, REFCLSID clsid, GpImage **image) 02748 { 02749 IPicture *pic; 02750 02751 TRACE("%p %p\n", stream, image); 02752 02753 if(!stream || !image) 02754 return InvalidParameter; 02755 02756 if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture, 02757 (LPVOID*) &pic) != S_OK){ 02758 TRACE("Could not load picture\n"); 02759 return GenericError; 02760 } 02761 02762 /* FIXME: missing initialization code */ 02763 *image = GdipAlloc(sizeof(GpMetafile)); 02764 if(!*image) return OutOfMemory; 02765 (*image)->type = ImageTypeMetafile; 02766 (*image)->picture = pic; 02767 (*image)->flags = ImageFlagsNone; 02768 (*image)->palette_flags = 0; 02769 (*image)->palette_count = 0; 02770 (*image)->palette_size = 0; 02771 (*image)->palette_entries = NULL; 02772 02773 TRACE("<-- %p\n", *image); 02774 02775 return Ok; 02776 } 02777 02778 typedef GpStatus (*encode_image_func)(GpImage *image, IStream* stream, 02779 GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params); 02780 02781 typedef GpStatus (*decode_image_func)(IStream *stream, REFCLSID clsid, GpImage** image); 02782 02783 typedef struct image_codec { 02784 ImageCodecInfo info; 02785 encode_image_func encode_func; 02786 decode_image_func decode_func; 02787 } image_codec; 02788 02789 typedef enum { 02790 BMP, 02791 JPEG, 02792 GIF, 02793 TIFF, 02794 EMF, 02795 WMF, 02796 PNG, 02797 ICO, 02798 NUM_CODECS 02799 } ImageFormat; 02800 02801 static const struct image_codec codecs[NUM_CODECS]; 02802 02803 static GpStatus get_decoder_info(IStream* stream, const struct image_codec **result) 02804 { 02805 BYTE signature[8]; 02806 const BYTE *pattern, *mask; 02807 LARGE_INTEGER seek; 02808 HRESULT hr; 02809 UINT bytesread; 02810 int i, j, sig; 02811 02812 /* seek to the start of the stream */ 02813 seek.QuadPart = 0; 02814 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL); 02815 if (FAILED(hr)) return hresult_to_status(hr); 02816 02817 /* read the first 8 bytes */ 02818 /* FIXME: This assumes all codecs have signatures <= 8 bytes in length */ 02819 hr = IStream_Read(stream, signature, 8, &bytesread); 02820 if (FAILED(hr)) return hresult_to_status(hr); 02821 if (hr == S_FALSE || bytesread == 0) return GenericError; 02822 02823 for (i = 0; i < NUM_CODECS; i++) { 02824 if ((codecs[i].info.Flags & ImageCodecFlagsDecoder) && 02825 bytesread >= codecs[i].info.SigSize) 02826 { 02827 for (sig=0; sig<codecs[i].info.SigCount; sig++) 02828 { 02829 pattern = &codecs[i].info.SigPattern[codecs[i].info.SigSize*sig]; 02830 mask = &codecs[i].info.SigMask[codecs[i].info.SigSize*sig]; 02831 for (j=0; j<codecs[i].info.SigSize; j++) 02832 if ((signature[j] & mask[j]) != pattern[j]) 02833 break; 02834 if (j == codecs[i].info.SigSize) 02835 { 02836 *result = &codecs[i]; 02837 return Ok; 02838 } 02839 } 02840 } 02841 } 02842 02843 TRACE("no match for %i byte signature %x %x %x %x %x %x %x %x\n", bytesread, 02844 signature[0],signature[1],signature[2],signature[3], 02845 signature[4],signature[5],signature[6],signature[7]); 02846 02847 return GenericError; 02848 } 02849 02850 GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream* stream, GpImage **image) 02851 { 02852 GpStatus stat; 02853 LARGE_INTEGER seek; 02854 HRESULT hr; 02855 const struct image_codec *codec=NULL; 02856 02857 /* choose an appropriate image decoder */ 02858 stat = get_decoder_info(stream, &codec); 02859 if (stat != Ok) return stat; 02860 02861 /* seek to the start of the stream */ 02862 seek.QuadPart = 0; 02863 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL); 02864 if (FAILED(hr)) return hresult_to_status(hr); 02865 02866 /* call on the image decoder to do the real work */ 02867 stat = codec->decode_func(stream, &codec->info.Clsid, image); 02868 02869 /* take note of the original data format */ 02870 if (stat == Ok) 02871 { 02872 memcpy(&(*image)->format, &codec->info.FormatID, sizeof(GUID)); 02873 } 02874 02875 return stat; 02876 } 02877 02878 /* FIXME: no ICM */ 02879 GpStatus WINGDIPAPI GdipLoadImageFromStreamICM(IStream* stream, GpImage **image) 02880 { 02881 TRACE("%p %p\n", stream, image); 02882 02883 return GdipLoadImageFromStream(stream, image); 02884 } 02885 02886 GpStatus WINGDIPAPI GdipRemovePropertyItem(GpImage *image, PROPID propId) 02887 { 02888 static int calls; 02889 02890 TRACE("(%p,%u)\n", image, propId); 02891 02892 if(!image) 02893 return InvalidParameter; 02894 02895 if(!(calls++)) 02896 FIXME("not implemented\n"); 02897 02898 return NotImplemented; 02899 } 02900 02901 GpStatus WINGDIPAPI GdipSetPropertyItem(GpImage *image, GDIPCONST PropertyItem* item) 02902 { 02903 static int calls; 02904 02905 TRACE("(%p,%p)\n", image, item); 02906 02907 if(!(calls++)) 02908 FIXME("not implemented\n"); 02909 02910 return NotImplemented; 02911 } 02912 02913 GpStatus WINGDIPAPI GdipSaveImageToFile(GpImage *image, GDIPCONST WCHAR* filename, 02914 GDIPCONST CLSID *clsidEncoder, 02915 GDIPCONST EncoderParameters *encoderParams) 02916 { 02917 GpStatus stat; 02918 IStream *stream; 02919 02920 TRACE("%p (%s) %p %p\n", image, debugstr_w(filename), clsidEncoder, encoderParams); 02921 02922 if (!image || !filename|| !clsidEncoder) 02923 return InvalidParameter; 02924 02925 stat = GdipCreateStreamOnFile(filename, GENERIC_WRITE, &stream); 02926 if (stat != Ok) 02927 return GenericError; 02928 02929 stat = GdipSaveImageToStream(image, stream, clsidEncoder, encoderParams); 02930 02931 IStream_Release(stream); 02932 return stat; 02933 } 02934 02935 /************************************************************************* 02936 * Encoding functions - 02937 * These functions encode an image in different image file formats. 02938 */ 02939 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */ 02940 #define BITMAP_FORMAT_JPEG 0xd8ff 02941 #define BITMAP_FORMAT_GIF 0x4947 02942 #define BITMAP_FORMAT_PNG 0x5089 02943 #define BITMAP_FORMAT_APM 0xcdd7 02944 02945 static GpStatus encode_image_WIC(GpImage *image, IStream* stream, 02946 GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) 02947 { 02948 GpStatus stat; 02949 GpBitmap *bitmap; 02950 IWICBitmapEncoder *encoder; 02951 IWICBitmapFrameEncode *frameencode; 02952 IPropertyBag2 *encoderoptions; 02953 HRESULT hr; 02954 UINT width, height; 02955 PixelFormat gdipformat=0; 02956 WICPixelFormatGUID wicformat; 02957 GpRect rc; 02958 BitmapData lockeddata; 02959 HRESULT initresult; 02960 UINT i; 02961 02962 if (image->type != ImageTypeBitmap) 02963 return GenericError; 02964 02965 bitmap = (GpBitmap*)image; 02966 02967 GdipGetImageWidth(image, &width); 02968 GdipGetImageHeight(image, &height); 02969 02970 rc.X = 0; 02971 rc.Y = 0; 02972 rc.Width = width; 02973 rc.Height = height; 02974 02975 initresult = CoInitialize(NULL); 02976 02977 hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, 02978 &IID_IWICBitmapEncoder, (void**)&encoder); 02979 if (FAILED(hr)) 02980 { 02981 if (SUCCEEDED(initresult)) CoUninitialize(); 02982 return hresult_to_status(hr); 02983 } 02984 02985 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache); 02986 02987 if (SUCCEEDED(hr)) 02988 { 02989 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &encoderoptions); 02990 } 02991 02992 if (SUCCEEDED(hr)) /* created frame */ 02993 { 02994 hr = IWICBitmapFrameEncode_Initialize(frameencode, encoderoptions); 02995 02996 if (SUCCEEDED(hr)) 02997 hr = IWICBitmapFrameEncode_SetSize(frameencode, width, height); 02998 02999 if (SUCCEEDED(hr)) 03000 /* FIXME: use the resolution from the image */ 03001 hr = IWICBitmapFrameEncode_SetResolution(frameencode, 96.0, 96.0); 03002 03003 if (SUCCEEDED(hr)) 03004 { 03005 for (i=0; wic_pixel_formats[i]; i++) 03006 { 03007 if (wic_gdip_formats[i] == bitmap->format) 03008 break; 03009 } 03010 if (wic_pixel_formats[i]) 03011 memcpy(&wicformat, wic_pixel_formats[i], sizeof(GUID)); 03012 else 03013 memcpy(&wicformat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID)); 03014 03015 hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &wicformat); 03016 03017 for (i=0; wic_pixel_formats[i]; i++) 03018 { 03019 if (IsEqualGUID(&wicformat, wic_pixel_formats[i])) 03020 break; 03021 } 03022 if (wic_pixel_formats[i]) 03023 gdipformat = wic_gdip_formats[i]; 03024 else 03025 { 03026 ERR("cannot provide pixel format %s\n", debugstr_guid(&wicformat)); 03027 hr = E_FAIL; 03028 } 03029 } 03030 03031 if (SUCCEEDED(hr)) 03032 { 03033 stat = GdipBitmapLockBits(bitmap, &rc, ImageLockModeRead, gdipformat, 03034 &lockeddata); 03035 03036 if (stat == Ok) 03037 { 03038 UINT row_size = (lockeddata.Width * PIXELFORMATBPP(gdipformat) + 7)/8; 03039 BYTE *row; 03040 03041 /* write one row at a time in case stride is negative */ 03042 row = lockeddata.Scan0; 03043 for (i=0; i<lockeddata.Height; i++) 03044 { 03045 hr = IWICBitmapFrameEncode_WritePixels(frameencode, 1, row_size, row_size, row); 03046 if (FAILED(hr)) break; 03047 row += lockeddata.Stride; 03048 } 03049 03050 GdipBitmapUnlockBits(bitmap, &lockeddata); 03051 } 03052 else 03053 hr = E_FAIL; 03054 } 03055 03056 if (SUCCEEDED(hr)) 03057 hr = IWICBitmapFrameEncode_Commit(frameencode); 03058 03059 IWICBitmapFrameEncode_Release(frameencode); 03060 IPropertyBag2_Release(encoderoptions); 03061 } 03062 03063 if (SUCCEEDED(hr)) 03064 hr = IWICBitmapEncoder_Commit(encoder); 03065 03066 IWICBitmapEncoder_Release(encoder); 03067 03068 if (SUCCEEDED(initresult)) CoUninitialize(); 03069 03070 return hresult_to_status(hr); 03071 } 03072 03073 static GpStatus encode_image_BMP(GpImage *image, IStream* stream, 03074 GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) 03075 { 03076 return encode_image_WIC(image, stream, &CLSID_WICBmpEncoder, params); 03077 } 03078 03079 static GpStatus encode_image_tiff(GpImage *image, IStream* stream, 03080 GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) 03081 { 03082 return encode_image_WIC(image, stream, &CLSID_WICTiffEncoder, params); 03083 } 03084 03085 static GpStatus encode_image_png(GpImage *image, IStream* stream, 03086 GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) 03087 { 03088 return encode_image_WIC(image, stream, &CLSID_WICPngEncoder, params); 03089 } 03090 03091 static GpStatus encode_image_jpeg(GpImage *image, IStream* stream, 03092 GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) 03093 { 03094 return encode_image_WIC(image, stream, &CLSID_WICJpegEncoder, params); 03095 } 03096 03097 /***************************************************************************** 03098 * GdipSaveImageToStream [GDIPLUS.@] 03099 */ 03100 GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream, 03101 GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) 03102 { 03103 GpStatus stat; 03104 encode_image_func encode_image; 03105 int i; 03106 03107 TRACE("%p %p %p %p\n", image, stream, clsid, params); 03108 03109 if(!image || !stream) 03110 return InvalidParameter; 03111 03112 /* select correct encoder */ 03113 encode_image = NULL; 03114 for (i = 0; i < NUM_CODECS; i++) { 03115 if ((codecs[i].info.Flags & ImageCodecFlagsEncoder) && 03116 IsEqualCLSID(clsid, &codecs[i].info.Clsid)) 03117 encode_image = codecs[i].encode_func; 03118 } 03119 if (encode_image == NULL) 03120 return UnknownImageFormat; 03121 03122 stat = encode_image(image, stream, clsid, params); 03123 03124 return stat; 03125 } 03126 03127 /***************************************************************************** 03128 * GdipGetImagePalette [GDIPLUS.@] 03129 */ 03130 GpStatus WINGDIPAPI GdipGetImagePalette(GpImage *image, ColorPalette *palette, INT size) 03131 { 03132 TRACE("(%p,%p,%i)\n", image, palette, size); 03133 03134 if (!image || !palette) 03135 return InvalidParameter; 03136 03137 if (size < (sizeof(UINT)*2+sizeof(ARGB)*image->palette_count)) 03138 { 03139 TRACE("<-- InsufficientBuffer\n"); 03140 return InsufficientBuffer; 03141 } 03142 03143 palette->Flags = image->palette_flags; 03144 palette->Count = image->palette_count; 03145 memcpy(palette->Entries, image->palette_entries, sizeof(ARGB)*image->palette_count); 03146 03147 return Ok; 03148 } 03149 03150 /***************************************************************************** 03151 * GdipSetImagePalette [GDIPLUS.@] 03152 */ 03153 GpStatus WINGDIPAPI GdipSetImagePalette(GpImage *image, 03154 GDIPCONST ColorPalette *palette) 03155 { 03156 TRACE("(%p,%p)\n", image, palette); 03157 03158 if(!image || !palette || palette->Count > 256) 03159 return InvalidParameter; 03160 03161 if (palette->Count > image->palette_size) 03162 { 03163 ARGB *new_palette; 03164 03165 new_palette = GdipAlloc(sizeof(ARGB) * palette->Count); 03166 if (!new_palette) return OutOfMemory; 03167 03168 GdipFree(image->palette_entries); 03169 image->palette_entries = new_palette; 03170 image->palette_size = palette->Count; 03171 } 03172 03173 image->palette_flags = palette->Flags; 03174 image->palette_count = palette->Count; 03175 memcpy(image->palette_entries, palette->Entries, sizeof(ARGB)*palette->Count); 03176 03177 return Ok; 03178 } 03179 03180 /************************************************************************* 03181 * Encoders - 03182 * Structures that represent which formats we support for encoding. 03183 */ 03184 03185 /* ImageCodecInfo creation routines taken from libgdiplus */ 03186 static const WCHAR bmp_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'B', 'M', 'P', 0}; /* Built-in BMP */ 03187 static const WCHAR bmp_extension[] = {'*','.','B', 'M', 'P',';', '*','.', 'D','I', 'B',';', '*','.', 'R', 'L', 'E',0}; /* *.BMP;*.DIB;*.RLE */ 03188 static const WCHAR bmp_mimetype[] = {'i', 'm', 'a','g', 'e', '/', 'b', 'm', 'p', 0}; /* image/bmp */ 03189 static const WCHAR bmp_format[] = {'B', 'M', 'P', 0}; /* BMP */ 03190 static const BYTE bmp_sig_pattern[] = { 0x42, 0x4D }; 03191 static const BYTE bmp_sig_mask[] = { 0xFF, 0xFF }; 03192 03193 static const WCHAR jpeg_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'J','P','E','G', 0}; 03194 static const WCHAR jpeg_extension[] = {'*','.','J','P','G',';', '*','.','J','P','E','G',';', '*','.','J','P','E',';', '*','.','J','F','I','F',0}; 03195 static const WCHAR jpeg_mimetype[] = {'i','m','a','g','e','/','j','p','e','g', 0}; 03196 static const WCHAR jpeg_format[] = {'J','P','E','G',0}; 03197 static const BYTE jpeg_sig_pattern[] = { 0xFF, 0xD8 }; 03198 static const BYTE jpeg_sig_mask[] = { 0xFF, 0xFF }; 03199 03200 static const WCHAR gif_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'G','I','F', 0}; 03201 static const WCHAR gif_extension[] = {'*','.','G','I','F',0}; 03202 static const WCHAR gif_mimetype[] = {'i','m','a','g','e','/','g','i','f', 0}; 03203 static const WCHAR gif_format[] = {'G','I','F',0}; 03204 static const BYTE gif_sig_pattern[4] = "GIF8"; 03205 static const BYTE gif_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF }; 03206 03207 static const WCHAR tiff_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'T','I','F','F', 0}; 03208 static const WCHAR tiff_extension[] = {'*','.','T','I','F','F',';','*','.','T','I','F',0}; 03209 static const WCHAR tiff_mimetype[] = {'i','m','a','g','e','/','t','i','f','f', 0}; 03210 static const WCHAR tiff_format[] = {'T','I','F','F',0}; 03211 static const BYTE tiff_sig_pattern[] = {0x49,0x49,42,0,0x4d,0x4d,0,42}; 03212 static const BYTE tiff_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 03213 03214 static const WCHAR emf_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'E','M','F', 0}; 03215 static const WCHAR emf_extension[] = {'*','.','E','M','F',0}; 03216 static const WCHAR emf_mimetype[] = {'i','m','a','g','e','/','x','-','e','m','f', 0}; 03217 static const WCHAR emf_format[] = {'E','M','F',0}; 03218 static const BYTE emf_sig_pattern[] = { 0x01, 0x00, 0x00, 0x00 }; 03219 static const BYTE emf_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF }; 03220 03221 static const WCHAR wmf_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'W','M','F', 0}; 03222 static const WCHAR wmf_extension[] = {'*','.','W','M','F',0}; 03223 static const WCHAR wmf_mimetype[] = {'i','m','a','g','e','/','x','-','w','m','f', 0}; 03224 static const WCHAR wmf_format[] = {'W','M','F',0}; 03225 static const BYTE wmf_sig_pattern[] = { 0xd7, 0xcd }; 03226 static const BYTE wmf_sig_mask[] = { 0xFF, 0xFF }; 03227 03228 static const WCHAR png_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'P','N','G', 0}; 03229 static const WCHAR png_extension[] = {'*','.','P','N','G',0}; 03230 static const WCHAR png_mimetype[] = {'i','m','a','g','e','/','p','n','g', 0}; 03231 static const WCHAR png_format[] = {'P','N','G',0}; 03232 static const BYTE png_sig_pattern[] = { 137, 80, 78, 71, 13, 10, 26, 10, }; 03233 static const BYTE png_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 03234 03235 static const WCHAR ico_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'I','C','O', 0}; 03236 static const WCHAR ico_extension[] = {'*','.','I','C','O',0}; 03237 static const WCHAR ico_mimetype[] = {'i','m','a','g','e','/','x','-','i','c','o','n', 0}; 03238 static const WCHAR ico_format[] = {'I','C','O',0}; 03239 static const BYTE ico_sig_pattern[] = { 0x00, 0x00, 0x01, 0x00 }; 03240 static const BYTE ico_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF }; 03241 03242 static const struct image_codec codecs[NUM_CODECS] = { 03243 { 03244 { /* BMP */ 03245 /* Clsid */ { 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, 03246 /* FormatID */ { 0xb96b3cabU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, 03247 /* CodecName */ bmp_codecname, 03248 /* DllName */ NULL, 03249 /* FormatDescription */ bmp_format, 03250 /* FilenameExtension */ bmp_extension, 03251 /* MimeType */ bmp_mimetype, 03252 /* Flags */ ImageCodecFlagsEncoder | ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin, 03253 /* Version */ 1, 03254 /* SigCount */ 1, 03255 /* SigSize */ 2, 03256 /* SigPattern */ bmp_sig_pattern, 03257 /* SigMask */ bmp_sig_mask, 03258 }, 03259 encode_image_BMP, 03260 decode_image_bmp 03261 }, 03262 { 03263 { /* JPEG */ 03264 /* Clsid */ { 0x557cf401, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, 03265 /* FormatID */ { 0xb96b3caeU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, 03266 /* CodecName */ jpeg_codecname, 03267 /* DllName */ NULL, 03268 /* FormatDescription */ jpeg_format, 03269 /* FilenameExtension */ jpeg_extension, 03270 /* MimeType */ jpeg_mimetype, 03271 /* Flags */ ImageCodecFlagsEncoder | ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin, 03272 /* Version */ 1, 03273 /* SigCount */ 1, 03274 /* SigSize */ 2, 03275 /* SigPattern */ jpeg_sig_pattern, 03276 /* SigMask */ jpeg_sig_mask, 03277 }, 03278 encode_image_jpeg, 03279 decode_image_jpeg 03280 }, 03281 { 03282 { /* GIF */ 03283 /* Clsid */ { 0x557cf402, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, 03284 /* FormatID */ { 0xb96b3cb0U, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, 03285 /* CodecName */ gif_codecname, 03286 /* DllName */ NULL, 03287 /* FormatDescription */ gif_format, 03288 /* FilenameExtension */ gif_extension, 03289 /* MimeType */ gif_mimetype, 03290 /* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin, 03291 /* Version */ 1, 03292 /* SigCount */ 1, 03293 /* SigSize */ 4, 03294 /* SigPattern */ gif_sig_pattern, 03295 /* SigMask */ gif_sig_mask, 03296 }, 03297 NULL, 03298 decode_image_gif 03299 }, 03300 { 03301 { /* TIFF */ 03302 /* Clsid */ { 0x557cf405, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, 03303 /* FormatID */ { 0xb96b3cb1U, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, 03304 /* CodecName */ tiff_codecname, 03305 /* DllName */ NULL, 03306 /* FormatDescription */ tiff_format, 03307 /* FilenameExtension */ tiff_extension, 03308 /* MimeType */ tiff_mimetype, 03309 /* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsEncoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin, 03310 /* Version */ 1, 03311 /* SigCount */ 2, 03312 /* SigSize */ 4, 03313 /* SigPattern */ tiff_sig_pattern, 03314 /* SigMask */ tiff_sig_mask, 03315 }, 03316 encode_image_tiff, 03317 decode_image_tiff 03318 }, 03319 { 03320 { /* EMF */ 03321 /* Clsid */ { 0x557cf403, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, 03322 /* FormatID */ { 0xb96b3cacU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, 03323 /* CodecName */ emf_codecname, 03324 /* DllName */ NULL, 03325 /* FormatDescription */ emf_format, 03326 /* FilenameExtension */ emf_extension, 03327 /* MimeType */ emf_mimetype, 03328 /* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportVector | ImageCodecFlagsBuiltin, 03329 /* Version */ 1, 03330 /* SigCount */ 1, 03331 /* SigSize */ 4, 03332 /* SigPattern */ emf_sig_pattern, 03333 /* SigMask */ emf_sig_mask, 03334 }, 03335 NULL, 03336 decode_image_olepicture_metafile 03337 }, 03338 { 03339 { /* WMF */ 03340 /* Clsid */ { 0x557cf404, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, 03341 /* FormatID */ { 0xb96b3cadU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, 03342 /* CodecName */ wmf_codecname, 03343 /* DllName */ NULL, 03344 /* FormatDescription */ wmf_format, 03345 /* FilenameExtension */ wmf_extension, 03346 /* MimeType */ wmf_mimetype, 03347 /* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportVector | ImageCodecFlagsBuiltin, 03348 /* Version */ 1, 03349 /* SigCount */ 1, 03350 /* SigSize */ 2, 03351 /* SigPattern */ wmf_sig_pattern, 03352 /* SigMask */ wmf_sig_mask, 03353 }, 03354 NULL, 03355 decode_image_olepicture_metafile 03356 }, 03357 { 03358 { /* PNG */ 03359 /* Clsid */ { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, 03360 /* FormatID */ { 0xb96b3cafU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, 03361 /* CodecName */ png_codecname, 03362 /* DllName */ NULL, 03363 /* FormatDescription */ png_format, 03364 /* FilenameExtension */ png_extension, 03365 /* MimeType */ png_mimetype, 03366 /* Flags */ ImageCodecFlagsEncoder | ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin, 03367 /* Version */ 1, 03368 /* SigCount */ 1, 03369 /* SigSize */ 8, 03370 /* SigPattern */ png_sig_pattern, 03371 /* SigMask */ png_sig_mask, 03372 }, 03373 encode_image_png, 03374 decode_image_png 03375 }, 03376 { 03377 { /* ICO */ 03378 /* Clsid */ { 0x557cf407, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, 03379 /* FormatID */ { 0xb96b3cabU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, 03380 /* CodecName */ ico_codecname, 03381 /* DllName */ NULL, 03382 /* FormatDescription */ ico_format, 03383 /* FilenameExtension */ ico_extension, 03384 /* MimeType */ ico_mimetype, 03385 /* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin, 03386 /* Version */ 1, 03387 /* SigCount */ 1, 03388 /* SigSize */ 4, 03389 /* SigPattern */ ico_sig_pattern, 03390 /* SigMask */ ico_sig_mask, 03391 }, 03392 NULL, 03393 decode_image_icon 03394 }, 03395 }; 03396 03397 /***************************************************************************** 03398 * GdipGetImageDecodersSize [GDIPLUS.@] 03399 */ 03400 GpStatus WINGDIPAPI GdipGetImageDecodersSize(UINT *numDecoders, UINT *size) 03401 { 03402 int decoder_count=0; 03403 int i; 03404 TRACE("%p %p\n", numDecoders, size); 03405 03406 if (!numDecoders || !size) 03407 return InvalidParameter; 03408 03409 for (i=0; i<NUM_CODECS; i++) 03410 { 03411 if (codecs[i].info.Flags & ImageCodecFlagsDecoder) 03412 decoder_count++; 03413 } 03414 03415 *numDecoders = decoder_count; 03416 *size = decoder_count * sizeof(ImageCodecInfo); 03417 03418 return Ok; 03419 } 03420 03421 /***************************************************************************** 03422 * GdipGetImageDecoders [GDIPLUS.@] 03423 */ 03424 GpStatus WINGDIPAPI GdipGetImageDecoders(UINT numDecoders, UINT size, ImageCodecInfo *decoders) 03425 { 03426 int i, decoder_count=0; 03427 TRACE("%u %u %p\n", numDecoders, size, decoders); 03428 03429 if (!decoders || 03430 size != numDecoders * sizeof(ImageCodecInfo)) 03431 return GenericError; 03432 03433 for (i=0; i<NUM_CODECS; i++) 03434 { 03435 if (codecs[i].info.Flags & ImageCodecFlagsDecoder) 03436 { 03437 if (decoder_count == numDecoders) return GenericError; 03438 memcpy(&decoders[decoder_count], &codecs[i].info, sizeof(ImageCodecInfo)); 03439 decoder_count++; 03440 } 03441 } 03442 03443 if (decoder_count < numDecoders) return GenericError; 03444 03445 return Ok; 03446 } 03447 03448 /***************************************************************************** 03449 * GdipGetImageEncodersSize [GDIPLUS.@] 03450 */ 03451 GpStatus WINGDIPAPI GdipGetImageEncodersSize(UINT *numEncoders, UINT *size) 03452 { 03453 int encoder_count=0; 03454 int i; 03455 TRACE("%p %p\n", numEncoders, size); 03456 03457 if (!numEncoders || !size) 03458 return InvalidParameter; 03459 03460 for (i=0; i<NUM_CODECS; i++) 03461 { 03462 if (codecs[i].info.Flags & ImageCodecFlagsEncoder) 03463 encoder_count++; 03464 } 03465 03466 *numEncoders = encoder_count; 03467 *size = encoder_count * sizeof(ImageCodecInfo); 03468 03469 return Ok; 03470 } 03471 03472 /***************************************************************************** 03473 * GdipGetImageEncoders [GDIPLUS.@] 03474 */ 03475 GpStatus WINGDIPAPI GdipGetImageEncoders(UINT numEncoders, UINT size, ImageCodecInfo *encoders) 03476 { 03477 int i, encoder_count=0; 03478 TRACE("%u %u %p\n", numEncoders, size, encoders); 03479 03480 if (!encoders || 03481 size != numEncoders * sizeof(ImageCodecInfo)) 03482 return GenericError; 03483 03484 for (i=0; i<NUM_CODECS; i++) 03485 { 03486 if (codecs[i].info.Flags & ImageCodecFlagsEncoder) 03487 { 03488 if (encoder_count == numEncoders) return GenericError; 03489 memcpy(&encoders[encoder_count], &codecs[i].info, sizeof(ImageCodecInfo)); 03490 encoder_count++; 03491 } 03492 } 03493 03494 if (encoder_count < numEncoders) return GenericError; 03495 03496 return Ok; 03497 } 03498 03499 GpStatus WINGDIPAPI GdipGetEncoderParameterListSize(GpImage *image, 03500 GDIPCONST CLSID* clsidEncoder, UINT *size) 03501 { 03502 static int calls; 03503 03504 TRACE("(%p,%s,%p)\n", image, debugstr_guid(clsidEncoder), size); 03505 03506 if(!(calls++)) 03507 FIXME("not implemented\n"); 03508 03509 *size = 0; 03510 03511 return NotImplemented; 03512 } 03513 03514 static PixelFormat get_16bpp_format(HBITMAP hbm) 03515 { 03516 BITMAPV4HEADER bmh; 03517 HDC hdc; 03518 PixelFormat result; 03519 03520 hdc = CreateCompatibleDC(NULL); 03521 03522 memset(&bmh, 0, sizeof(bmh)); 03523 bmh.bV4Size = sizeof(bmh); 03524 bmh.bV4Width = 1; 03525 bmh.bV4Height = 1; 03526 bmh.bV4V4Compression = BI_BITFIELDS; 03527 bmh.bV4BitCount = 16; 03528 03529 GetDIBits(hdc, hbm, 0, 0, NULL, (BITMAPINFO*)&bmh, DIB_RGB_COLORS); 03530 03531 if (bmh.bV4RedMask == 0x7c00 && 03532 bmh.bV4GreenMask == 0x3e0 && 03533 bmh.bV4BlueMask == 0x1f) 03534 { 03535 result = PixelFormat16bppRGB555; 03536 } 03537 else if (bmh.bV4RedMask == 0xf800 && 03538 bmh.bV4GreenMask == 0x7e0 && 03539 bmh.bV4BlueMask == 0x1f) 03540 { 03541 result = PixelFormat16bppRGB565; 03542 } 03543 else 03544 { 03545 FIXME("unrecognized bitfields %x,%x,%x\n", bmh.bV4RedMask, 03546 bmh.bV4GreenMask, bmh.bV4BlueMask); 03547 result = PixelFormatUndefined; 03548 } 03549 03550 DeleteDC(hdc); 03551 03552 return result; 03553 } 03554 03555 /***************************************************************************** 03556 * GdipCreateBitmapFromHBITMAP [GDIPLUS.@] 03557 */ 03558 GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBitmap** bitmap) 03559 { 03560 BITMAP bm; 03561 GpStatus retval; 03562 PixelFormat format; 03563 BitmapData lockeddata; 03564 INT y; 03565 03566 TRACE("%p %p %p\n", hbm, hpal, bitmap); 03567 03568 if(!hbm || !bitmap) 03569 return InvalidParameter; 03570 03571 if (GetObjectA(hbm, sizeof(bm), &bm) != sizeof(bm)) 03572 return InvalidParameter; 03573 03574 /* TODO: Figure out the correct format for 16, 32, 64 bpp */ 03575 switch(bm.bmBitsPixel) { 03576 case 1: 03577 format = PixelFormat1bppIndexed; 03578 break; 03579 case 4: 03580 format = PixelFormat4bppIndexed; 03581 break; 03582 case 8: 03583 format = PixelFormat8bppIndexed; 03584 break; 03585 case 16: 03586 format = get_16bpp_format(hbm); 03587 if (format == PixelFormatUndefined) 03588 return InvalidParameter; 03589 break; 03590 case 24: 03591 format = PixelFormat24bppRGB; 03592 break; 03593 case 32: 03594 format = PixelFormat32bppRGB; 03595 break; 03596 case 48: 03597 format = PixelFormat48bppRGB; 03598 break; 03599 default: 03600 FIXME("don't know how to handle %d bpp\n", bm.bmBitsPixel); 03601 return InvalidParameter; 03602 } 03603 03604 retval = GdipCreateBitmapFromScan0(bm.bmWidth, bm.bmHeight, 0, 03605 format, NULL, bitmap); 03606 03607 if (retval == Ok) 03608 { 03609 retval = GdipBitmapLockBits(*bitmap, NULL, ImageLockModeWrite, 03610 format, &lockeddata); 03611 if (retval == Ok) 03612 { 03613 if (bm.bmBits) 03614 { 03615 for (y=0; y<bm.bmHeight; y++) 03616 { 03617 memcpy((BYTE*)lockeddata.Scan0+lockeddata.Stride*y, 03618 (BYTE*)bm.bmBits+bm.bmWidthBytes*(bm.bmHeight-1-y), 03619 bm.bmWidthBytes); 03620 } 03621 } 03622 else 03623 { 03624 HDC hdc; 03625 HBITMAP oldhbm; 03626 BITMAPINFO *pbmi; 03627 INT src_height, dst_stride; 03628 BYTE *dst_bits; 03629 03630 hdc = CreateCompatibleDC(NULL); 03631 oldhbm = SelectObject(hdc, hbm); 03632 03633 pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); 03634 03635 if (pbmi) 03636 { 03637 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 03638 pbmi->bmiHeader.biBitCount = 0; 03639 03640 GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS); 03641 03642 src_height = abs(pbmi->bmiHeader.biHeight); 03643 03644 if (pbmi->bmiHeader.biHeight > 0) 03645 { 03646 dst_bits = (BYTE*)lockeddata.Scan0+lockeddata.Stride*(src_height-1); 03647 dst_stride = -lockeddata.Stride; 03648 } 03649 else 03650 { 03651 dst_bits = lockeddata.Scan0; 03652 dst_stride = lockeddata.Stride; 03653 } 03654 03655 for (y=0; y<src_height; y++) 03656 { 03657 GetDIBits(hdc, hbm, y, 1, dst_bits+dst_stride*y, 03658 pbmi, DIB_RGB_COLORS); 03659 } 03660 03661 GdipFree(pbmi); 03662 } 03663 else 03664 retval = OutOfMemory; 03665 03666 SelectObject(hdc, oldhbm); 03667 DeleteDC(hdc); 03668 } 03669 03670 GdipBitmapUnlockBits(*bitmap, &lockeddata); 03671 } 03672 03673 if (retval == Ok && hpal) 03674 { 03675 WORD num_palette_entries; 03676 PALETTEENTRY *palette_entries=NULL; 03677 ColorPalette *palette=NULL; 03678 int i; 03679 03680 if (!GetObjectW(hpal, sizeof(num_palette_entries), &num_palette_entries)) 03681 retval = GenericError; 03682 03683 if (retval == Ok) 03684 { 03685 palette_entries = GdipAlloc(sizeof(PALETTEENTRY) * num_palette_entries); 03686 palette = GdipAlloc(sizeof(ColorPalette) + sizeof(ARGB) * (num_palette_entries-1)); 03687 03688 if (!palette_entries || !palette) 03689 retval = OutOfMemory; 03690 } 03691 03692 if (retval == Ok) 03693 { 03694 if (!GetPaletteEntries(hpal, 0, num_palette_entries, palette_entries)) 03695 retval = GenericError; 03696 } 03697 03698 if (retval == Ok) 03699 { 03700 palette->Flags = 0; 03701 palette->Count = num_palette_entries; 03702 03703 for (i=0; i<num_palette_entries; i++) 03704 { 03705 PALETTEENTRY * entry = &palette_entries[i]; 03706 palette->Entries[i] = 0xff000000 | entry->peRed << 16 | 03707 entry->peGreen << 8 | entry->peBlue; 03708 } 03709 03710 retval = GdipSetImagePalette((GpImage*)*bitmap, palette); 03711 } 03712 03713 GdipFree(palette_entries); 03714 GdipFree(palette); 03715 } 03716 03717 if (retval != Ok) 03718 { 03719 GdipDisposeImage((GpImage*)*bitmap); 03720 *bitmap = NULL; 03721 } 03722 } 03723 03724 return retval; 03725 } 03726 03727 GpStatus WINGDIPAPI GdipDeleteEffect(CGpEffect *effect) 03728 { 03729 FIXME("(%p): stub\n", effect); 03730 /* note: According to Jose Roca's GDI+ Docs, this is not implemented 03731 * in Windows's gdiplus */ 03732 return NotImplemented; 03733 } 03734 03735 /***************************************************************************** 03736 * GdipSetEffectParameters [GDIPLUS.@] 03737 */ 03738 GpStatus WINGDIPAPI GdipSetEffectParameters(CGpEffect *effect, 03739 const VOID *params, const UINT size) 03740 { 03741 static int calls; 03742 03743 TRACE("(%p,%p,%u)\n", effect, params, size); 03744 03745 if(!(calls++)) 03746 FIXME("not implemented\n"); 03747 03748 return NotImplemented; 03749 } 03750 03751 /***************************************************************************** 03752 * GdipGetImageFlags [GDIPLUS.@] 03753 */ 03754 GpStatus WINGDIPAPI GdipGetImageFlags(GpImage *image, UINT *flags) 03755 { 03756 TRACE("%p %p\n", image, flags); 03757 03758 if(!image || !flags) 03759 return InvalidParameter; 03760 03761 *flags = image->flags; 03762 03763 return Ok; 03764 } 03765 03766 GpStatus WINGDIPAPI GdipTestControl(GpTestControlEnum control, void *param) 03767 { 03768 TRACE("(%d, %p)\n", control, param); 03769 03770 switch(control){ 03771 case TestControlForceBilinear: 03772 if(param) 03773 FIXME("TestControlForceBilinear not handled\n"); 03774 break; 03775 case TestControlNoICM: 03776 if(param) 03777 FIXME("TestControlNoICM not handled\n"); 03778 break; 03779 case TestControlGetBuildNumber: 03780 *((DWORD*)param) = 3102; 03781 break; 03782 } 03783 03784 return Ok; 03785 } 03786 03787 GpStatus WINGDIPAPI GdipRecordMetafileFileName(GDIPCONST WCHAR* fileName, 03788 HDC hdc, EmfType type, GDIPCONST GpRectF *pFrameRect, 03789 MetafileFrameUnit frameUnit, GDIPCONST WCHAR *desc, 03790 GpMetafile **metafile) 03791 { 03792 FIXME("%s %p %d %p %d %s %p stub!\n", debugstr_w(fileName), hdc, type, pFrameRect, 03793 frameUnit, debugstr_w(desc), metafile); 03794 03795 return NotImplemented; 03796 } 03797 03798 GpStatus WINGDIPAPI GdipRecordMetafileFileNameI(GDIPCONST WCHAR* fileName, HDC hdc, EmfType type, 03799 GDIPCONST GpRect *pFrameRect, MetafileFrameUnit frameUnit, 03800 GDIPCONST WCHAR *desc, GpMetafile **metafile) 03801 { 03802 FIXME("%s %p %d %p %d %s %p stub!\n", debugstr_w(fileName), hdc, type, pFrameRect, 03803 frameUnit, debugstr_w(desc), metafile); 03804 03805 return NotImplemented; 03806 } 03807 03808 GpStatus WINGDIPAPI GdipImageForceValidation(GpImage *image) 03809 { 03810 TRACE("%p\n", image); 03811 03812 return Ok; 03813 } 03814 03815 /***************************************************************************** 03816 * GdipGetImageThumbnail [GDIPLUS.@] 03817 */ 03818 GpStatus WINGDIPAPI GdipGetImageThumbnail(GpImage *image, UINT width, UINT height, 03819 GpImage **ret_image, GetThumbnailImageAbort cb, 03820 VOID * cb_data) 03821 { 03822 GpStatus stat; 03823 GpGraphics *graphics; 03824 UINT srcwidth, srcheight; 03825 03826 TRACE("(%p %u %u %p %p %p)\n", 03827 image, width, height, ret_image, cb, cb_data); 03828 03829 if (!image || !ret_image) 03830 return InvalidParameter; 03831 03832 if (!width) width = 120; 03833 if (!height) height = 120; 03834 03835 GdipGetImageWidth(image, &srcwidth); 03836 GdipGetImageHeight(image, &srcheight); 03837 03838 stat = GdipCreateBitmapFromScan0(width, height, 0, PixelFormat32bppARGB, 03839 NULL, (GpBitmap**)ret_image); 03840 03841 if (stat == Ok) 03842 { 03843 stat = GdipGetImageGraphicsContext(*ret_image, &graphics); 03844 03845 if (stat == Ok) 03846 { 03847 stat = GdipDrawImageRectRectI(graphics, image, 03848 0, 0, width, height, 0, 0, srcwidth, srcheight, UnitPixel, 03849 NULL, NULL, NULL); 03850 03851 GdipDeleteGraphics(graphics); 03852 } 03853 03854 if (stat != Ok) 03855 { 03856 GdipDisposeImage(*ret_image); 03857 *ret_image = NULL; 03858 } 03859 } 03860 03861 return stat; 03862 } 03863 03864 /***************************************************************************** 03865 * GdipImageRotateFlip [GDIPLUS.@] 03866 */ 03867 GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type) 03868 { 03869 GpBitmap *new_bitmap; 03870 GpBitmap *bitmap; 03871 int bpp, bytesperpixel; 03872 int rotate_90, flip_x, flip_y; 03873 int src_x_offset, src_y_offset; 03874 LPBYTE src_origin; 03875 UINT x, y, width, height; 03876 BitmapData src_lock, dst_lock; 03877 GpStatus stat; 03878 03879 TRACE("(%p, %u)\n", image, type); 03880 03881 rotate_90 = type&1; 03882 flip_x = (type&6) == 2 || (type&6) == 4; 03883 flip_y = (type&3) == 1 || (type&3) == 2; 03884 03885 if (image->type != ImageTypeBitmap) 03886 { 03887 FIXME("Not implemented for type %i\n", image->type); 03888 return NotImplemented; 03889 } 03890 03891 bitmap = (GpBitmap*)image; 03892 bpp = PIXELFORMATBPP(bitmap->format); 03893 03894 if (bpp < 8) 03895 { 03896 FIXME("Not implemented for %i bit images\n", bpp); 03897 return NotImplemented; 03898 } 03899 03900 if (rotate_90) 03901 { 03902 width = bitmap->height; 03903 height = bitmap->width; 03904 } 03905 else 03906 { 03907 width = bitmap->width; 03908 height = bitmap->height; 03909 } 03910 03911 bytesperpixel = bpp/8; 03912 03913 stat = GdipCreateBitmapFromScan0(width, height, 0, bitmap->format, NULL, &new_bitmap); 03914 03915 if (stat != Ok) 03916 return stat; 03917 03918 stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, bitmap->format, &src_lock); 03919 03920 if (stat == Ok) 03921 { 03922 stat = GdipBitmapLockBits(new_bitmap, NULL, ImageLockModeWrite, bitmap->format, &dst_lock); 03923 03924 if (stat == Ok) 03925 { 03926 LPBYTE src_row, src_pixel; 03927 LPBYTE dst_row, dst_pixel; 03928 03929 src_origin = src_lock.Scan0; 03930 if (flip_x) src_origin += bytesperpixel * (bitmap->width - 1); 03931 if (flip_y) src_origin += src_lock.Stride * (bitmap->height - 1); 03932 03933 if (rotate_90) 03934 { 03935 if (flip_y) src_x_offset = -src_lock.Stride; 03936 else src_x_offset = src_lock.Stride; 03937 if (flip_x) src_y_offset = -bytesperpixel; 03938 else src_y_offset = bytesperpixel; 03939 } 03940 else 03941 { 03942 if (flip_x) src_x_offset = -bytesperpixel; 03943 else src_x_offset = bytesperpixel; 03944 if (flip_y) src_y_offset = -src_lock.Stride; 03945 else src_y_offset = src_lock.Stride; 03946 } 03947 03948 src_row = src_origin; 03949 dst_row = dst_lock.Scan0; 03950 for (y=0; y<height; y++) 03951 { 03952 src_pixel = src_row; 03953 dst_pixel = dst_row; 03954 for (x=0; x<width; x++) 03955 { 03956 /* FIXME: This could probably be faster without memcpy. */ 03957 memcpy(dst_pixel, src_pixel, bytesperpixel); 03958 dst_pixel += bytesperpixel; 03959 src_pixel += src_x_offset; 03960 } 03961 src_row += src_y_offset; 03962 dst_row += dst_lock.Stride; 03963 } 03964 03965 GdipBitmapUnlockBits(new_bitmap, &dst_lock); 03966 } 03967 03968 GdipBitmapUnlockBits(bitmap, &src_lock); 03969 } 03970 03971 if (stat == Ok) 03972 move_bitmap(bitmap, new_bitmap, FALSE); 03973 else 03974 GdipDisposeImage((GpImage*)new_bitmap); 03975 03976 return stat; 03977 } 03978 03979 /***************************************************************************** 03980 * GdipConvertToEmfPlusToFile [GDIPLUS.@] 03981 */ 03982 03983 GpStatus WINGDIPAPI GdipConvertToEmfPlusToFile(const GpGraphics* refGraphics, 03984 GpMetafile* metafile, BOOL* conversionSuccess, 03985 const WCHAR* filename, EmfType emfType, 03986 const WCHAR* description, GpMetafile** out_metafile) 03987 { 03988 FIXME("stub: %p, %p, %p, %p, %u, %p, %p\n", refGraphics, metafile, conversionSuccess, filename, emfType, description, out_metafile); 03989 return NotImplemented; 03990 } Generated on Sat May 26 2012 04:19:06 for ReactOS by
1.7.6.1
|