Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make from_slice() const? #20

Open
mlund opened this issue Feb 20, 2024 · 7 comments
Open

Make from_slice() const? #20

mlund opened this issue Feb 20, 2024 · 7 comments

Comments

@mlund
Copy link

mlund commented Feb 20, 2024

  • Version of tinytga in use (if applicable): 0.5.0

Description of the problem/feature request/other

I'm experimenting with embedded-graphics on a very restricted system with only 40 kB available RAM, and while it does work with primitives like circles, fonts etc., using tinytga, the size grows up to 80 kB bytes or so while loading a 2 kB file. I therefore wonder if fn from_slice() could be made const so that image processing is done at compile-time? I realise that this could be an elaborate task due to the limitations of constant expressions.

@mlund mlund changed the title Make parse_slice() const? Make from_slice() const? Feb 20, 2024
@rfuest
Copy link
Member

rfuest commented Feb 20, 2024

I don't think that will be possible, but I also don't think that this is your problem. I'm pretty sure I've successfully used tinytga on a microcontroller with 8 kB of RAM in the past.

Can you provide a bit more information about the system, like what architecture/controller you are working with? Or can you even make the code that you use to draw the image and an example image available?

@mlund
Copy link
Author

mlund commented Feb 20, 2024

Thanks for the quick reply. It could be that it's the rust compiler that does something unexpected. The target is a a Commodore 64 8-bit computer using llvm-mos/rust-mos. I'll shortly push the display driver to a crate with instructions how to run this (which involves Docker due to the special toolchain).

@rfuest
Copy link
Member

rfuest commented Feb 20, 2024

Now that's an interesting project, I'm happy to help with that. I had never expected to use any Rust code I've written to run on my C64, but I'll definitely try it when we get this working.

@mlund
Copy link
Author

mlund commented Feb 20, 2024

Sounds great - here's preview of what I have so far ;-)

display-driver.mov

@mlund
Copy link
Author

mlund commented Feb 21, 2024

The retro-display display driver is out: https://crates.io/crates/retro-display

@rfuest
Copy link
Member

rfuest commented Feb 24, 2024

I had some permission problems with using Podman to run the development container, which made development a little inconvenient, but after some tinkering I was able to display an image using the ImageRaw type from embedded-graphics:

vice-video-2024022405220580.mp4

Here is the code I used to display the image:

#[start]
fn _main(_argc: isize, _argv: *const *const u8) -> isize {
    let mut display = PetsciiDisplay {};
    display.set_border_color(VicIIPalette::Black);
    display.clear(VicIIPalette::Black).unwrap();

    let data = include_bytes!("../eg-logo.raw");
    let image = ImageRawLE::new(data, 20);
    Image::new(&image, Point::new(10, 0))
        .draw(&mut display)
        .unwrap();
    loop {}
}

The generated binary is 1730 bytes with 250 bytes taken up by the image.

There are some minor tweaks which I had to make in the library to get this working. I'll open a PR for these changes when I've sorted out my permission issues. I've also added a set_border_color method to make the demo look nicer.

The data file was created by a small external program, which uses tinytga and e-g's Framebuffer. The code was just a quick hack and is very inflexible with many hardcoded values. A real implementation could map the RGB colors in an image to their closest C64 palette entry.

fn main() {
    let logo_data = include_bytes!("../assets/eg-logo.tga");
    let logo = Tga::<Gray4>::from_slice(logo_data).unwrap();

    let mut fb =
        Framebuffer::<Gray4, _, LittleEndian, 20, 25, { buffer_size::<Gray4>(20, 25) }>::new();
    Image::new(&logo, Point::zero()).draw(&mut fb).unwrap();

    for p in fb.bounding_box().points() {
        let c = fb.pixel(p).unwrap();

        let c64_c = match c.into_storage() {
            8 => 6,
            15 => 14,
            _ => 0,
        };

        fb.set_pixel(p, Gray4::new(c64_c));
    }

    std::fs::write("/tmp/eg-logo.raw", fb.data()).unwrap();
}

@mlund
Copy link
Author

mlund commented Feb 24, 2024

This is great, and 2K is not bad at all. Yes, I started looking into conversion from RGB by calculating the color difference and realised that this can be done in many ways. There are crates available, but I didn't continue investigating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants