roxify 1.9.4 → 1.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +1 -1
- package/dist/utils/inspection.js +7 -0
- package/native/image_utils.rs +12 -7
- package/native/lib.rs +7 -0
- package/native/png_utils.rs +21 -6
- package/native/reconstitution.rs +14 -5
- package/package.json +1 -1
- package/roxify_native-x86_64-pc-windows-msvc.node +0 -0
package/Cargo.toml
CHANGED
package/dist/utils/inspection.js
CHANGED
|
@@ -126,6 +126,13 @@ export async function listFilesInPng(pngBuf, opts = {}) {
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
catch (e) { }
|
|
129
|
+
try {
|
|
130
|
+
const json = native.extractFileListFromPixels(pngBuf);
|
|
131
|
+
if (json) {
|
|
132
|
+
return parseFileList(JSON.parse(json));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch (e) { }
|
|
129
136
|
return null;
|
|
130
137
|
}
|
|
131
138
|
export async function hasPassphraseInPng(pngBuf) {
|
package/native/image_utils.rs
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
use image::{ImageFormat, DynamicImage};
|
|
1
|
+
use image::{ImageFormat, DynamicImage, ImageReader};
|
|
2
2
|
use std::io::Cursor;
|
|
3
3
|
|
|
4
|
+
fn load_no_limits(input: &[u8]) -> Result<DynamicImage, String> {
|
|
5
|
+
let mut reader = ImageReader::new(Cursor::new(input))
|
|
6
|
+
.with_guessed_format()
|
|
7
|
+
.map_err(|e| format!("Failed to guess format: {}", e))?;
|
|
8
|
+
reader.no_limits();
|
|
9
|
+
reader.decode().map_err(|e| format!("Failed to load image: {}", e))
|
|
10
|
+
}
|
|
11
|
+
|
|
4
12
|
pub fn sharp_resize(
|
|
5
13
|
input: &[u8],
|
|
6
14
|
width: u32,
|
|
7
15
|
height: u32,
|
|
8
16
|
kernel: &str,
|
|
9
17
|
) -> Result<Vec<u8>, String> {
|
|
10
|
-
let img =
|
|
11
|
-
.map_err(|e| format!("Failed to load image: {}", e))?;
|
|
18
|
+
let img = load_no_limits(input)?;
|
|
12
19
|
|
|
13
20
|
let filter = match kernel {
|
|
14
21
|
"nearest" => image::imageops::FilterType::Nearest,
|
|
@@ -28,8 +35,7 @@ pub fn sharp_resize(
|
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
pub fn sharp_raw_pixels(input: &[u8]) -> Result<(Vec<u8>, u32, u32), String> {
|
|
31
|
-
let img =
|
|
32
|
-
.map_err(|e| format!("Failed to load image: {}", e))?;
|
|
38
|
+
let img = load_no_limits(input)?;
|
|
33
39
|
|
|
34
40
|
let rgb = img.to_rgb8();
|
|
35
41
|
let width = rgb.width();
|
|
@@ -40,8 +46,7 @@ pub fn sharp_raw_pixels(input: &[u8]) -> Result<(Vec<u8>, u32, u32), String> {
|
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
pub fn sharp_metadata(input: &[u8]) -> Result<(u32, u32, String), String> {
|
|
43
|
-
let img =
|
|
44
|
-
.map_err(|e| format!("Failed to load image: {}", e))?;
|
|
49
|
+
let img = load_no_limits(input)?;
|
|
45
50
|
|
|
46
51
|
let width = img.width();
|
|
47
52
|
let height = img.height();
|
package/native/lib.rs
CHANGED
|
@@ -389,6 +389,13 @@ pub fn crop_and_reconstitute(png_buffer: Buffer) -> Result<Vec<u8>> {
|
|
|
389
389
|
.map_err(|e| Error::from_reason(e))
|
|
390
390
|
}
|
|
391
391
|
|
|
392
|
+
#[cfg(not(test))]
|
|
393
|
+
#[napi]
|
|
394
|
+
pub fn extract_file_list_from_pixels(png_buffer: Buffer) -> Result<String> {
|
|
395
|
+
png_utils::extract_file_list_from_pixels(&png_buffer)
|
|
396
|
+
.map_err(|e| Error::from_reason(e))
|
|
397
|
+
}
|
|
398
|
+
|
|
392
399
|
// ─── WAV container NAPI exports ──────────────────────────────────────────────
|
|
393
400
|
|
|
394
401
|
#[cfg(not(test))]
|
package/native/png_utils.rs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
use bytemuck::{Pod, Zeroable};
|
|
2
|
-
use
|
|
2
|
+
use image::ImageReader;
|
|
3
|
+
use std::io::{Cursor, Read, Seek, SeekFrom};
|
|
3
4
|
|
|
4
5
|
#[repr(C)]
|
|
5
6
|
#[derive(Clone, Copy, Pod, Zeroable)]
|
|
@@ -176,7 +177,11 @@ fn find_pixel_header(raw: &[u8]) -> Result<usize, String> {
|
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
fn decode_to_rgb(png_data: &[u8]) -> Result<Vec<u8>, String> {
|
|
179
|
-
let
|
|
180
|
+
let mut reader = ImageReader::new(Cursor::new(png_data))
|
|
181
|
+
.with_guessed_format()
|
|
182
|
+
.map_err(|e| format!("format guess error: {}", e))?;
|
|
183
|
+
reader.no_limits();
|
|
184
|
+
let img = reader.decode().map_err(|e| format!("image decode error: {}", e))?;
|
|
180
185
|
Ok(img.to_rgb8().into_raw())
|
|
181
186
|
}
|
|
182
187
|
|
|
@@ -184,8 +189,13 @@ pub fn extract_name_from_png(png_data: &[u8]) -> Option<String> {
|
|
|
184
189
|
if let Some(name) = extract_name_direct(png_data) {
|
|
185
190
|
return Some(name);
|
|
186
191
|
}
|
|
187
|
-
let reconst = crate::reconstitution::crop_and_reconstitute(png_data)
|
|
188
|
-
|
|
192
|
+
if let Ok(reconst) = crate::reconstitution::crop_and_reconstitute(png_data) {
|
|
193
|
+
if let Some(name) = extract_name_direct(&reconst) {
|
|
194
|
+
return Some(name);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
let unstretched = crate::reconstitution::unstretch_nn(png_data).ok()?;
|
|
198
|
+
extract_name_direct(&unstretched)
|
|
189
199
|
}
|
|
190
200
|
|
|
191
201
|
fn extract_name_direct(png_data: &[u8]) -> Option<String> {
|
|
@@ -224,8 +234,13 @@ pub fn extract_file_list_from_pixels(png_data: &[u8]) -> Result<String, String>
|
|
|
224
234
|
if let Ok(result) = extract_file_list_direct(png_data) {
|
|
225
235
|
return Ok(result);
|
|
226
236
|
}
|
|
227
|
-
let reconst = crate::reconstitution::crop_and_reconstitute(png_data)
|
|
228
|
-
|
|
237
|
+
if let Ok(reconst) = crate::reconstitution::crop_and_reconstitute(png_data) {
|
|
238
|
+
if let Ok(result) = extract_file_list_direct(&reconst) {
|
|
239
|
+
return Ok(result);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
let unstretched = crate::reconstitution::unstretch_nn(png_data)?;
|
|
243
|
+
extract_file_list_direct(&unstretched)
|
|
229
244
|
}
|
|
230
245
|
|
|
231
246
|
fn extract_file_list_direct(png_data: &[u8]) -> Result<String, String> {
|
package/native/reconstitution.rs
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
use image::{Rgba, RgbaImage};
|
|
1
|
+
use image::{Rgba, RgbaImage, DynamicImage, ImageReader};
|
|
2
2
|
use std::cmp::min;
|
|
3
|
+
use std::io::Cursor;
|
|
4
|
+
|
|
5
|
+
fn load_image_no_limits(data: &[u8]) -> Result<DynamicImage, String> {
|
|
6
|
+
let mut reader = ImageReader::new(Cursor::new(data))
|
|
7
|
+
.with_guessed_format()
|
|
8
|
+
.map_err(|e| format!("format guess error: {}", e))?;
|
|
9
|
+
reader.no_limits();
|
|
10
|
+
reader.decode().map_err(|e| format!("image decode error: {}", e))
|
|
11
|
+
}
|
|
3
12
|
|
|
4
13
|
fn color_dist(a: [u8; 4], b: [u8; 4]) -> i32 {
|
|
5
14
|
(a[0] as i32 - b[0] as i32).abs() +
|
|
@@ -77,7 +86,7 @@ fn intra_block_transitions_v(
|
|
|
77
86
|
}
|
|
78
87
|
|
|
79
88
|
pub fn crop_and_reconstitute(png_data: &[u8]) -> Result<Vec<u8>, String> {
|
|
80
|
-
let img =
|
|
89
|
+
let img = load_image_no_limits(png_data)?;
|
|
81
90
|
let rgba = img.to_rgba8();
|
|
82
91
|
let width = rgba.width();
|
|
83
92
|
let height = rgba.height();
|
|
@@ -411,13 +420,13 @@ pub fn crop_and_reconstitute(png_data: &[u8]) -> Result<Vec<u8>, String> {
|
|
|
411
420
|
}
|
|
412
421
|
|
|
413
422
|
let mut output = Vec::new();
|
|
414
|
-
out.write_to(&mut std::io::Cursor::new(&mut output), image::ImageFormat::Png)
|
|
423
|
+
out.write_to(&mut std::io::Cursor::new(&mut output), image::ImageFormat::Png)
|
|
424
|
+
.map_err(|e| format!("PNG write error: {}", e))?;
|
|
415
425
|
Ok(output)
|
|
416
426
|
}
|
|
417
427
|
|
|
418
428
|
pub fn unstretch_nn(png_data: &[u8]) -> Result<Vec<u8>, String> {
|
|
419
|
-
let img =
|
|
420
|
-
.map_err(|e| format!("image load error: {}", e))?;
|
|
429
|
+
let img = load_image_no_limits(png_data)?;
|
|
421
430
|
let rgba = img.to_rgba8();
|
|
422
431
|
let width = rgba.width() as usize;
|
|
423
432
|
let height = rgba.height() as usize;
|
package/package.json
CHANGED
|
Binary file
|