c2pa-rs

A fork of https://github.com/contentauth/c2pa-rs/
git clone git://archive.git.mtrnord.blog/mtrnords-photography-manager/c2pa-rs.git
Log | Files | Refs | README

thumbnail.rs (3144B)


      1 // Copyright 2022 Adobe. All rights reserved.
      2 // This file is licensed to you under the Apache License,
      3 // Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
      4 // or the MIT license (http://opensource.org/licenses/MIT),
      5 // at your option.
      6 
      7 // Unless required by applicable law or agreed to in writing,
      8 // this software is distributed on an "AS IS" BASIS, WITHOUT
      9 // WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
     10 // implied. See the LICENSE-MIT and LICENSE-APACHE files for the
     11 // specific language governing permissions and limitations under
     12 // each license.
     13 
     14 use std::io::{Read, Seek};
     15 
     16 use image::{io::Reader, ImageFormat};
     17 
     18 use crate::{Error, Result};
     19 
     20 // max edge size allowed in pixels for thumbnail creation
     21 const THUMBNAIL_LONGEST_EDGE: u32 = 1024;
     22 
     23 ///  utility to generate a thumbnail from a file at path
     24 /// returns Result (format, image_bits) if successful, otherwise Error
     25 #[cfg(feature = "file_io")]
     26 pub fn make_thumbnail(path: &std::path::Path) -> Result<(String, Vec<u8>)> {
     27     let format = ImageFormat::from_path(path)?;
     28 
     29     let mut img = image::open(path)?;
     30     let longest_edge = THUMBNAIL_LONGEST_EDGE;
     31 
     32     // generate a thumbnail image scaled down and in jpeg format
     33     if img.width() > longest_edge || img.height() > longest_edge {
     34         img = img.thumbnail(longest_edge, longest_edge);
     35     }
     36     // for png files, use png thumbnails if there is an alpha channel
     37     // for other supported types try a jpeg thumbnail
     38     let (output_format, format) = match format {
     39         ImageFormat::Png if img.color().has_alpha() => (ImageFormat::Png, "image/png"),
     40         _ => (ImageFormat::Jpeg, "image/jpeg"),
     41     };
     42     let thumbnail_bits = Vec::new();
     43     let mut cursor = std::io::Cursor::new(thumbnail_bits);
     44     img.write_to(&mut cursor, output_format)?;
     45 
     46     let format = format.to_owned();
     47     Ok((format, cursor.into_inner()))
     48 }
     49 
     50 ///  utility to generate a thumbnail from a file at path
     51 /// returns Result (format, image_bits) if successful, otherwise Error
     52 pub fn make_thumbnail_from_stream<R: Read + Seek + ?Sized>(
     53     format: &str,
     54     stream: &mut R,
     55 ) -> Result<(String, Vec<u8>)> {
     56     let format = ImageFormat::from_extension(format)
     57         .or_else(|| ImageFormat::from_mime_type(format))
     58         .ok_or(Error::UnsupportedType)?;
     59 
     60     let reader = Reader::with_format(std::io::BufReader::new(stream), format);
     61     let mut img = reader.decode()?;
     62 
     63     let longest_edge = THUMBNAIL_LONGEST_EDGE;
     64 
     65     // generate a thumbnail image scaled down and in jpeg format
     66     if img.width() > longest_edge || img.height() > longest_edge {
     67         img = img.thumbnail(longest_edge, longest_edge);
     68     }
     69 
     70     // for png files, use png thumbnails for transparency
     71     // for other supported types try a jpeg thumbnail
     72     let (output_format, format) = match format {
     73         ImageFormat::Png => (ImageFormat::Png, "image/png"),
     74         _ => (ImageFormat::Jpeg, "image/jpeg"),
     75     };
     76     let thumbnail_bits = Vec::new();
     77     let mut cursor = std::io::Cursor::new(thumbnail_bits);
     78     img.write_to(&mut cursor, output_format)?;
     79 
     80     let format = format.to_owned();
     81     Ok((format, cursor.into_inner()))
     82 }