git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11437 a95241bf-73f2-0310-859d-f6bbb57e9c96
220 lines
3.9 KiB
C++
220 lines
3.9 KiB
C++
/*
|
|
* ValidRect.cpp
|
|
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
|
|
* Copyright 2005 Michael Pfeiffer. All Rights Reserved.
|
|
* - Rewrote get_valid_rect from scratch.
|
|
*/
|
|
|
|
#include <Bitmap.h>
|
|
#include "ValidRect.h"
|
|
|
|
#define INLINE inline
|
|
|
|
class BoundsCalculator
|
|
{
|
|
public:
|
|
bool getValidRect(BBitmap *bitmap, RECT *rect);
|
|
|
|
private:
|
|
const uchar *fBits;
|
|
int fBPR;
|
|
int fLeft;
|
|
int fRight;
|
|
int fTop;
|
|
int fBottom;
|
|
int fWidth;
|
|
|
|
int fLeftBound;
|
|
int fRightBound;
|
|
|
|
INLINE bool isEmpty(const rgb_color *pixel);
|
|
|
|
INLINE bool isRowEmpty(const rgb_color *row);
|
|
|
|
INLINE const uchar *getRow(int x, int y);
|
|
|
|
int getTop();
|
|
|
|
int getBottom();
|
|
|
|
INLINE void updateLeftBound(const rgb_color *row);
|
|
INLINE void updateRightBound(const rgb_color *row);
|
|
};
|
|
|
|
bool
|
|
BoundsCalculator::isEmpty(const rgb_color *pixel)
|
|
{
|
|
return pixel->red == 0xff && pixel->green == 0xff && pixel->blue == 0xff;
|
|
}
|
|
|
|
|
|
bool
|
|
BoundsCalculator::isRowEmpty(const rgb_color *row)
|
|
{
|
|
for (int x = 0; x < fWidth; x ++) {
|
|
if (!isEmpty(row)) {
|
|
return false;
|
|
}
|
|
row ++;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const uchar *
|
|
BoundsCalculator::getRow(int x, int y)
|
|
{
|
|
return fBits + x + fBPR * y;
|
|
}
|
|
|
|
int
|
|
BoundsCalculator::getTop()
|
|
{
|
|
const uchar* row = getRow(fLeft, fTop);
|
|
|
|
int top;
|
|
for (top = fTop; top <= fBottom; top ++) {
|
|
if (!isRowEmpty((const rgb_color*)row)) {
|
|
break;
|
|
}
|
|
row += fBPR;
|
|
}
|
|
|
|
return top;
|
|
}
|
|
|
|
int
|
|
BoundsCalculator::getBottom()
|
|
{
|
|
const uchar *row = getRow(fLeft, fBottom);
|
|
|
|
int bottom;
|
|
for (bottom = fBottom; bottom >= fTop; bottom --) {
|
|
if (!isRowEmpty((const rgb_color*)row)) {
|
|
break;
|
|
}
|
|
row -= fBPR;
|
|
}
|
|
|
|
return bottom;
|
|
}
|
|
|
|
void
|
|
BoundsCalculator::updateLeftBound(const rgb_color *row)
|
|
{
|
|
for (int x = fLeft; x < fLeftBound; x ++) {
|
|
if (!isEmpty(row)) {
|
|
fLeftBound = x;
|
|
return;
|
|
}
|
|
row ++;
|
|
}
|
|
}
|
|
|
|
void
|
|
BoundsCalculator::updateRightBound(const rgb_color *row)
|
|
{
|
|
row += fWidth - 1;
|
|
for (int x = fRight; x > fRightBound; x --) {
|
|
if (!isEmpty(row)) {
|
|
fRightBound = x;
|
|
return;
|
|
}
|
|
row --;
|
|
}
|
|
}
|
|
|
|
// returns false if the bitmap is empty or has wrong color space.
|
|
bool
|
|
BoundsCalculator::getValidRect(BBitmap *bitmap, RECT *rect)
|
|
{
|
|
enum {
|
|
kRectIsInvalid = false,
|
|
kRectIsEmpty = false,
|
|
kRectIsValid = true
|
|
};
|
|
|
|
switch (bitmap->ColorSpace()) {
|
|
case B_RGB32:
|
|
case B_RGB32_BIG:
|
|
break;
|
|
default:
|
|
return kRectIsInvalid;
|
|
break;
|
|
};
|
|
|
|
// initialize member variables
|
|
fBits = (uchar*)bitmap->Bits();
|
|
fBPR = bitmap->BytesPerRow();
|
|
|
|
fLeft = rect->left;
|
|
fRight = rect->right;
|
|
fTop = rect->top;
|
|
fBottom = rect->bottom;
|
|
|
|
fWidth = fRight - fLeft + 1;
|
|
|
|
// get top bound
|
|
fTop = getTop();
|
|
if (fTop > fBottom) {
|
|
return kRectIsEmpty;
|
|
}
|
|
|
|
// get bottom bound
|
|
fBottom = getBottom();
|
|
|
|
// calculate left and right bounds
|
|
fLeftBound = fRight + 1;
|
|
fRightBound = fLeft - 1;
|
|
|
|
const uchar *row = getRow(fLeft, fTop);
|
|
for (int y = fTop; y <= fBottom; y ++) {
|
|
updateLeftBound((const rgb_color*)row);
|
|
updateRightBound((const rgb_color*)row);
|
|
if (fLeft == fLeftBound && fRight == fRightBound) {
|
|
break;
|
|
}
|
|
row += fBPR;
|
|
}
|
|
|
|
// return bounds in rectangle
|
|
rect->left = fLeftBound;
|
|
rect->right = fRightBound;
|
|
rect->top = fTop;
|
|
rect->bottom = fBottom;
|
|
|
|
return kRectIsValid;
|
|
}
|
|
|
|
bool get_valid_rect(BBitmap *a_bitmap, RECT *rc)
|
|
{
|
|
BoundsCalculator calculator;
|
|
return calculator.getValidRect(a_bitmap, rc);
|
|
}
|
|
|
|
int color_space2pixel_depth(color_space cs)
|
|
{
|
|
int pixel_depth;
|
|
|
|
switch (cs) {
|
|
case B_GRAY1: /* Y0[0],Y1[0],Y2[0],Y3[0],Y4[0],Y5[0],Y6[0],Y7[0] */
|
|
pixel_depth = 1;
|
|
break;
|
|
case B_GRAY8: /* Y[7:0] */
|
|
case B_CMAP8: /* D[7:0] */
|
|
pixel_depth = 8;
|
|
break;
|
|
case B_RGB15: /* G[2:0],B[4:0] -[0],R[4:0],G[4:3] */
|
|
case B_RGB15_BIG: /* -[0],R[4:0],G[4:3] G[2:0],B[4:0] */
|
|
pixel_depth = 16;
|
|
break;
|
|
case B_RGB32: /* B[7:0] G[7:0] R[7:0] -[7:0] */
|
|
case B_RGB32_BIG: /* -[7:0] R[7:0] G[7:0] B[7:0] */
|
|
pixel_depth = 32;
|
|
break;
|
|
default:
|
|
pixel_depth = 0;
|
|
break;
|
|
}
|
|
return pixel_depth;
|
|
}
|