# Ticket #8367: edge3x.diff.2.v2

File edge3x.diff.2.v2, 26.0 KB (added by , 19 years ago) |
---|

Line | |
---|---|

1 | diff -ruN -u scummvm_old/backends/sdl/graphics.cpp scummvm_new/backends/sdl/graphics.cpp |

2 | --- scummvm_old/backends/sdl/graphics.cpp 2004-10-15 17:28:12.000000000 -0500 |

3 | +++ scummvm_new/backends/sdl/graphics.cpp 2004-11-06 04:54:22.000000000 -0600 |

4 | @@ -38,6 +38,7 @@ |

5 | {"hq3x", "HQ3x", GFX_HQ3X}, |

6 | {"tv2x", "TV2x", GFX_TV2X}, |

7 | {"dotmatrix", "DotMatrix", GFX_DOTMATRIX}, |

8 | + {"edge3x", "Edge3x", GFX_EDGE3X}, |

9 | {0, 0, 0} |

10 | }; |

11 | |

12 | @@ -105,6 +106,10 @@ |

13 | newScaleFactor = 2; |

14 | newScalerProc = DotMatrix; |

15 | break; |

16 | + case GFX_EDGE3X: |

17 | + newScaleFactor = 3; |

18 | + newScalerProc = Edge3x; |

19 | + break; |

20 | |

21 | default: |

22 | warning("unknown gfx mode %d", mode); |

23 | diff -ruN -u scummvm_old/backends/sdl/sdl-common.h scummvm_new/backends/sdl/sdl-common.h |

24 | --- scummvm_old/backends/sdl/sdl-common.h 2004-10-15 17:28:12.000000000 -0500 |

25 | +++ scummvm_new/backends/sdl/sdl-common.h 2004-11-06 04:54:22.000000000 -0600 |

26 | @@ -44,7 +44,8 @@ |

27 | { GFX_NORMAL, GFX_SUPER2XSAI, -1, -1 }, |

28 | { GFX_NORMAL, GFX_SUPEREAGLE, -1, -1 }, |

29 | { GFX_NORMAL, GFX_TV2X, -1, -1 }, |

30 | - { GFX_NORMAL, GFX_DOTMATRIX, -1, -1 } |

31 | + { GFX_NORMAL, GFX_DOTMATRIX, -1, -1 }, |

32 | + { GFX_NORMAL, -1, GFX_EDGE3X, -1 } |

33 | }; |

34 | |

35 | |

36 | diff -ruN -u scummvm_old/base/gameDetector.cpp scummvm_new/base/gameDetector.cpp |

37 | --- scummvm_old/base/gameDetector.cpp 2004-11-05 19:41:30.000000000 -0600 |

38 | +++ scummvm_new/base/gameDetector.cpp 2004-11-06 04:54:22.000000000 -0600 |

39 | @@ -56,7 +56,7 @@ |

40 | " -F, --no-fullscreen Force windowed mode\n" |

41 | " -g, --gfx-mode=MODE Select graphics scaler (normal,2x,3x,2xsai,\n" |

42 | " super2xsai,supereagle,advmame2x,advmame3x,hq2x,\n" |

43 | - " hq3x,tv2x,dotmatrix)\n" |

44 | + " hq3x,tv2x,dotmatrix,edge3x)\n" |

45 | " -e, --music-driver=MODE Select music driver (see README for details)\n" |

46 | " -q, --language=LANG Select language (en,de,fr,it,pt,es,jp,zh,kr,se,gb,\n" |

47 | " hb,ru,cz)\n" |

48 | diff -ruN -u scummvm_old/common/module.mk scummvm_new/common/module.mk |

49 | --- scummvm_old/common/module.mk 2004-08-26 16:01:22.000000000 -0500 |

50 | +++ scummvm_new/common/module.mk 2004-11-06 04:54:22.000000000 -0600 |

51 | @@ -20,7 +20,8 @@ |

52 | common/scaler/hq3x.o \ |

53 | common/scaler/scale2x.o \ |

54 | common/scaler/scale3x.o \ |

55 | - common/scaler/scalebit.o |

56 | + common/scaler/scalebit.o \ |

57 | + common/scaler/edge3x.o |

58 | |

59 | ifdef HAVE_NASM |

60 | MODULE_OBJS += \ |

61 | diff -ruN -u scummvm_old/common/scaler/edge3x.cpp scummvm_new/common/scaler/edge3x.cpp |

62 | --- scummvm_old/common/scaler/edge3x.cpp 1969-12-31 18:00:00.000000000 -0600 |

63 | +++ scummvm_new/common/scaler/edge3x.cpp 2004-11-06 04:54:34.000000000 -0600 |

64 | @@ -0,0 +1,816 @@ |

65 | +/* ScummVM - Scumm Interpreter |

66 | + * Copyright (C) 2001 Ludvig Strigeus |

67 | + * Copyright (C) 2001-2004 The ScummVM project |

68 | + * |

69 | + * This program is free software; you can redistribute it and/or |

70 | + * modify it under the terms of the GNU General Public License |

71 | + * as published by the Free Software Foundation; either version 2 |

72 | + * of the License, or (at your option) any later version. |

73 | + |

74 | + * This program is distributed in the hope that it will be useful, |

75 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |

76 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |

77 | + * GNU General Public License for more details. |

78 | + |

79 | + * You should have received a copy of the GNU General Public License |

80 | + * along with this program; if not, write to the Free Software |

81 | + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |

82 | + * |

83 | + * $Header: /cvsroot/scummvm/scummvm/common/scaler/hq3x.h,v 1.2 2004/01/06 12:45:28 fingolfin Exp $ |

84 | + * |

85 | + */ |

86 | + |

87 | +/* Another edge-directed 3x anti-aliasing scaler for ScummVM |

88 | + * |

89 | + * Author: Eric A. Welsh |

90 | + * |

91 | + * Features: |

92 | + * |

93 | + * More anti-aliasing than advmame3x, but at the cost of some blurriness |

94 | + * Low contrast areas are sharper than hq3x (which is very blurry) |

95 | + * High contrast areas aren't as nice as hq3x (which is VERY nice) |

96 | + * Overall, it strikes a good balance between sharpness and blurriness |

97 | + * It could probably use some further speed optimization |

98 | + * It's a bit slow... but ScummVM runs everything fine on my 1.53 Gz Athlon |

99 | + */ |

100 | + |

101 | +#include "common/stdafx.h" |

102 | +#include "common/scummsys.h" |

103 | +#include "common/system.h" |

104 | + |

105 | +#define SIN45 0.7071067811865 /* sin of 45 degrees */ |

106 | +#define LUMA_SHIFT 13 |

107 | + |

108 | +int32 luma_table[65536] = {0}; |

109 | +int edge3x_init_flag = 0; |

110 | +const uint16 *src_addr_min; /* start of src screen array */ |

111 | +const uint16 *src_addr_max; /* end of src screen array */ |

112 | +uint16 div3[189]; /* tables for pixel interpolation */ |

113 | +uint16 div9[567]; |

114 | + |

115 | +/* faster than FPU atan(), nearly as accurate as single precision */ |

116 | +double fast_atan(double v0) |

117 | +{ |

118 | + double v2; |

119 | + double v; |

120 | + |

121 | + v = fabs(v0); |

122 | + v2 = v*v; |

123 | + if (v > 1) |

124 | + { |

125 | + v2 = 1.570796326795 - |

126 | + v * (0.446350590597 + v2) / |

127 | + ((0.0900271979249 + v2) * (0.689454091687 + v2)); |

128 | + if (v0 < 0) return -v2; |

129 | + return v2; |

130 | + } |

131 | + v2 = v * (16.11094124024 + 7.191128136096 * v2) / |

132 | + ((1.450422895714 + v2) * (11.10775435761 + v2)); |

133 | + |

134 | + if (v0 < 0) return -v2; |

135 | + return v2; |

136 | +} |

137 | + |

138 | +/* More complicated and slower than most algorithms, but it fails far less |

139 | + * often (ie. assigning diagonal when it should be horizontal, or 90 degrees |

140 | + * from what it should be). Slow, but necessary to avoid artifacts. |

141 | + * |

142 | + * Edge detection takes up a whopping 53% of the CPU time spent in ScummVM. |

143 | + * Perhaps this could be optimized a bit more ... ? |

144 | + */ |

145 | +char convolve_edges_compass_luma(uint16 *pixels, int x_orig, int y_orig, |

146 | + int w) |

147 | +{ |

148 | + int32 *bptr; |

149 | + uint16 *pptr; |

150 | + int32 bplane[9]; |

151 | + int32 sums_dir1, sums_dir2, sums_dir3, sums_dir4; /* NE E SE S */ |

152 | + int32 max_sums; |

153 | + int32 mag, mag1, mag2; |

154 | + double angle; |

155 | + double new_angle = 999; |

156 | + int n; |

157 | + |

158 | + /* fill the 9 pixel window with luma values */ |

159 | + bptr = bplane; |

160 | + pptr = pixels; |

161 | + for (n = 0; n < 9; n++) |

162 | + *bptr++ = luma_table[*pptr++]; |

163 | + bptr = bplane; |

164 | + |

165 | + /* bi-directional edge detection */ |

166 | + /* mis-detections are easier to correct than the vector-based method */ |

167 | + mag = (bptr[2] + bptr[4] + bptr[6]) << 1; |

168 | + mag1 = labs((3 * (bptr[1] + bptr[3]) - mag) >> 1); |

169 | + mag2 = labs((3 * (bptr[5] + bptr[7]) - mag) >> 1); |

170 | + mag = mag1; |

171 | + if (mag2 > mag) mag = mag2; |

172 | + sums_dir1 = mag; |

173 | + |

174 | + mag = bptr[3] + bptr[4] + bptr[5]; |

175 | + mag1 = labs(bptr[0] + bptr[1] + bptr[2] - mag); |

176 | + mag2 = labs(bptr[6] + bptr[7] + bptr[8] - mag); |

177 | + mag = mag1; |

178 | + if (mag2 > mag) mag = mag2; |

179 | + sums_dir2 = mag; |

180 | + |

181 | + mag = (bptr[0] + bptr[4] + bptr[8]) << 1; |

182 | + mag1 = labs((3 * (bptr[1] + bptr[5]) - mag) >> 1); |

183 | + mag2 = labs((3 * (bptr[3] + bptr[7]) - mag) >> 1); |

184 | + mag = mag1; |

185 | + if (mag2 > mag) mag = mag2; |

186 | + sums_dir3 = mag; |

187 | + |

188 | + mag = bptr[1] + bptr[4] + bptr[7]; |

189 | + mag1 = labs(bptr[0] + bptr[3] + bptr[6] - mag); |

190 | + mag2 = labs(bptr[2] + bptr[5] + bptr[8] - mag); |

191 | + mag = mag1; |

192 | + if (mag2 > mag) mag = mag2; |

193 | + sums_dir4 = mag; |

194 | + |

195 | + /* find the strongest edge */ |

196 | + max_sums = sums_dir1; |

197 | + if (sums_dir2 > max_sums) max_sums = sums_dir2; |

198 | + if (sums_dir3 > max_sums) max_sums = sums_dir3; |

199 | + if (sums_dir4 > max_sums) max_sums = sums_dir4; |

200 | + |

201 | + n = 0; |

202 | + if (max_sums == sums_dir1) |

203 | + { |

204 | + new_angle = 135; |

205 | + n++; |

206 | + } |

207 | + if (max_sums == sums_dir2) |

208 | + { |

209 | + new_angle = 0; |

210 | + n++; |

211 | + } |

212 | + if (max_sums == sums_dir3) |

213 | + { |

214 | + new_angle = 45; |

215 | + n++; |

216 | + } |

217 | + if (max_sums == sums_dir4) |

218 | + { |

219 | + new_angle = 90; |

220 | + n++; |

221 | + } |

222 | + |

223 | + if (max_sums == 0) /* grid of solid color */ |

224 | + return 0; |

225 | + if (max_sums && n == 1) /* we found a strong edge */ |

226 | + { |

227 | + angle = new_angle; |

228 | + } |

229 | + else if (n == 4) /* x, +, . type patterns */ |

230 | + { |

231 | + return '*'; |

232 | + } |

233 | + else /* difficult edge, try vector method */ |

234 | + { |

235 | + double x, y; |

236 | + |

237 | + sums_dir1 = (3 * (bptr[1] - bptr[3] + bptr[5] - bptr[7])) >> 1; |

238 | + |

239 | + sums_dir2 = bptr[0] + bptr[1] + bptr[2] - |

240 | + bptr[6] - bptr[7] - bptr[8]; |

241 | + |

242 | + sums_dir3 = (3 * (bptr[1] + bptr[3] - bptr[5] - bptr[7])) >> 1; |

243 | + |

244 | + sums_dir4 = bptr[0] - bptr[2] + bptr[3] - |

245 | + bptr[5] + bptr[6] - bptr[8]; |

246 | + |

247 | + /* add the vectors in x,y space, North points up */ /* NE E SE S */ |

248 | + x = sums_dir1 * SIN45; |

249 | + x += sums_dir2; |

250 | + x += sums_dir3 * SIN45; |

251 | + y = sums_dir1 * SIN45; |

252 | + y -= sums_dir3 * SIN45; |

253 | + y -= sums_dir4; |

254 | + |

255 | + if (x) |

256 | + { |

257 | + angle = 57.29577951307 * fast_atan(y / x); |

258 | + if (x < 0) angle += 180; |

259 | + } |

260 | + else |

261 | + { |

262 | + if (y > 0) angle = 90; |

263 | + else if (y < 0) angle = -90; |

264 | + else return '*'; |

265 | + } |

266 | + } |

267 | + |

268 | + /* fix detection errors that are off by 90 degrees */ |

269 | + { |

270 | + int32 dist1, dist2; |

271 | + int32 dist_good, dist_bad; |

272 | + |

273 | + if (angle < 0) angle += 360; |

274 | + |

275 | + /* horizontal */ |

276 | + if ((angle > (180 - 22.5) && angle < (180 + 22.5)) || |

277 | + angle < 22.5 || angle > (360 - 22.5)) |

278 | + { |

279 | + dist1 = bptr[4] - bptr[3]; |

280 | + dist2 = bptr[4] - bptr[5]; |

281 | + dist_good = dist1*dist1 + dist2*dist2; |

282 | + |

283 | + dist1 = bptr[4] - bptr[1]; |

284 | + dist2 = bptr[4] - bptr[7]; |

285 | + dist_bad = dist1*dist1 + dist2*dist2; |

286 | + |

287 | + if (dist_good <= dist_bad) |

288 | + return '-'; |

289 | + |

290 | + return '|'; |

291 | + } |

292 | + |

293 | + /* vertical */ |

294 | + if ((angle > (90 - 22.5) && angle < (90 + 22.5)) || |

295 | + (angle > (90 - 22.5 + 180) && angle < (90 + 22.5 + 180))) |

296 | + { |

297 | + dist1 = bptr[4] - bptr[1]; |

298 | + dist2 = bptr[4] - bptr[7]; |

299 | + dist_good = dist1*dist1 + dist2*dist2; |

300 | + |

301 | + dist1 = bptr[4] - bptr[3]; |

302 | + dist2 = bptr[4] - bptr[5]; |

303 | + dist_bad = dist1*dist1 + dist2*dist2; |

304 | + |

305 | + if (dist_good <= dist_bad) |

306 | + return '|'; |

307 | + |

308 | + return '-'; |

309 | + } |

310 | + |

311 | + /* 45 */ |

312 | + if ((angle > (45 - 22.5) && angle < (45 + 22.5)) || |

313 | + (angle > (45 - 22.5 + 180) && angle < (45 + 22.5 + 180))) |

314 | + { |

315 | + dist1 = bptr[4] - bptr[0]; |

316 | + dist2 = bptr[4] - bptr[8]; |

317 | + dist_good = dist1*dist1 + dist2*dist2; |

318 | + |

319 | + /* side diags */ |

320 | + dist1 = bptr[1] - bptr[5]; |

321 | + dist2 = bptr[3] - bptr[7]; |

322 | + dist_good += dist1*dist1 + dist2*dist2; |

323 | + |

324 | + dist1 = bptr[4] - bptr[2]; |

325 | + dist2 = bptr[4] - bptr[6]; |

326 | + dist_bad = dist1*dist1 + dist2*dist2; |

327 | + |

328 | + /* side diags */ |

329 | + dist1 = bptr[1] - bptr[3]; |

330 | + dist2 = bptr[5] - bptr[7]; |

331 | + dist_bad += dist1*dist1 + dist2*dist2; |

332 | + |

333 | + if (dist_good <= dist_bad) |

334 | + return '\\'; |

335 | + |

336 | + return '/'; |

337 | + } |

338 | + |

339 | + /* 135 */ |

340 | + if ((angle > (135 - 22.5) && angle < (135 + 22.5)) || |

341 | + (angle > (135 - 22.5 + 180) && angle < (135 + 22.5 + 180))) |

342 | + { |

343 | + dist1 = bptr[4] - bptr[2]; |

344 | + dist2 = bptr[4] - bptr[6]; |

345 | + dist_good = dist1*dist1 + dist2*dist2; |

346 | + |

347 | + /* side diags */ |

348 | + dist1 = bptr[1] - bptr[3]; |

349 | + dist2 = bptr[5] - bptr[7]; |

350 | + dist_good += dist1*dist1 + dist2*dist2; |

351 | + |

352 | + dist1 = bptr[4] - bptr[0]; |

353 | + dist2 = bptr[4] - bptr[8]; |

354 | + dist_bad = dist1*dist1 + dist2*dist2; |

355 | + |

356 | + /* side diags */ |

357 | + dist1 = bptr[1] - bptr[5]; |

358 | + dist2 = bptr[3] - bptr[7]; |

359 | + dist_bad += dist1*dist1 + dist2*dist2; |

360 | + |

361 | + if (dist_good <= dist_bad) |

362 | + return '/'; |

363 | + |

364 | + return '\\'; |

365 | + } |

366 | + } |

367 | + |

368 | + return '*'; |

369 | +} |

370 | + |

371 | +/* From ScummVM hq2x/hq3x scalers (Maxim Stepin and Max Horn) */ |

372 | +#define highBits 0xF7DEF7DE |

373 | +#define lowBits 0x08210821 |

374 | +#define qhighBits 0xE79CE79C |

375 | +#define qlowBits 0x18631863 |

376 | +#define redblueMask 0xF81F |

377 | +#define greenMask 0x07E0 |

378 | + |

379 | +/* From ScummVM hq2x/hq3x scalers (Maxim Stepin and Max Horn) */ |

380 | +/** |

381 | + * Interpolate two 16 bit pixel pairs at once with equal weights 1. |

382 | + * In particular, A and B can contain two pixels/each in the upper |

383 | + * and lower halves. |

384 | + */ |

385 | +uint32 INTERPOLATE(uint32 A, uint32 B) |

386 | +{ |

387 | + return (((A & highBits) >> 1) + ((B & highBits) >> 1) + (A & B & lowBits)); |

388 | +} |

389 | + |

390 | +/* From ScummVM hq2x/hq3x scalers (Maxim Stepin and Max Horn) */ |

391 | +/** |

392 | + * Interpolate four 16 bit pixel pairs at once with equal weights 1. |

393 | + * In particular, A and B can contain two pixels/each in the upper |

394 | + * and lower halves. |

395 | + */ |

396 | +uint32 Q_INTERPOLATE(uint32 A, uint32 B, uint32 C, uint32 D) |

397 | +{ |

398 | + uint32 x = ((A & qhighBits) >> 2) + ((B & qhighBits) >> 2) + ((C & qhighBits) >> 2) + ((D & qhighBits) >> 2); |

399 | + uint32 y = ((A & qlowBits) + (B & qlowBits) + (C & qlowBits) + (D & qlowBits)) >> 2; |

400 | + |

401 | + y &= qlowBits; |

402 | + return x + y; |

403 | +} |

404 | + |

405 | +uint16 average_three_pixels(uint16 pixel1, uint16 pixel2, uint16 pixel3) |

406 | +{ |

407 | + uint32 rsum, gsum, bsum; |

408 | + |

409 | + rsum = (pixel1 & 0xF800); |

410 | + rsum += (pixel2 & 0xF800); |

411 | + rsum += (pixel3 & 0xF800); |

412 | + rsum = div3[rsum >> 11]; |

413 | + |

414 | + gsum = (pixel1 & 0x07E0); |

415 | + gsum += (pixel2 & 0x07E0); |

416 | + gsum += (pixel3 & 0x07E0); |

417 | + gsum = div3[gsum >> 5]; |

418 | + |

419 | + bsum = (pixel1 & 0x001F); |

420 | + bsum += (pixel2 & 0x001F); |

421 | + bsum += (pixel3 & 0x001F); |

422 | + bsum = div3[bsum]; |

423 | + |

424 | + return ((rsum << 11) | (gsum << 5) | bsum); |

425 | +} |

426 | + |

427 | +uint16 average_one_third(uint16 pixel1, uint16 pixel2) |

428 | +{ |

429 | + uint32 rsum, gsum, bsum; |

430 | + |

431 | + rsum = (pixel1 & 0xF800) << 1; |

432 | + rsum += (pixel2 & 0xF800); |

433 | + rsum = div3[rsum >> 11]; |

434 | + |

435 | + gsum = (pixel1 & 0x07E0) << 1; |

436 | + gsum += (pixel2 & 0x07E0); |

437 | + gsum = div3[gsum >> 5]; |

438 | + |

439 | + bsum = (pixel1 & 0x001F) << 1; |

440 | + bsum += (pixel2 & 0x001F); |

441 | + bsum = div3[bsum]; |

442 | + |

443 | + return ((rsum << 11) | (gsum << 5) | bsum); |

444 | +} |

445 | + |

446 | +/* interpolate a diagnoal pixel for linear interpolation on a 3x3 grid */ |

447 | +uint16 average_four_pixels_radial(uint16 pixel1, uint16 pixel2, |

448 | + uint16 pixel3, uint16 pixel4) |

449 | +{ |

450 | + uint32 rsum, gsum, bsum; |

451 | + |

452 | + rsum = (pixel1 & 0xF800) << 2; |

453 | + rsum += (pixel2 & 0xF800) << 1; |

454 | + rsum += (pixel3 & 0xF800) << 1; |

455 | + rsum += (pixel4 & 0xF800); |

456 | + rsum = div9[rsum >> 11]; |

457 | + |

458 | + gsum = (pixel1 & 0x07E0) << 2; |

459 | + gsum += (pixel2 & 0x07E0) << 1; |

460 | + gsum += (pixel3 & 0x07E0) << 1; |

461 | + gsum += (pixel4 & 0x07E0); |

462 | + gsum = div9[gsum >> 5]; |

463 | + |

464 | + bsum = (pixel1 & 0x001F) << 2; |

465 | + bsum += (pixel2 & 0x001F) << 1; |

466 | + bsum += (pixel3 & 0x001F) << 1; |

467 | + bsum += (pixel4 & 0x001F); |

468 | + bsum = div9[bsum]; |

469 | + |

470 | + return ((rsum << 11) | (gsum << 5) | bsum); |

471 | +} |

472 | + |

473 | +/* perform different interpolations depending on the detected edge */ |

474 | +void anti_alias_grid(uint8 *dptr, int dstPitch, |

475 | + uint16 *pixels, char edge_type) |

476 | +{ |

477 | + uint16 *dptr2; |

478 | + uint16 tmp_pixel; |

479 | + uint16 center = pixels[4]; |

480 | + static uint16 tmp[9]; |

481 | + uint16 *ptmp; |

482 | + |

483 | + switch (edge_type) |

484 | + { |

485 | + case 0: |

486 | + dptr2 = ((uint16 *) (dptr - dstPitch)) - 1; |

487 | + *dptr2++ = center; |

488 | + *dptr2++ = center; |

489 | + *dptr2 = center; |

490 | + dptr2 = ((uint16 *) dptr) - 1; |

491 | + *dptr2++ = center; |

492 | + *dptr2++ = center; |

493 | + *dptr2 = center; |

494 | + dptr2 = ((uint16 *) (dptr + dstPitch)) - 1; |

495 | + *dptr2++ = center; |

496 | + *dptr2++ = center; |

497 | + *dptr2 = center; |

498 | + |

499 | + return; |

500 | + |

501 | + break; |

502 | + |

503 | + case '-': |

504 | + tmp[0] = tmp[3] = tmp[6] = average_one_third(center, pixels[3]); |

505 | + tmp[1] = tmp[4] = tmp[7] = center; |

506 | + tmp[2] = tmp[5] = tmp[8] = average_one_third(center, pixels[5]); |

507 | + |

508 | + if (center == pixels[0]) tmp[0] = center; |

509 | + if (center == pixels[2]) tmp[2] = center; |

510 | + if (center == pixels[6]) tmp[6] = center; |

511 | + if (center == pixels[8]) tmp[8] = center; |

512 | + |

513 | + if (center == pixels[0] || center == pixels[6]) |

514 | + tmp[3] = INTERPOLATE(tmp[0], tmp[6]); |

515 | + if (center == pixels[2] || center == pixels[8]) |

516 | + tmp[5] = INTERPOLATE(tmp[2], tmp[8]); |

517 | + |

518 | + break; |

519 | + |

520 | + case '|': |

521 | + tmp[0] = tmp[1] = tmp[2] = average_one_third(center, pixels[1]); |

522 | + tmp[3] = tmp[4] = tmp[5] = center; |

523 | + tmp[6] = tmp[7] = tmp[8] = average_one_third(center, pixels[7]); |

524 | + |

525 | + if (center == pixels[0]) tmp[0] = center; |

526 | + if (center == pixels[2]) tmp[2] = center; |

527 | + if (center == pixels[6]) tmp[6] = center; |

528 | + if (center == pixels[8]) tmp[8] = center; |

529 | + |

530 | + if (center == pixels[0] || center == pixels[2]) |

531 | + tmp[1] = INTERPOLATE(tmp[0], tmp[2]); |

532 | + if (center == pixels[6] || center == pixels[8]) |

533 | + tmp[7] = INTERPOLATE(tmp[6], tmp[8]); |

534 | + |

535 | + break; |

536 | + |

537 | + case '/': |

538 | + if (pixels[1] == center && center == pixels[6]) |

539 | + tmp[0] = Q_INTERPOLATE(pixels[1], pixels[3], |

540 | + center, pixels[6]); |

541 | + else if (pixels[2] == pixels[3] && pixels[3] == center) |

542 | + tmp[0] = Q_INTERPOLATE(pixels[1], pixels[2], |

543 | + pixels[3], center); |

544 | + else |

545 | + tmp[0] = average_three_pixels(pixels[1], pixels[3], center); |

546 | + |

547 | + tmp[2] = average_one_third(center, pixels[2]); |

548 | + |

549 | + if (pixels[1] == center) |

550 | + tmp[1] = center; |

551 | + else |

552 | + { |

553 | + tmp_pixel = average_one_third(pixels[1], center); |

554 | + tmp[1] = Q_INTERPOLATE(tmp_pixel, center, |

555 | + tmp[0], |

556 | + tmp[2]); |

557 | + } |

558 | + |

559 | + tmp[6] = average_one_third(center, pixels[6]); |

560 | + if (pixels[2] == center && center == pixels[7]) |

561 | + tmp[8] = Q_INTERPOLATE(pixels[2], center, |

562 | + pixels[5], pixels[7]); |

563 | + else if (center == pixels[5] && pixels[5] == pixels[6]) |

564 | + tmp[8] = Q_INTERPOLATE(center, pixels[5], |

565 | + pixels[6], pixels[7]); |

566 | + else |

567 | + tmp[8] = average_three_pixels(center, pixels[5], pixels[7]); |

568 | + |

569 | + if (pixels[7] == center) |

570 | + tmp[7] = center; |

571 | + else |

572 | + { |

573 | + tmp_pixel = average_one_third(pixels[7], center); |

574 | + tmp[7] = Q_INTERPOLATE(tmp_pixel, center, |

575 | + tmp[6], |

576 | + tmp[8]); |

577 | + } |

578 | + |

579 | + if (pixels[3] == center) |

580 | + tmp[3] = center; |

581 | + else |

582 | + { |

583 | + tmp_pixel = average_one_third(pixels[3], center); |

584 | + tmp[3] = Q_INTERPOLATE(tmp_pixel, center, |

585 | + tmp[0], |

586 | + tmp[6]); |

587 | + } |

588 | + |

589 | + tmp[4] = center; |

590 | + |

591 | + if (pixels[5] == center) |

592 | + tmp[5] = center; |

593 | + else |

594 | + { |

595 | + tmp_pixel = average_one_third(pixels[5], center); |

596 | + tmp[5] = Q_INTERPOLATE(tmp_pixel, center, |

597 | + tmp[2], |

598 | + tmp[8]); |

599 | + } |

600 | + |

601 | + break; |

602 | + |

603 | + case '\\': |

604 | + tmp[0] = average_one_third(center, pixels[0]); |

605 | + |

606 | + if (pixels[1] == center && center == pixels[8]) |

607 | + tmp[2] = Q_INTERPOLATE(pixels[1], center, |

608 | + pixels[5], pixels[8]); |

609 | + else if (pixels[0] == center && center == pixels[5]) |

610 | + tmp[2] = Q_INTERPOLATE(pixels[0], pixels[1], |

611 | + center, pixels[5]); |

612 | + else |

613 | + tmp[2] = average_three_pixels(pixels[1], center, pixels[5]); |

614 | + |

615 | + if (pixels[1] == center) |

616 | + tmp[1] = center; |

617 | + else |

618 | + { |

619 | + tmp_pixel = average_one_third(pixels[1], center); |

620 | + tmp[1] = Q_INTERPOLATE(tmp_pixel, center, |

621 | + tmp[0], |

622 | + tmp[2]); |

623 | + } |

624 | + |

625 | + if (pixels[0] == center && center == pixels[7]) |

626 | + tmp[6] = Q_INTERPOLATE(pixels[0], pixels[3], |

627 | + center, pixels[7]); |

628 | + else if (pixels[3] == center && center == pixels[8]) |

629 | + tmp[6] = Q_INTERPOLATE(pixels[3], center, |

630 | + pixels[7], pixels[8]); |

631 | + else |

632 | + tmp[6] = average_three_pixels(pixels[3], center, pixels[7]); |

633 | + |

634 | + tmp[8] = average_one_third(center, pixels[8]); |

635 | + |

636 | + if (pixels[7] == center) |

637 | + tmp[7] = center; |

638 | + else |

639 | + { |

640 | + tmp_pixel = average_one_third(pixels[7], center); |

641 | + tmp[7] = Q_INTERPOLATE(tmp_pixel, center, |

642 | + tmp[6], |

643 | + tmp[8]); |

644 | + } |

645 | + |

646 | + if (pixels[3] == center) |

647 | + tmp[3] = center; |

648 | + else |

649 | + { |

650 | + tmp_pixel = average_one_third(pixels[3], center); |

651 | + tmp[3] = Q_INTERPOLATE(tmp_pixel, center, |

652 | + tmp[0], |

653 | + tmp[6]); |

654 | + } |

655 | + |

656 | + tmp[4] = center; |

657 | + |

658 | + if (pixels[5] == center) |

659 | + tmp[5] = center; |

660 | + else |

661 | + { |

662 | + tmp_pixel = average_one_third(pixels[5], center); |

663 | + tmp[5] = Q_INTERPOLATE(tmp_pixel, center, |

664 | + tmp[2], |

665 | + tmp[8]); |

666 | + } |

667 | + |

668 | + break; |

669 | + |

670 | + case '*': |

671 | + tmp[0] = average_four_pixels_radial(center, pixels[1], |

672 | + pixels[3], pixels[0]); |

673 | + tmp[1] = average_one_third(center, pixels[1]); |

674 | + tmp[2] = average_four_pixels_radial(center, pixels[1], |

675 | + pixels[5], pixels[2]); |

676 | + tmp[3] = average_one_third(center, pixels[3]); |

677 | + tmp[4] = center; |

678 | + tmp[5] = average_one_third(center, pixels[5]); |

679 | + tmp[6] = average_four_pixels_radial(center, pixels[3], |

680 | + pixels[7], pixels[6]); |

681 | + tmp[7] = average_one_third(center, pixels[7]); |

682 | + tmp[8] = average_four_pixels_radial(center, pixels[5], |

683 | + pixels[7], pixels[8]); |

684 | + |

685 | + |

686 | + if (center == pixels[1]) |

687 | + tmp[0] = tmp[2] = center; |

688 | + if (center == pixels[3]) |

689 | + tmp[0] = tmp[6] = center; |

690 | + if (center == pixels[5]) |

691 | + tmp[2] = tmp[8] = center; |

692 | + if (center == pixels[7]) |

693 | + tmp[6] = tmp[8] = center; |

694 | + |

695 | + if (center == pixels[0]) |

696 | + tmp[0] = center; |

697 | + if (center == pixels[2]) |

698 | + tmp[2] = center; |

699 | + if (center == pixels[6]) |

700 | + tmp[6] = center; |

701 | + if (center == pixels[8]) |

702 | + tmp[8] = center; |

703 | + |

704 | + break; |

705 | + |

706 | + default: |

707 | + return; |

708 | + |

709 | + break; |

710 | + } |

711 | + |

712 | + ptmp = tmp; |

713 | + dptr2 = ((uint16 *) (dptr - dstPitch)) - 1; |

714 | + *dptr2++ = *ptmp++; |

715 | + *dptr2++ = *ptmp++; |

716 | + *dptr2 = *ptmp++; |

717 | + dptr2 = ((uint16 *) dptr) - 1; |

718 | + *dptr2++ = *ptmp++; |

719 | + *dptr2++ = *ptmp++; |

720 | + *dptr2 = *ptmp++; |

721 | + dptr2 = ((uint16 *) (dptr + dstPitch)) - 1; |

722 | + *dptr2++ = *ptmp++; |

723 | + *dptr2++ = *ptmp++; |

724 | + *dptr2 = *ptmp; |

725 | +} |

726 | + |

727 | +/* perform edge detection, then interpolate */ |

728 | +void anti_alias_pass(const uint8 *src, uint8 *dst, |

729 | + int w, int h, int w_new, int h_new, |

730 | + int srcPitch, int dstPitch) |

731 | +{ |

732 | + int x, y; |

733 | + const uint16 *sptr16; |

734 | + uint16 *dptr16; |

735 | + |

736 | + for (y = 0; y < h; y++) |

737 | + { |

738 | + sptr16 = ((const uint16 *) (src + y * srcPitch)) + 0; |

739 | + dptr16 = ((uint16 *) (dst + y * dstPitch * 3 + dstPitch)) + 1 + 0; |

740 | + for (x = 0; x < w; x++, sptr16++, dptr16 += 3) |

741 | + { |

742 | + const uint16 *sptr2, *addr3; |

743 | + static uint16 pixels[9]; |

744 | + uint16 *pptr = pixels; |

745 | + char edge_type; |

746 | + |

747 | + sptr2 = ((const uint16 *) ((const uint8 *) sptr16 - srcPitch)) - 1; |

748 | + addr3 = ((const uint16 *) ((const uint8 *) sptr16 + srcPitch)) + 1; |

749 | + |

750 | + /* fill the 3x3 grid */ |

751 | + if (sptr2 >= src_addr_min && addr3 <= src_addr_max) |

752 | + { |

753 | + memcpy(pixels, sptr2, 3*sizeof(uint16)); |

754 | + memcpy(pixels+3, sptr16 - 1, 3*sizeof(uint16)); |

755 | + memcpy(pixels+6, addr3 - 2, 3*sizeof(uint16)); |

756 | + } |

757 | + else /* if we go off the screen, set the pixel to 0 */ |

758 | + { |

759 | + if (sptr2 >= src_addr_min && sptr2 <= src_addr_max) |

760 | + *pptr++ = *sptr2++; |

761 | + else { |

762 | + *pptr++ = 0; |

763 | + sptr2++; |

764 | + } |

765 | + if (sptr2 >= src_addr_min && sptr2 <= src_addr_max) |

766 | + *pptr++ = *sptr2++; |

767 | + else { |

768 | + *pptr++ = 0; |

769 | + sptr2++; |

770 | + } |

771 | + if (sptr2 >= src_addr_min && sptr2 <= src_addr_max) |

772 | + *pptr++ = *sptr2; |

773 | + else |

774 | + *pptr++ = 0; |

775 | + |

776 | + sptr2 = sptr16 - 1; |

777 | + if (sptr2 >= src_addr_min && sptr2 <= src_addr_max) |

778 | + *pptr++ = *sptr2++; |

779 | + else { |

780 | + *pptr++ = 0; |

781 | + sptr2++; |

782 | + } |

783 | + if (sptr2 >= src_addr_min && sptr2 <= src_addr_max) |

784 | + *pptr++ = *sptr2++; |

785 | + else { |

786 | + *pptr++ = 0; |

787 | + sptr2++; |

788 | + } |

789 | + if (sptr2 >= src_addr_min && sptr2 <= src_addr_max) |

790 | + *pptr++ = *sptr2; |

791 | + else |

792 | + *pptr++ = 0; |

793 | + |

794 | + sptr2 = addr3 - 2; |

795 | + if (sptr2 >= src_addr_min && sptr2 <= src_addr_max) |

796 | + *pptr++ = *sptr2++; |

797 | + else { |

798 | + *pptr++ = 0; |

799 | + sptr2++; |

800 | + } |

801 | + if (sptr2 >= src_addr_min && sptr2 <= src_addr_max) |

802 | + *pptr++ = *sptr2++; |

803 | + else { |

804 | + *pptr++ = 0; |

805 | + sptr2++; |

806 | + } |

807 | + if (sptr2 >= src_addr_min && sptr2 <= src_addr_max) |

808 | + *pptr = *sptr2; |

809 | + else |

810 | + *pptr = 0; |

811 | + } |

812 | + |

813 | + edge_type = convolve_edges_compass_luma(pixels, x, y, w); |

814 | + anti_alias_grid((uint8 *) dptr16, dstPitch, pixels, edge_type); |

815 | + } |

816 | + } |

817 | +} |

818 | + |

819 | +void initialize_tables(const uint8 *srcPtr, uint32 srcPitch, |

820 | + uint8 *dstPtr, uint32 dstPitch, |

821 | + int width, int height) |

822 | +{ |

823 | + double r_float, g_float, b_float, luma; |

824 | + int r, g, b; |

825 | + |

826 | + /* initialize luma table */ |

827 | + for (r = 0; r < 32; r++) |

828 | + { |

829 | + r_float = r / 31.0; |

830 | + |

831 | + for (g = 0; g < 64; g++) |

832 | + { |

833 | + g_float = g / 63.0; |

834 | + |

835 | + for (b = 0; b < 32; b++) |

836 | + { |

837 | + b_float = b / 31.0; |

838 | + |

839 | + luma = 0.299*r_float + 0.587*g_float + 0.114*b_float; |

840 | + luma_table[(r << 11) | (g << 5) | b] = |

841 | + (int32)(luma * (1 << LUMA_SHIFT) + 0.5); |

842 | + } |

843 | + } |

844 | + } |

845 | + |

846 | + /* initialize interpolation division tables */ |

847 | + for (r = 0; r <= 189; r++) |

848 | + div3[r] = ((r<<1)+1) / 6; |

849 | + for (r = 0; r <= 567; r++) |

850 | + div9[r] = ((r<<1)+1) / 18; |

851 | + |

852 | + /* set initial best guess on min/max screen addresses */ |

853 | + src_addr_min = (const uint16 *) srcPtr; |

854 | + src_addr_max = ((const uint16 *) (srcPtr + (height - 1) * srcPitch)) + |

855 | + (width - 1); |

856 | +} |

857 | + |

858 | +void Edge3x(const uint8 *srcPtr, uint32 srcPitch, |

859 | + uint8 *dstPtr, uint32 dstPitch, int width, int height) |

860 | +{ |

861 | + /* initialize stuff */ |

862 | + if (!edge3x_init_flag) |

863 | + { |

864 | + initialize_tables(srcPtr, srcPitch, dstPtr, dstPitch, width, height); |

865 | + edge3x_init_flag = 1; |

866 | + } |

867 | + |

868 | + /* ah ha, we're doing the whole screen, so we can save the bounds of the |

869 | + src array for later bounds checking */ |

870 | + if (width == g_system->getWidth() && |

871 | + height == g_system->getHeight()) |

872 | + { |

873 | + src_addr_min = (const uint16 *) srcPtr; |

874 | + src_addr_max = ((const uint16 *) (srcPtr + (height - 1) * srcPitch)) + |

875 | + (width - 1); |

876 | + } |

877 | + |

878 | + anti_alias_pass(srcPtr, dstPtr, width, height, |

879 | + 3*width, 3*height, srcPitch, dstPitch); |

880 | +} |

881 | diff -ruN -u scummvm_old/common/scaler.h scummvm_new/common/scaler.h |

882 | --- scummvm_old/common/scaler.h 2004-05-21 15:43:08.000000000 -0500 |

883 | +++ scummvm_new/common/scaler.h 2004-11-06 04:54:22.000000000 -0600 |

884 | @@ -45,6 +45,7 @@ |

885 | DECLARE_SCALER(DotMatrix); |

886 | DECLARE_SCALER(HQ2x); |

887 | DECLARE_SCALER(HQ3x); |

888 | +DECLARE_SCALER(Edge3x); |

889 | |

890 | FORCEINLINE int real2Aspect(int y) { |

891 | return y + (y + 1) / 5; |

892 | @@ -70,7 +71,8 @@ |

893 | GFX_HQ2X = 8, |

894 | GFX_HQ3X = 9, |

895 | GFX_TV2X = 10, |

896 | - GFX_DOTMATRIX = 11 |

897 | + GFX_DOTMATRIX = 11, |

898 | + GFX_EDGE3X = 12 |

899 | }; |

900 | |

901 |