/*! This basically does two things. First, create a bitmap from the designated area of the source bitmap. Then, converts it 8 or 16 bpp, depending on \a gr.gfxBpp. Conversion to lower bpp is done later, when it's more convenient. The resultant bitmap is put into \a gr._dib, and will be used in later preparation. */ bool grit_prep_work_dib(GritRec *gr) { int ii, nn; RGBQUAD *rgb; lprintf(LOG_STATUS, "Work-DIB creation.\n"); // --- resize --- CLDIB *dib= dib_copy(gr->srcDib, gr->areaLeft, gr->areaTop, gr->areaRight, gr->areaBottom, false); if(dib == NULL) { lprintf(LOG_ERROR, " Work-DIB creation failed.\n"); return false; } // ... that's it? Yeah, looks like. // --- resample (to 8 or 16) --- // int dibB= dib_get_bpp(dib); // Convert to 16bpp, but ONLY for bitmaps if( gr->gfxBpp == 16 && gr->gfxMode != GRIT_GFX_TILE ) { if(dibB != 16) { lprintf(LOG_WARNING, " converting from %d bpp to %d bpp.\n", dibB, gr->gfxBpp); CLDIB *dib2= dib_convert_copy(dib, 16, 0); // If paletted src AND -pT AND NOT -gT[!] // use trans color pal[T] //# PONDER: did I fix this right? if(dibB <= 8 && gr->palHasAlpha && !gr->gfxHasAlpha) { rgb= &dib_get_pal(dib)[gr->palAlphaId]; lprintf(LOG_WARNING, " pal->true-color conversion with transp pal-id option.\n" " using color %02X%02X%02X", rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue); gr->gfxHasAlpha= true; gr->gfxAlphaColor= *rgb; } dib_free(dib); if(dib2 == NULL) { lprintf(LOG_ERROR, "prep: Bpp conversion failed.\n"); return false; } dib= dib2; } // --- Dealing with 16bpp images --- // Modes: // 555 | GBA | swap R_B // 555+A=1 | NDS | swap R_B + add NDS_ALPHA // 555+A | NDS, transp | swap R_B + NDS_ALPHA if !trans-clr // src-pal + -pT -> NDS, transp // Swap palette bRGB to bBGR // And resolve -gT nn= dib_get_size_img(dib)/2; WORD *dibD2= (WORD*)dib_get_img(dib); // Single transparent color if(gr->gfxHasAlpha) { rgb= &gr->gfxAlphaColor; WORD clr= RGB16(rgb->rgbBlue, rgb->rgbGreen, rgb->rgbRed), wd; lprintf(LOG_STATUS, " converting to: 16bpp BGR, alpha=1, except for 0x%04X.\n", clr); for(ii=0; ii<nn; ii++) { wd= swap_rgb16(dibD2[ii]); dibD2[ii]= (wd == clr ? wd : wd | NDS_ALPHA); } } else if(gr->gfxMode == GRIT_GFX_BMP_A) { lprintf(LOG_STATUS, "converting to: 16bpp BGR, alpha=1.\n"); for(ii=0; ii<nn; ii++) dibD2[ii]= swap_rgb16(dibD2[ii]) | NDS_ALPHA; } else { lprintf(LOG_STATUS, "converting to: 16bpp, BGR.\n"); for(ii=0; ii<nn; ii++) dibD2[ii]= swap_rgb16(dibD2[ii]); } } else if(dibB != 8) // otherwise, convert to 8bpp { lprintf(LOG_WARNING, " converting from %d bpp to %d bpp.\n", dibB, gr->gfxBpp); if(!dib_convert(dib, 8, 0)) { dib_free(dib); lprintf(LOG_ERROR, " Bpp conversion failed.\n"); return false; } } // Palette transparency additions. if(dib_get_bpp(dib)==8) { // If gfx-trans && !pal-trans: // Find gfx-trans in palette and use that if(gr->gfxHasAlpha && !gr->palHasAlpha) { rgb= &gr->gfxAlphaColor; RGBQUAD *pal= dib_get_pal(dib); lprintf(LOG_WARNING, " tru/pal -> pal conversion with transp color option.\n" " looking for color %02X%02X%02X in palette.\n", rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue); uint ii_min= 0, dist, dist_min; dist_min= rgb_dist(rgb, &pal[0]); for(ii=1; ii<256; ii++) { dist= rgb_dist(rgb, &pal[ii]); if(dist < dist_min) { ii_min= ii; dist_min= dist; } } // HACK: count 'match' only if average error is < +/-14 if(dist_min < 576) { gr->palHasAlpha= true; gr->palAlphaId= ii_min; } } // Swap alpha and pixels palette entry if(gr->palHasAlpha) { lprintf(LOG_STATUS, " Palette transparency: pal[%d].\n", gr->palAlphaId); BYTE *imgD= dib_get_img(dib); nn= dib_get_size_img(dib); for(ii=0; ii<nn; ii++) { if(imgD[ii] == 0) imgD[ii]= gr->palAlphaId; else if(imgD[ii] == gr->palAlphaId) imgD[ii]= 0; } RGBQUAD tmp, *pal= dib_get_pal(dib); SWAP3(pal[0], pal[gr->palAlphaId], tmp); } // TODO: Palette merging. if(gr->palIsShared) { lprintf(LOG_STATUS, " Palette merging\n"); nn= dib_pal_reduce(dib, &gr->shared->palRec); if(nn>PAL_MAX) lprintf(LOG_WARNING, " New palette exceeds 256. Truncating.\n"); } } dib_free(gr->_dib); gr->_dib= dib; lprintf(LOG_STATUS, "Work-DIB creation complete: %dx%d@%d.\n", dib_get_width(gr->_dib), dib_get_height(gr->_dib), dib_get_bpp(gr->_dib)); return true; }
/*********************************************************************** * CreateBrushIndirect (GDI32.@) * * Create a logical brush with a given style, color or pattern. * * PARAMS * brush [I] Pointer to a LOGBRUSH structure describing the desired brush. * * RETURNS * A handle to the created brush, or a NULL handle if the brush cannot be * created. * * NOTES * - The brush returned should be freed by the caller using DeleteObject() * when it is no longer required. * - Windows 95 and earlier cannot create brushes from bitmaps or DIBs larger * than 8x8 pixels. If a larger bitmap is given, only a portion of the bitmap * is used. */ HBRUSH WINAPI CreateBrushIndirect( const LOGBRUSH * brush ) { BRUSHOBJ * ptr; HBRUSH hbrush; if (!(ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(*ptr) ))) return 0; ptr->logbrush.lbStyle = brush->lbStyle; ptr->logbrush.lbColor = brush->lbColor; ptr->logbrush.lbHatch = brush->lbHatch; switch (ptr->logbrush.lbStyle) { case BS_PATTERN8X8: ptr->logbrush.lbStyle = BS_PATTERN; /* fall through */ case BS_PATTERN: ptr->logbrush.lbHatch = (ULONG_PTR)BITMAP_CopyBitmap( (HBITMAP) ptr->logbrush.lbHatch ); if (!ptr->logbrush.lbHatch) goto error; break; case BS_DIBPATTERNPT: ptr->logbrush.lbStyle = BS_DIBPATTERN; ptr->logbrush.lbHatch = (ULONG_PTR)dib_copy( (BITMAPINFO *) ptr->logbrush.lbHatch, ptr->logbrush.lbColor); if (!ptr->logbrush.lbHatch) goto error; break; case BS_DIBPATTERN8X8: case BS_DIBPATTERN: { BITMAPINFO* bmi; HGLOBAL h = (HGLOBAL)ptr->logbrush.lbHatch; ptr->logbrush.lbStyle = BS_DIBPATTERN; if (!(bmi = GlobalLock( h ))) goto error; ptr->logbrush.lbHatch = (ULONG_PTR)dib_copy( bmi, ptr->logbrush.lbColor); GlobalUnlock( h ); if (!ptr->logbrush.lbHatch) goto error; break; } default: if(ptr->logbrush.lbStyle > BS_MONOPATTERN) goto error; break; } if ((hbrush = alloc_gdi_handle( &ptr->header, OBJ_BRUSH, &brush_funcs ))) { TRACE("%p\n", hbrush); return hbrush; } error: if (ptr->logbrush.lbHatch) { if (ptr->logbrush.lbStyle == BS_PATTERN) DeleteObject( (HGDIOBJ)ptr->logbrush.lbHatch ); else if (ptr->logbrush.lbStyle == BS_DIBPATTERN) GlobalFree( (HGLOBAL)ptr->logbrush.lbHatch ); } HeapFree( GetProcessHeap(), 0, ptr ); return 0; }