Rewrote get_valid_rect because it contained bugs.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11437 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
acc60ee067
commit
5d4b78560b
@ -1,110 +1,194 @@
|
|||||||
/*
|
/*
|
||||||
* ValidRect.cpp
|
* ValidRect.cpp
|
||||||
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
|
* 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 <Bitmap.h>
|
||||||
#include "ValidRect.h"
|
#include "ValidRect.h"
|
||||||
|
|
||||||
bool get_valid_line_RGB32(
|
#define INLINE inline
|
||||||
const uchar *bits,
|
|
||||||
int width,
|
class BoundsCalculator
|
||||||
int *left,
|
|
||||||
int *right)
|
|
||||||
{
|
{
|
||||||
int i = 0;
|
public:
|
||||||
rgb_color c;
|
bool getValidRect(BBitmap *bitmap, RECT *rect);
|
||||||
const rgb_color *ptr = (const rgb_color *)bits;
|
|
||||||
|
|
||||||
while (i < *left) {
|
private:
|
||||||
c = *ptr++;
|
const uchar *fBits;
|
||||||
if (c.red != 0xff || c.green != 0xff || c.blue != 0xff) {
|
int fBPR;
|
||||||
*left = i;
|
int fLeft;
|
||||||
break;
|
int fRight;
|
||||||
}
|
int fTop;
|
||||||
i++;
|
int fBottom;
|
||||||
}
|
int fWidth;
|
||||||
|
|
||||||
if (i == width) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
row ++;
|
||||||
i = width - 1;
|
|
||||||
ptr = (const rgb_color *)bits + width - 1;
|
|
||||||
|
|
||||||
while (i > *right) {
|
|
||||||
c = *ptr--;
|
|
||||||
if (c.red != 0xff || c.green != 0xff || c.blue != 0xff) {
|
|
||||||
*right = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i--;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*PFN_GET_VALID_LINE)(const uchar *, int, int *, int *);
|
const uchar *
|
||||||
|
BoundsCalculator::getRow(int x, int y)
|
||||||
bool get_valid_rect(BBitmap *a_bitmap, RECT *rc)
|
|
||||||
{
|
{
|
||||||
int width = rc->right - rc->left + 1;
|
return fBits + x + fBPR * y;
|
||||||
int height = rc->bottom - rc->top + 1;
|
}
|
||||||
int delta = a_bitmap->BytesPerRow();
|
|
||||||
|
|
||||||
int left = width;
|
int
|
||||||
int right = 0;
|
BoundsCalculator::getTop()
|
||||||
int top = 0;
|
{
|
||||||
int bottom = 0;
|
const uchar* row = getRow(fLeft, fTop);
|
||||||
|
|
||||||
PFN_GET_VALID_LINE get_valid_line;
|
int top;
|
||||||
|
for (top = fTop; top <= fBottom; top ++) {
|
||||||
|
if (!isRowEmpty((const rgb_color*)row)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
row += fBPR;
|
||||||
|
}
|
||||||
|
|
||||||
switch (a_bitmap->ColorSpace()) {
|
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:
|
||||||
case B_RGB32_BIG:
|
case B_RGB32_BIG:
|
||||||
get_valid_line = get_valid_line_RGB32;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return kRectIsInvalid;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
int i = 0;
|
// initialize member variables
|
||||||
uchar *ptr = (uchar *)a_bitmap->Bits();
|
fBits = (uchar*)bitmap->Bits();
|
||||||
|
fBPR = bitmap->BytesPerRow();
|
||||||
|
|
||||||
while (i < height) {
|
fLeft = rect->left;
|
||||||
if (get_valid_line(ptr, width, &left, &right)) {
|
fRight = rect->right;
|
||||||
top = i;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
ptr += delta;
|
row += fBPR;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == height) {
|
// return bounds in rectangle
|
||||||
return false;
|
rect->left = fLeftBound;
|
||||||
}
|
rect->right = fRightBound;
|
||||||
|
rect->top = fTop;
|
||||||
|
rect->bottom = fBottom;
|
||||||
|
|
||||||
int j = height - 1;
|
return kRectIsValid;
|
||||||
ptr = (uchar *)a_bitmap->Bits() + (height - 1) * delta;
|
}
|
||||||
bool found_boundary = false;
|
|
||||||
|
|
||||||
while (j >= i) {
|
bool get_valid_rect(BBitmap *a_bitmap, RECT *rc)
|
||||||
if (get_valid_line(ptr, width, &left, &right)) {
|
{
|
||||||
if (!found_boundary) {
|
BoundsCalculator calculator;
|
||||||
bottom = j;
|
return calculator.getValidRect(a_bitmap, rc);
|
||||||
found_boundary = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ptr -= delta;
|
|
||||||
j--;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc->left = left;
|
|
||||||
rc->top = top;
|
|
||||||
rc->right = right;
|
|
||||||
rc->bottom = bottom;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int color_space2pixel_depth(color_space cs)
|
int color_space2pixel_depth(color_space cs)
|
||||||
|
Loading…
Reference in New Issue
Block a user