fixed all bugs in de- and encoder, version bump to 0.9.0
This commit is contained in:
parent
06c36fb1ec
commit
140476e3a0
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
/qoi_test_images
|
/qoi_test_images
|
||||||
|
*.qoi
|
||||||
|
*.png
|
||||||
|
227
Cargo.lock
generated
227
Cargo.lock
generated
@ -8,6 +8,61 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler2"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is_terminal_polyfill",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "array-init"
|
name = "array-init"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
@ -26,6 +81,39 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.5.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colors-transform"
|
name = "colors-transform"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
@ -41,6 +129,15 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fdeflate"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb"
|
||||||
|
dependencies = [
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
@ -48,17 +145,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
|
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"miniz_oxide",
|
"miniz_oxide 0.5.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "is_terminal_polyfill"
|
||||||
version = "0.4.17"
|
version = "1.70.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
[[package]]
|
||||||
]
|
name = "log"
|
||||||
|
version = "0.4.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
@ -70,23 +170,126 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "miniz_oxide"
|
||||||
version = "0.17.6"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f0e7f4c94ec26ff209cee506314212639d6c91b80afb82984819fafce9df01c"
|
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
|
||||||
|
dependencies = [
|
||||||
|
"adler2",
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.17.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
|
"fdeflate",
|
||||||
"flate2",
|
"flate2",
|
||||||
"miniz_oxide",
|
"miniz_oxide 0.8.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "qoi"
|
name = "qoi"
|
||||||
version = "0.1.1"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"array-init",
|
"array-init",
|
||||||
|
"clap",
|
||||||
"colors-transform",
|
"colors-transform",
|
||||||
"log",
|
"log",
|
||||||
"png",
|
"png",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simd-adler32"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "qoi"
|
name = "qoi"
|
||||||
version = "0.1.1"
|
version = "0.9.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["nihil carcosa <nihil@valhrafnaz.gay>"]
|
authors = ["nihil carcosa <nihil@valhrafnaz.gay>"]
|
||||||
description = "CLI tool and rust library for the de- and encoding of images to the QOI format."
|
description = "CLI tool and rust library for the de- and encoding of images to the QOI format."
|
||||||
@ -18,6 +18,7 @@ publish = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
array-init = "2.0.1"
|
array-init = "2.0.1"
|
||||||
png = "0.17.6"
|
png = "0.17.14"
|
||||||
log = "0.4.17"
|
log = "0.4.22"
|
||||||
colors-transform = "0.2.11"
|
colors-transform = "0.2.11"
|
||||||
|
clap = "4.5.21"
|
||||||
|
215
src/lib.rs
215
src/lib.rs
@ -1,15 +1,15 @@
|
|||||||
//! # qoi_img
|
//! # qoi_img
|
||||||
//! `qoi_img` is a bad, from-scratch implementation of the decoder and encoder for the `.qoi` file format as described as on [qoiformat.org](https://qoiformat.org/qoi-specification.pdf).
|
//! `qoi_img` is a bad, from-scratch implementation of the decoder and encoder for the `.qoi` file format as described as on [qoiformat.org](https://qoiformat.org/qoi-specification.pdf).
|
||||||
//! This crate should not be published as better crates are available, e.g. [rapid-qoi](https://crates.io/crates/rapid-qoi).
|
//! This crate should not be published as better crates are available, e.g. [rapid-qoi](https://crates.io/crates/rapid-qoi).
|
||||||
|
|
||||||
#![allow(dead_code, unused_variables)]
|
#![allow(dead_code, unused_variables)]
|
||||||
pub mod qoi_lib {
|
pub mod qoi_lib {
|
||||||
|
|
||||||
use log::{debug, info, Level, LevelFilter, Record, SetLoggerError};
|
use log::{debug, info, Level, LevelFilter, Record, SetLoggerError};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fs::File;
|
use std::fs::*;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
||||||
|
|
||||||
use array_init;
|
use array_init;
|
||||||
|
|
||||||
//Custom error for custom error handling
|
//Custom error for custom error handling
|
||||||
@ -60,7 +60,7 @@ pub mod qoi_lib {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use std::error::Error;
|
/// # use std::error::Error;
|
||||||
/// # use crate::qoi_test::qoi_img::*;
|
/// # use crate::qoi::qoi_lib::*;
|
||||||
/// # fn main() -> Result<(), Box<ImgError>> {
|
/// # fn main() -> Result<(), Box<ImgError>> {
|
||||||
/// init().expect("Failed to initialize logger");
|
/// init().expect("Failed to initialize logger");
|
||||||
/// #
|
/// #
|
||||||
@ -73,7 +73,7 @@ pub mod qoi_lib {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use std::error::Error;
|
/// # use std::error::Error;
|
||||||
/// # use crate::qoi_test::qoi_img::*;
|
/// # use crate::qoi::qoi_lib::*;
|
||||||
/// # fn main() -> Result<(), ImgError> {
|
/// # fn main() -> Result<(), ImgError> {
|
||||||
/// match init() {
|
/// match init() {
|
||||||
/// Ok(()) => (),
|
/// Ok(()) => (),
|
||||||
@ -97,7 +97,7 @@ pub mod qoi_lib {
|
|||||||
/// Create a new image via constructor [`Image::new()`];
|
/// Create a new image via constructor [`Image::new()`];
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use std::error::Error;
|
/// # use std::error::Error;
|
||||||
/// # use crate::qoi_test::qoi_img::*;
|
/// # use crate::qoi::qoi_lib::*;
|
||||||
/// # fn main() -> Result<(), Box<ImgError>> {
|
/// # fn main() -> Result<(), Box<ImgError>> {
|
||||||
///
|
///
|
||||||
/// let pixels: Vec<u8> = vec![0;1024*1024*4];
|
/// let pixels: Vec<u8> = vec![0;1024*1024*4];
|
||||||
@ -129,7 +129,13 @@ pub mod qoi_lib {
|
|||||||
channels: u8,
|
channels: u8,
|
||||||
colorspace: u8,
|
colorspace: u8,
|
||||||
) -> Result<Image, ImgError> {
|
) -> Result<Image, ImgError> {
|
||||||
let pixels: Vec<Pixel> = match Image::pixels_from_bytes(data) {
|
let alpha: bool;
|
||||||
|
if channels == 4 {
|
||||||
|
alpha = true;
|
||||||
|
} else {
|
||||||
|
alpha = false;
|
||||||
|
}
|
||||||
|
let pixels: Vec<Pixel> = match Image::pixels_from_bytes(data, alpha) {
|
||||||
Ok(out) => out,
|
Ok(out) => out,
|
||||||
Err(error) => return Err(error),
|
Err(error) => return Err(error),
|
||||||
};
|
};
|
||||||
@ -164,21 +170,39 @@ pub mod qoi_lib {
|
|||||||
img
|
img
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pixels_from_bytes(data: Vec<u8>) -> Result<Vec<Pixel>, ImgError> {
|
//Expects pixel data in order left to right, top to bottom, with values for rgba in sequential order
|
||||||
|
fn pixels_from_bytes(data: Vec<u8>, alpha: bool) -> Result<Vec<Pixel>, ImgError> {
|
||||||
let mut pixels: Vec<Pixel> = Vec::with_capacity(data.len() / 4);
|
let mut pixels: Vec<Pixel> = Vec::with_capacity(data.len() / 4);
|
||||||
if data.len() % 4 == 0 {
|
if alpha {
|
||||||
for i in 0..data.len() / 4 {
|
if data.len() % 4 == 0 {
|
||||||
pixels.push(Pixel {
|
for i in 0..data.len() / 4 {
|
||||||
r: data[i * 4],
|
pixels.push(Pixel {
|
||||||
g: data[i * 4 + 1],
|
r: data[i * 4],
|
||||||
b: data[i * 4 + 2],
|
g: data[i * 4 + 1],
|
||||||
a: data[i * 4 + 3],
|
b: data[i * 4 + 2],
|
||||||
});
|
a: data[i * 4 + 3],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(pixels)
|
||||||
|
} else {
|
||||||
|
Err(ImgError::DataError)
|
||||||
}
|
}
|
||||||
Ok(pixels)
|
|
||||||
} else {
|
} else {
|
||||||
Err(ImgError::DataError)
|
if data.len() % 4 == 0 {
|
||||||
|
for i in 0..data.len() / 3 {
|
||||||
|
pixels.push(Pixel {
|
||||||
|
r: data[i * 3],
|
||||||
|
g: data[i * 3 + 1],
|
||||||
|
b: data[i * 3 + 2],
|
||||||
|
a: 255,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(pixels)
|
||||||
|
} else {
|
||||||
|
Err(ImgError::DataError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,6 +402,7 @@ pub mod qoi_lib {
|
|||||||
(store % 64) as u8
|
(store % 64) as u8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Definitely broken in some way
|
||||||
pub fn encode_from_image(img: Image) -> Vec<u8> {
|
pub fn encode_from_image(img: Image) -> Vec<u8> {
|
||||||
let mut prev_pixel: Pixel = Pixel {
|
let mut prev_pixel: Pixel = Pixel {
|
||||||
r: 0u8,
|
r: 0u8,
|
||||||
@ -399,7 +424,7 @@ pub mod qoi_lib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut encoded_bytes: Vec<u8> = Vec::new();
|
let mut encoded_bytes: Vec<u8> = Vec::new();
|
||||||
let mut run: u8 = 0;
|
let mut run: u64 = 0;
|
||||||
|
|
||||||
let head = Header {
|
let head = Header {
|
||||||
magic: ['q', 'o', 'i', 'f'],
|
magic: ['q', 'o', 'i', 'f'],
|
||||||
@ -414,7 +439,7 @@ pub mod qoi_lib {
|
|||||||
encoded_bytes.push(i);
|
encoded_bytes.push(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut counter: u32 = 0;
|
let mut counter: u64 = 0;
|
||||||
|
|
||||||
for pixel in img.pixels {
|
for pixel in img.pixels {
|
||||||
counter += 1;
|
counter += 1;
|
||||||
@ -432,18 +457,21 @@ pub mod qoi_lib {
|
|||||||
encoded_bytes.push(QOI_OP_RUN | (62 - RUN_BIAS));
|
encoded_bytes.push(QOI_OP_RUN | (62 - RUN_BIAS));
|
||||||
run -= 62;
|
run -= 62;
|
||||||
} else if run % 62 > 0 {
|
} else if run % 62 > 0 {
|
||||||
encoded_bytes.push(QOI_OP_RUN | (run - RUN_BIAS));
|
let run_remainder: u8 = run.try_into().unwrap();
|
||||||
|
encoded_bytes.push(QOI_OP_RUN | (run_remainder - RUN_BIAS));
|
||||||
run = 0;
|
run = 0;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
encoded_bytes.push(QOI_OP_RUN | (run - RUN_BIAS));
|
let run8: u8 = run.try_into().unwrap();
|
||||||
|
encoded_bytes.push(QOI_OP_RUN | (run8 - RUN_BIAS));
|
||||||
run = 0;
|
run = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
match chunk {
|
match chunk {
|
||||||
(ChunkType::Index, Some((index, irr1, irr2))) => {
|
(ChunkType::Index, Some((index, irr1, irr2))) => {
|
||||||
encoded_bytes.push(QOI_OP_INDEX | index);
|
encoded_bytes.push(QOI_OP_INDEX | index);
|
||||||
@ -509,14 +537,17 @@ pub mod qoi_lib {
|
|||||||
encoded_bytes.push(QOI_OP_RUN | (62 - RUN_BIAS));
|
encoded_bytes.push(QOI_OP_RUN | (62 - RUN_BIAS));
|
||||||
run -= 62;
|
run -= 62;
|
||||||
} else if run % 62 > 0 {
|
} else if run % 62 > 0 {
|
||||||
encoded_bytes.push(QOI_OP_RUN | (run - RUN_BIAS));
|
let run_remainder: u8 = run.try_into().unwrap();
|
||||||
|
encoded_bytes.push(QOI_OP_RUN | (run_remainder - RUN_BIAS));
|
||||||
run = 0;
|
run = 0;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
encoded_bytes.push(QOI_OP_RUN | (run - RUN_BIAS));
|
let run8: u8 = run.try_into().unwrap();
|
||||||
|
encoded_bytes.push(QOI_OP_RUN | (run8 - RUN_BIAS));
|
||||||
|
// run = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,10 +791,13 @@ pub mod qoi_lib {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
use png::ColorType;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::fs::File;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{BufReader, Read};
|
use std::io::{BufReader, Read};
|
||||||
|
use std::path::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn diff_test() {
|
fn diff_test() {
|
||||||
@ -781,40 +815,131 @@ pub mod qoi_lib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn encode_test() -> io::Result<()> {
|
fn qoi_to_qoi_test() -> io::Result<()> {
|
||||||
let f: File = File::open("test.qoi")?;
|
//Open path to test images
|
||||||
let mut reader = BufReader::new(f);
|
let path: &Path = Path::new("./qoi_test_images/");
|
||||||
let mut bytes: Vec<u8> = Vec::new();
|
let dir: ReadDir = match path.read_dir() {
|
||||||
|
Ok(d) => d,
|
||||||
|
Err(e) => panic!("Error reading path {e:?}"),
|
||||||
|
};
|
||||||
|
//Loop over files in directory, attempt to decode .qoi images and reencode
|
||||||
|
for entry in dir {
|
||||||
|
|
||||||
reader.read_to_end(&mut bytes)?;
|
let file_path = match entry {
|
||||||
|
Ok(d) => d.path(),
|
||||||
|
Err(e) => panic!("Non-functional dir entry! \n {e:?}")
|
||||||
|
};
|
||||||
|
let file_path_str = match file_path.to_str() {
|
||||||
|
Some(s) => s,
|
||||||
|
None => ""
|
||||||
|
};
|
||||||
|
if !(file_path_str.contains(".qoi")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let out_img: super::Image;
|
let file = match File::open(&file_path) {
|
||||||
|
Ok(f) => f,
|
||||||
|
Err(e) => panic!("Error reading file with path {:?}", file_path_str),
|
||||||
|
};
|
||||||
|
let mut reader = BufReader::new(file);
|
||||||
|
let mut bytes: Vec<u8> = Vec::new();
|
||||||
|
|
||||||
match super::decode(bytes) {
|
reader.read_to_end(&mut bytes)?;
|
||||||
Ok(img) => out_img = img,
|
|
||||||
Err(err) => panic!("wallah geht nicht :/ {:?}", err),
|
let output_image: super::Image;
|
||||||
|
match super::decode(bytes) {
|
||||||
|
Ok(img) => output_image = img,
|
||||||
|
Err(err) => panic!("Image decode failed for {:?}" , file_path.to_str())
|
||||||
|
}
|
||||||
|
let mut name = match file_path.file_name() {
|
||||||
|
Some(s) => match s.to_str() {
|
||||||
|
Some(ss) => ss,
|
||||||
|
None => panic!("File Name Error!")
|
||||||
|
},
|
||||||
|
None => panic!("File Name Error!"),
|
||||||
|
};
|
||||||
|
name = match name.strip_suffix(".qoi") {
|
||||||
|
Some(n) => n,
|
||||||
|
None => name,
|
||||||
|
};
|
||||||
|
write_to_file(encode_from_image(output_image), name).expect("Writing image failed!");
|
||||||
}
|
}
|
||||||
write_to_file(encode_from_image(out_img), "test_dec").expect("wallahi!");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decode_test() -> io::Result<()> {
|
fn png_to_qoi_test() -> io::Result<()> {
|
||||||
let f: File = File::open("testcard_rgba.qoi")?;
|
//Open path to test images
|
||||||
let mut reader = BufReader::new(f);
|
let path: &Path = Path::new("./qoi_test_images/");
|
||||||
let mut bytes: Vec<u8> = Vec::new();
|
let dir: ReadDir = match path.read_dir() {
|
||||||
|
Ok(d) => d,
|
||||||
|
Err(e) => panic!("Error reading path {e:?}"),
|
||||||
|
};
|
||||||
|
//Loop over files in directory, attempt to decode png and encode as qoi, compare to qoi
|
||||||
|
for entry in dir {
|
||||||
|
|
||||||
reader.read_to_end(&mut bytes)?;
|
let file_path = match entry {
|
||||||
|
Ok(d) => d.path(),
|
||||||
|
Err(e) => panic!("Non-functional dir entry! \n {e:?}")
|
||||||
|
};
|
||||||
|
let file_path_str = match file_path.to_str() {
|
||||||
|
Some(s) => s,
|
||||||
|
None => ""
|
||||||
|
};
|
||||||
|
if !(file_path_str.contains(".png")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
println!("{:}",file_path_str);
|
||||||
|
let file = match File::open(&file_path) {
|
||||||
|
Ok(f) => f,
|
||||||
|
Err(e) => panic!("Cannot read file! \n {e:?}")
|
||||||
|
};
|
||||||
|
let decoder = png::Decoder::new(file);
|
||||||
|
let mut reader = match decoder.read_info() {
|
||||||
|
Ok(reader) => reader,
|
||||||
|
Err(e) => panic!("ERROR: couldn't decode file: {e:}"),
|
||||||
|
};
|
||||||
|
//read image metadata
|
||||||
|
let width: u32 = reader.info().width;
|
||||||
|
let height: u32 = reader.info().height;
|
||||||
|
//for now: hardcoded to 4
|
||||||
|
let channels = match reader.info().color_type {
|
||||||
|
ColorType::Rgb => 3,
|
||||||
|
ColorType::Rgba => 4,
|
||||||
|
_ => panic!("ERROR: Incompatible png file!")
|
||||||
|
};
|
||||||
|
|
||||||
let out_img: super::Image;
|
//create buffer matching the size of png-decoder output, writing size to output
|
||||||
|
let mut buf = vec![0; reader.output_buffer_size()];
|
||||||
|
let info = match reader.next_frame(&mut buf) {
|
||||||
|
Ok(i) => i,
|
||||||
|
Err(e) => panic!("ERROR: {e:?}"),
|
||||||
|
};
|
||||||
|
let bytes = &buf[..info.buffer_size()];
|
||||||
|
let byte_vec: Vec<u8> = bytes.to_vec();
|
||||||
|
|
||||||
match super::decode(bytes) {
|
//create bitmap data from raw byte vector
|
||||||
Ok(img) => out_img = img,
|
let img: Image = match Image::new(byte_vec, height, width, channels, 0) {
|
||||||
Err(err) => panic!("Ja bruder war nicht so erfolgreich ahahahahahha {:?}", err),
|
Ok(image) => image,
|
||||||
|
Err(err) => panic!("Problem generating image: {:?}", err),
|
||||||
|
};
|
||||||
|
|
||||||
|
let encoded_buffer = super::encode_from_image(img);
|
||||||
|
let mut name = match file_path.file_name() {
|
||||||
|
None => panic!("whoops!"),
|
||||||
|
Some(n) => match n.to_str() {
|
||||||
|
None => panic!("im shiddin"),
|
||||||
|
Some(s) => s,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
name = match name.strip_suffix(".png") {
|
||||||
|
Some(n) => n,
|
||||||
|
None => name,
|
||||||
|
};
|
||||||
|
write_to_file(encoded_buffer,name ).expect("Can't write resulting file!");
|
||||||
}
|
}
|
||||||
|
|
||||||
write_to_file(encode_from_image(out_img), "testcard_new").expect("Boowomb!");
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
src/main.rs
29
src/main.rs
@ -82,35 +82,6 @@ fn encode_debug() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn demo() {
|
fn demo() {
|
||||||
let decoder = png::Decoder::new(File::open("testcard_rgba.png").unwrap());
|
|
||||||
let mut reader = match decoder.read_info() {
|
|
||||||
Ok(reader) => reader,
|
|
||||||
Err(e) => panic!("ERROR: couldn't read file: {e:}"),
|
|
||||||
};
|
|
||||||
let mut buf = vec![0; reader.output_buffer_size()];
|
|
||||||
|
|
||||||
let info = match reader.next_frame(&mut buf) {
|
|
||||||
Ok(i) => i,
|
|
||||||
Err(e) => panic!("ERROR: {e:?}"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let bytes = &buf[..info.buffer_size()];
|
|
||||||
let byte_vec: Vec<u8> = bytes.to_vec();
|
|
||||||
|
|
||||||
let img: Image = match Image::new(byte_vec, 256, 256, 4, 0) {
|
|
||||||
Ok(image) => image,
|
|
||||||
Err(err) => panic!("Problem generating imag: {:?}", err),
|
|
||||||
};
|
|
||||||
let start = SystemTime::now();
|
|
||||||
write_to_file(encode_from_image(img), "img").expect("Error writing file!");
|
|
||||||
let stop = match start.elapsed() {
|
|
||||||
Ok(elapsed) => elapsed.as_millis(),
|
|
||||||
Err(e) => {
|
|
||||||
println!("Error: {e:?}");
|
|
||||||
return ();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
println!("Encode took: {} ms.", stop);
|
|
||||||
let start = SystemTime::now();
|
let start = SystemTime::now();
|
||||||
encode_checkerboard();
|
encode_checkerboard();
|
||||||
let stop = match start.elapsed() {
|
let stop = match start.elapsed() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user