Ich habe mit dem Modul jpeg-js und Node JS Buffer gearbeitet und versucht, ein kleines Befehlszeilenprogramm zu erstellen, das die decodierten JPEG-Pufferdaten modifiziert und ein Muster aus X-Anzahl von umgekehrten Scanlinien und X-Anzahl von normalen Scanlinien erzeugt Speichern eines neuen JPEG. Mit anderen Worten, ich versuche, Teile des Bildes umzudrehen, aber nicht das gesamte Bild selbst (viele Module, die so etwas tun, aber nicht den spezifischen Anwendungsfall, den ich habe).Wie reverse ich eine Scanline mit dem jpeg-js-Modul/Knoten JS-Puffer?
Um die umgekehrten/normalen Linienmuster zu erstellen, habe ich Zeile für Zeile gelesen/geschrieben und ein Stück dieser Linie in einer Variablen gespeichert, dann am Ende der Scanlinie beginnend und inkrementell um 4 Stück nach unten gegangen Bytes (die Zuweisung für einen RGBA-Wert), bis ich am Anfang der Zeile bin. Code für das Programm:
'use strict';
const fs = require('fs');
const jpeg = require('jpeg-js');
const getPixels = require('get-pixels');
let a = fs.readFileSync('./IMG_0006_2.jpg');
let d = Buffer.allocUnsafe(a.width * a.height * 4);
let c = jpeg.decode(a);
let val = false; // track whether normal or reversed scanlines
let lineWidth = b.width * 4;
let lineCount = 0;
let track = 0;
let track2 = 0;
let track3 = 0;
let curr, currLine; // storage for writing/reading scnalines, respectively
let limit = {
one: Math.floor(Math.random() * 141),
two: Math.floor(Math.random() * 151),
three: Math.floor(Math.random() * 121)
};
if (limit.one < 30) {
limit.one = 30;
}
if (limit.two < 40) {
limit.two = 40;
}
if (limit.two < 20) {
limit.two = 20;
}
let calc = {};
calc.floor = 0;
calc.ceil = 0 + lineWidth;
d.forEach(function(item, i) {
if (i % lineWidth === 0) {
lineCount++;
/* // alternate scanline type, currently disabled to figure out how to succesfully reverse image
if (lineCount > 1 && lineCount % limit.one === 0) {
// val = !val;
}
*/
if (lineCount === 1) {
val = !val; // setting alt scanline check to true initially
} else if (calc.floor + lineWidth < b.data.length - 1) {
calc.floor += lineWidth;
calc.ceil += lineWidth;
}
currLine = c.data.slice(calc.floor, calc.ceil); // current line
track = val ? lineWidth : 0; // tracking variable for reading from scanline
track2 = val ? 4 : 0; // tracking variable for writing from scanline
}
//check if reversed and writing variable has written 4 bytes for RGBA
//if so, set writing source to 4 bytes at end of line and read from there incrementally
if (val && track2 === 4) {
track2 = 0; // reset writing count
curr = currLine.slice(track - 4, track); // store 4 previous bytes as writing source
if (lineCount === 1 && lineWidth - track < 30) console.log(curr); //debug
} else {
curr = currLine; //set normal scanline
}
d[i] = curr[track2];
// check if there is no match between data source and decoded image
if (d[i] !== curr[track2]) {
if (track3 < 50) {
console.log(i);
}
track3++;
}
track2++; //update tracking variable
track = val ? track - 1 : track + 1; //update tracking variable
});
var rawImageData = {
data: d,
width: b.width,
height: b.height
};
console.log(b.data.length);
console.log('errors\t', track3);
var jpegImageData = jpeg.encode(rawImageData, 100);
fs.writeFile('foo2223.jpg', jpegImageData.data);
Leider ist der umgekehrte Scanline-Code, den ich geschrieben habe, nicht richtig. Leider konnte ich nur den roten Kanal meines Testbilds erfolgreich umkehren (siehe unten links), wobei die blauen und grünen Kanäle gerade zu verschwommenen Unschärfen werden. Das Farbschema sollte in etwa dem richtigen Bild entsprechen.
Was mache ich hier falsch?