예제 #1
0
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 */
예제 #2
0
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();
}
예제 #3
0
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 );

	}
}
예제 #4
0
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;
}
예제 #6
0
/*!
 * \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;
}