From 861baa9999c7e32976b1a9fca6538c509b28436f Mon Sep 17 00:00:00 2001
From: G2-Games <ke0bhogsg@gmail.com>
Date: Sun, 28 Jul 2024 23:58:52 -0500
Subject: [PATCH] Fixed minor issues

---
 .gitignore             |  1 +
 src/compression/dct.rs |  4 +--
 src/lib.rs             | 66 ++++++++++++++++++++++++++++++++++++++++--
 src/picture.rs         | 46 +++++++++++++++++++----------
 4 files changed, 97 insertions(+), 20 deletions(-)

diff --git a/.gitignore b/.gitignore
index d373bb5..5e9f178 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ Cargo.lock
 # Ignore images
 *.png
 *.dpf
+*.sqp
 *.raw
 *.rgba
 *.jpg
diff --git a/src/compression/dct.rs b/src/compression/dct.rs
index 260e004..1072539 100644
--- a/src/compression/dct.rs
+++ b/src/compression/dct.rs
@@ -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.
 ///
-/// 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.
 const BASE_QUANTIZATION_MATRIX: [u16; 64] = [
     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 offset = if start_x + 8 >= parameters.width {
+                let offset = if start_x + 8 > parameters.width {
                     parameters.width % 8
                 } else {
                     8
diff --git a/src/lib.rs b/src/lib.rs
index 59c3fca..afd64f5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,52 @@
-//! SQP (SQuishy Picture Format) is an image format. It can be used to store
-//! image data in lossless or lossy compressed form.
+//! SQP (**SQ**uishy **P**icture Format) is an image format. It can be used to store
+//! 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 {
     pub mod dct;
@@ -10,3 +57,18 @@ mod operations;
 
 pub mod picture;
 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;
diff --git a/src/picture.rs b/src/picture.rs
index 197e22c..4f952d9 100644
--- a/src/picture.rs
+++ b/src/picture.rs
@@ -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 integer_encoding::VarInt;
@@ -11,11 +13,6 @@ use crate::{
     operations::{diff_line, line_diff},
 };
 
-pub struct DangoPicture {
-    pub header: Header,
-    pub bitmap: Vec<u8>,
-}
-
 #[derive(Error, Debug)]
 pub enum Error {
     #[error("incorrect identifier, got {0:02X?}")]
@@ -28,7 +25,13 @@ pub enum Error {
     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`].
     ///
     /// The quality parameter does nothing if the compression type is not
@@ -36,7 +39,7 @@ impl DangoPicture {
     ///
     /// # Example
     /// ```ignore
-    /// let dpf_lossy = DangoPicture::from_raw(
+    /// let dpf_lossy = SquishyPicture::from_raw(
     ///     input.width(),
     ///     input.height(),
     ///     ColorFormat::Rgba32,
@@ -72,13 +75,13 @@ impl DangoPicture {
             color_format,
         };
 
-        DangoPicture {
+        Self {
             header,
             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.
     pub fn from_raw_lossy(
         width: u32,
@@ -97,7 +100,8 @@ impl DangoPicture {
         )
     }
 
-
+    /// Convenience method over [`SquishyPicture::from_raw`] which creates a
+    /// lossless image.
     pub fn from_raw_lossless(
         width: u32,
         height: u32,
@@ -114,8 +118,9 @@ impl DangoPicture {
         )
     }
 
-    /// Encode the image into anything that implements [Write]. Returns the
-    /// number of bytes written.
+    /// Encode the image into anything that implements [`Write`].
+    ///
+    /// Returns the number of bytes written.
     pub fn encode<O: Write + WriteBytesExt>(&self, mut output: O) -> Result<usize, Error> {
         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
         let (compressed_data, compression_info) = compress(modified_data)?;
 
@@ -168,8 +176,8 @@ impl DangoPicture {
         Ok(())
     }
 
-    /// Decode the image from anything that implements [Read]
-    pub fn decode<I: Read + ReadBytesExt>(mut input: I) -> Result<DangoPicture, Error> {
+    /// Decode the image from anything that implements [`Read`]
+    pub fn decode<I: Read + ReadBytesExt>(mut input: I) -> Result<Self, Error> {
         let header = Header::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
 }
+
+pub fn open<P: AsRef<Path>>(path: P) -> Result<SquishyPicture, Error> {
+    let input = File::open(path)?;
+
+    Ok(SquishyPicture::decode(input)?)
+}