From ffdeb62b9f088e6893429bdb2b3f5f372c0fe8ac Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Fri, 1 Nov 2019 01:35:18 +0100 Subject: [PATCH 1/8] Rework the tag macro to make it reusable Factor out parts that are unique to instantiations such as the name, the documentation, the underlying type, the public conversion methods. Also adds the ability to document individual items and remodels the syntax to more closely resemble ordinary enum definitions. --- src/decoder/ifd.rs | 133 +++++++++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 54 deletions(-) diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs index 82181b0..d0a7ebb 100644 --- a/src/decoder/ifd.rs +++ b/src/decoder/ifd.rs @@ -10,27 +10,35 @@ use {TiffError, TiffFormatError, TiffResult, TiffUnsupportedError}; use self::Value::{Ascii, List, Rational, Unsigned, Signed, SRational}; macro_rules! tags { - {$( - $tag:ident - $val:expr; - )*} => { - - /// TIFF tag - #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] - pub enum Tag { - $($tag,)* - Unknown(u16) + { + // Permit arbitrary meta items, which include documentation. + $( #[$enum_attr:meta] )* + pub enum $name:ident($ty:ty) { + // Each of the `Name = Val,` permitting documentation. + $($(#[$ident_attr:meta])* $tag:ident = $val:expr,)* } - impl Tag { - pub fn from_u16(n: u16) -> Tag { - $(if n == $val { Tag::$tag } else)* { - Tag::Unknown(n) + } => { + $( #[$enum_attr] )* + #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] + pub enum $name { + $($(#[$ident_attr])* $tag,)* + Unknown($ty), + #[doc(hidden)] + __NonExhaustive, + } + + impl $name { + fn __from_inner_type(n: u16) -> Self { + $(if n == $val { $name::$tag } else)* { + $name::Unknown(n) } } - pub fn to_u16(&self) -> u16 { + + fn __to_inner_type(&self) -> u16 { match *self { - $( Tag::$tag => $val, )* - Tag::Unknown(n) => n, + $( $name::$tag => $val, )* + $name::Unknown(n) => n, + $name::__NonExhaustive => unreachable!(), } } } @@ -39,47 +47,60 @@ macro_rules! tags { // Note: These tags appear in the order they are mentioned in the TIFF reference tags! { +/// TIFF tags +pub enum Tag(u16) { // Baseline tags: - Artist 315; + Artist = 315, // grayscale images PhotometricInterpretation 1 or 3 - BitsPerSample 258; - CellLength 265; // TODO add support - CellWidth 264; // TODO add support + BitsPerSample = 258, + CellLength = 265, // TODO add support + CellWidth = 264, // TODO add support // palette-color images (PhotometricInterpretation 3) - ColorMap 320; // TODO add support - Compression 259; // TODO add support for 2 and 32773 - Copyright 33_432; - DateTime 306; - ExtraSamples 338; // TODO add support - FillOrder 266; // TODO add support - FreeByteCounts 289; // TODO add support - FreeOffsets 288; // TODO add support - GrayResponseCurve 291; // TODO add support - GrayResponseUnit 290; // TODO add support - HostComputer 316; - ImageDescription 270; - ImageLength 257; - ImageWidth 256; - Make 271; - MaxSampleValue 281; // TODO add support - MinSampleValue 280; // TODO add support - Model 272; - NewSubfileType 254; // TODO add support - Orientation 274; // TODO add support - PhotometricInterpretation 262; - PlanarConfiguration 284; - ResolutionUnit 296; // TODO add support - RowsPerStrip 278; - SamplesPerPixel 277; - Software 305; - StripByteCounts 279; - StripOffsets 273; - SubfileType 255; // TODO add support - Threshholding 263; // TODO add support - XResolution 282; - YResolution 283; + ColorMap = 320, // TODO add support + Compression = 259, // TODO add support for 2 and 32773 + Copyright = 33_432, + DateTime = 306, + ExtraSamples = 338, // TODO add support + FillOrder = 266, // TODO add support + FreeByteCounts = 289, // TODO add support + FreeOffsets = 288, // TODO add support + GrayResponseCurve = 291, // TODO add support + GrayResponseUnit = 290, // TODO add support + HostComputer = 316, + ImageDescription = 270, + ImageLength = 257, + ImageWidth = 256, + Make = 271, + MaxSampleValue = 281, // TODO add support + MinSampleValue = 280, // TODO add support + Model = 272, + NewSubfileType = 254, // TODO add support + Orientation = 274, // TODO add support + PhotometricInterpretation = 262, + PlanarConfiguration = 284, + ResolutionUnit = 296, // TODO add support + RowsPerStrip = 278, + SamplesPerPixel = 277, + Software = 305, + StripByteCounts = 279, + StripOffsets = 273, + SubfileType = 255, // TODO add support + Threshholding = 263, // TODO add support + XResolution = 282, + YResolution = 283, // Advanced tags - Predictor 317; + Predictor = 317, +} +} + +impl Tag { + pub fn from_u16(val: u16) -> Self { + Self::__from_inner_type(val) + } + + pub fn to_u16(&self) -> u16 { + Self::__to_inner_type(self) + } } #[derive(Clone, Copy, Debug, FromPrimitive)] @@ -93,6 +114,8 @@ pub enum Type { SSHORT = 8, SLONG = 9, SRATIONAL = 10, + #[doc(hidden)] // Do not match against this. + __NonExhaustive, } #[allow(unused_qualifications)] @@ -104,6 +127,8 @@ pub enum Value { Rational(u32, u32), SRational(i32, i32), Ascii(String), + #[doc(hidden)] // Do not match against this. + __NonExhaustive, } impl Value { From f80f4a06d5da24f119c5e9878347e2b5e804bc78 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Sun, 10 Nov 2019 17:30:05 +0100 Subject: [PATCH 2/8] Make the Unknown field optional Several other uses that currently rely on num-traits for conversion have no Unknown representation. Thus, the converter now outputs only known variants or an error and the exposing function then can put the error value into an Unknown variant instead. --- src/decoder/ifd.rs | 41 +++++++++++++++++++++++++++++------------ src/decoder/mod.rs | 2 +- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs index d0a7ebb..1b4bbe9 100644 --- a/src/decoder/ifd.rs +++ b/src/decoder/ifd.rs @@ -13,7 +13,7 @@ macro_rules! tags { { // Permit arbitrary meta items, which include documentation. $( #[$enum_attr:meta] )* - pub enum $name:ident($ty:ty) { + pub enum $name:ident($ty:ty) $(unknown($unknown_doc:literal))* { // Each of the `Name = Val,` permitting documentation. $($(#[$ident_attr:meta])* $tag:ident = $val:expr,)* } @@ -22,22 +22,28 @@ macro_rules! tags { #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub enum $name { $($(#[$ident_attr])* $tag,)* - Unknown($ty), + // FIXME: switch to non_exhaustive once stabilized and compiler requirement new enough #[doc(hidden)] __NonExhaustive, + $( + #[doc = $unknown_doc] + Unknown($ty), + )* } impl $name { - fn __from_inner_type(n: u16) -> Self { - $(if n == $val { $name::$tag } else)* { - $name::Unknown(n) + #[inline(always)] + fn __from_inner_type(n: u16) -> Result { + $(if n == $val { Ok($name::$tag) } else)* { + Err(n) } } + #[inline(always)] fn __to_inner_type(&self) -> u16 { match *self { $( $name::$tag => $val, )* - $name::Unknown(n) => n, + $( $name::Unknown(n) => { $unknown_doc; n }, )* $name::__NonExhaustive => unreachable!(), } } @@ -48,7 +54,7 @@ macro_rules! tags { // Note: These tags appear in the order they are mentioned in the TIFF reference tags! { /// TIFF tags -pub enum Tag(u16) { +pub enum Tag(u16) unknown("A private or extension tag") { // Baseline tags: Artist = 315, // grayscale images PhotometricInterpretation 1 or 3 @@ -95,7 +101,7 @@ pub enum Tag(u16) { impl Tag { pub fn from_u16(val: u16) -> Self { - Self::__from_inner_type(val) + Self::__from_inner_type(val).unwrap_or_else(Tag::Unknown) } pub fn to_u16(&self) -> u16 { @@ -103,8 +109,9 @@ impl Tag { } } -#[derive(Clone, Copy, Debug, FromPrimitive)] -pub enum Type { +tags! { +/// The type of an IFD entry (a 2 byte field). +pub enum Type(u16) { BYTE = 1, ASCII = 2, SHORT = 3, @@ -114,9 +121,19 @@ pub enum Type { SSHORT = 8, SLONG = 9, SRATIONAL = 10, - #[doc(hidden)] // Do not match against this. - __NonExhaustive, } +} + +impl Type { + pub fn from_u16(val: u16) -> Option { + Self::__from_inner_type(val).ok() + } + + pub fn to_u16(&self) -> u16 { + Self::__to_inner_type(self) + } +} + #[allow(unused_qualifications)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 67e9c88..cb69db0 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -454,7 +454,7 @@ impl Decoder { // Value 4 bytes either a pointer the value itself fn read_entry(&mut self) -> TiffResult> { let tag = ifd::Tag::from_u16(self.read_short()?); - let type_: ifd::Type = match FromPrimitive::from_u16(self.read_short()?) { + let type_ = match ifd::Type::from_u16(self.read_short()?) { Some(t) => t, None => { // Unknown type. Skip this entry according to spec. From f88c9f00c3f901d91b9caa16192f544881d412c2 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Sun, 10 Nov 2019 17:40:53 +0100 Subject: [PATCH 3/8] Move everything to the tags macro --- src/decoder/ifd.rs | 6 ++-- src/decoder/mod.rs | 70 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs index 1b4bbe9..f162f8b 100644 --- a/src/decoder/ifd.rs +++ b/src/decoder/ifd.rs @@ -13,7 +13,7 @@ macro_rules! tags { { // Permit arbitrary meta items, which include documentation. $( #[$enum_attr:meta] )* - pub enum $name:ident($ty:ty) $(unknown($unknown_doc:literal))* { + $vis:vis enum $name:ident($ty:ty) $(unknown($unknown_doc:literal))* { // Each of the `Name = Val,` permitting documentation. $($(#[$ident_attr:meta])* $tag:ident = $val:expr,)* } @@ -33,14 +33,14 @@ macro_rules! tags { impl $name { #[inline(always)] - fn __from_inner_type(n: u16) -> Result { + fn __from_inner_type(n: $ty) -> Result { $(if n == $val { Ok($name::$tag) } else)* { Err(n) } } #[inline(always)] - fn __to_inner_type(&self) -> u16 { + fn __to_inner_type(&self) -> $ty { match *self { $( $name::$tag => $val, )* $( $name::Unknown(n) => { $unknown_doc; n }, )* diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index cb69db0..a409b97 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -1,4 +1,4 @@ -use num_traits::{FromPrimitive, Num}; +use num_traits::{Num}; use std::collections::HashMap; use std::io::{self, Read, Seek}; use std::cmp; @@ -9,6 +9,7 @@ use self::ifd::Directory; use self::stream::{ByteOrder, EndianReader, LZWReader, DeflateReader, PackBitsReader, SmartReader}; +#[macro_use] pub mod ifd; mod stream; @@ -80,8 +81,8 @@ impl<'a> DecodingBuffer<'a> { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, FromPrimitive)] -pub enum PhotometricInterpretation { +tags! { +pub enum PhotometricInterpretation(u32) { WhiteIsZero = 0, BlackIsZero = 1, RGB = 2, @@ -91,9 +92,10 @@ pub enum PhotometricInterpretation { YCbCr = 6, CIELab = 8, } +} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, FromPrimitive)] -pub enum CompressionMethod { +tags! { +pub enum CompressionMethod(u32) { None = 1, Huffman = 2, Fax3 = 3, @@ -104,18 +106,61 @@ pub enum CompressionMethod { OldDeflate = 0x80B2, PackBits = 0x8005, } +} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, FromPrimitive)] -pub enum PlanarConfiguration { +tags! { +pub enum PlanarConfiguration(u32) { Chunky = 1, Planar = 2, } +} -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, FromPrimitive)] -enum Predictor { +tags! { +enum Predictor(u32) { None = 1, Horizontal = 2, } +} + +impl PhotometricInterpretation { + pub fn from_u32(val: u32) -> Option { + Self::__from_inner_type(val).ok() + } + + pub fn to_u32(&self) -> u32 { + Self::__to_inner_type(self) + } +} + +impl CompressionMethod { + pub fn from_u32(val: u32) -> Option { + Self::__from_inner_type(val).ok() + } + + pub fn to_u32(&self) -> u32 { + Self::__to_inner_type(self) + } +} + +impl PlanarConfiguration { + pub fn from_u32(val: u32) -> Option { + Self::__from_inner_type(val).ok() + } + + pub fn to_u32(&self) -> u32 { + Self::__to_inner_type(self) + } +} + +impl Predictor { + pub fn from_u32(val: u32) -> Option { + Self::__from_inner_type(val).ok() + } + + pub fn to_u32(&self) -> u32 { + Self::__to_inner_type(self) + } +} #[derive(Debug)] struct StripDecodeState { @@ -334,7 +379,7 @@ impl Decoder { self.width = self.get_tag_u32(ifd::Tag::ImageWidth)?; self.height = self.get_tag_u32(ifd::Tag::ImageLength)?; self.strip_decoder = None; - self.photometric_interpretation = match FromPrimitive::from_u32( + self.photometric_interpretation = match PhotometricInterpretation::from_u32( self.get_tag_u32(ifd::Tag::PhotometricInterpretation)? ) { Some(val) => val, @@ -345,7 +390,7 @@ impl Decoder { } }; if let Some(val) = self.find_tag_u32(ifd::Tag::Compression)? { - match FromPrimitive::from_u32(val) { + match CompressionMethod::from_u32(val) { Some(method) => self.compression_method = method, None => { return Err(TiffError::UnsupportedError( @@ -720,7 +765,7 @@ impl Decoder { )); } if let Ok(predictor) = self.get_tag_u32(ifd::Tag::Predictor) { - match FromPrimitive::from_u32(predictor) { + match Predictor::from_u32(predictor) { Some(Predictor::None) => (), Some(Predictor::Horizontal) => { rev_hpredict( @@ -734,6 +779,7 @@ impl Decoder { predictor, ))) } + Some(Predictor::__NonExhaustive) => unreachable!(), } } Ok(()) From 258edf4a46d6278b4ec1a44cbcbb7731fe9b9b09 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Sun, 10 Nov 2019 17:41:54 +0100 Subject: [PATCH 4/8] Remove the num-derive dependency --- Cargo.toml | 1 - src/lib.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bdba5b7..7ed8885 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ exclude = ["tests/images/*", "tests/fuzz_images/*"] [dependencies] byteorder = "1.2" lzw = "0.10" -num-derive = "0.3" num-traits = "0.2" miniz_oxide = "0.3" diff --git a/src/lib.rs b/src/lib.rs index fe194e0..3280de2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,8 +9,6 @@ extern crate byteorder; extern crate lzw; extern crate miniz_oxide; -#[macro_use] -extern crate num_derive; extern crate num_traits; pub mod decoder; From a6696ab02fd544563441a932088ba5b4ffb8fee7 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Sun, 10 Nov 2019 19:22:55 +0100 Subject: [PATCH 5/8] fixup! Move everything to the tags macro --- src/decoder/mod.rs | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index a409b97..cdace31 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -82,7 +82,7 @@ impl<'a> DecodingBuffer<'a> { } tags! { -pub enum PhotometricInterpretation(u32) { +pub enum PhotometricInterpretation(u16) { WhiteIsZero = 0, BlackIsZero = 1, RGB = 2, @@ -95,7 +95,7 @@ pub enum PhotometricInterpretation(u32) { } tags! { -pub enum CompressionMethod(u32) { +pub enum CompressionMethod(u16) { None = 1, Huffman = 2, Fax3 = 3, @@ -109,55 +109,55 @@ pub enum CompressionMethod(u32) { } tags! { -pub enum PlanarConfiguration(u32) { +pub enum PlanarConfiguration(u16) { Chunky = 1, Planar = 2, } } tags! { -enum Predictor(u32) { +enum Predictor(u16) { None = 1, Horizontal = 2, } } impl PhotometricInterpretation { - pub fn from_u32(val: u32) -> Option { + pub fn from_u16(val: u16) -> Option { Self::__from_inner_type(val).ok() } - pub fn to_u32(&self) -> u32 { + pub fn to_u16(&self) -> u16 { Self::__to_inner_type(self) } } impl CompressionMethod { - pub fn from_u32(val: u32) -> Option { + pub fn from_u16(val: u16) -> Option { Self::__from_inner_type(val).ok() } - pub fn to_u32(&self) -> u32 { + pub fn to_u16(&self) -> u16 { Self::__to_inner_type(self) } } impl PlanarConfiguration { - pub fn from_u32(val: u32) -> Option { + pub fn from_u16(val: u16) -> Option { Self::__from_inner_type(val).ok() } - pub fn to_u32(&self) -> u32 { + pub fn to_u16(&self) -> u16 { Self::__to_inner_type(self) } } impl Predictor { - pub fn from_u32(val: u32) -> Option { + pub fn from_u16(val: u16) -> Option { Self::__from_inner_type(val).ok() } - pub fn to_u32(&self) -> u32 { + pub fn to_u16(&self) -> u16 { Self::__to_inner_type(self) } } @@ -379,8 +379,9 @@ impl Decoder { self.width = self.get_tag_u32(ifd::Tag::ImageWidth)?; self.height = self.get_tag_u32(ifd::Tag::ImageLength)?; self.strip_decoder = None; - self.photometric_interpretation = match PhotometricInterpretation::from_u32( - self.get_tag_u32(ifd::Tag::PhotometricInterpretation)? + // TODO: error on non-SHORT value. + self.photometric_interpretation = match PhotometricInterpretation::from_u16( + self.get_tag_u32(ifd::Tag::PhotometricInterpretation)? as u16 ) { Some(val) => val, None => { @@ -389,8 +390,9 @@ impl Decoder { )) } }; + // TODO: error on non-SHORT value. if let Some(val) = self.find_tag_u32(ifd::Tag::Compression)? { - match CompressionMethod::from_u32(val) { + match CompressionMethod::from_u16(val as u16) { Some(method) => self.compression_method = method, None => { return Err(TiffError::UnsupportedError( @@ -765,7 +767,8 @@ impl Decoder { )); } if let Ok(predictor) = self.get_tag_u32(ifd::Tag::Predictor) { - match Predictor::from_u32(predictor) { + // TODO: error on non-SHORT value. + match Predictor::from_u16(predictor as u16) { Some(Predictor::None) => (), Some(Predictor::Horizontal) => { rev_hpredict( From 517638a38fe4edbeb22ea2219048f978fb088330 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Sun, 10 Nov 2019 23:07:55 +0100 Subject: [PATCH 6/8] Prefer explicit conversion over `as` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The discriminant of some enum types can be retrieved with the `as` operator and in C style enums it is also possible to set a specific discriminant. However, that may silently change—breaking the value written to the file. It is better to use that technique mostly for ffi purposes. --- src/encoder/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index 96ba414..f09b0a9 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -438,7 +438,7 @@ impl<'a, W: 'a + Write + Seek> DirectoryEncoder<'a, W> { } self.ifd - .insert(tag.to_u16(), (::FIELD_TYPE as u16, value.count(), bytes)); + .insert(tag.to_u16(), (::FIELD_TYPE.to_u16(), value.count(), bytes)); } fn write_directory(&mut self) -> TiffResult { @@ -565,7 +565,7 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> { encoder.write_tag(Tag::Compression, 1u16); encoder.write_tag(Tag::BitsPerSample, ::BITS_PER_SAMPLE); - encoder.write_tag(Tag::PhotometricInterpretation, ::TIFF_VALUE as u16); + encoder.write_tag(Tag::PhotometricInterpretation, ::TIFF_VALUE.to_u16()); encoder.write_tag(Tag::RowsPerStrip, rows_per_strip as u32); From 07e8501ad60a0e309862596738f419c0bb16bf44 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Tue, 12 Nov 2019 10:53:38 +0100 Subject: [PATCH 7/8] Prefer matching over if-else-chain in tags macro Thanks to the review comment for pointing this style issue out. --- src/decoder/ifd.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs index f162f8b..2be016b 100644 --- a/src/decoder/ifd.rs +++ b/src/decoder/ifd.rs @@ -34,8 +34,9 @@ macro_rules! tags { impl $name { #[inline(always)] fn __from_inner_type(n: $ty) -> Result { - $(if n == $val { Ok($name::$tag) } else)* { - Err(n) + match n { + $( $val => Ok($name::$tag), )* + n => Err(n), } } From 7b672998db394a042164a456037c779be403faa9 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Tue, 12 Nov 2019 20:06:02 +0100 Subject: [PATCH 8/8] Get rid of num-traits crate Turns out the only use was as a private bound which was unused within that method. --- Cargo.toml | 1 - src/decoder/mod.rs | 3 +-- src/lib.rs | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7ed8885..cb4c7f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ exclude = ["tests/images/*", "tests/fuzz_images/*"] [dependencies] byteorder = "1.2" lzw = "0.10" -num-traits = "0.2" miniz_oxide = "0.3" [dev-dependencies] diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index cdace31..a3aff91 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -1,4 +1,3 @@ -use num_traits::{Num}; use std::collections::HashMap; use std::io::{self, Read, Seek}; use std::cmp; @@ -236,7 +235,7 @@ impl Wrapping for u16 { fn rev_hpredict_nsamp(image: &mut [T], size: (u32, u32), samples: usize) where - T: Num + Copy + Wrapping, + T: Copy + Wrapping, { let width = size.0 as usize; let height = size.1 as usize; diff --git a/src/lib.rs b/src/lib.rs index 3280de2..8550be3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,6 @@ extern crate byteorder; extern crate lzw; extern crate miniz_oxide; -extern crate num_traits; pub mod decoder; pub mod encoder;