Skip to content

Commit

Permalink
Add JPEG as format, use for maps
Browse files Browse the repository at this point in the history
  • Loading branch information
ackwell committed Aug 30, 2024
1 parent 43c5f36 commit d4ccbee
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 25 deletions.
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ fs4 = { version = "= 0.8.2", features = ["sync"] }
futures = "0.3.25"
git-version = "0.3.9"
graphql_client = { version = "0.14.0" }
image = { version = "0.25.1", default-features = false, features = ["png"] }
image = { version = "0.25.1", default-features = false, features = [
"jpeg",
"png",
] }
ironworks = { git = "https://github.com/ackwell/ironworks.git", features = [
"excel",
"sqpack",
Expand Down
14 changes: 4 additions & 10 deletions src/asset/convert.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::{io::Cursor, path::Path};
use std::path::Path;

use anyhow::Context;
use image::ImageFormat;

use crate::data;
Expand All @@ -24,8 +23,9 @@ impl Converter for Image {
.extension()
.and_then(|extension| extension.to_str());

// TODO: add error handling case on this once more than one format exists.
// TODO: add error handling case on this once a failure case actually exists.
let output_format = match format {
Format::Jpeg => ImageFormat::Jpeg,
Format::Png => ImageFormat::Png,
};

Expand All @@ -43,12 +43,6 @@ impl Converter for Image {
}
}?;

// TODO: are there any non-failure cases here?
let mut bytes = Cursor::new(vec![]);
buffer
.write_to(&mut bytes, output_format)
.context("failed to write output buffer")?;

Ok(bytes.into_inner())
texture::write(buffer, output_format)
}
}
4 changes: 4 additions & 0 deletions src/asset/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@ use super::{convert, error::Error};

#[derive(Debug, Clone, Copy, EnumIter)]
pub enum Format {
Jpeg,
Png,
}

impl Format {
pub fn extension(&self) -> &str {
match self {
Self::Jpeg => "jpg",
Self::Png => "png",
}
}

pub(super) fn converter(&self) -> &dyn convert::Converter {
match self {
Self::Jpeg => &convert::Image,
Self::Png => &convert::Image,
}
}
Expand All @@ -45,6 +48,7 @@ impl FromStr for Format {

fn from_str(input: &str) -> Result<Self, Self::Err> {
Ok(match input {
"jpg" => Self::Jpeg,
"png" => Self::Png,
other => return Err(Error::UnknownFormat(other.into())),
})
Expand Down
17 changes: 6 additions & 11 deletions src/asset/service.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{io::Cursor, sync::Arc};
use std::sync::Arc;

use anyhow::{anyhow, Context};
use image::{ImageBuffer, Pixel, Rgba};
use image::{ImageBuffer, Pixel, Rgb};
use ironworks::Ironworks;

use crate::{data, version::VersionKey};
Expand Down Expand Up @@ -48,27 +48,22 @@ impl Service {

let image = self.compose_map(&ironworks, territory, index)?;

let mut bytes = Cursor::new(vec![]);
image
.write_to(&mut bytes, image::ImageFormat::Png)
.context("failed to write output buffer")?;

Ok(bytes.into_inner())
texture::write(image, image::ImageFormat::Jpeg)
}

fn compose_map(
&self,
ironworks: &Ironworks,
territory: &str,
index: &str,
) -> Result<ImageBuffer<Rgba<u8>, Vec<u8>>> {
) -> Result<ImageBuffer<Rgb<u8>, Vec<u8>>> {
let path = format!("ui/map/{territory}/{index}/{territory}{index}");
let mut buffer_map = texture::read(&ironworks, &format!("{path}_m.tex"))?.into_rgba8();
let mut buffer_map = texture::read(&ironworks, &format!("{path}_m.tex"))?.into_rgb8();

let buffer_background = match texture::read(&ironworks, &format!("{path}m_m.tex")) {
// If the background texture wasn't found, we can assume the map texture is pre-composed.
Err(Error::NotFound(_)) => return Ok(buffer_map),
Ok(image) => image.into_rgba8(),
Ok(image) => image.into_rgb8(),
Err(error) => Err(error)?,
};

Expand Down
28 changes: 27 additions & 1 deletion src/asset/texture.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::io::Cursor;

use anyhow::Context;
use image::{DynamicImage, ImageBuffer};
use image::{DynamicImage, ImageBuffer, ImageFormat};
use ironworks::{file::tex, Ironworks};
use itertools::Itertools;

Expand Down Expand Up @@ -123,3 +125,27 @@ fn read_texture_dxt(texture: tex::Texture, dxt_format: texpresso::Format) -> Res
.context("failed to build image buffer")?;
Ok(DynamicImage::ImageRgba8(image_buffer))
}

pub fn write(image: impl Into<DynamicImage>, format: ImageFormat) -> Result<Vec<u8>> {
fn inner(mut image: DynamicImage, format: ImageFormat) -> Result<Vec<u8>> {
// JPEG encoder errors out on anything with an alpha channel.
if format == ImageFormat::Jpeg {
image = match image {
image @ DynamicImage::ImageLumaA8(..) | image @ DynamicImage::ImageLuma16(..) => {
image.into_luma8().into()
}
other => other.into_rgb8().into(),
}
}

// TODO: are there any non-failure cases here?
let mut bytes = Cursor::new(vec![]);
image
.write_to(&mut bytes, format)
.context("failed to write output buffer")?;

Ok(bytes.into_inner())
}

inner(image.into(), format)
}
5 changes: 3 additions & 2 deletions src/http/api1/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ async fn asset2(

fn format_mime(format: Format) -> mime::Mime {
match format {
Format::Jpeg => mime::IMAGE_JPEG,
Format::Png => mime::IMAGE_PNG,
}
}
Expand Down Expand Up @@ -210,10 +211,10 @@ async fn map(
let bytes = asset.map(version_key, &territory, &index)?;

let response = (
TypedHeader(ContentType::png()),
TypedHeader(ContentType::jpeg()),
[(
header::CONTENT_DISPOSITION,
format!("inline; filename=\"{territory}_{index}.png\""),
format!("inline; filename=\"{territory}_{index}.jpg\""),
)],
bytes,
);
Expand Down

0 comments on commit d4ccbee

Please sign in to comment.