128x192 with 4 levels compatible
Re: 128x192 with 4 levels compatible
I cannot understad this. Is it about automatic dithering? If so it would be interesting to achieve any blending of colours which is a trick used to simulate oranges for example interleaving ditherings in red and yellow. Automatic dithering in colours, not only for greys, might Not be "ugly". I don't think dithering is ugly in general. Just plain flat colours don't help to tell bright and dimmed colours, besides a bit of noise is interesting to suggest volumes and shades.
Re: 128x192 with 4 levels compatible
No, the original idea was for an extra screen mode that still looks OK if you don't have the modified hardware to display it properly.
I don't think it's really worth trying, because the fallback image doesn't look good enough. There were a few games converted from the C64 and amstrad to the Spectrum that just used dithers in place of colours for lazy ports of the graphics, and they all looked terrible.
Mind you, Gobots looked crap on the Amstrad in the first place...
Maybe if you could get the dithers to swap places on alternate rows so you got proper chessboard stipples, like Mr Heli there, but then it'd be an immense pain to program the 4-colour versions as the bit order would be reversed on alternate rows. Fine I suppose if you stick to 2-pixel movements of sprites as then the bits are always in the same positions...
I don't think it's really worth trying, because the fallback image doesn't look good enough. There were a few games converted from the C64 and amstrad to the Spectrum that just used dithers in place of colours for lazy ports of the graphics, and they all looked terrible.
Mind you, Gobots looked crap on the Amstrad in the first place...
Maybe if you could get the dithers to swap places on alternate rows so you got proper chessboard stipples, like Mr Heli there, but then it'd be an immense pain to program the 4-colour versions as the bit order would be reversed on alternate rows. Fine I suppose if you stick to 2-pixel movements of sprites as then the bits are always in the same positions...
Re: 128x192 with 4 levels compatible
what about something really subtle? just enough to make you believe there are more colours
something subtler than this
something subtler than this
Re: 128x192 with 4 levels compatible
That works but you only get one intermediate tone (3 levels).
The advantage of using the pixel order is to have 2 intermediate tones (4 levels).
I agree that the fallback image is not nice.
So lets consider changing the pixel order on alternate lines
That way, we could still use the normal chessboard dithering....
I really need to write a converter (or try to mod an emulator), but if I'm not mistaken, we would get this:
Original
Converted
So it would be:
Even lines
00 = black
01 = grey 1
10 = grey 2
11 = white
Odd lines
00 = black
10 = grey 1
01 = grey 2
11 = white
The advantage of using the pixel order is to have 2 intermediate tones (4 levels).
I agree that the fallback image is not nice.
So lets consider changing the pixel order on alternate lines
That way, we could still use the normal chessboard dithering....
I really need to write a converter (or try to mod an emulator), but if I'm not mistaken, we would get this:
Original
Converted
So it would be:
Even lines
00 = black
01 = grey 1
10 = grey 2
11 = white
Odd lines
00 = black
10 = grey 1
01 = grey 2
11 = white
Re: 128x192 with 4 levels compatible
Off-topic
This : https://commons.m.wikimedia.org/wiki/Fi ... hering.png
See? you'd make your graphics as usual and the engine would change small chameleon-esque ditherings for you on the fly!
This : https://commons.m.wikimedia.org/wiki/Fi ... hering.png
See? you'd make your graphics as usual and the engine would change small chameleon-esque ditherings for you on the fly!
Re: 128x192 with 4 levels compatible
You need large shaded or blended areas for all those different dithers to look any good. Even then, the pixels are pretty big and distinct, so it only really works for blending similar colours.
Within the usual size of Speccy game graphics, anything more than 01/10 dithering is too complicated. And you sometimes have to invert the stipple pattern (or move it by 1 pixel) when putting it next to the solid or clear parts of your design.
Within the usual size of Speccy game graphics, anything more than 01/10 dithering is too complicated. And you sometimes have to invert the stipple pattern (or move it by 1 pixel) when putting it next to the solid or clear parts of your design.
Re: 128x192 with 4 levels compatible
This is the idea! It was already invented around 2009 by Gasman ?
It's called Chunkypaint 53c :
http://chunkypaint.zxdemo.org
http://events.retroscene.org/53c
http://53c.verve.space
There are some works from parties on zx-art, pouet, demozoo, etc
https://demozoo.org/parties/1779/
http://www.pouet.net/prod.php?which=61392
Dunno if this would be possible to make games or it's just useful for lower resolution loading screens.
It's called Chunkypaint 53c :
http://chunkypaint.zxdemo.org
http://events.retroscene.org/53c
http://53c.verve.space
There are some works from parties on zx-art, pouet, demozoo, etc
https://demozoo.org/parties/1779/
http://www.pouet.net/prod.php?which=61392
Dunno if this would be possible to make games or it's just useful for lower resolution loading screens.
Last edited by hikoki on Fri Apr 06, 2018 6:43 pm, edited 1 time in total.
Re: 128x192 with 4 levels compatible
hikoki, those examples are different. They use dithering to simulate a 50% mix between paper and ink.
The point here it to try to use dithering in a way that:
- still looks decent on a normal spectrum
- encodes two values, so you can have 33% and 66% mixing (on compatible "hardware")
The point here it to try to use dithering in a way that:
- still looks decent on a normal spectrum
- encodes two values, so you can have 33% and 66% mixing (on compatible "hardware")
Re: 128x192 with 4 levels compatible
Good luck 4thRock. Hope someone will help you mod some emulator.
Anyways I like the idea of painting with a virtual extended palette like and the paint editor makes all the dithering for you. This might be a nice feature suggestion for ZXPaintBrush. According to Joefish this is not feasible to make games? Please let me know if there is some game using this technique intensively.
Anyways I like the idea of painting with a virtual extended palette like and the paint editor makes all the dithering for you. This might be a nice feature suggestion for ZXPaintBrush. According to Joefish this is not feasible to make games? Please let me know if there is some game using this technique intensively.
Re: 128x192 with 4 levels compatible
OK, wrote a simple Javascript image converter and got some results
Standard image
Decoded
Not horrible on a standard display.
I'll share the code latter.
Standard image
Decoded
Not horrible on a standard display.
I'll share the code latter.
Re: 128x192 with 4 levels compatible
Using a different encoding on different scanlines would be pretty much unworkable for moving images, so you'd really be limiting the use to static screens.
Re: 128x192 with 4 levels compatible
Not really. Because of the drop in resolution, things would only move horizontally in 2-pixel steps, so it would be reasonable for things to move vertically in 2-pixel steps too, thus preserving the stipple alignment.
Re: 128x192 with 4 levels compatible
Copy this into a HTML file and you have an encoder / decoder.
The JS code is quite basic and not optimized, so it's very simple to understand.
You can see it working here:
http://4throckworld.com/dev/128x192/
Of course, for better results it's better to start with images already converted to 4 levels.
The converter will only do straight brightness level mapping.
Attributes are completely ignored.
The JS code is quite basic and not optimized, so it's very simple to understand.
You can see it working here:
http://4throckworld.com/dev/128x192/
Of course, for better results it's better to start with images already converted to 4 levels.
The converter will only do straight brightness level mapping.
Attributes are completely ignored.
Code: Select all
<!DOCTYPE html>
<html>
<head>
<script>
function draw(img) {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
img.style.display = 'none';
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
var Encode = function() {
for (var i = 0; i < data.length; i += 8) {
//get average value
var avg = (data[i] + data[i + 1] + data[i + 2] + data[i + 4] + data[i + 5] + data[i + 6]) / 6;
var lineNumber = Math.round( (i/4)/256 );
var oddLine = lineNumber % 2
// 00
if ( avg < 64) {var avg_a = 0 ; var avg_b = 0};
// 01
if ( (avg > 64) && (avg < 127) ) { if ( oddLine == 0 ) { var avg_a = 0 ; var avg_b = 255} else { avg_a = 255 ; avg_b = 0} };
// 10
if ( (avg > 127) && (avg < 191) ) { if ( oddLine == 0 ) { var avg_a = 255 ; var avg_b = 0} else { avg_a = 0 ; avg_b = 255} };
// 11
if ( avg > 191 ) { var avg_a = 255 ; var avg_b = 255};
data[i] = avg_a; // red
data[i + 1] = avg_a; // green
data[i + 2] = avg_a; // blue
//data[i + 3 ] = 255; // red
data[i + 4] = avg_b; // green
data[i + 5] = avg_b; // blue
data[i + 6] = avg_b; // green
//data[i + 7] = 255; // blue
}
ctx.putImageData(imageData, 0, 0);
};
var Decode = function() {
for (var i = 0; i < data.length; i += 8) {
//get average values of two consecutive pixels
var avg_a = (data[i] + data[i + 1] + data[i + 2] ) / 3;
var avg_b = (data[i + 4] + data[i + 5] + data[i + 6] ) /3;
var lineNumber = Math.round( (i/4)/256 );
var oddLine = lineNumber % 2
// 00
if ( (avg_a < 85) && (avg_b < 85) ) {avg = 0};
// 01
if ( (avg_a < 85) && (avg_b > 170) ) { if ( oddLine == 0 ) { avg = 85} else { avg = 170} };
// 10
if ( (avg_a > 170) && (avg_b < 85) ) { if ( oddLine == 0 ) { avg = 170} else { avg = 85} };
// 11
if ( (avg_a > 170) && (avg_b > 170) ) {avg = 255};
data[i] = avg; // red
data[i + 1] = avg; // green
data[i + 2] = avg; // blue
//data[i + 3 ] = 255; // red
data[i + 4] = avg; // green
data[i + 5] = avg; // blue
data[i + 6] = avg; // green
//data[i + 7] = 255; // blue
}
ctx.putImageData(imageData, 0, 0);
};
var Encodebtn = document.getElementById('Encodebtn');
Encodebtn.addEventListener('click', Encode);
var Decodebtn = document.getElementById('Decodebtn');
Decodebtn.addEventListener('click', Decode);
}
function handleImage(e){
var reader = new FileReader();
var img = new Image();
//img.src = 'heli.png';
reader.onload = function(event){
img.src = event.target.result;
img.onload = function() {
draw(this);
};
}
reader.readAsDataURL(e.target.files[0]);
}
function readImage() {
if ( this.files && this.files[0] ) {
var FR= new FileReader();
FR.onload = function(e) {
//var img = new Image();
img.addEventListener("load", function() {
ctx.drawImage(img, 0, 0);
});
img.src = e.target.result;
};
FR.readAsDataURL( this.files[0] );
}
}
function pageLoaded() {
var imageLoader = document.getElementById('fileUpload');
imageLoader.addEventListener('change', handleImage);
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
}
</script>
</head>
<body onload = "pageLoaded();">
<label>Loads a 256x192 image.<br> Encodes / decodes a 192x192 4 bit level image using 1 bit dithering. <br>Bit order is reversed on each line for better visual quality on the undecoded image.</label><br/>
<hr>
<input type='file' id="fileUpload" />
<canvas id="canvas" width="256" height="192"></canvas>
<div>
<input id="Decodebtn" value="Decode" type="button">
<input id="Encodebtn" value="Encode" type="button">
</div>
</body>
</html>
-
- Microbot
- Posts: 168
- Joined: Tue Nov 28, 2017 7:39 am
Re: 128x192 with 4 levels compatible
Seems some of the video modes of machine ZX Prism from Jeff Braine
https://youtu.be/Jrge4HtnqPI
Minute 5.37
You can test it on ZEsarUX
https://youtu.be/Jrge4HtnqPI
Minute 5.37
You can test it on ZEsarUX