16f9cddeaSMichael Pfeiffer/*
26f9cddeaSMichael Pfeiffer * ValidRect.cpp
36f9cddeaSMichael Pfeiffer * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
45d4b7856SMichael Pfeiffer * Copyright 2005 Michael Pfeiffer. All Rights Reserved.
55d4b7856SMichael Pfeiffer * - Rewrote get_valid_rect from scratch.
66f9cddeaSMichael Pfeiffer */
76f9cddeaSMichael Pfeiffer
86f9cddeaSMichael Pfeiffer#include <Bitmap.h>
96f9cddeaSMichael Pfeiffer#include "ValidRect.h"
106f9cddeaSMichael Pfeiffer
115d4b7856SMichael Pfeiffer#define INLINE inline
125d4b7856SMichael Pfeiffer
135d4b7856SMichael Pfeifferclass BoundsCalculator
146f9cddeaSMichael Pfeiffer{
155d4b7856SMichael Pfeifferpublic:
165d4b7856SMichael Pfeiffer	bool getValidRect(BBitmap *bitmap, RECT *rect);
175d4b7856SMichael Pfeiffer
185d4b7856SMichael Pfeifferprivate:
195d4b7856SMichael Pfeiffer	const uchar *fBits;
205d4b7856SMichael Pfeiffer	int fBPR;
215d4b7856SMichael Pfeiffer	int fLeft;
225d4b7856SMichael Pfeiffer	int fRight;
235d4b7856SMichael Pfeiffer	int fTop;
245d4b7856SMichael Pfeiffer	int fBottom;
255d4b7856SMichael Pfeiffer	int fWidth;
265d4b7856SMichael Pfeiffer
275d4b7856SMichael Pfeiffer	int fLeftBound;
285d4b7856SMichael Pfeiffer	int fRightBound;
295d4b7856SMichael Pfeiffer
305d4b7856SMichael Pfeiffer	INLINE bool isEmpty(const rgb_color *pixel);
315d4b7856SMichael Pfeiffer
325d4b7856SMichael Pfeiffer	INLINE bool isRowEmpty(const rgb_color *row);
335d4b7856SMichael Pfeiffer
345d4b7856SMichael Pfeiffer	INLINE const uchar *getRow(int x, int y);
355d4b7856SMichael Pfeiffer
365d4b7856SMichael Pfeiffer	int getTop();
375d4b7856SMichael Pfeiffer
385d4b7856SMichael Pfeiffer	int getBottom();
395d4b7856SMichael Pfeiffer
405d4b7856SMichael Pfeiffer	INLINE void updateLeftBound(const rgb_color *row);
415d4b7856SMichael Pfeiffer	INLINE void updateRightBound(const rgb_color *row);
425d4b7856SMichael Pfeiffer};
435d4b7856SMichael Pfeiffer
4408d759feSMichael Pfeiffer
455d4b7856SMichael Pfeifferbool
465d4b7856SMichael PfeifferBoundsCalculator::isEmpty(const rgb_color *pixel)
475d4b7856SMichael Pfeiffer{
485d4b7856SMichael Pfeiffer	return pixel->red == 0xff && pixel->green == 0xff && pixel->blue == 0xff;
495d4b7856SMichael Pfeiffer}
505d4b7856SMichael Pfeiffer
515d4b7856SMichael Pfeiffer
525d4b7856SMichael Pfeifferbool
535d4b7856SMichael PfeifferBoundsCalculator::isRowEmpty(const rgb_color *row)
545d4b7856SMichael Pfeiffer{
555d4b7856SMichael Pfeiffer	for (int x = 0; x < fWidth; x ++) {
565d4b7856SMichael Pfeiffer		if (!isEmpty(row)) {
575d4b7856SMichael Pfeiffer			return false;
586f9cddeaSMichael Pfeiffer		}
595d4b7856SMichael Pfeiffer		row ++;
606f9cddeaSMichael Pfeiffer	}
615d4b7856SMichael Pfeiffer	return true;
625d4b7856SMichael Pfeiffer}
636f9cddeaSMichael Pfeiffer
6408d759feSMichael Pfeiffer
655d4b7856SMichael Pfeifferconst uchar *
665d4b7856SMichael PfeifferBoundsCalculator::getRow(int x, int y)
675d4b7856SMichael Pfeiffer{
685d4b7856SMichael Pfeiffer	return fBits + x + fBPR * y;
695d4b7856SMichael Pfeiffer}
7008d759feSMichael Pfeiffer
7108d759feSMichael Pfeiffer
725d4b7856SMichael Pfeifferint
735d4b7856SMichael PfeifferBoundsCalculator::getTop()
745d4b7856SMichael Pfeiffer{
755d4b7856SMichael Pfeiffer	const uchar* row = getRow(fLeft, fTop);
765d4b7856SMichael Pfeiffer
775d4b7856SMichael Pfeiffer	int top;
785d4b7856SMichael Pfeiffer	for (top = fTop; top <= fBottom; top ++) {
795d4b7856SMichael Pfeiffer		if (!isRowEmpty((const rgb_color*)row)) {
805d4b7856SMichael Pfeiffer			break;
815d4b7856SMichael Pfeiffer		}
825d4b7856SMichael Pfeiffer		row += fBPR;
836f9cddeaSMichael Pfeiffer	}
845d4b7856SMichael Pfeiffer
855d4b7856SMichael Pfeiffer	return top;
865d4b7856SMichael Pfeiffer}
876f9cddeaSMichael Pfeiffer
8808d759feSMichael Pfeiffer
895d4b7856SMichael Pfeifferint
905d4b7856SMichael PfeifferBoundsCalculator::getBottom()
915d4b7856SMichael Pfeiffer{
925d4b7856SMichael Pfeiffer	const uchar *row = getRow(fLeft, fBottom);
936f9cddeaSMichael Pfeiffer
945d4b7856SMichael Pfeiffer	int bottom;
955d4b7856SMichael Pfeiffer	for (bottom = fBottom; bottom >= fTop; bottom --) {
965d4b7856SMichael Pfeiffer		if (!isRowEmpty((const rgb_color*)row)) {
976f9cddeaSMichael Pfeiffer			break;
986f9cddeaSMichael Pfeiffer		}
995d4b7856SMichael Pfeiffer		row -= fBPR;
1006f9cddeaSMichael Pfeiffer	}
1015d4b7856SMichael Pfeiffer
1025d4b7856SMichael Pfeiffer	return bottom;
1036f9cddeaSMichael Pfeiffer}
1046f9cddeaSMichael Pfeiffer
10508d759feSMichael Pfeiffer
1065d4b7856SMichael Pfeiffervoid
1075d4b7856SMichael PfeifferBoundsCalculator::updateLeftBound(const rgb_color *row)
1086f9cddeaSMichael Pfeiffer{
1095d4b7856SMichael Pfeiffer	for (int x = fLeft; x < fLeftBound; x ++) {
1105d4b7856SMichael Pfeiffer		if (!isEmpty(row)) {
1115d4b7856SMichael Pfeiffer			fLeftBound = x;
1125d4b7856SMichael Pfeiffer			return;
1136f9cddeaSMichael Pfeiffer		}
1145d4b7856SMichael Pfeiffer		row ++;
1156f9cddeaSMichael Pfeiffer	}
1165d4b7856SMichael Pfeiffer}
1176f9cddeaSMichael Pfeiffer
11808d759feSMichael Pfeiffer
1195d4b7856SMichael Pfeiffervoid
1205d4b7856SMichael PfeifferBoundsCalculator::updateRightBound(const rgb_color *row)
1215d4b7856SMichael Pfeiffer{
1225d4b7856SMichael Pfeiffer	row += fWidth - 1;
1235d4b7856SMichael Pfeiffer	for (int x = fRight; x > fRightBound; x --) {
1245d4b7856SMichael Pfeiffer		if (!isEmpty(row)) {
1255d4b7856SMichael Pfeiffer			fRightBound = x;
1265d4b7856SMichael Pfeiffer			return;
1275d4b7856SMichael Pfeiffer		}
1285d4b7856SMichael Pfeiffer		row --;
1296f9cddeaSMichael Pfeiffer	}
1305d4b7856SMichael Pfeiffer}
1316f9cddeaSMichael Pfeiffer
13208d759feSMichael Pfeiffer
1335d4b7856SMichael Pfeiffer// returns false if the bitmap is empty or has wrong color space.
1345d4b7856SMichael Pfeifferbool
1355d4b7856SMichael PfeifferBoundsCalculator::getValidRect(BBitmap *bitmap, RECT *rect)
1365d4b7856SMichael Pfeiffer{
1375d4b7856SMichael Pfeiffer	enum {
1385d4b7856SMichael Pfeiffer		kRectIsInvalid = false,
1395d4b7856SMichael Pfeiffer		kRectIsEmpty = false,
1405d4b7856SMichael Pfeiffer		kRectIsValid = true
1415d4b7856SMichael Pfeiffer	};
1425d4b7856SMichael Pfeiffer
1435d4b7856SMichael Pfeiffer	switch (bitmap->ColorSpace()) {
1445d4b7856SMichael Pfeiffer		case B_RGB32:
1455d4b7856SMichael Pfeiffer		case B_RGB32_BIG:
1465d4b7856SMichael Pfeiffer			break;
1475d4b7856SMichael Pfeiffer		default:
1485d4b7856SMichael Pfeiffer			return kRectIsInvalid;
1495d4b7856SMichael Pfeiffer			break;
1505d4b7856SMichael Pfeiffer	};
1516f9cddeaSMichael Pfeiffer
1525d4b7856SMichael Pfeiffer	// initialize member variables
1535d4b7856SMichael Pfeiffer	fBits = (uchar*)bitmap->Bits();
1545d4b7856SMichael Pfeiffer	fBPR  = bitmap->BytesPerRow();
1555d4b7856SMichael Pfeiffer
1565d4b7856SMichael Pfeiffer	fLeft   = rect->left;
1575d4b7856SMichael Pfeiffer	fRight  = rect->right;
1585d4b7856SMichael Pfeiffer	fTop    = rect->top;
1595d4b7856SMichael Pfeiffer	fBottom = rect->bottom;
1605d4b7856SMichael Pfeiffer
1615d4b7856SMichael Pfeiffer	fWidth = fRight - fLeft + 1;
1625d4b7856SMichael Pfeiffer
1635d4b7856SMichael Pfeiffer	// get top bound
1645d4b7856SMichael Pfeiffer	fTop = getTop();
1655d4b7856SMichael Pfeiffer	if (fTop > fBottom) {
1665d4b7856SMichael Pfeiffer		return kRectIsEmpty;
1675d4b7856SMichael Pfeiffer	}
1685d4b7856SMichael Pfeiffer
1695d4b7856SMichael Pfeiffer	// get bottom bound
1705d4b7856SMichael Pfeiffer	fBottom = getBottom();
1715d4b7856SMichael Pfeiffer
1725d4b7856SMichael Pfeiffer	// calculate left and right bounds
1735d4b7856SMichael Pfeiffer	fLeftBound = fRight + 1;
1745d4b7856SMichael Pfeiffer	fRightBound = fLeft - 1;
1755d4b7856SMichael Pfeiffer
1765d4b7856SMichael Pfeiffer	const uchar *row = getRow(fLeft, fTop);
1775d4b7856SMichael Pfeiffer	for (int y = fTop; y <= fBottom; y ++) {
1785d4b7856SMichael Pfeiffer		updateLeftBound((const rgb_color*)row);
1795d4b7856SMichael Pfeiffer		updateRightBound((const rgb_color*)row);
1805d4b7856SMichael Pfeiffer		if (fLeft == fLeftBound && fRight == fRightBound) {
1815d4b7856SMichael Pfeiffer			break;
1826f9cddeaSMichael Pfeiffer		}
1835d4b7856SMichael Pfeiffer		row += fBPR;
1846f9cddeaSMichael Pfeiffer	}
1855d4b7856SMichael Pfeiffer
1865d4b7856SMichael Pfeiffer	// return bounds in rectangle
1875d4b7856SMichael Pfeiffer	rect->left = fLeftBound;
1885d4b7856SMichael Pfeiffer	rect->right = fRightBound;
1895d4b7856SMichael Pfeiffer	rect->top = fTop;
1905d4b7856SMichael Pfeiffer	rect->bottom = fBottom;
1915d4b7856SMichael Pfeiffer
1925d4b7856SMichael Pfeiffer	return kRectIsValid;
1935d4b7856SMichael Pfeiffer}
1946f9cddeaSMichael Pfeiffer
19508d759feSMichael Pfeiffer
1965d4b7856SMichael Pfeifferbool get_valid_rect(BBitmap *a_bitmap, RECT *rc)
1975d4b7856SMichael Pfeiffer{
1985d4b7856SMichael Pfeiffer	BoundsCalculator calculator;
1995d4b7856SMichael Pfeiffer	return calculator.getValidRect(a_bitmap, rc);
2006f9cddeaSMichael Pfeiffer}
2016f9cddeaSMichael Pfeiffer
20208d759feSMichael Pfeiffer
2036f9cddeaSMichael Pfeifferint color_space2pixel_depth(color_space cs)
2046f9cddeaSMichael Pfeiffer{
2056f9cddeaSMichael Pfeiffer	int pixel_depth;
2066f9cddeaSMichael Pfeiffer
2076f9cddeaSMichael Pfeiffer	switch (cs) {
2086f9cddeaSMichael Pfeiffer	case B_GRAY1:		/* Y0[0],Y1[0],Y2[0],Y3[0],Y4[0],Y5[0],Y6[0],Y7[0]	*/
2096f9cddeaSMichael Pfeiffer		pixel_depth = 1;
2106f9cddeaSMichael Pfeiffer		break;
2116f9cddeaSMichael Pfeiffer	case B_GRAY8:		/* Y[7:0]											*/
2126f9cddeaSMichael Pfeiffer	case B_CMAP8:		/* D[7:0]  											*/
2136f9cddeaSMichael Pfeiffer		pixel_depth = 8;
2146f9cddeaSMichael Pfeiffer		break;
2156f9cddeaSMichael Pfeiffer	case B_RGB15:		/* G[2:0],B[4:0]  	   -[0],R[4:0],G[4:3]			*/
2166f9cddeaSMichael Pfeiffer	case B_RGB15_BIG:	/* -[0],R[4:0],G[4:3]  G[2:0],B[4:0]				*/
2176f9cddeaSMichael Pfeiffer		pixel_depth = 16;
2186f9cddeaSMichael Pfeiffer		break;
2196f9cddeaSMichael Pfeiffer	case B_RGB32:		/* B[7:0]  G[7:0]  R[7:0]  -[7:0]					*/
2206f9cddeaSMichael Pfeiffer	case B_RGB32_BIG:	/* -[7:0]  R[7:0]  G[7:0]  B[7:0]					*/
2216f9cddeaSMichael Pfeiffer		pixel_depth = 32;
2226f9cddeaSMichael Pfeiffer		break;
2236f9cddeaSMichael Pfeiffer	default:
2246f9cddeaSMichael Pfeiffer		pixel_depth = 0;
2256f9cddeaSMichael Pfeiffer		break;
2266f9cddeaSMichael Pfeiffer	}
2276f9cddeaSMichael Pfeiffer	return pixel_depth;
2286f9cddeaSMichael Pfeiffer}
229