| 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 | switch(bpp) { |
| 120 | case 1: |
| 121 | { |
| 122 | for(int32 looph = 0; looph < srcHeight; ++looph) { |
| 123 | for(int32 loopw = 0; loopw < srcWidth; ++ loopw) { |
| 124 | uint8 b = *(uint8*)(srcBits + (MAX(0, looph - 1) * srcBPR) |
| 125 | + (1 * loopw)); |
| 126 | uint8 d = *(uint8*)(srcBits + (looph * srcBPR) |
| 127 | + (1 * MAX(0, loopw - 1))); |
| 128 | uint8 e = *(uint8*)(srcBits + (looph * srcBPR) |
| 129 | + (1 * loopw)); |
| 130 | uint8 f = *(uint8*)(srcBits + (looph * srcBPR) |
| 131 | + (1 * MIN(srcWidth - 1, loopw+1))); |
| 132 | uint8 h = *(uint8*)(srcBits + (MIN(srcHeight - 1, looph + 1) |
| 133 | * srcBPR) + (1 * loopw)); |
| 134 | |
| 135 | uint8 e0 = d == b && b != f && d != h ? d : e; |
| 136 | uint8 e1 = b == f && b != d && f != h ? f : e; |
| 137 | uint8 e2 = d == h && d != b && h != f ? d : e; |
| 138 | uint8 e3 = h == f && d != h && b != f ? f : e; |
| 139 | |
| 140 | *(uint8*)(dstBits + looph * 2 * dstBPR |
| 141 | + loopw * 2 * 1) = e0; |
| 142 | *(uint8*)(dstBits + looph * 2 * dstBPR |
| 143 | + (loopw * 2 + 1) * 1) = e1; |
| 144 | *(uint8*)(dstBits + (looph * 2 + 1) * dstBPR |
| 145 | + loopw * 2 * 1) = e2; |
| 146 | *(uint8*)(dstBits + (looph * 2 + 1) * dstBPR |
| 147 | + (loopw * 2 + 1) * 1) = e3; |
| 148 | } |
| 149 | } |
| 150 | break; |
| 151 | } |
| 152 | case 4: |
| 153 | { |
| 154 | for(int32 looph = 0; looph < srcHeight; ++looph) { |
| 155 | for(int32 loopw = 0; loopw < srcWidth; ++ loopw) { |
| 156 | uint32 b = *(uint32*)(srcBits + (MAX(0, looph - 1) * srcBPR) |
| 157 | + (4 * loopw)); |
| 158 | uint32 d = *(uint32*)(srcBits + (looph * srcBPR) |
| 159 | + (4 * MAX(0, loopw - 1))); |
| 160 | uint32 e = *(uint32*)(srcBits + (looph * srcBPR) |
| 161 | + (4 * loopw)); |
| 162 | uint32 f = *(uint32*)(srcBits + (looph * srcBPR) |
| 163 | + (4 * MIN(srcWidth - 1,loopw + 1))); |
| 164 | uint32 h = |
| 165 | *(uint32*)(srcBits + (MIN(srcHeight - 1, looph + 1) |
| 166 | * srcBPR) + (4 * loopw)); |
| 167 | |
| 168 | uint32 e0 = d == b && b != f && d != h ? d : e; |
| 169 | uint32 e1 = b == f && b != d && f != h ? f : e; |
| 170 | uint32 e2 = d == h && d != b && h != f ? d : e; |
| 171 | uint32 e3 = h == f && d != h && b != f ? f : e; |
| 172 | |
| 173 | *(uint32*)(dstBits + looph * 2 * dstBPR |
| 174 | + loopw * 2 * 4) = e0; |
| 175 | *(uint32*)(dstBits + looph * 2 * dstBPR |
| 176 | + (loopw * 2 + 1) * 4) = e1; |
| 177 | *(uint32*)(dstBits + (looph * 2 + 1) * dstBPR |
| 178 | + loopw * 2 * 4) = e2; |
| 179 | *(uint32*)(dstBits + (looph * 2 + 1) * dstBPR |
| 180 | + (loopw * 2 + 1) * 4) = e3; |
| 181 | } |
| 182 | } |
| 183 | break; |
| 184 | } |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | |
484 | | // up scaling |
485 | | scale_bilinear((uint8*)result->Bits(), width, height, dstWidth, |
486 | | dstHeight, dstBPR); |
| 577 | if (dstWidth == 2 * width && dstHeight == 2 * height) { |
| 578 | // scale using the scale2x algorithm |
| 579 | BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1), |
| 580 | result->ColorSpace()); |
| 581 | converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8); |
| 582 | uint8* convertedBits = (uint8*)converted->Bits(); |
| 583 | int32 convertedBPR = converted->BytesPerRow(); |
| 584 | scale2x(convertedBits, dst, width, height, convertedBPR, dstBPR, 4); |
| 585 | } else { |
| 586 | // bilinear scaling |
| 587 | scale_bilinear(dst, width, height, dstWidth, dstHeight, dstBPR); |
| 588 | } |