1 /* 2 * ValidRect.cpp 3 * Copyright 1999-2000 Y.Takagi. All Rights Reserved. 4 * Copyright 2005 Michael Pfeiffer. All Rights Reserved. 5 * - Rewrote get_valid_rect from scratch. 6 */ 7 8 #include <Bitmap.h> 9 #include "ValidRect.h" 10 11 #define INLINE inline 12 13 class BoundsCalculator 14 { 15 public: 16 bool getValidRect(BBitmap *bitmap, RECT *rect); 17 18 private: 19 const uchar *fBits; 20 int fBPR; 21 int fLeft; 22 int fRight; 23 int fTop; 24 int fBottom; 25 int fWidth; 26 27 int fLeftBound; 28 int fRightBound; 29 30 INLINE bool isEmpty(const rgb_color *pixel); 31 32 INLINE bool isRowEmpty(const rgb_color *row); 33 34 INLINE const uchar *getRow(int x, int y); 35 36 int getTop(); 37 38 int getBottom(); 39 40 INLINE void updateLeftBound(const rgb_color *row); 41 INLINE void updateRightBound(const rgb_color *row); 42 }; 43 44 45 bool 46 BoundsCalculator::isEmpty(const rgb_color *pixel) 47 { 48 return pixel->red == 0xff && pixel->green == 0xff && pixel->blue == 0xff; 49 } 50 51 52 bool 53 BoundsCalculator::isRowEmpty(const rgb_color *row) 54 { 55 for (int x = 0; x < fWidth; x ++) { 56 if (!isEmpty(row)) { 57 return false; 58 } 59 row ++; 60 } 61 return true; 62 } 63 64 65 const uchar * 66 BoundsCalculator::getRow(int x, int y) 67 { 68 return fBits + x + fBPR * y; 69 } 70 71 72 int 73 BoundsCalculator::getTop() 74 { 75 const uchar* row = getRow(fLeft, fTop); 76 77 int top; 78 for (top = fTop; top <= fBottom; top ++) { 79 if (!isRowEmpty((const rgb_color*)row)) { 80 break; 81 } 82 row += fBPR; 83 } 84 85 return top; 86 } 87 88 89 int 90 BoundsCalculator::getBottom() 91 { 92 const uchar *row = getRow(fLeft, fBottom); 93 94 int bottom; 95 for (bottom = fBottom; bottom >= fTop; bottom --) { 96 if (!isRowEmpty((const rgb_color*)row)) { 97 break; 98 } 99 row -= fBPR; 100 } 101 102 return bottom; 103 } 104 105 106 void 107 BoundsCalculator::updateLeftBound(const rgb_color *row) 108 { 109 for (int x = fLeft; x < fLeftBound; x ++) { 110 if (!isEmpty(row)) { 111 fLeftBound = x; 112 return; 113 } 114 row ++; 115 } 116 } 117 118 119 void 120 BoundsCalculator::updateRightBound(const rgb_color *row) 121 { 122 row += fWidth - 1; 123 for (int x = fRight; x > fRightBound; x --) { 124 if (!isEmpty(row)) { 125 fRightBound = x; 126 return; 127 } 128 row --; 129 } 130 } 131 132 133 // returns false if the bitmap is empty or has wrong color space. 134 bool 135 BoundsCalculator::getValidRect(BBitmap *bitmap, RECT *rect) 136 { 137 enum { 138 kRectIsInvalid = false, 139 kRectIsEmpty = false, 140 kRectIsValid = true 141 }; 142 143 switch (bitmap->ColorSpace()) { 144 case B_RGB32: 145 case B_RGB32_BIG: 146 break; 147 default: 148 return kRectIsInvalid; 149 break; 150 }; 151 152 // initialize member variables 153 fBits = (uchar*)bitmap->Bits(); 154 fBPR = bitmap->BytesPerRow(); 155 156 fLeft = rect->left; 157 fRight = rect->right; 158 fTop = rect->top; 159 fBottom = rect->bottom; 160 161 fWidth = fRight - fLeft + 1; 162 163 // get top bound 164 fTop = getTop(); 165 if (fTop > fBottom) { 166 return kRectIsEmpty; 167 } 168 169 // get bottom bound 170 fBottom = getBottom(); 171 172 // calculate left and right bounds 173 fLeftBound = fRight + 1; 174 fRightBound = fLeft - 1; 175 176 const uchar *row = getRow(fLeft, fTop); 177 for (int y = fTop; y <= fBottom; y ++) { 178 updateLeftBound((const rgb_color*)row); 179 updateRightBound((const rgb_color*)row); 180 if (fLeft == fLeftBound && fRight == fRightBound) { 181 break; 182 } 183 row += fBPR; 184 } 185 186 // return bounds in rectangle 187 rect->left = fLeftBound; 188 rect->right = fRightBound; 189 rect->top = fTop; 190 rect->bottom = fBottom; 191 192 return kRectIsValid; 193 } 194 195 196 bool get_valid_rect(BBitmap *a_bitmap, RECT *rc) 197 { 198 BoundsCalculator calculator; 199 return calculator.getValidRect(a_bitmap, rc); 200 } 201 202 203 int color_space2pixel_depth(color_space cs) 204 { 205 int pixel_depth; 206 207 switch (cs) { 208 case B_GRAY1: /* Y0[0],Y1[0],Y2[0],Y3[0],Y4[0],Y5[0],Y6[0],Y7[0] */ 209 pixel_depth = 1; 210 break; 211 case B_GRAY8: /* Y[7:0] */ 212 case B_CMAP8: /* D[7:0] */ 213 pixel_depth = 8; 214 break; 215 case B_RGB15: /* G[2:0],B[4:0] -[0],R[4:0],G[4:3] */ 216 case B_RGB15_BIG: /* -[0],R[4:0],G[4:3] G[2:0],B[4:0] */ 217 pixel_depth = 16; 218 break; 219 case B_RGB32: /* B[7:0] G[7:0] R[7:0] -[7:0] */ 220 case B_RGB32_BIG: /* -[7:0] R[7:0] G[7:0] B[7:0] */ 221 pixel_depth = 32; 222 break; 223 default: 224 pixel_depth = 0; 225 break; 226 } 227 return pixel_depth; 228 } 229