FloydSteinberg.asm 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. BasicUpstart2(start)
  2. //--------------------------------------------------------------------------
  3. //--------------------------------------------------------------------------
  4. // Graphic conversion with FloydSteinberg
  5. //--------------------------------------------------------------------------
  6. //--------------------------------------------------------------------------
  7. start: sei
  8. lda #$3b
  9. sta $d011
  10. lda #$18
  11. sta $d018
  12. lda #BLACK
  13. sta $d020
  14. ldx #0
  15. lda #BLACK | (WHITE<<4)
  16. loop: sta $0400,x
  17. sta $0500,x
  18. sta $0600,x
  19. sta $0700,x
  20. inx
  21. bne loop
  22. jmp *
  23. *=$2000 "Picture"
  24. .var pic1 = floydSteinberg("camel.jpg")
  25. .fill 40*200, pic1.get(i)
  26. //--------------------------------------------------------------------------
  27. .function floydSteinberg(filename) {
  28. .var width = 320
  29. .var height = 200
  30. .var picture = LoadPicture(filename)
  31. // Create intensity map
  32. .var intensityMap = List();
  33. .var maxInt = $0;
  34. .var minInt = $ffffff
  35. .for (var y=0; y<height; y++) {
  36. .for (var x=0; x<width; x++) {
  37. .var rgb = picture.getPixel(x,y)
  38. .var intensity = sqrt(pow(rgb&$ff,2) + pow((rgb>>8)&$ff,2) + pow((rgb>>16)&$ff,2))
  39. .eval intensityMap.add(intensity)
  40. .eval maxInt = max(maxInt, intensity)
  41. .eval minInt = min(minInt, intensity)
  42. }
  43. .eval intensityMap.add(0) // Add extra colunn to catch overflow
  44. }
  45. .for (var x=0; x<width+1; x++)
  46. .eval intensityMap.add(0) // Add extra row to catch overflow
  47. // Do Floyd-Steinberg dithering
  48. .var limit = (maxInt+minInt)/2
  49. .for (var y=0; y<height; y++) {
  50. .for (var x=0; x<width; x++) {
  51. .var int = intensityMap.get(x+y*(width+1))
  52. .var selectedPixel = int < limit ? 0 : 1
  53. .var selectedIntensity = int < limit ? minInt : maxInt
  54. .var error = int - selectedIntensity
  55. .eval intensityMap.set(x+y*(width+1), selectedPixel)
  56. .var idx;
  57. .eval idx = (x+1)+(y+0)*(width+1)
  58. .eval intensityMap.set(idx, intensityMap.get(idx) + error *7/16)
  59. .eval idx = (x-1)+(y+1)*(width+1)
  60. .eval intensityMap.set(idx, intensityMap.get(idx) + error *3/16)
  61. .eval idx = (x+0)+(y+1)*(width+1)
  62. .eval intensityMap.set(idx, intensityMap.get(idx) + error *5/16)
  63. .eval idx = (x+1)+(y+1)*(width+1)
  64. .eval intensityMap.set(idx, intensityMap.get(idx) + error *1/16)
  65. }
  66. }
  67. // Convert to byteStream
  68. .var result = List()
  69. .for (var charY=0; charY<25; charY++) {
  70. .for (var charX=0; charX<40; charX++) {
  71. .for (var charRow=0;charRow<8; charRow++) {
  72. .var byte = 0
  73. .var idx = charX*8 + (charY*8+charRow)*(width+1)
  74. .for (var pixelNo=0;pixelNo<8; pixelNo++)
  75. .eval byte=byte*2+intensityMap.get(idx+pixelNo)
  76. .eval result.add(byte)
  77. }
  78. }
  79. }
  80. .return result
  81. }