Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Jun 12 12:50

    HeroicKatora on master

    Add width()/height() to Dynamic… Merge pull request #1493 from p… (compare)

  • Jun 12 12:50
    HeroicKatora closed #1493
  • Jun 11 19:56
    pedrocr opened #1493
  • Jun 08 22:59
    dabreegster closed #1492
  • Jun 08 22:59
    dabreegster commented #1492
  • Jun 08 22:33
    dabreegster opened #1492
  • Jun 07 22:18
    johannesvollmer edited #1491
  • Jun 07 22:18
    johannesvollmer edited #1491
  • Jun 07 22:18
    johannesvollmer edited #1491
  • Jun 07 22:18
    johannesvollmer opened #1491
  • Jun 07 21:47
    johannesvollmer edited #1475
  • Jun 07 21:47
    johannesvollmer synchronize #1475
  • Jun 07 14:00
    fintelia commented #1468
  • Jun 06 23:00
    johannesvollmer edited #1475
  • Jun 06 23:00
    johannesvollmer edited #1475
  • Jun 06 22:56
    johannesvollmer ready_for_review #1475
  • Jun 06 22:34
    johannesvollmer commented #1475
  • Jun 06 22:34
    johannesvollmer synchronize #1475
  • Jun 06 22:15
    johannesvollmer synchronize #1475
  • Jun 06 21:10
    fintelia closed #1311
Dakota
@codabrink
How do you create a DynamicImage from an RgbImage? I'd like to write it to a vec in a jpeg format in memory.
The documentation isn't clear on how to handle it
Dakota
@codabrink
Figured it out.. still new to Rust. let img = DynamicImage::ImageRgb8(img);
HeroicKatora
@HeroicKatora
Yes, that was quick. Exactly right :+1:
Danilo
@dbrgn:matrix.coredump.ch
[m]

Hi, I got stuck a bit when trying to implement a combined transformation...

How do I get from a GenericImageView to an ImageBuffer (without any modification) without iterating over rows/cols and calling get_pixel / set_pixel? (That seems really inefficient to me)

Also, is there a good way to combine multiple transforms efficiently without copying each time?

For context, I'm implementing EXIF rotation. This means that depending on the input parameter, we'll do nothing, rotate, flip or rotate + flip.

Rotating by 0 and 180 degrees as well as flipping can be done in-place, so no copying would be necessary. The buffer could be modified in-place.

Rotating by 90 and 270 degrees however always requires a copy, because the image may not be square.

Right now the APIs seem to take &self and return a new ImageBuffer. Do you have a good way to solve this? We could use something like fn rotate(&mut self) -> RotationResult with enum RotationResult { Modified, Copied<ImageBuffer> }, but that seems very ugly from an API point of view.

HeroicKatora
@HeroicKatora
flip and rotate180 have in-place variants that should be more efficient than copying. As far as combining goes, I don't think we have a good solution. I had some vague ideas for an expression-based DSL that might allow this but nothing specific and too complicated for image itself anways.
I'm also fairly sure the GenericImage-based interface is not at all optimized for this work. For example, as you've observed, it isn't efficient to iterate pixels individually but that's pretty much all you can do with the generic interface and what's done internally. Also the layout would—I guess—be more efficient (cache oblivious) if it were a recursive, space-filling curve of macroblocks of pixels instead of row-by-row or col-by-col but that requires an extra conversion of layouts and is somewhat specialized.
There's a lot of room for improvement and specialization that's not in image currently.
If you want to go for serious speed, you could go the route of GL/Vulkan rendering the images instead. Basically offputting the design work on efficient layouts and pipelines to spir-v/graphics card vendors
Danilo
@dbrgn:matrix.coredump.ch
[m]

@HeroicKatora: thanks for the reply! sorry, I somehow missed it.

then I guess I'll do the implementation locally only for now. would be nice if multiple transformations could be combined in the future!

zwerdlds
@zwerdlds
Could someone give a suggestion for moving betwen ImageBuffer and a GTK(-rs) PixBuff? Preferably without copying data or unsafe
HeroicKatora
@heroic_katora:matrix.org
[m]
Hm, have you tried the flat:: module? It's not possible to go between the buffers them without copying since each of them is an owning buffer, with their own allocations strategy. But you can certainly create a view on a GTK buffer which implements GenericImage.
fintelia
@fintelia:matrix.org
[m]
ImageBuffer also deref's into a slice, so it might be as simple as PixBuf::from_bytes((*img_buf).into(), ...)
humbletang
@humbletang:matrix.org
[m]
Hi there! I'm trying to use the image crate to export a texture for a gpu particle system, is there a way to store decimal values in an rgb image? I've been thinking of multiplying by a large constant and then trying to use the Rgb16 type but I wanted to ask around here first if there's a better approach.
1 reply
HeroicKatora
@heroic_katora:matrix.org
[m]
I treat the rgb value as a 3-digit number in base 2**16, basically.
Another approach: you can use grayscale with enough bit-depth as well if you store them as TIFF. The rgb-encoding trick is a hack to fit the bits into the usual formats offered by the GPU's texture buffer interface.
Tomáš Král
@tomaskral:matrix.org
[m]
HeroicKatora: Hi, I've been working on decoding tiled Tiffs. I've generated a few test images using Imagemagick, but I can't figure out a way of actually verifying the pixel checksum I get out of the tests... Is there any program that can calculate that ?
1 reply
Tomáš Král
@tomaskral:matrix.org
[m]
(so far I've just been dumping the pixels into a PGM, just for a rough check)
HeroicKatora
@heroic_katora:matrix.org
[m]
Or, convert to pgm and view that :)
It's just a bit more tedious in bulk
Tomáš Král
@tomaskral:matrix.org
[m]
Hmm, I can't compile emulsion with the newest version of tiff, because image doesn't handle CMYK and signed formats yet for the tiff codec.
Lakelezz
@Lakelezz

hello! I tried loading a webp from memory and encountered an unsupport error: Err` value: Unsupported(UnsupportedError { format: Exact(WebP), kind: GenericFeature("ALPH") })

I assume image does not support alpha webp? Is this intentional? The supported file table says it does not only decode lossy/luma channel? Should I open an issue about this?

HeroicKatora
@heroic_katora:matrix.org
[m]
Yes, please.
Raphael
@ruffson
Hello peops. I wonder if it would be at all possible to speed up the decoding of TIFF images by making it multi-threaded? I attempted this once a few months ago, but the way the strips are read into one buffer seemed difficult to parallelize. But I think once the data is loaded into memory, the way tiffs are setup should allow to load the parts in parallel. Does anyone have an idea about feasibility about this?
(I am dealing with large planetary tiffs and just loading the tiff takes more than 5 seconds. I am also dealing with many of such images making just the waiting times quite more noticeable.)
4 replies
HeroicKatora
@heroic_katora:matrix.org
[m]
Texel is just a fancy name for a slight generalization of pixel, because the interpretation of a single value might be a group of 2·2 pixels or more, in color systems where you average the brightness to save some space for example.
So, texel = indivisible unit of the format, pixel = indivisible unit of your display
More or less
Raphael
@ruffson
Ah okay sounds much more sane.
Owen Walpole
@owenthewizard
Hey guys, is there a way to convert an image to another non-const ColorType? Something like this:
let color = image.color();
let img = image.to_rgba8();
// do stuff with RGBA8 image...
let img = img.into::<color>();
HeroicKatora
@heroic_katora:matrix.org
[m]

I'm not entirely sure if I understand exactly what you intend to your code to do. Since Rust does not have dependent typing (types that depend on values), I don't think that would work. You can't use color in the type context of a generic parameter. So, no, there is no such way where color can influence the type of img on line 4. However it might be feasible to have the last line produce a DynamicImage with the previous variant again, as in:

let img = DynamicImage::from(img).convert_into(color);

That's not implemented either but, theoretically, something like this could be possible in Rust.

Moggers
@Moggers
hey hey, https://en.wikipedia.org/wiki/Silicon_Graphics_Image I've found myself in the unfortunate situation of needing to convert SGI images to jpeg for thumbnails, I don't think there's currently support for this, is anyone familiar with the format already?
fintelia
@fintelia:matrix.org
[m]
Not familiar with the format, but based on http://paulbourke.net/dataformats/sgirgb/sgiversion.html, it looks like it wouldn't be too difficult to write your own parser. Once you have the raw RGB data loaded, it shouldn't be much of an issue to use image to write it out as a jpeg
Moggers
@Moggers
oh man I was hoping someone else would do the work for me, I'll see if I can implement it and then open a PR
5225225
@r522:matrix.org
[m]

Hey, I'm working on fixing the issues found by the fuzzer for image-tiff, and am running into an infinite loop when doing

loop {
    decoder.next_image().unwrap();
    assert!(decoder.more_images());
}

using

pub fn goto_offset_u64(&mut self, offset: u64) -> io::Result<()> {
    dbg!(offset);
    self.reader.seek(io::SeekFrom::Start(offset)).map(|_| ())
}

indicates that offset is always 8, so it's re-reading the same ifd every time.

From reading the format, it seems like it has a next_ifd field, so it's basically a linked list.

My question is how should we handle this? Have a HashSet<u64> or something in the decoder, and bail out if we try to go to an ifd that we've seen before? Or mandate that the next ifd offset must be at least 1 byte ahead of the current one, so we'll always be making progress in the file?

pinging HeroicKatora

HeroicKatora
@heroic_katora:matrix.org
[m]
5225225: Huh, interesting failure mode. I would go for a HashSet because the standard does not forbid offsets that go backwards
By the way, I wonder how other decoders react
5225225
@r522:matrix.org
[m]

it'd be interesting to see if some decoders reject offsets that go backwards

yeah, i'll go with the hashset of offsets (and maybe respect the intermediate buffer limit for the size of it)

I think other limits would be tripped long before that limit
but I might as well check that limit too
or make a new limit for "maximum number of IFDs"
HeroicKatora
@heroic_katora:matrix.org
[m]
I'm pretty sure that go's image-tiff trips over this as well :D
https://github.com/chai2010/tiff
At least this one does
5225225
@r522:matrix.org
[m]

nice

what error should it throw if we see a repeat?

make a new variant to FormatError like IfdOffsetRepeated?

also is there a reason we're not using #[non_exhaustive] on the enums other than "it wasn't around when the enums were written"?

I tried running clippy on the codebase and like half the warnings are about manual non_exhaustive

HeroicKatora
@heroic_katora:matrix.org
[m]
No, there is no other reason than compatibility for not using non_exhaustive
I'd say that a new variant is good, and I like the idea of having maximum IFDs as a strategy as well.
Hm, actually a nicer strategy to avoid memory exhaustion as well..
HeroicKatora
@heroic_katora:matrix.org
[m]
5225225: I suppose a simple strategy would be to use a limit in the fuzzing loop.
Most issues should show up with a limited number of ifd's and we might generally expect the runtime environment to somewhat limit the number of iterated ifds. I mean, we don't internally iterate over the ifds in a loop, it's the loop around next_image that does
That is, changing the loop from while to for _ in 0..128 or similar
Grant Handy
@grantshandy
Hi I'm trying to make a utility that changes the perspective of an image.
It'll take the corners of a quadrilateral and then change the contents of the quadrilateral into a rectangle by manipulating the perspective. Does image have this functionality? Are there other crates that do this? Or should I try to do the math myself.
HeroicKatora
@heroic_katora:matrix.org
[m]