128x192 with 4 levels compatible
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