- Timestamp:
- Jan 23, 2008, 12:32:01 AM (15 years ago)
- Location:
- www/labs
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
www/labs/img2oric.c
r2209 r2212 5 5 * 6 6 * $Id$ 7 * 8 * Changes: 9 * Jan 18, 2008: initial release 10 * Jan 23, 2008: add support for inverse video on attribute change 11 * improve Floyd-Steinberg coefficient values 7 12 * 8 13 * This program is free software. It comes without any warranty, to … … 28 33 /* 29 34 * Image dimensions and recursion depth. DEPTH = 2 is a reasonable value, 30 * higher values may improve the results but at the cost of significantly31 * longer computation times.35 * DEPTH = 3 gives good quality, and higher values may improve the results 36 * even more but at the cost of significantly longer computation times. 32 37 */ 33 38 #define WIDTH 240 … … 52 57 * +-------+-------+-------+ 53 58 */ 54 #define FS0 1 259 #define FS0 15 55 60 #define FS1 6 56 #define FS2 1261 #define FS2 9 57 62 #define FS3 1 58 63 #define FSX 32 … … 114 119 static inline void domove(uint8_t move, uint8_t *bg, uint8_t *fg) 115 120 { 116 if(move < 8) 117 *bg = move; 118 else if(move < 16) 119 *fg = move - 8; 121 if(move < 16) 122 *fg = move & 0x7; 123 else if(move < 32) 124 *bg = move & 0x7; 125 } 126 127 /* 128 * Clamp pixel value to avoid colour bleeding. Deactivated because it 129 * does not give satisfactory results. 130 */ 131 #define CLAMP 0x1000 132 static inline int clamp(int p) 133 { 134 #if 0 135 /* FIXME: doesn’t give terribly good results on eg. eatme.png */ 136 if(p < - CLAMP) return - CLAMP; 137 if(p > 0xffff + CLAMP) return 0xffff + CLAMP; 138 #endif 139 return p; 120 140 } 121 141 … … 144 164 { 145 165 /* Experiment shows that this is important at small depths */ 146 int a = in[i * 3 + c] + tmperr[c];166 int a = clamp(in[i * 3 + c] + tmperr[c]); 147 167 int b = out[i * 3 + c]; 148 168 tmperr[c] = (a - b) * FS0 / FSX; … … 182 202 int *error, int *out) 183 203 { 184 int voidvec[3], bestrgb[6 * 3], tmprgb[6 * 3], tmpvec[3];185 int const *voidrgb, * vec, *rgb;186 int besterror, curerror, suberror, statice, voide ;204 int voidvec[3], nvoidvec[3], bestrgb[6 * 3], tmprgb[6 * 3], tmpvec[3]; 205 int const *voidrgb, *nvoidrgb, *vec, *rgb; 206 int besterror, curerror, suberror, statice, voide, nvoide; 187 207 int i, c; 188 208 uint8_t command, bestcommand; 189 209 190 /* Precompute error for the case where we don’t print pixels */ 210 /* Precompute error for the case where we change the foreground colour 211 * and hence only print the background colour or its negative */ 191 212 voidrgb = palette[bg]; 192 213 voide = geterror(in, errvec, voidrgb, voidvec); 214 nvoidrgb = palette[7 - bg]; 215 nvoide = geterror(in, errvec, nvoidrgb, nvoidvec); 193 216 194 217 /* Precompute sub-error for the case where we print pixels (and hence … … 202 225 203 226 /* Check every likely command: 204 * 0-7: change background to 0-7 205 * 8-15: change foreground to 0-7 206 * 16: normal stuff 207 * 17: inverse video stuff */ 227 * 0-7: change foreground to 0-7 228 * 8-15: change foreground to 0-7, print negative background 229 * 16-23: change background to 0-7 230 * 24-31: change background to 0-7, print negative background 231 * 32: normal stuff 232 * 33: inverse video stuff */ 208 233 besterror = 0x7ffffff; 209 234 bestcommand = 16; 210 235 memcpy(bestrgb, voidrgb, 6 * 3 * sizeof(int)); 211 for(command = 0; command < 18; command++) 212 { 213 if(command < 16) 236 for(command = 0; command < 34; command++) 237 { 238 uint8_t newbg = bg, newfg = fg; 239 domove(command, &newbg, &newfg); 240 241 /* Keeping bg and fg is useless, because we could use commands 242 * 32 and 33 instead */ 243 if(command < 32 && newbg == bg && newfg == fg) 244 continue; 245 246 /* I *think* having newfg == newbg is useless, too, but I don’t 247 * want to miss some corner case where swapping bg and fg may be 248 * interesting, so we continue anyway. */ 249 250 if(command < 8) 214 251 { 215 252 curerror = voide; … … 217 254 vec = voidvec; 218 255 } 256 else if(command < 16) 257 { 258 curerror = nvoide; 259 rgb = nvoidrgb; 260 vec = nvoidvec; 261 } 262 else if(command < 24) 263 { 264 rgb = palette[newbg]; 265 curerror = geterror(in, errvec, rgb, tmpvec); 266 vec = tmpvec; 267 } 268 else if(command < 32) 269 { 270 rgb = palette[7 - newbg]; 271 curerror = geterror(in, errvec, rgb, tmpvec); 272 vec = tmpvec; 273 } 219 274 else 220 275 { 221 276 int const *bgcolor, *fgcolor; 222 277 223 bgcolor = palette[bg + (command - 16) * (7 - 2 * bg)]; 224 fgcolor = palette[fg + (command - 16) * (7 - 2 * fg)]; 278 if(command == 32) 279 { 280 bgcolor = palette[bg]; fgcolor = palette[fg]; 281 } 282 else 283 { 284 bgcolor = palette[7 - bg]; fgcolor = palette[7 - fg]; 285 } 225 286 226 287 memcpy(tmpvec, errvec, 3 * sizeof(int)); … … 237 298 { 238 299 int delta1, delta2; 239 delta1 = in[i * 3 + c] + tmpvec[c]- bgcolor[c];300 delta1 = clamp(in[i * 3 + c] + tmpvec[c]) - bgcolor[c]; 240 301 vec1[c] = delta1 * FS0 / FSX; 241 302 smalle1 += delta1 / 256 * delta1; 242 delta2 = in[i * 3 + c] + tmpvec[c]- fgcolor[c];303 delta2 = clamp(in[i * 3 + c] + tmpvec[c]) - fgcolor[c]; 243 304 vec2[c] = delta2 * FS0 / FSX; 244 305 smalle2 += delta2 / 256 * delta2; … … 274 335 if(depth == 0) 275 336 suberror = 0; /* It’s the end of the tree */ 276 else if(command < 16) 277 { 278 uint8_t newbg = bg, newfg = fg; 279 domove(command, &newbg, &newfg); 280 /* Keeping bg and fg is useless, because we could use commands 281 * 16 and 17 instead */ 282 if(newbg == bg && newfg == fg) 283 continue; 284 337 else if(command < 32) 338 { 285 339 bestmove(in + 6 * 3, newbg, newfg, vec, depth - 1, 286 340 besterror - curerror, &suberror, NULL); 287 341 342 #if 0 288 343 /* Penalty for background changes; they're hard to revert. The 289 344 * value of 2 was determined empirically. 1.5 is not enough and … … 291 346 if(newbg != bg) 292 347 suberror *= 2; 348 #endif 293 349 } 294 350 else … … 373 429 { 374 430 int error = srcl[i * 3 + c] - dstl[i * 3 + c]; 375 srcl[i * 3 + c + 3] += error * FS0 / FSX; 431 srcl[i * 3 + c + 3] = 432 clamp(srcl[i * 3 + c + 3] + error * FS0 / FSX); 376 433 srcl[i * 3 + c + stride - 3] += error * FS1 / FSX; 377 434 srcl[i * 3 + c + stride] += error * FS2 / FSX; 378 435 srcl[i * 3 + c + stride + 3] += error * FS3 / FSX; 379 436 } 437 438 for(i = -1; i < 7; i++) 439 srcl[i * 3 + c + stride] = clamp(srcl[i * 3 + c + stride]); 380 440 } 381 441 /* Iterate */ -
www/labs/img2oric.html
r2210 r2212 31 31 32 32 <p> The graphical part of the Oric screen has 240×200 pixels and can only 33 display 8 different colours (black, blue, red, green, cyan, magenta, yellow and 34 white). Each horizontal group of 6 pixels can only use two different colours: 35 either the foreground and the background colours, or the negative values 36 thereof. The background <i>or</i> the foreground colour may also be changed 37 (one at a time), but while doing so the next 6 pixels cannot be chosen: they 38 will use the background colour instead. </p> 33 display 8 different colours (black, blue, red, green, cyan, magenta, yellow 34 and white). Each horizontal group of 6 pixels can only use two different 35 colours: the foreground and the background colours. The background <i>or</i> 36 the foreground colour may also be changed (one at a time), but while doing 37 so the next 6 pixels cannot be chosen: they will use the background colour 38 instead. Finally, a special bit may be activated to display the current group 39 of pixels in reverse video. </p> 39 40 40 41 <h2 style="clear: both;"> Downloads </h2> … … 42 43 <p> No downloads are available yet. However, the file <tt><a 43 44 href="img2oric.c">img2oric.c</a></tt> may be compiled on Linux to obtain an 44 almost functional, yet extremely slow (around 1 minute to process an image on a45 modern computer) program. </p>45 almost functional, yet extremely slow (around 2 minutes to process an image on 46 a modern computer) program. </p> 46 47 47 48 <h2> Screenshots </h2> … … 89 90 90 91 <p> The following images use real Oric artwork, taken from the Buggy Boy 91 and the VIP 4 demos. As can be seen, the result is not perfect, but is still 92 rather acceptable. </p> 92 and the VIP 4 demos: they are almost pixel-perfect. </p> 93 93 94 94 <p style="text-align: center;"> … … 110 110 </p> 111 111 112 <h2> Credits </h2> 113 114 <p> <tt>img2oric</tt> was written by Sam Hocevar. Thanks to Jean-Yves 115 Lamoureux, Mickaël Pointier, Robert Chéramy and Fabrice Frances for their 116 help, their work and the information they provided. </p> 117 112 118 <?php $rev = '$Id$'; 113 119 include($_SERVER['DOCUMENT_ROOT'].'/footer.inc'); ?>
Note: See TracChangeset
for help on using the changeset viewer.