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

Invert Alpha method #2257

Open
HeCorr opened this issue Jun 7, 2024 · 5 comments
Open

Invert Alpha method #2257

HeCorr opened this issue Jun 7, 2024 · 5 comments

Comments

@HeCorr
Copy link

HeCorr commented Jun 7, 2024

I would like to be able to easily flip the image's Alpha channel with a method provided by the crate.

My specific use case for this functionality is converting certain Blender textures which store Glossiness in the Alpha channel but need to be plugged into the Roughness material input.

Draft

I would like to implement this if possible.
I'm having a bit of trouble figuring out the best way to do this but I'll keep trying. I have absolutely no idea. any guidance would be very welcome.

@theotherphil
Copy link
Contributor

I’m not a maintainer of this crate but my first impression is that this feels a bit too niche to be worth adding.

As for how to implement this function: you should be able to just use (or copy-paste) https://github.com/image-rs/imageproc/blob/master/src/map.rs#L159-L175

@HeCorr
Copy link
Author

HeCorr commented Jun 7, 2024

this feels a bit too niche to be worth adding.

@theotherphil sure, but seeing as I'm struggling to even figure out how to do this without a dedicated method, why not implement it for when someone does need it? I don't personally see any downsides to doing it.

you should be able to just use (or copy-paste) ...

I'll give it another shot. I tried with .map_with_alpha() and .apply_with_alpha() but couldn't figure out how to get the value of the Subpixel (u8? u32? f32?) and convert that back to a Subpixel.

@HeCorr
Copy link
Author

HeCorr commented Jun 8, 2024

I still don't know how I can get a Subpixel from a number. That's all I need to know.

@theotherphil that code you linked is from the imageproc crate which has their own Image type with it's own methods (like to_vec and from_vec) that this crate does not have.

@theotherphil
Copy link
Contributor

The Image type in that crate is just an alias for the ImageBuffer type from this crate.

However, I guess the problem you’re actually having is that you’ve loaded an image into a DynamicImage? This is an enum over a range of possible image types. Your options here are to either convert to a fixed ImageBuffer type using one of the to_x methods on DynamicImage or to use DynamicImage’s implementation of GenericImage and GenericImageView which uses a pixel type of Rgba<u8> for get_pixel and put_pixel and converts between this type and whatever the actual underlying pixel type is. The latter is obviously going to be lossy if your input image is using f32 for its input channels - this is a limitation of using a generic representation for data whose actual type could vary.

@HeCorr
Copy link
Author

HeCorr commented Jun 8, 2024

The Image type in that crate is just an alias for the ImageBuffer type from this crate.

Oh, that makes more sense.

However, I guess the problem you’re actually having is that you’ve loaded an image into a DynamicImage?

I've actually just copied invert()'s code as a base, which takes in a GenericImage. I honestly don't know the difference between all the image types.

The latter is obviously going to be lossy if your input image is using f32 for its input channels

Yeah, I figured this would be the case but I don't know how to workaround that at the moment.

I think I sort of figured it out by looking at how brighten() reads and writes pixels (the only part I was missing).
I have no idea if this is the correct way of doing it but it does seem to work on my test image:

pub fn invert_alpha<I: GenericImage>(image: &mut I) {
    let (width, height) = image.dimensions();
    for y in 0..height {
        for x in 0..width {
            let mut p = image.get_pixel(x, y);
            p.apply_with_alpha(
                |f| f,
                |g| {
                    let a: u8 = NumCast::from(g).unwrap();
                    NumCast::from(u8::MAX - a).unwrap()
                },
            );
            image.put_pixel(x, y, p);
        }
    }
}

image

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