diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs new file mode 100644 index 0000000000..57a6eda5f3 --- /dev/null +++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs @@ -0,0 +1,21 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Formats.Tiff +{ + /// + /// Enumerates the available bits per pixel the tiff encoder supports. + /// + public enum TiffBitsPerPixel + { + /// + /// 8 bits per pixel. Each pixel consists of 1 byte. + /// + Pixel8 = 8, + + /// + /// 24 bits per pixel. Each pixel consists of 3 bytes. + /// + Pixel24 = 24, + } +} diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index bbf361e0d6..08b00d5bac 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -33,6 +33,19 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// private readonly bool ignoreMetadata; + /// + /// The image metadata. + /// + private ImageMetadata metadata; + + /// + /// The tiff specific metadata. + /// + private TiffMetadata tiffMetaData; + + /// + /// The stream to decode from. + /// private BufferedReadStream inputStream; /// @@ -104,7 +117,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff framesMetadata.Add(frameMetadata); } - ImageMetadata metadata = framesMetadata.CreateMetadata(this.ignoreMetadata, tiffStream.ByteOrder); + this.metadata = framesMetadata.CreateMetadata(this.ignoreMetadata, tiffStream.ByteOrder); + this.tiffMetaData = this.metadata.GetTiffMetadata(); + this.SetBitsPerPixel(framesMetadata); // todo: tiff frames can have different sizes { @@ -119,11 +134,31 @@ namespace SixLabors.ImageSharp.Formats.Tiff } } - var image = new Image(this.configuration, metadata, frames); + var image = new Image(this.configuration, this.metadata, frames); return image; } + private void SetBitsPerPixel(List framesMetadata) + { + TiffFrameMetadata firstMetaData = framesMetadata.First(); + ushort[] bitsPerSample = firstMetaData.BitsPerSample; + var bitsPerPixel = 0; + foreach (var bps in bitsPerSample) + { + bitsPerPixel += bps; + } + + if (bitsPerPixel == 24) + { + this.tiffMetaData.BitsPerPixel = TiffBitsPerPixel.Pixel24; + } + else if (bitsPerPixel == 8) + { + this.tiffMetaData.BitsPerPixel = TiffBitsPerPixel.Pixel8; + } + } + /// public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken) { @@ -168,7 +203,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff private static TiffByteOrder ReadByteOrder(Stream stream) { - byte[] headerBytes = new byte[2]; + var headerBytes = new byte[2]; stream.Read(headerBytes, 0, 2); if (headerBytes[0] == TiffConstants.ByteOrderLittleEndian && headerBytes[1] == TiffConstants.ByteOrderLittleEndian) { @@ -187,26 +222,26 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// /// The pixel format. /// The IFD tags. - /// The frame metadata. + /// The frame metadata. /// /// The tiff frame. /// - private ImageFrame DecodeFrame(IExifValue[] tags, out TiffFrameMetadata metadata) + private ImageFrame DecodeFrame(IExifValue[] tags, out TiffFrameMetadata frameMetaData) where TPixel : unmanaged, IPixel { var coreMetadata = new ImageFrameMetadata(); - metadata = coreMetadata.GetTiffMetadata(); - metadata.Tags = tags; + frameMetaData = coreMetadata.GetTiffMetadata(); + frameMetaData.Tags = tags; - this.VerifyAndParseOptions(metadata); + this.VerifyAndParseOptions(frameMetaData); - int width = (int)metadata.Width; - int height = (int)metadata.Height; + int width = (int)frameMetaData.Width; + int height = (int)frameMetaData.Height; var frame = new ImageFrame(this.configuration, width, height, coreMetadata); - int rowsPerStrip = (int)metadata.RowsPerStrip; - uint[] stripOffsets = metadata.StripOffsets; - uint[] stripByteCounts = metadata.StripByteCounts; + int rowsPerStrip = (int)frameMetaData.RowsPerStrip; + uint[] stripOffsets = frameMetaData.StripOffsets; + uint[] stripByteCounts = frameMetaData.StripByteCounts; if (this.PlanarConfiguration == TiffPlanarConfiguration.Planar) { diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs index 250fb23895..10d22b25b8 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs @@ -5,8 +5,10 @@ using System; using System.Collections.Generic; using System.IO; using System.Threading; + using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; @@ -32,6 +34,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// private Configuration configuration; + /// + /// The color depth, in number of bits per pixel. + /// + private TiffBitsPerPixel? bitsPerPixel; + /// /// Initializes a new instance of the class. /// @@ -66,9 +73,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff Guard.NotNull(stream, nameof(stream)); this.configuration = image.GetConfiguration(); + ImageMetadata metadata = image.Metadata; + TiffMetadata tiffMetadata = metadata.GetTiffMetadata(); + this.bitsPerPixel ??= tiffMetadata.BitsPerPixel; - // TODO: bits per pixel hardcoded to 24 for the start. - short bpp = 24; + short bpp = (short)this.bitsPerPixel; int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32); this.padding = bytesPerLine - (int)(image.Width * (bpp / 8F)); diff --git a/src/ImageSharp/Formats/Tiff/TiffMetadata.cs b/src/ImageSharp/Formats/Tiff/TiffMetadata.cs index ae25480ed6..fd1d84ef38 100644 --- a/src/ImageSharp/Formats/Tiff/TiffMetadata.cs +++ b/src/ImageSharp/Formats/Tiff/TiffMetadata.cs @@ -1,9 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using System.Collections; -using System.Collections.Generic; - namespace SixLabors.ImageSharp.Formats.Tiff { /// @@ -26,6 +23,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff { this.ByteOrder = other.ByteOrder; this.XmpProfile = other.XmpProfile; + this.BitsPerPixel = other.BitsPerPixel; } /// @@ -33,6 +31,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// public TiffByteOrder ByteOrder { get; set; } + /// + /// Gets or sets the number of bits per pixel. + /// + public TiffBitsPerPixel BitsPerPixel { get; set; } = TiffBitsPerPixel.Pixel24; + /// /// Gets or sets the XMP profile. ///