Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Dec 01 18:14
    Xaeroxe opened #1830
  • Dec 01 10:01
    BearOve edited #1829
  • Dec 01 10:01
    BearOve opened #1829
  • Nov 25 19:52
    pratik-mahamuni edited #1822
  • Nov 25 19:49
    pratik-mahamuni commented #1822
  • Nov 25 19:47
    pratik-mahamuni commented #1822
  • Nov 25 15:50

    HeroicKatora on master

    Remove exception for old flate2… Merge pull request #1827 from f… (compare)

  • Nov 25 15:50
    HeroicKatora closed #1827
  • Nov 25 03:31
    fintelia opened #1827
  • Nov 21 12:10
    kangalioo commented #1825
  • Nov 21 12:07
    kangalioo commented #1825
  • Nov 21 12:00
    HeroicKatora commented #1825
  • Nov 21 10:01
    kangalioo commented #1825
  • Nov 20 13:10
    HeroicKatora commented #1825
  • Nov 20 12:55
    HeroicKatora commented #1826
  • Nov 20 12:55

    HeroicKatora on master

    Update to gif 0.12 Merge pull request #1826 from s… (compare)

  • Nov 20 12:55
    HeroicKatora closed #1826
  • Nov 20 09:52
    sdroege opened #1826
  • Nov 20 04:35
    HeroicKatora edited #1825
  • Nov 20 03:56
    lidarbtc opened #1825
HeroicKatora
@HeroicKatora
@ZargorNET Sorry for the delay, it's probably better to open an issue on imageproc as this channel is for main image.
zero-systems
@zero-systems
Hello, Is it possible to asynchronously read image? I have actix-multipart crate, which helps me gathering multipart data from http, but I don't see any things which can help me generating thumbnails on the fly. is it possible to do this with image-rs crate?
it's very important, because opening even 0.5 MiB image takes almost infinite and generating thumbnail too... So I think I have to make thumbnail on the fly
Kunal Mohan
@kunalmohan
Hi! I am somewhat new to using the image crate. I have been facing problem with the load_from _memory function. Doesn't it support jpeg images?
Mahdi Robatipoor
@robatipoor
hi
extern crate png;

use png::{Decoder, Encoder};
use std::fs::File;
use std::io::{BufReader, BufWriter};

fn main() {
    let file = File::open("interview.png").unwrap();
    let buff_reader = BufReader::new(file);
    let decoder = Decoder::new(buff_reader);
    let (info, mut reader) = decoder.read_info().unwrap();
    let mut data_image = vec![0; info.buffer_size()];
    // do somthing ...
    reader.next_frame(&mut data_image).unwrap();
    let file = File::create("interview2.png").unwrap();
    let ref mut buff_writer = BufWriter::new(file);
    let mut encoder = Encoder::new(buff_writer, info.width, info.height);
    encoder.set_color(png::ColorType::RGBA);
    encoder.set_depth(png::BitDepth::Eight);
    let mut header = encoder.write_header().unwrap();
    header.write_image_data(&data_image).unwrap();
}
i got error message
thread 'main' panicked at 'called Result::unwrap() on an Err value: Format("wrong data size, expected 3714816 got 2786112")'
How I Can Fix This
HeroicKatora
@HeroicKatora
Hi, have you checked if the decoded buffer you receive into data_image actually has rgba color type and bit depth of eight?
A color type of rgb would perfect fit the numbers in the error. Note that write_image_data does not do the transformation of adding an alpha channel internally.
Mahdi Robatipoor
@robatipoor
thanks
        let rgb_image :RgbImage ; // ...
        let img_data = rgb_image.clone().to_vec();
        let w = rgb_image.width();
        let h = rgb_image.height();
        let png_image = vec![0;img_data.len()]; // <- how calculate len png_image ? 
        let ref mut buff_writer = BufWriter::new(img_data);
        let mut encoder = png::Encoder::new(buff_writer, w, h);
        encoder.set_color(png::ColorType::RGBA);
        encoder.set_depth(png::BitDepth::Eight);
        let mut header = encoder.write_header().unwrap();
        header.write_image_data(&png_image).unwrap();
i use crate image and png
I want to encode type RgbImage to png image but the problem I have is I do not know how to calculate the data png_image length
```
Mahdi Robatipoor
@robatipoor
error
panicked at 'called `Result::unwrap()` on an `Err` value: Format("wrong data size, expected 106964 got 80223")
Jorge Carrasco
@carrascomj_gitlab
You're trying to write a RGBImage with a RGBA encoder. You can check in the error that 80223/3+80223 = 106964; that is, one channel (alpha) is missing per pixel
HeroicKatora
@HeroicKatora
You don't need to calculate the length yourself.
Instead, use DynamicImage for the conversion.
let rgb_image: RgbImage = /* */
let rgba_image: RgbaImage = DynamicImage::ImageRgb8(rgb_image).into_rgba();
// .. same as you create the encoder.
png.write_image_data(&rgba_image.into_vec())?;
Mahdi Robatipoor
@robatipoor
@carrascomj_gitlab thanks
@HeroicKatora thanks
Rupansh
@rupansh
Hello I am trying to implement seam resize
Deleting seam along the width seems to be working fine but I can't figure out what's wrong with it when I try to delete them along the height.
Here's the code for deleting a single seam
    fn nuke_seamline_h(&self, buf: &mut Vec<u8>, image: &mut Vec<u8>, width: usize) {
        let mut min_idx: usize = 0;
        let mut min: u8 = 255;
        let mut seam = BTreeSet::<usize>::new();
        for i in (0..(buf.len()-width+1)).step_by(width) {
            if buf[i] <= min {
                min_idx = i;
                min = buf[i];
            }
        }

        seam.insert(min_idx);
        while (min_idx + 1) % width != 0 {
            let tedge =  min_idx < width;
            let bedge = min_idx + width >= buf.len();
            let midi = min_idx+1;
            let mid = buf[midi];
            let bef = if !tedge { buf[midi-width] } else { 255 };
            let aft = if !bedge { buf[midi+width] } else { 255 };
            let mut min = bef;
            let mut t_minid = midi-width;
            if mid <= bef {
                min = mid;
                t_minid = midi;
            }
            if min <= aft {
                min_idx = t_minid;
            } else {
                min_idx = midi+width;
            }

            seam.insert(min_idx);
        }

        for (rem, i) in seam.iter().enumerate() {
            image.remove(*i - rem);
            buf.remove(*i - rem);
        }
    }
The resulting image looks like this
buf is the gradient of the image by the way
HeroicKatora
@HeroicKatora
I'm assuming you have an image buffer as in image, i.e. the buf is always stored row-major? This would significantly affect the indexing correction in the last loop.
In *i - rem it assumes that exactly rem pixels have been removed prior to the one to-be removed in any iteration.
For the aforementioned layout this holds true for row-by-row removal as each row has increasing indices and removes exactly one pixel.
But if you traverse the same layout column by column then the first column might remove a pixel at the end of the buffer so the next column now removes the wrong pixel.
I'd personally sort the indices before removing them and then remove them in strictly inreasing order.
This is an overhead of O(width ln width) (typically square root of your image) but you don't have to do any index correction during removal
Chehui Chou
@deadshot465_gitlab
Anyone knows what causes the failed to fill whole buffer error? I try to use image to decode a JPEG and read into a buffer, but it keeps showing me this error. I checked that the buffer length and total_bytes() is the same, and I have no problem getting dimension and color types from the stream, so I think there are no problems in decoding.
Still I don't know what causes the failed to fill whole buffer error.
Chehui Chou
@deadshot465_gitlab
I tried load_from_memory_with_format but to no avail
HeroicKatora
@HeroicKatora
Very likely the jpeg is actually corrupt. Do you know what produced it?
Many implementations have varying strategies for recovering but that incurs a lot of complexity.
And I'm afraid no-one had enough time to deal with that.
You can try djpeg or convert -verbose to see if any warnings or errors occur in other decoders
Chehui Chou
@deadshot465_gitlab
It's some base64-encoded texture files embedded inside glTF 3D models
Should I first try to decode it using base64 crate before constructing a JpegDecoder?
HeroicKatora
@HeroicKatora
Certainly image won't magically know that it happens to be base64 encoded.
I doubt that what you're passing to image is still base64-encoded as otherwise the decoder should complain much sooner.
Chehui Chou
@deadshot465_gitlab
Ok. I will try to decode it first and see if it fixes
Thanks
Martin Tomasi
@GyrosOfWar
hi there, i was wondering if there's an elegant way to convert a DynamicImage into an image buffer containing Rgb<f32> (instead of whatever the original representation was)? If there is one, I haven't been able to find it so far
HeroicKatora
@HeroicKatora
@GyrosOfWar I'm afraid there is no elegant way, that is a single statement or so for the conversion. In any case I would DynamicImage::into_rgb()and go from there. Then probably convert it into the vec container and map each pixel.
Martin Tomasi
@GyrosOfWar
alright, yeah, i was sort of expecting that
Raphael
@ruffson
Hi there, I do not want to pressure anyone but are there any concerns about image-rs/image-tiff#100 on the image-tiff repo implementing support for GeoTiff?
HeroicKatora
@HeroicKatora
I didn't get around to review it fully, no.
My first impression is that it's a breaking change and seems tacked on with free methods and little interaction.
Maybe just add the missing Tags first
Raphael
@ruffson
Ok. It is not a breaking change. Non-GeoTIff images can be opened fine. I'll wait for a review, no rush. Thank you!
HeroicKatora
@HeroicKatora
It's not? Hm, maybe I did misread the code on a first glance :)
Raphael
@ruffson
Haha maybe.
Raphael
@ruffson
Also I think I spotted a regression in image-tiff. Until a few weeks ago, I was able to load normal sized TIFF images with over 300MiB after I increased the buffer limits. Now, I get a InconsistentSizesEncountered error in expand_strip() because for whatever reason at some point a strip that was read is bigger than all the others. I don't really have time to do much debugging, I just observed that the new of LZWDecoder reads more bytes than a strip contains at some point, first few runs are fine. Has anyone any idea what could've changed that caused this?
HeroicKatora
@HeroicKatora
The lzw decoder changed, and the integration with it.
Assuming you're using 0.6 now
Raphael
@ruffson
I should be on master (using my PR'ed branch which I rebased when I created the PR)
Jorge Carrasco
@carrascomj_gitlab

Hello! I'm trying to use rayon with Pixels, but, although I see it implements ParallelBridge, I am unable to do it. Here's the sample code

use image::{GenericImage, Pixel};
#[cfg(feature = "rayon")]
use rayon::prelude::*;

pub type Image<P> = ImageBuffer<P, Vec<<P as Pixel>::Subpixel>>;

pub fn map_colors<I, P, Q, F>(image: &I, f: F) -> Image<Q>
where
    I: GenericImage<Pixel = P>,
    P: Pixel,
    Q: Pixel + 'static,
    F: Fn(P) -> Q,
{
    let (width, height) = image.dimensions();
    let mut out: ImageBuffer<Q, Vec<Q::Subpixel>> = ImageBuffer::new(width, height);

    #[cfg(feature = "rayon")]
    let iter = image.pixels().par_bridge();
    #[cfg(not(feature = "rayon"))]
    let iter = image.pixels();

    // UNSAFE JUSTIFICATION:
    // - no need to check bounds
    // - `out` is created from the dimensions of `image`
    iter.for_each(|(x, y, pixel)| unsafe { out.unsafe_put_pixel(x, y, f(pixel)) });

    out
}

And the error is

error[E0599]: no method named `par_bridge` found for struct `image::Pixels<'_, I>` in the current scope
   --> src/map.rs:103:43
    |
103 |     let iter = image.pixels().into_iter().par_bridge();
    |                                           ^^^^^^^^^^ method not found in `image::Pixels<'_, I>`
    |
   ::: /home/georg/.local/share/cargo/registry/src/github.com-1ecc6299db9ec823/image-0.23.11/./src/image.rs:558:1
    |
558 | pub struct Pixels<'a, I: ?Sized + 'a> {
    | -------------------------------------
    | |
    | doesn't satisfy `image::Pixels<'_, I>: rayon::iter::ParallelBridge`
    | doesn't satisfy `image::Pixels<'_, I>: std::marker::Send`
    |
    = note: the method `par_bridge` exists but the following trait bounds were not satisfied:
            `image::Pixels<'_, I>: std::marker::Send`
            which is required by `image::Pixels<'_, I>: rayon::iter::ParallelBridge`
            `(u32, u32, P): std::marker::Send`
            which is required by `image::Pixels<'_, I>: rayon::iter::ParallelBridge`
            `&image::Pixels<'_, I>: std::marker::Send`
            which is required by `&image::Pixels<'_, I>: rayon::iter::ParallelBridge`
            `&image::Pixels<'_, I>: std::iter::Iterator`
            which is required by `&image::Pixels<'_, I>: rayon::iter::ParallelBridge`
            `&mut image::Pixels<'_, I>: std::marker::Send`
            which is required by `&mut image::Pixels<'_, I>: rayon::iter::ParallelBridge`
            `(u32, u32, P): std::marker::Send`
            which is required by `&mut image::Pixels<'_, I>: rayon::iter::ParallelBridge`

Does anyone know if it's possible to get it to work?

Jorge Carrasco
@carrascomj_gitlab
Solved it by putting Send + Sync on everything (including <Q as Pixel>::Subpixel) and gathering it into an intermediate vector. The vector is then flushed into the ImageBuffer (single threaded). I am unsure if this is the best alternative, could the ImageBuffer be separated into chunks and then merged? Would that be better?
Jorge Carrasco
@carrascomj_gitlab
All this babbling is related to image-rs/imageproc#446, if someone is interested
HeroicKatora
@HeroicKatora
Sounds like you did everything right. Maybe some of the Sync is execessive but Send should be required on most structures.
As far as separating the buffer goes, it depends. You need not use Pixels if you iterate the container by hand.
Jorge Carrasco
@carrascomj_gitlab
Right, my first implementation relied on a custom struct that implements iterator "by hand" (using unsafes and such). I opted for Pixels in the end because it ended up being more readable and the par_bridge was already there, so I didn't have to reinvent the wheel. However, if the goal is ultimate performance, I would need to go that route I think
Jorge Carrasco
@carrascomj_gitlab
Just in case, I have this "by hand" implementation working here https://github.com/carrascomj/imageproc/blob/pixeliter/src/map.rs#L71 but I'm still unsure if it's worth it
arthmis
@arthmis
Hello I want to be able to reinterpret an image. I'm essentially doing some processing, transposing the image, do some more processing, and transposing the image back to its original dimensions. Would flat samples allow me to reinterpret the dimensions of the image?
HeroicKatora
@HeroicKatora
@arthmis That depends on the needs for reinterpretation.
With flat samples you get a standard slices of samples so you can do anything that's sound on such a slice.
You might want to use a dedicated library such as bytemuck for the actual reinterpretation but it should work in principle.