| 103 | static void |
| 104 | scale2x(const uint8* srcBits, uint8* dstBits, int32 srcWidth, int32 srcHeight, |
| 105 | int32 srcBPR, int32 dstBPR, int32 bpp) |
| 106 | { |
| 107 | /* |
| 108 | * This implements the AdvanceMAME Scale2x algorithm found on: |
| 109 | * http://scale2x.sourceforge.net/ |
| 110 | * |
| 111 | * It is an incredibly simple and powerful image doubling routine that does |
| 112 | * an astonishing job of doubling game graphic data while interpolating out |
| 113 | * the jaggies. |
| 114 | * |
| 115 | * Derived from the (public domain) SDL version of the library by Pete |
| 116 | * Shinners |
| 117 | */ |
| 118 | |
| 119 | int looph, loopw; |
| 120 | |
| 121 | switch(bpp) { |
| 122 | case 1: |
| 123 | { |
| 124 | uint8 E0, E1, E2, E3, B, D, E, F, H; |
| 125 | |
| 126 | for(looph = 0; looph < srcHeight; ++looph) { |
| 127 | for(loopw = 0; loopw < srcWidth; ++ loopw) { |
| 128 | B = *(uint8*)(srcBits + (MAX(0, looph - 1) * srcBPR) |
| 129 | + (1 * loopw)); |
| 130 | D = *(uint8*)(srcBits + (looph * srcBPR) |
| 131 | + (1 * MAX(0, loopw - 1))); |
| 132 | E = *(uint8*)(srcBits + (looph * srcBPR) + (1 * loopw)); |
| 133 | F = *(uint8*)(srcBits + (looph * srcBPR) |
| 134 | + (1 * MIN(srcWidth - 1, loopw+1))); |
| 135 | H = *(uint8*)(srcBits + (MIN(srcHeight - 1, looph + 1) |
| 136 | * srcBPR) + (1 * loopw)); |
| 137 | |
| 138 | E0 = D == B && B != F && D != H ? D : E; |
| 139 | E1 = B == F && B != D && F != H ? F : E; |
| 140 | E2 = D == H && D != B && H != F ? D : E; |
| 141 | E3 = H == F && D != H && B != F ? F : E; |
| 142 | |
| 143 | *(uint8*)(dstBits + looph * 2 * dstBPR |
| 144 | + loopw * 2 * 1) = E0; |
| 145 | *(uint8*)(dstBits + looph * 2 * dstBPR |
| 146 | + (loopw * 2 + 1) * 1) = E1; |
| 147 | *(uint8*)(dstBits + (looph * 2 + 1) * dstBPR |
| 148 | + loopw * 2 * 1) = E2; |
| 149 | *(uint8*)(dstBits + (looph * 2 + 1) * dstBPR |
| 150 | + (loopw * 2 + 1) * 1) = E3; |
| 151 | } |
| 152 | } |
| 153 | break; |
| 154 | } |
| 155 | case 4: |
| 156 | { |
| 157 | uint32 E0, E1, E2, E3, B, D, E, F, H; |
| 158 | |
| 159 | for(looph = 0; looph < srcHeight; ++looph) { |
| 160 | for(loopw = 0; loopw < srcWidth; ++ loopw) { |
| 161 | B = *(uint32*)(srcBits + (MAX(0, looph - 1) * srcBPR) |
| 162 | + (4 * loopw)); |
| 163 | D = *(uint32*)(srcBits + (looph * srcBPR) |
| 164 | + (4 * MAX(0, loopw - 1))); |
| 165 | E = *(uint32*)(srcBits + (looph * srcBPR) + (4 * loopw)); |
| 166 | F = *(uint32*)(srcBits + (looph * srcBPR) |
| 167 | + (4 * MIN(srcWidth - 1,loopw + 1))); |
| 168 | H = *(uint32*)(srcBits + (MIN(srcHeight - 1, looph + 1) |
| 169 | * srcBPR) + (4 * loopw)); |
| 170 | |
| 171 | E0 = D == B && B != F && D != H ? D : E; |
| 172 | E1 = B == F && B != D && F != H ? F : E; |
| 173 | E2 = D == H && D != B && H != F ? D : E; |
| 174 | E3 = H == F && D != H && B != F ? F : E; |
| 175 | |
| 176 | *(uint32*)(dstBits + looph * 2 * dstBPR |
| 177 | + loopw * 2 * 4) = E0; |
| 178 | *(uint32*)(dstBits + looph * 2 * dstBPR |
| 179 | + (loopw * 2 + 1) * 4) = E1; |
| 180 | *(uint32*)(dstBits + (looph * 2 + 1) * dstBPR |
| 181 | + loopw * 2 * 4) = E2; |
| 182 | *(uint32*)(dstBits + (looph * 2 + 1) * dstBPR |
| 183 | + (loopw * 2 + 1) * 4) = E3; |
| 184 | } |
| 185 | } |
| 186 | break; |
| 187 | } |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | |
484 | | // up scaling |
485 | | scale_bilinear((uint8*)result->Bits(), width, height, dstWidth, |
486 | | dstHeight, dstBPR); |
| 580 | if (dstWidth == 2 * width && dstHeight == 2 * height) { |
| 581 | // scale using the scale2x algorithm |
| 582 | BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1), |
| 583 | result->ColorSpace()); |
| 584 | converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8); |
| 585 | uint8* convertedBits = (uint8*)converted->Bits(); |
| 586 | int32 convertedBPR = converted->BytesPerRow(); |
| 587 | scale2x(convertedBits, dst, width, height, convertedBPR, dstBPR, 4); |
| 588 | } else { |
| 589 | // bilinear scaling |
| 590 | scale_bilinear(dst, width, height, dstWidth, dstHeight, dstBPR); |
| 591 | } |