Skip to content

Commit f1ecfa6

Browse files
committed
edit: saving files, WARN: not working
1 parent b34967d commit f1ecfa6

File tree

2 files changed

+116
-130
lines changed

2 files changed

+116
-130
lines changed

main/imageToData.js

+26-94
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// main/imageToData.js
12
const fs = require('fs');
23
const fsExtra = require('fs-extra');
34
const path = require('path');
@@ -45,43 +46,18 @@ function nibblesToBytes(nibbles) {
4546
return bytes;
4647
}
4748

48-
function extractFileData(nibbles) {
49-
const dataNibbles = [];
50-
const nameNibbles = [];
51-
let isReadingName = false;
52-
for (let i = 0; i < nibbles.length; i++) {
53-
const nibble = nibbles[i];
54-
switch (nibble) {
55-
case 'A':
56-
isReadingName = !isReadingName;
57-
break;
58-
case 'D':
59-
i = nibbles.length;
60-
break;
61-
default:
62-
if (isReadingName) nameNibbles.push(nibble);
63-
else dataNibbles.push(nibble);
64-
}
65-
}
66-
return { dataNibbles, nameNibbles };
67-
}
68-
6949
async function processWithLimitedWorkers(filePaths, maxWorkers) {
7050
const progressTracker = new Array(filePaths.length).fill(0);
7151
const processFilesProgress = createIntermediateProgressOutput('Processing Images ->', filePaths.length);
7252
let completedFiles = 0;
73-
7453
const results = [];
7554
const activeWorkers = new Set();
76-
7755
for (const filePath of filePaths) {
7856
while (activeWorkers.size >= maxWorkers) {
7957
await Promise.race(activeWorkers);
8058
}
81-
8259
const workerPromise = new Promise((resolve, reject) => {
8360
const worker = new Worker('./workers/imageWorker.js', { workerData: filePath });
84-
8561
worker.on('message', (message) => {
8662
if (typeof message === 'number') {
8763
progressTracker[filePaths.indexOf(filePath)] = message;
@@ -96,18 +72,15 @@ async function processWithLimitedWorkers(filePaths, maxWorkers) {
9672
resolve(message);
9773
}
9874
});
99-
10075
worker.on('error', reject);
10176
worker.on('exit', (code) => {
10277
if (code !== 0) reject(new Error(`Worker exited with code ${code}`));
10378
});
10479
});
105-
10680
activeWorkers.add(workerPromise);
10781
workerPromise.finally(() => activeWorkers.delete(workerPromise));
10882
results.push(workerPromise);
10983
}
110-
11184
await Promise.all(results);
11285
console.log("");
11386
return results;
@@ -130,103 +103,62 @@ function playSound(times, delay = 500) {
130103

131104
async function main() {
132105
console.time("Processing Time");
133-
134106
try {
135107
const files = fs.readdirSync(folderPath).sort((a, b) =>
136108
a.localeCompare(b, undefined, { numeric: true })
137109
);
138110
const filePaths = files.map((file) => path.join(folderPath, file));
139111
const results = await processWithLimitedWorkers(filePaths, MAX_WORKERS);
140112
const resolvedResults = await Promise.all(results);
141-
142113
const streamFinished = util.promisify(require('stream').finished);
143114
const extractProgress = createIntermediateProgressOutput('Saving file ->', results.length);
144-
let dataFileStream = null;
145115

146116
for (let index = 0; index < resolvedResults.length; index++) {
147117
const tempFilePath = resolvedResults[index];
148-
let fileContent = fs.readFileSync(tempFilePath);
118+
const fileContent = fs.readFileSync(tempFilePath);
149119
const identifyFilePath = path.join(tempFolder, `${path.parse(tempFilePath).name}.id`);
150120

121+
// Nové zpracování identifikačního souboru – očekáváme páry řádků (A a D)
151122
if (fs.existsSync(identifyFilePath)) {
152-
const identifyLines = fs.readFileSync(identifyFilePath, 'utf8').split('\n');
153-
let currentByteOffset = 0;
154-
155-
for (const line of identifyLines) {
156-
if (!line.trim()) continue;
157-
158-
const regex = /^(\d+)-(\d+)\s([A|D])$/;
159-
const match = line.match(regex);
160-
if (!match) continue;
161-
162-
const start = parseInt(match[1], 10);
163-
const end = parseInt(match[2], 10);
164-
const identifier = match[3];
165-
166-
if (identifier === 'A') {
167-
const extractedBytes = fileContent.slice(start, end);
168-
const extractedName = extractedBytes.toString('utf-8').replace(/\0/g, '').trim();
169-
const outputFilePath = path.join(outputFolder, extractedName);
170-
171-
const outputDir = path.dirname(outputFilePath);
172-
fsExtra.ensureDirSync(outputDir);
173-
174-
if (dataFileStream) {
175-
dataFileStream.end();
176-
await streamFinished(dataFileStream);
177-
}
178-
179-
dataFileStream = fs.createWriteStream(outputFilePath);
180-
currentByteOffset = 0;
181-
182-
fileContent = Buffer.concat([
183-
fileContent.slice(0, start),
184-
fileContent.slice(end),
185-
]);
186-
}
187-
188-
if (identifier === 'D') {
189-
const bytesToWrite = end - currentByteOffset;
190-
const contentToWrite = fileContent.slice(0, bytesToWrite);
191-
192-
if (dataFileStream) {
193-
dataFileStream.write(contentToWrite);
194-
currentByteOffset += contentToWrite.length;
195-
dataFileStream.end();
196-
await streamFinished(dataFileStream);
197-
dataFileStream = null;
198-
}
199-
200-
fileContent = fileContent.slice(bytesToWrite);
123+
const lines = fs.readFileSync(identifyFilePath, 'utf8')
124+
.split('\n')
125+
.filter(line => line.trim() !== "");
126+
if (lines.length % 2 !== 0) {
127+
console.error("Invalid identify file format: expected even number of lines.");
128+
} else {
129+
for (let i = 0; i < lines.length; i += 2) {
130+
const aLine = lines[i];
131+
const dLine = lines[i + 1];
132+
// Opravený regulární výraz – bez zbytečného "|"
133+
const matchA = aLine.match(/^(\d+)-(\d+)\sA$/);
134+
const matchD = dLine.match(/^(\d+)-(\d+)\sD$/);
135+
if (!matchA || !matchD) continue;
136+
const aStart = parseInt(matchA[1], 10);
137+
const aEnd = parseInt(matchA[2], 10);
138+
const dStart = parseInt(matchD[1], 10);
139+
const dEnd = parseInt(matchD[2], 10);
140+
const nameBuffer = fileContent.slice(aStart, aEnd);
141+
const fileName = nameBuffer.toString('utf8').replace(/\0/g, '').trim();
142+
const fileData = fileContent.slice(dStart, dEnd);
143+
const outputFilePath = path.join(outputFolder, fileName);
144+
fsExtra.ensureDirSync(path.dirname(outputFilePath));
145+
fs.writeFileSync(outputFilePath, fileData);
201146
}
202147
}
203148
}
204-
205-
if (dataFileStream) {
206-
dataFileStream.write(fileContent);
207-
fileContent = null;
208-
}
209-
210149
const progressBar = extractProgress(index + 1);
211150
if (progressBar) {
212151
process.stdout.clearLine();
213152
process.stdout.cursorTo(0);
214153
process.stdout.write(progressBar);
215154
}
216155
}
217-
218-
if (dataFileStream) {
219-
dataFileStream.end();
220-
await streamFinished(dataFileStream);
221-
}
222156
} catch (error) {
223157
console.error('Error processing files:', error);
224158
playSound(2, 500);
225159
}
226-
227160
console.log("\nAll images processed.");
228161
console.timeEnd("Processing Time");
229-
230162
playSound(1);
231163
}
232164

workers/imageWorker.js

+90-36
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// workers/imageWorker.js
12
const { workerData, parentPort } = require("worker_threads");
23
const sharp = require("sharp");
34
const fs = require("fs");
@@ -56,41 +57,79 @@ function nibblesToBytes(nibbles) {
5657
}
5758

5859
function extractFileData(nibbles) {
59-
const dataNibbles = [];
60-
const identify = [];
61-
let isReadingName = false;
62-
let nameStartIndex = 0;
63-
for (let i = 0; i < nibbles.length; i++) {
64-
const nibble = nibbles[i];
65-
switch (nibble) {
66-
case "A":
67-
if (!isReadingName) {
68-
nameStartIndex = Math.floor(dataNibbles.length / 2);
69-
} else {
70-
const nameEndIndex = Math.floor(dataNibbles.length / 2);
71-
identify.push({ type: "A", start: nameStartIndex, end: nameEndIndex });
72-
}
73-
isReadingName = !isReadingName;
74-
break;
75-
case "D":
76-
const dataEndIndex = Math.floor(dataNibbles.length / 2);
77-
identify.push({ type: "D", start: dataEndIndex, end: dataEndIndex });
78-
i = nibbles.length;
79-
break;
80-
default:
81-
dataNibbles.push(nibble);
60+
let segments = [];
61+
let nonMarkerNibbles = [];
62+
let collectingName = false;
63+
let currentFile = null;
64+
65+
// Projdeme všechny nibbly a akumulujeme pouze ty, které nejsou marker
66+
for (let nib of nibbles) {
67+
if (nib === "A") {
68+
if (!collectingName) {
69+
// Start názvu souboru – zaznamenáme počáteční offset (v bajtech)
70+
currentFile = {
71+
fileNameRange: { start: nonMarkerNibbles.length / 2, end: null },
72+
dataRange: { start: null, end: null }
73+
};
74+
collectingName = true;
75+
} else {
76+
// Konec názvu souboru – zaznamenáme koncový offset pro název
77+
currentFile.fileNameRange.end = nonMarkerNibbles.length / 2;
78+
collectingName = false;
79+
// Data pro soubor začínají hned za názvem
80+
currentFile.dataRange.start = nonMarkerNibbles.length / 2;
81+
}
82+
} else if (nib === "D") {
83+
// Příkaz D – podle nové specifikace zaznamenáme pouze jeden bajt jako konec dat
84+
currentFile.dataRange.end = nonMarkerNibbles.length / 2;
85+
segments.push(currentFile);
86+
currentFile = null;
87+
} else {
88+
// Akumulujeme reálné nibbly (bez markerů)
89+
nonMarkerNibbles.push(nib);
90+
}
91+
}
92+
return { segments, nonMarkerNibbles };
93+
}
94+
95+
// Nová funkce pro extrakci více souborů z nibblového proudu
96+
function extractFilesFromNibbles(nibbles) {
97+
const files = [];
98+
let i = 0;
99+
while (i < nibbles.length) {
100+
// Vyhledáme značku A jako začátek názvu
101+
while (i < nibbles.length && nibbles[i] !== "A") {
102+
i++;
103+
}
104+
if (i >= nibbles.length) break;
105+
i++; // přeskočíme počáteční 'A'
106+
const nameNibbles = [];
107+
while (i < nibbles.length && nibbles[i] !== "A") {
108+
nameNibbles.push(nibbles[i]);
109+
i++;
110+
}
111+
if (i < nibbles.length && nibbles[i] === "A") {
112+
i++; // přeskočíme koncovou značku pro název
113+
}
114+
const dataNibbles = [];
115+
// Čteme data až narazíme na značku 'D' (ukončení souboru) nebo případně začátek dalšího souboru ('A')
116+
while (i < nibbles.length && nibbles[i] !== "D" && nibbles[i] !== "A") {
117+
dataNibbles.push(nibbles[i]);
118+
i++;
82119
}
120+
if (i < nibbles.length && nibbles[i] === "D") {
121+
i++; // přeskočíme značku 'D'
122+
}
123+
files.push({ nameNibbles, dataNibbles });
83124
}
84-
return { dataNibbles, identify };
125+
return files;
85126
}
86127

87128
async function decodeImage(imagePath) {
88129
const image = sharp(imagePath);
89130
const { width, height } = await image.metadata();
90131
const buffer = await image.raw().toBuffer();
91-
let nibbles = [];
92-
const binaryFilePath = path.join("./temp", `${path.parse(imagePath).name}.bin`);
93-
const identifyFilePath = path.join("./temp", `${path.parse(imagePath).name}.id`);
132+
const nibbles = [];
94133
const totalPixels = width * height;
95134
let lastReportedProgress = 0;
96135
for (let i = 0; i < buffer.length; i += 3) {
@@ -106,16 +145,31 @@ async function decodeImage(imagePath) {
106145
}
107146
}
108147
parentPort.postMessage(100);
109-
const { dataNibbles, identify } = extractFileData(nibbles);
110-
const bytes = nibblesToBytes(dataNibbles);
148+
149+
const binaryFilePath = path.join("./temp", `${path.parse(imagePath).name}.bin`);
150+
const identifyFilePath = path.join("./temp", `${path.parse(imagePath).name}.id`);
151+
152+
// Využijeme extrakci více souborů
153+
const files = extractFilesFromNibbles(nibbles);
154+
let combinedNibbles = [];
155+
let currentOffset = 0;
156+
const identifyEntries = [];
157+
files.forEach(file => {
158+
const nameBytes = Math.floor(file.nameNibbles.length / 2);
159+
const dataBytes = Math.floor(file.dataNibbles.length / 2);
160+
identifyEntries.push({ type: "A", start: currentOffset, end: currentOffset + nameBytes });
161+
currentOffset += nameBytes;
162+
// U značky D nyní zapisujeme rozsah dat (dataBytes)
163+
identifyEntries.push({ type: "D", start: currentOffset, end: currentOffset + dataBytes });
164+
currentOffset += dataBytes;
165+
combinedNibbles = combinedNibbles.concat(file.nameNibbles, file.dataNibbles);
166+
});
167+
const bytes = nibblesToBytes(combinedNibbles);
111168
fs.writeFileSync(binaryFilePath, Buffer.from(bytes));
112-
if (identify.length > 0) {
113-
const identifyContent = identify
114-
.map((id) => {
115-
if (id.type === "A") return `${id.start}-${id.end} A`;
116-
else if (id.type === "D") return `${id.start}-${id.end} D`;
117-
return "";
118-
})
169+
170+
if (identifyEntries.length > 0) {
171+
const identifyContent = identifyEntries
172+
.map(entry => `${entry.start}-${entry.end} ${entry.type}`)
119173
.join("\n");
120174
fs.writeFileSync(identifyFilePath, identifyContent);
121175
}

0 commit comments

Comments
 (0)