Fixed minor issues

This commit is contained in:
G2-Games 2024-07-28 23:58:52 -05:00
parent 765f7f7789
commit 861baa9999
4 changed files with 97 additions and 20 deletions

1
.gitignore vendored
View file

@ -5,6 +5,7 @@ Cargo.lock
# Ignore images # Ignore images
*.png *.png
*.dpf *.dpf
*.sqp
*.raw *.raw
*.rgba *.rgba
*.jpg *.jpg

View file

@ -98,7 +98,7 @@ pub fn idct(input: &[f32], width: usize, height: usize) -> Vec<u8> {
/// JPEG 8x8 Base Quantization Matrix for a quality level of 50. /// JPEG 8x8 Base Quantization Matrix for a quality level of 50.
/// ///
/// Instead of using this, utilize the [`quantization_matrix`] function to /// Instead of using this, use the [`quantization_matrix`] function to
/// get a quantization matrix corresponding to the image quality value. /// get a quantization matrix corresponding to the image quality value.
const BASE_QUANTIZATION_MATRIX: [u16; 64] = [ const BASE_QUANTIZATION_MATRIX: [u16; 64] = [
16, 11, 10, 16, 24, 40, 51, 61, 16, 11, 10, 16, 24, 40, 51, 61,
@ -221,7 +221,7 @@ pub fn dct_decompress(input: &[i16], parameters: DctParameters) -> Vec<u8> {
let row_offset = row_num * parameters.width; let row_offset = row_num * parameters.width;
let offset = if start_x + 8 >= parameters.width { let offset = if start_x + 8 > parameters.width {
parameters.width % 8 parameters.width % 8
} else { } else {
8 8

View file

@ -1,5 +1,52 @@
//! SQP (SQuishy Picture Format) is an image format. It can be used to store //! SQP (**SQ**uishy **P**icture Format) is an image format. It can be used to store
//! image data in lossless or lossy compressed form. //! image data in lossless or lossy compressed form. It is designed to be
//! relatively simple compared to other more standard formats.
//!
//! This image format is mainly for experimentation and learning about
//! compression. While it can be used, there are no guarantees about stability,
//! breaking changes, or features.
//!
//! If you're looking for an image format to use, you might want to consider
//! using a more standard one such as those supported by the
//! [image crate](https://docs.rs/image/latest/image/).
//!
//! # Example
//! ## Creating and writing an SQP
//! ```no_run
//! use sqp::{SquishyPicture, ColorFormat};
//!
//! let width = 2;
//! let height = 2;
//! let bitmap = vec![
//! 255, 255, 255, 255, 0, 255, 0, 128,
//! 255, 255, 255, 255, 0, 255, 0, 128
//! ];
//!
//! // Create a 2×2 image in memory. Nothing is compressed or encoded
//! // at this point.
//! let sqp_image = SquishyPicture::from_raw_lossless(
//! width,
//! height,
//! ColorFormat::Rgba8,
//! bitmap
//! );
//!
//! // Write it out to a file. This performs compression and encoding.
//! sqp_image.save("my_image.sqp").expect("Could not save the image");
//! ```
//!
//! ## Reading an SQP from a file.
//! ```no_run
//! use std::fs::File;
//! use sqp::SquishyPicture;
//!
//! // Load it directly with the `open` function...
//! let image = sqp::open("my_image.sqp").expect("Could not open file");
//!
//! // ...or from something implementing Read.
//! let input_file = File::open("my_image.sqp").expect("Could not open image file");
//! let image2 = SquishyPicture::decode(&input_file);
//! ```
mod compression { mod compression {
pub mod dct; pub mod dct;
@ -10,3 +57,18 @@ mod operations;
pub mod picture; pub mod picture;
pub mod header; pub mod header;
// ----------------------- //
// INLINED USEFUL FEATURES //
// ----------------------- //
#[doc(inline)]
pub use picture::SquishyPicture;
#[doc(inline)]
pub use header::ColorFormat;
#[doc(inline)]
pub use header::CompressionType;
#[doc(inline)]
pub use picture::open;

View file

@ -1,4 +1,6 @@
use std::{fs::File, io::{self, BufWriter, Read, Write}}; //! Functions and other utilities surrounding the [`SquishyPicture`] type.
use std::{fs::File, io::{self, BufWriter, Read, Write}, path::Path};
use byteorder::{ReadBytesExt, WriteBytesExt}; use byteorder::{ReadBytesExt, WriteBytesExt};
use integer_encoding::VarInt; use integer_encoding::VarInt;
@ -11,11 +13,6 @@ use crate::{
operations::{diff_line, line_diff}, operations::{diff_line, line_diff},
}; };
pub struct DangoPicture {
pub header: Header,
pub bitmap: Vec<u8>,
}
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum Error { pub enum Error {
#[error("incorrect identifier, got {0:02X?}")] #[error("incorrect identifier, got {0:02X?}")]
@ -28,7 +25,13 @@ pub enum Error {
CompressionError(#[from] CompressionError), CompressionError(#[from] CompressionError),
} }
impl DangoPicture { /// The basic Squishy Picture type for manipulation in-memory.
pub struct SquishyPicture {
pub header: Header,
pub bitmap: Vec<u8>,
}
impl SquishyPicture {
/// Create a DPF from raw bytes in a particular [`ColorFormat`]. /// Create a DPF from raw bytes in a particular [`ColorFormat`].
/// ///
/// The quality parameter does nothing if the compression type is not /// The quality parameter does nothing if the compression type is not
@ -36,7 +39,7 @@ impl DangoPicture {
/// ///
/// # Example /// # Example
/// ```ignore /// ```ignore
/// let dpf_lossy = DangoPicture::from_raw( /// let dpf_lossy = SquishyPicture::from_raw(
/// input.width(), /// input.width(),
/// input.height(), /// input.height(),
/// ColorFormat::Rgba32, /// ColorFormat::Rgba32,
@ -72,13 +75,13 @@ impl DangoPicture {
color_format, color_format,
}; };
DangoPicture { Self {
header, header,
bitmap, bitmap,
} }
} }
/// Convenience method over [`DangoPicture::from_raw`] which creates a /// Convenience method over [`SquishyPicture::from_raw`] which creates a
/// lossy image with a given quality. /// lossy image with a given quality.
pub fn from_raw_lossy( pub fn from_raw_lossy(
width: u32, width: u32,
@ -97,7 +100,8 @@ impl DangoPicture {
) )
} }
/// Convenience method over [`SquishyPicture::from_raw`] which creates a
/// lossless image.
pub fn from_raw_lossless( pub fn from_raw_lossless(
width: u32, width: u32,
height: u32, height: u32,
@ -114,8 +118,9 @@ impl DangoPicture {
) )
} }
/// Encode the image into anything that implements [Write]. Returns the /// Encode the image into anything that implements [`Write`].
/// number of bytes written. ///
/// Returns the number of bytes written.
pub fn encode<O: Write + WriteBytesExt>(&self, mut output: O) -> Result<usize, Error> { pub fn encode<O: Write + WriteBytesExt>(&self, mut output: O) -> Result<usize, Error> {
let mut count = 0; let mut count = 0;
@ -146,6 +151,9 @@ impl DangoPicture {
}, },
}; };
let mut inspection_file = File::create("raw_data").unwrap();
inspection_file.write_all(&modified_data).unwrap();
// Compress the final image data using the basic LZW scheme // Compress the final image data using the basic LZW scheme
let (compressed_data, compression_info) = compress(modified_data)?; let (compressed_data, compression_info) = compress(modified_data)?;
@ -168,8 +176,8 @@ impl DangoPicture {
Ok(()) Ok(())
} }
/// Decode the image from anything that implements [Read] /// Decode the image from anything that implements [`Read`]
pub fn decode<I: Read + ReadBytesExt>(mut input: I) -> Result<DangoPicture, Error> { pub fn decode<I: Read + ReadBytesExt>(mut input: I) -> Result<Self, Error> {
let header = Header::read_from(&mut input)?; let header = Header::read_from(&mut input)?;
let compression_info = CompressionInfo::read_from(&mut input); let compression_info = CompressionInfo::read_from(&mut input);
@ -194,7 +202,7 @@ impl DangoPicture {
}, },
}; };
Ok(DangoPicture { header, bitmap }) Ok(Self { header, bitmap })
} }
} }
@ -209,3 +217,9 @@ fn decode_varint_stream(stream: &[u8]) -> Vec<i16> {
output output
} }
pub fn open<P: AsRef<Path>>(path: P) -> Result<SquishyPicture, Error> {
let input = File::open(path)?;
Ok(SquishyPicture::decode(input)?)
}