roxify 1.13.4 → 1.13.5

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.
@@ -5,6 +5,8 @@ use rayon::prelude::*;
5
5
  use serde::Serialize;
6
6
  use walkdir::WalkDir;
7
7
 
8
+ use crate::png_chunk_writer::{ChunkedIdatWriter, write_png_chunk};
9
+
8
10
  const PNG_HEADER: &[u8] = &[137, 80, 78, 71, 13, 10, 26, 10];
9
11
  const PIXEL_MAGIC: &[u8] = b"PXL1";
10
12
  const MARKER_START: [(u8, u8, u8); 3] = [(255, 0, 0), (0, 255, 0), (0, 0, 255)];
@@ -20,6 +22,7 @@ const PARALLEL_IO_FILE_THRESHOLD: u64 = MB;
20
22
  const PARALLEL_IO_BATCH_BYTES: u64 = 128 * MB;
21
23
  const PARALLEL_IO_BATCH_FILES: usize = 512;
22
24
  const PARALLEL_IO_MIN_FILES: usize = 8;
25
+ const HEADER_VERSION_V2: u8 = 2;
23
26
 
24
27
  pub type ProgressCallback = Box<dyn Fn(u64, u64, &str) + Send>;
25
28
 
@@ -345,12 +348,12 @@ fn write_png_from_zst_mem(
345
348
 
346
349
  let encrypted_payload_len = enc_header_len + zst_size + hmac_trailer_len;
347
350
 
348
- let version = 1u8;
351
+ let version = HEADER_VERSION_V2;
349
352
  let name_bytes = name.map(|n| n.as_bytes()).unwrap_or(&[]);
350
353
  let name_len = name_bytes.len().min(255) as u8;
351
- let payload_len_bytes = (encrypted_payload_len as u32).to_be_bytes();
354
+ let payload_len_bytes = (encrypted_payload_len as u64).to_be_bytes();
352
355
 
353
- let mut meta_header = Vec::with_capacity(1 + 1 + name_len as usize + 4);
356
+ let mut meta_header = Vec::with_capacity(1 + 1 + name_len as usize + 8);
354
357
  meta_header.push(version);
355
358
  meta_header.push(name_len);
356
359
  if name_len > 0 {
@@ -398,13 +401,6 @@ fn write_png_from_zst_mem(
398
401
 
399
402
  let header_bytes = build_header_bytes(&meta_header, &enc_header_bytes);
400
403
 
401
- let stride = row_bytes + 1;
402
- let scanlines_total = height * stride;
403
-
404
- const MAX_BLOCK: usize = 65535;
405
- let num_blocks = (scanlines_total + MAX_BLOCK - 1) / MAX_BLOCK;
406
- let idat_len = 2 + num_blocks * 5 + scanlines_total + 4;
407
-
408
404
  let out_file = File::create(output_path)?;
409
405
  let buf_capacity = if total_data_bytes > 256 * 1024 * 1024 { 16 * 1024 * 1024 }
410
406
  else if total_data_bytes > 16 * 1024 * 1024 { 8 * 1024 * 1024 }
@@ -418,7 +414,7 @@ fn write_png_from_zst_mem(
418
414
  ihdr[4..8].copy_from_slice(&(height as u32).to_be_bytes());
419
415
  ihdr[8] = 8;
420
416
  ihdr[9] = 2;
421
- write_chunk_hdr(&mut w, b"IHDR", &ihdr)?;
417
+ write_png_chunk(&mut w, b"IHDR", &ihdr)?;
422
418
 
423
419
  let mut zst_reader = std::io::Cursor::new(zst_buf);
424
420
 
@@ -433,15 +429,14 @@ fn write_png_from_zst_mem(
433
429
  height,
434
430
  row_bytes,
435
431
  marker_end_pos,
436
- idat_len,
437
432
  total_data_bytes,
438
433
  progress,
439
434
  )?;
440
435
 
441
436
  if let Some(fl) = file_list {
442
- write_chunk_hdr(&mut w, b"rXFL", fl.as_bytes())?;
437
+ write_png_chunk(&mut w, b"rXFL", fl.as_bytes())?;
443
438
  }
444
- write_chunk_hdr(&mut w, b"IEND", &[])?;
439
+ write_png_chunk(&mut w, b"IEND", &[])?;
445
440
  w.flush()?;
446
441
 
447
442
  Ok(())
@@ -470,22 +465,16 @@ fn write_idat_streaming<W: Write, R: Read>(
470
465
  height: usize,
471
466
  row_bytes: usize,
472
467
  marker_end_pos: usize,
473
- idat_len: usize,
474
468
  total_data_bytes: usize,
475
469
  progress: &Option<ProgressCallback>,
476
470
  ) -> anyhow::Result<()> {
477
- w.write_all(&(idat_len as u32).to_be_bytes())?;
478
- w.write_all(b"IDAT")?;
479
-
480
- let mut crc = crc32fast::Hasher::new();
481
- crc.update(b"IDAT");
471
+ let mut idat = ChunkedIdatWriter::new(w);
482
472
 
483
473
  let stride = row_bytes + 1;
484
474
  let scanlines_total = height * stride;
485
475
 
486
476
  let zlib = [0x78u8, 0x01];
487
- w.write_all(&zlib)?;
488
- crc.update(&zlib);
477
+ idat.write_all(&zlib)?;
489
478
 
490
479
  let fl_chunk_data = file_list_chunk.unwrap_or(&[]);
491
480
  let payload_total = header_bytes.len() + zst_size + hmac_trailer_len + fl_chunk_data.len();
@@ -524,14 +513,12 @@ fn write_idat_streaming<W: Write, R: Read>(
524
513
  !block_size as u8,
525
514
  (!(block_size >> 8)) as u8,
526
515
  ];
527
- w.write_all(&header)?;
528
- crc.update(&header);
516
+ idat.write_all(&header)?;
529
517
  deflate_block_remaining = block_size;
530
518
  }
531
519
 
532
520
  let filter_byte = [0u8];
533
- w.write_all(&filter_byte)?;
534
- crc.update(&filter_byte);
521
+ idat.write_all(&filter_byte)?;
535
522
  adler.write(&filter_byte);
536
523
  scanline_pos += 1;
537
524
  deflate_block_remaining -= 1;
@@ -549,8 +536,7 @@ fn write_idat_streaming<W: Write, R: Read>(
549
536
  !block_size as u8,
550
537
  (!(block_size >> 8)) as u8,
551
538
  ];
552
- w.write_all(&header)?;
553
- crc.update(&header);
539
+ idat.write_all(&header)?;
554
540
  deflate_block_remaining = block_size;
555
541
  }
556
542
 
@@ -567,8 +553,7 @@ fn write_idat_streaming<W: Write, R: Read>(
567
553
  let me_remaining = 9 - me_offset;
568
554
  let take = need.min(me_remaining);
569
555
  let slice = &marker_end_bytes[me_offset..me_offset + take];
570
- w.write_all(slice)?;
571
- crc.update(slice);
556
+ idat.write_all(slice)?;
572
557
  adler.write(slice);
573
558
  flat_pos += take;
574
559
  chunk_written += take;
@@ -582,8 +567,7 @@ fn write_idat_streaming<W: Write, R: Read>(
582
567
  let avail = header_bytes.len() - header_pos;
583
568
  let take = need.min(avail);
584
569
  let slice = &header_bytes[header_pos..header_pos + take];
585
- w.write_all(slice)?;
586
- crc.update(slice);
570
+ idat.write_all(slice)?;
587
571
  adler.write(slice);
588
572
  header_pos += take;
589
573
  flat_pos += take;
@@ -599,8 +583,7 @@ fn write_idat_streaming<W: Write, R: Read>(
599
583
  if let Some(ref mut enc) = encryptor {
600
584
  enc.encrypt_chunk(&mut transfer_buf[..got]);
601
585
  }
602
- w.write_all(&transfer_buf[..got])?;
603
- crc.update(&transfer_buf[..got]);
586
+ idat.write_all(&transfer_buf[..got])?;
604
587
  adler.write(&transfer_buf[..got]);
605
588
  zst_remaining -= got;
606
589
  flat_pos += got;
@@ -618,8 +601,7 @@ fn write_idat_streaming<W: Write, R: Read>(
618
601
  let avail = hmac_trailer_len - hmac_pos;
619
602
  let take = need.min(avail);
620
603
  let slice = &hmac_bytes[hmac_pos..hmac_pos + take];
621
- w.write_all(slice)?;
622
- crc.update(slice);
604
+ idat.write_all(slice)?;
623
605
  adler.write(slice);
624
606
  hmac_pos += take;
625
607
  flat_pos += take;
@@ -637,8 +619,7 @@ fn write_idat_streaming<W: Write, R: Read>(
637
619
  let avail = fl_chunk_data.len() - fl_pos;
638
620
  let take = need.min(avail);
639
621
  let slice = &fl_chunk_data[fl_pos..fl_pos + take];
640
- w.write_all(slice)?;
641
- crc.update(slice);
622
+ idat.write_all(slice)?;
642
623
  adler.write(slice);
643
624
  fl_pos += take;
644
625
  flat_pos += take;
@@ -654,8 +635,7 @@ fn write_idat_streaming<W: Write, R: Read>(
654
635
  };
655
636
  let take = need.min(zero_remaining).min(buf_size).min(max_before_marker);
656
637
  if take == 0 { break; }
657
- w.write_all(&zero_buf[..take])?;
658
- crc.update(&zero_buf[..take]);
638
+ idat.write_all(&zero_buf[..take])?;
659
639
  adler.write(&zero_buf[..take]);
660
640
  zero_remaining -= take;
661
641
  flat_pos += take;
@@ -678,11 +658,8 @@ fn write_idat_streaming<W: Write, R: Read>(
678
658
 
679
659
  let adler_val = adler.finish();
680
660
  let adler_bytes = adler_val.to_be_bytes();
681
- w.write_all(&adler_bytes)?;
682
- crc.update(&adler_bytes);
683
-
684
- w.write_all(&crc.finalize().to_be_bytes())?;
685
- Ok(())
661
+ idat.write_all(&adler_bytes)?;
662
+ idat.finish()
686
663
  }
687
664
 
688
665
  fn build_marker_end_bytes() -> [u8; 9] {
@@ -695,13 +672,3 @@ fn build_marker_end_bytes() -> [u8; 9] {
695
672
  buf
696
673
  }
697
674
 
698
- fn write_chunk_hdr<W: Write>(w: &mut W, chunk_type: &[u8; 4], data: &[u8]) -> anyhow::Result<()> {
699
- w.write_all(&(data.len() as u32).to_be_bytes())?;
700
- w.write_all(chunk_type)?;
701
- w.write_all(data)?;
702
- let mut h = crc32fast::Hasher::new();
703
- h.update(chunk_type);
704
- h.update(data);
705
- w.write_all(&h.finalize().to_be_bytes())?;
706
- Ok(())
707
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roxify",
3
- "version": "1.13.4",
3
+ "version": "1.13.5",
4
4
  "type": "module",
5
5
  "description": "Ultra-lightweight PNG steganography with native Rust acceleration. Encode binary data into PNG images with zstd compression.",
6
6
  "main": "dist/index.js",