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