mirror of
https://github.com/Dangoware/sqp.git
synced 2025-04-19 07:12:55 -05:00
Fixed minor issues
This commit is contained in:
parent
765f7f7789
commit
861baa9999
4 changed files with 97 additions and 20 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,6 +5,7 @@ Cargo.lock
|
||||||
# Ignore images
|
# Ignore images
|
||||||
*.png
|
*.png
|
||||||
*.dpf
|
*.dpf
|
||||||
|
*.sqp
|
||||||
*.raw
|
*.raw
|
||||||
*.rgba
|
*.rgba
|
||||||
*.jpg
|
*.jpg
|
||||||
|
|
|
@ -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
|
||||||
|
|
66
src/lib.rs
66
src/lib.rs
|
@ -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;
|
||||||
|
|
|
@ -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)?)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue