void InitSelectedMap() { BScreen screen; rgb_color c, d; int32 i; for (i = 0; i < 255; i++) { d = c = screen.ColorForIndex(i); c.red = c.red * 2 / 3; c.green = c.green * 2 / 3; c.blue = c.blue * 2 / 3; gSelectedMap[i] = screen.IndexForColor(c); d.red = (c.red + 438) / 3; d.green = (c.green + 438) / 3; d.blue = (c.blue + 438) / 3; gDisabledMap[i] = screen.IndexForColor(d); } gSelectedMap[255] = 255; gDisabledMap[255] = 255; } /* InitSelectedMap */
void CMenuTool::SetBitmap( BBitmap *bitmap) { D_OPERATION(("CMenuTool::SetBitmap()\n")); if (bitmap && (bitmap != m_bitmap)) { delete m_bitmap; delete m_disabledBitmap; m_bitmap = bitmap; // calculate disabled bitmap BScreen screen; uint8 light = screen.IndexForColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_1_TINT)); uint8 dark = screen.IndexForColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT)); m_disabledBitmap = new BBitmap(bitmap); uint8 *start = (uint8 *)m_disabledBitmap->Bits(); uint8 *end = start + m_disabledBitmap->BitsLength(); for (uint8 *pos = start; pos < end; pos++) { rgb_color color = screen.ColorForIndex(*pos); if ((color.alpha < 255) || (color.red + color.green + color.blue >= 765)) continue; if (color.red + color.green + color.blue > 384) *pos = light; else *pos = dark; } } if (ToolBar()) ToolBar()->Invalidate(); }
void DockItem::MakeHighlitIcon( void ) { size_t size; BBitmap *icon, *iconHi; BScreen screen; for ( int i=0; i<2; i++ ) { switch ( i ) { case 0: size = 1024; icon = mLargeIcon; iconHi = mLargeIconHi; break; case 1: size = 256; icon = mSmallIcon; iconHi = mSmallIconHi; break; } uchar *hilitBits = new uchar[size]; uchar *hilitBitsPtr = &hilitBits[0]; uchar *bitsPtr = (uchar *)icon->Bits(); rgb_color hilitColor; for ( int i=0; i<size; i++ ) { if ( *bitsPtr != B_TRANSPARENT_8_BIT ) { hilitColor = system_colors()->color_list[*bitsPtr++]; hilitColor.red *= 0.7; hilitColor.green *= 0.7; hilitColor.blue *= 0.7; *hilitBitsPtr++ = screen.IndexForColor( hilitColor ); } else { *hilitBitsPtr++ = *bitsPtr++; } } iconHi->SetBits( hilitBits, size, 0, B_COLOR_8_BIT ); } }
void Scaler::Dither(int32 fromRow, int32 toRow) { BBitmap* src; BBitmap* dest; intType destW; intType x, y; uchar* srcBits; intType srcBPR; uchar* srcDataRow; uchar* srcData; uchar* destBits; intType destBPR; uchar* destDataRow; uchar* destData; const int32 kBPP = 4; DitheringColumnData* columnData0; DitheringColumnData* columnData; DitheringColumnData* cd; BScreen screen; intType error[3], err[3]; src = fScaledImage; dest = GetDestImage(); ASSERT(src->ColorSpace() == B_RGB32 || src->ColorSpace() == B_RGBA32); ASSERT(dest->ColorSpace() == B_CMAP8); ASSERT(src->Bounds().IntegerWidth() == dest->Bounds().IntegerWidth()); ASSERT(src->Bounds().IntegerHeight() == dest->Bounds().IntegerHeight()); destW = dest->Bounds().IntegerWidth(); srcBits = (uchar*)src->Bits(); srcBPR = src->BytesPerRow(); destBits = (uchar*)dest->Bits(); destBPR = dest->BytesPerRow(); // Allocate space for sentinel at left and right bounds, // so that columnData[-1] and columnData[destW+1] can be safely accessed columnData0 = new DitheringColumnData[destW+3]; columnData = columnData0 + 1; // clear error cd = columnData; for (x = destW; x >= 0; x --, cd ++) { cd->error[0] = cd->error[1] = cd->error[2] =0; } srcDataRow = srcBits + fromRow * srcBPR; destDataRow = destBits + fromRow * destBPR; for (y = fromRow; IsRunning() && y <= toRow; y ++, srcDataRow += srcBPR, destDataRow += destBPR) { // left to right error[0] = error[1] = error[2] = 0; srcData = srcDataRow; destData = destDataRow; for (x = 0; x <= destW; x ++, srcData += kBPP, destData += 1) { rgb_color color, actualColor; uint8 index; color.red = Limit(srcData[2] + error[0] / 16); color.green = Limit(srcData[1] + error[1] / 16); color.blue = Limit(srcData[0] + error[2] / 16); index = screen.IndexForColor(color); actualColor = screen.ColorForIndex(index); *destData = index; err[0] = color.red - actualColor.red; err[1] = color.green -actualColor.green; err[2] = color.blue -actualColor.blue; // distribute error // get error for next pixel cd = &columnData[x+1]; error[0] = cd->error[0] + 7 * err[0]; error[1] = cd->error[1] + 7 * err[1]; error[2] = cd->error[2] + 7 * err[2]; // set error for right pixel below current pixel cd->error[0] = err[0]; cd->error[1] = err[1]; cd->error[2] = err[2]; // add error for pixel below current pixel cd --; cd->error[0] += 5 * err[0]; cd->error[1] += 5 * err[1]; cd->error[2] += 5 * err[2]; // add error for left pixel below current pixel cd --; cd->error[0] += 3 * err[0]; cd->error[1] += 3 * err[1]; cd->error[2] += 3 * err[2]; } // Note: Alogrithm has good results with "left to right" already // Optionally remove code to end of block: y ++; srcDataRow += srcBPR; destDataRow += destBPR; if (y > toRow) break; // right to left error[0] = error[1] = error[2] = 0; srcData = srcDataRow + destW * kBPP; destData = destDataRow + destW; for (x = 0; x <= destW; x ++, srcData -= kBPP, destData -= 1) { rgb_color color, actualColor; uint8 index; color.red = Limit(srcData[2] + error[0] / 16); color.green = Limit(srcData[1] + error[1] / 16); color.blue = Limit(srcData[0] + error[2] / 16); index = screen.IndexForColor(color); actualColor = screen.ColorForIndex(index); *destData = index; err[0] = color.red - actualColor.red; err[1] = color.green -actualColor.green; err[2] = color.blue -actualColor.blue; // distribute error // get error for next pixel cd = &columnData[x-1]; error[0] = cd->error[0] + 7 * err[0]; error[1] = cd->error[1] + 7 * err[1]; error[2] = cd->error[2] + 7 * err[2]; // set error for left pixel below current pixel cd->error[0] = err[0]; cd->error[1] = err[1]; cd->error[2] = err[2]; // add error for pixel below current pixel cd ++; cd->error[0] += 5 * err[0]; cd->error[1] += 5 * err[1]; cd->error[2] += 5 * err[2]; // add error for right pixel below current pixel cd ++; cd->error[0] += 3 * err[0]; cd->error[1] += 3 * err[1]; cd->error[2] += 3 * err[2]; } } delete[] columnData0; }
BBitmap *ConvertTo8bit( BBitmap *bitmap ) { if( bitmap->ColorSpace() == B_COLOR_8_BIT ) return new BBitmap( bitmap ); if( (bitmap->ColorSpace()!=B_RGB32) && (bitmap->ColorSpace()!=B_RGBA32) ) return NULL; BBitmap *bitmap_8bit = new BBitmap( bitmap->Bounds(), B_COLOR_8_BIT, false ); int width = (int)bitmap->Bounds().Width()+1; int height = (int)bitmap->Bounds().Height()+1; bool srchasalpha = bitmap->ColorSpace()==B_RGBA32; BScreen screen; int *forward = new int[3*width*3]; memset( forward, 0, 3*width*3*sizeof(int) ); bitmap_rgb *srcbits = (bitmap_rgb*)bitmap->Bits(); int srcstride = bitmap->BytesPerRow()/sizeof(bitmap_rgb); uint8 *dstbits = (uint8*)bitmap_8bit->Bits(); int dststride = bitmap_8bit->BytesPerRow()/sizeof(uint8); for( int iy=0; iy<height; iy++ ) { for( int ix=0; ix<width; ix++ ) { bitmap_rgb rgb = srcbits[ix+iy*srcstride]; int red = clamp( rgb.red+forward[0+ix*3], 0, 255 ); int green = clamp( rgb.green+forward[1+ix*3], 0, 255 ); int blue = clamp( rgb.blue+forward[2+ix*3], 0, 255 ); #if 0 uint8 close_col = screen.IndexForColor( red, green, blue ); #else uint8 close_col = 0; uint32 close_err = 0x7fffffff; for( int i=0; i<256; i++ ) { rgb_color col = screen.ColorForIndex( i ); uint32 err = (col.red-red)*(col.red-red)*299 + (col.green-green)*(col.green-green)*587 + (col.blue-blue)*(col.blue-blue)*114; if( err<close_err ) { close_col = i; close_err = err; } } #endif rgb_color close_rgb = screen.ColorForIndex( close_col ); #if 1 if( srchasalpha && rgb.alpha<192 ) close_col = 255; #endif dstbits[ix+iy*dststride] = close_col; int err[3] = {red-close_rgb.red,green-close_rgb.green,blue-close_rgb.blue}; for( int i=0; i<3; i++ ) { #if 0 int h = err[i]>>1; int e1 = (7*h)>>3; int e2 = h-e1; h = err[i]-h; int e3 = (5*h)>>3; int e4 = h-e3; if( ix<width-1 ) { forward[i+(ix+1)*3]+=e1; forward[i+(ix+1)*3+3*width]+=e2; } forward[i+ix*3+3*width]+=e3; if( ix>0 ) forward[i+(ix-1)*3+3*width]+=e4; #else int e1 = (err[i]*8+21)/42; int e2 = (err[i]*4+21)/42; int e3 = (err[i]*2+21)/42; int e4 = (err[i]*4+21)/42; int e5 = (err[i]*8+21)/42; int e6 = (err[i]*4+21)/42; int e7 = (err[i]*2+21)/42; int e8 = (err[i]*1+21)/42; int e9 = (err[i]*2+21)/42; int e10 = (err[i]*4+21)/42; int e11 = (err[i]*2+21)/42; int e12 = (err[i]*1+21)/42; if( ix>1 ) { forward[i+(ix-2)*3+3*width]+=e3; forward[i+(ix-2)*3+2*3*width]+=e8; } if( ix>0 ) { forward[i+(ix-1)*3+3*width]+=e4; forward[i+(ix-1)*3+2*3*width]+=e9; } forward[i+(ix)*3+3*width]+=e5; forward[i+(ix)*3+2*3*width]+=e10; if( ix<width-1 ) { forward[i+(ix+1)*3]+=e1; forward[i+(ix+1)*3+3*width]+=e6; forward[i+(ix+1)*3+2*3*width]+=e11; } if( ix<width-2 ) { forward[i+(ix+1)*3]+=e2; forward[i+(ix+1)*3+3*width]+=e7; forward[i+(ix+1)*3+2*3*width]+=e12; } #endif } // uint8 col = screen.IndexForColor( rgb.red, rgb.green, rgb.blue ); // dstbits[ix+iy*dststride] = col; } memmove( forward, forward+3*width, 3*width*2*sizeof(int) ); memset( forward+3*width*2, 0, width*3*sizeof(int) ); } delete forward; return bitmap_8bit; }
/*! * \brief Turn a bitmap in grayscale * * The output bitmap will be of the same size and will use the same color space * of the original. Currently supports the following color spaces: B_CMAP8, * B_RGB24, B_RGB24_BIG, B_RGB32, B_BRGBA32, B_RGB32_BIG, B_RGBA32_BIG; * transparency is maintained. With all other color spaces, the function will * return a copy of the bitmap (note that B_GRAY8 and B_GRAY1 are already * grayscale). * * \todo Support more color spaces * * @param[in] bitmap The bitmap you want to turn in grayscale * * \return If bitmap is \c NULL or isn't valid, returns \c NULL, or a new * bitmap. It's up to you to delete the bitmap when you are done with * it. */ BBitmap * BitmapUtils::Grayscale(BBitmap *bitmap) { if (bitmap == NULL) return NULL; if (!bitmap->IsValid()) return NULL; // To obtain the disabled bitmap, we turn the original bitmap in // grayscale, converting each pixel from RGB to YCbCr and taking only // the Y component (luminance). int32 x, y, width, height, offset, row_length; unsigned char *i_bits, *o_bits; BBitmap *ret; uint8 Yc; ret = new BBitmap(bitmap->Bounds(), bitmap->ColorSpace()); i_bits = (unsigned char*)bitmap->Bits(); o_bits = (unsigned char*)ret->Bits(); height = bitmap->Bounds().IntegerHeight() + 1; width = bitmap->Bounds().IntegerWidth() + 1; row_length = bitmap->BytesPerRow(); switch (bitmap->ColorSpace()) { // B_CMAP8: each pixel (one byte) is the index of a color in the // system's color table. The table can be obtained from a BScreen // object. case B_CMAP8: { const rgb_color *color; const color_map *map; BScreen screen; map = screen.ColorMap(); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { offset = y * row_length + x; if (i_bits[offset] == B_TRANSPARENT_8_BIT) o_bits[offset] = B_TRANSPARENT_8_BIT; else { color = map->color_list + i_bits[offset]; Yc = __Yc(color->red, color->green, color->blue); o_bits[offset] = screen.IndexForColor(Yc, Yc, Yc); } } } } break; // B_RGB24 = BGR 8:8:8 case B_RGB24: for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { offset = y * row_length + x * 3; Yc = __Yc(i_bits[offset + 2], i_bits[offset + 1], i_bits[offset]); o_bits[offset + 1] = Yc; o_bits[offset + 2] = Yc; o_bits[offset + 3] = Yc; } } break; // B_RGB32 = BGRA 8:8:8:8 // B_RGBA32 = BGRx 8:8:8:8 case B_RGB32: case B_RGBA32: for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { offset = y * row_length + x * 4; Yc = __Yc(i_bits[offset + 2], i_bits[offset + 1], i_bits[offset]); o_bits[offset] = Yc; o_bits[offset + 1] = Yc; o_bits[offset + 2] = Yc; o_bits[offset + 3] = i_bits[offset]; } } break; // B_RGB24_BIG = RGB 8:8:8 case B_RGB24_BIG: for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { offset = y * row_length + x * 3; Yc = __Yc(i_bits[offset], i_bits[offset + 1], i_bits[offset + 2]); o_bits[offset + 1] = Yc; o_bits[offset + 2] = Yc; o_bits[offset + 3] = Yc; } } break; // B_RGB32_BIG = xRGB 8:8:8:8 // B_RGBA32_BIG = ARGB 8:8:8:8 case B_RGB32_BIG: case B_RGBA32_BIG: for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { offset = y * row_length + x * 4; Yc = __Yc(i_bits[offset + 1], i_bits[offset + 2], i_bits[offset + 3]); o_bits[offset] = i_bits[offset]; o_bits[offset + 1] = Yc; o_bits[offset + 2] = Yc; o_bits[offset + 3] = Yc; } } break; default: memcpy(ret->Bits(), bitmap->Bits(), bitmap->BitsLength()); break; } return ret; }