khora_lanes/asset_lane/loading/texture_loader_lane.rs
1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Texture loading and management.
16
17use super::AssetLoaderLane;
18use anyhow::{Context, Result};
19use khora_core::{
20 math::Extent3D,
21 renderer::{
22 api::{SampleCount, TextureDimension, TextureFormat, TextureUsage},
23 CpuTexture,
24 },
25};
26
27/// A lane dedicated to loading and decoding texture files on the CPU
28#[derive(Clone)]
29pub struct TextureLoaderLane;
30
31impl AssetLoaderLane<CpuTexture> for TextureLoaderLane {
32 fn load(
33 &self,
34 bytes: &[u8],
35 ) -> Result<CpuTexture, Box<dyn std::error::Error + Send + Sync + 'static>> {
36 // Decode the image using the `image` crate
37 let img = image::load_from_memory(bytes).context("Failed to decode image from memory")?;
38
39 // Convert to RGBA8 (keep in sRGB space)
40 let rgba_img = img.to_rgba8();
41 let (width, height) = rgba_img.dimensions();
42
43 Ok(CpuTexture {
44 pixels: rgba_img.into_raw(),
45 size: Extent3D {
46 width,
47 height,
48 depth_or_array_layers: 1,
49 },
50 format: TextureFormat::Rgba8UnormSrgb,
51 mip_level_count: 1,
52 sample_count: SampleCount::X1,
53 dimension: TextureDimension::D2,
54 usage: TextureUsage::COPY_DST | TextureUsage::TEXTURE_BINDING,
55 })
56 }
57}