Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic metadata-only image parsing API #292

Merged
merged 27 commits into from
Jan 19, 2018
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f8573e3
Add an equivalent for System.Drawing.Image.GetPixelFormatSize() (#258)
Aug 10, 2017
a56893a
merge with master
Aug 14, 2017
1d81aed
fixes on code review
Aug 18, 2017
47454de
sync with upstream
Aug 24, 2017
ebe664c
update packages
Aug 24, 2017
d6a2d40
fix test image filename
Aug 24, 2017
75a89d6
sync with upstream
Sep 26, 2017
93419ab
fix bugs after merge
Sep 26, 2017
4a59c6f
remove duplicates in .csproj files
Sep 26, 2017
e1dcdef
Merge branch 'master' into master
xakep139 Sep 27, 2017
b5855a0
Merge branch 'master' into master
xakep139 Oct 4, 2017
79e2523
Merge branch 'master' into master
xakep139 Oct 6, 2017
d0e802d
Merge branch 'master' into master
xakep139 Oct 9, 2017
d204e88
Merge branch 'master' into master
xakep139 Oct 10, 2017
a44ceb8
merge with upstream
Oct 13, 2017
68af168
Merge branch 'master' of https://github.com/xakep139/ImageSharp
Oct 13, 2017
8ad7769
Merge branch 'master' into master
xakep139 Oct 18, 2017
5fa82af
Merge branch 'master' into master
xakep139 Nov 23, 2017
d2c0338
Merge branch 'master' into master
xakep139 Dec 8, 2017
75efd72
Merge branch 'master' into master
xakep139 Jan 10, 2018
def3d93
Merge branch 'master' into master
xakep139 Jan 17, 2018
a631a64
Added an API to read base image information without decoding it
denisivan0v Jan 17, 2018
52af4e3
Merge branch 'master' of https://github.com/xakep139/ImageSharp
denisivan0v Jan 17, 2018
b435f5e
codestyle fixes
denisivan0v Jan 17, 2018
9f719d5
codestyle fix
denisivan0v Jan 17, 2018
e88e138
bugfix in GifDecoderCore.Identity
denisivan0v Jan 18, 2018
61c9caf
changes on code review
denisivan0v Jan 19, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/ImageSharp/Formats/Bmp/BmpDecoder.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.

using System;
using System.Collections.Generic;
using System.IO;
using SixLabors.ImageSharp.PixelFormats;

Expand All @@ -23,7 +21,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Formats will be supported in a later releases. We advise always
/// to use only 24 Bit Windows bitmaps.
/// </remarks>
public sealed class BmpDecoder : IImageDecoder, IBmpDecoderOptions
public sealed class BmpDecoder : IImageDecoder, IBmpDecoderOptions, IImageInfoDetector
{
/// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream)
Expand All @@ -34,5 +32,13 @@ public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream)

return new BmpDecoderCore(configuration, this).Decode<TPixel>(stream);
}

/// <inheritdoc/>
public IImage Identify(Configuration configuration, Stream stream)
{
Guard.NotNull(stream, "stream");

return new BmpDecoderCore(configuration, this).Identify(stream);
}
}
}
134 changes: 80 additions & 54 deletions src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.IO;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;

namespace SixLabors.ImageSharp.Formats.Bmp
Expand Down Expand Up @@ -94,62 +95,9 @@ public BmpDecoderCore(Configuration configuration, IBmpDecoderOptions options)
public Image<TPixel> Decode<TPixel>(Stream stream)
where TPixel : struct, IPixel<TPixel>
{
this.currentStream = stream;

try
{
this.ReadFileHeader();
this.ReadInfoHeader();

// see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517
// If the height is negative, then this is a Windows bitmap whose origin
// is the upper-left corner and not the lower-left.The inverted flag
// indicates a lower-left origin.Our code will be outputting an
// upper-left origin pixel array.
bool inverted = false;
if (this.infoHeader.Height < 0)
{
inverted = true;
this.infoHeader.Height = -this.infoHeader.Height;
}

int colorMapSize = -1;

if (this.infoHeader.ClrUsed == 0)
{
if (this.infoHeader.BitsPerPixel == 1 ||
this.infoHeader.BitsPerPixel == 4 ||
this.infoHeader.BitsPerPixel == 8)
{
colorMapSize = (int)Math.Pow(2, this.infoHeader.BitsPerPixel) * 4;
}
}
else
{
colorMapSize = this.infoHeader.ClrUsed * 4;
}

byte[] palette = null;

if (colorMapSize > 0)
{
// 256 * 4
if (colorMapSize > 1024)
{
throw new ImageFormatException($"Invalid bmp colormap size '{colorMapSize}'");
}

palette = new byte[colorMapSize];

this.currentStream.Read(palette, 0, colorMapSize);
}

if (this.infoHeader.Width > int.MaxValue || this.infoHeader.Height > int.MaxValue)
{
throw new ArgumentOutOfRangeException(
$"The input bitmap '{this.infoHeader.Width}x{this.infoHeader.Height}' is "
+ $"bigger then the max allowed size '{int.MaxValue}x{int.MaxValue}'");
}
this.ReadImageHeaders(stream, out bool inverted, out byte[] palette);

var image = new Image<TPixel>(this.configuration, this.infoHeader.Width, this.infoHeader.Height);
using (PixelAccessor<TPixel> pixels = image.Lock())
Expand Down Expand Up @@ -192,6 +140,16 @@ public Image<TPixel> Decode<TPixel>(Stream stream)
}
}

/// <summary>
/// Reads the image base information from the specified stream.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
public IImage Identify(Stream stream)
{
this.ReadImageHeaders(stream, out _, out _);
return new ImageInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), this.infoHeader.Width, this.infoHeader.Height, new ImageMetaData());
}

/// <summary>
/// Returns the y- value based on the given height.
/// </summary>
Expand Down Expand Up @@ -624,5 +582,73 @@ private void ReadFileHeader()
Offset = BitConverter.ToInt32(data, 10)
};
}

/// <summary>
/// Reads the <see cref="BmpFileHeader"/> and <see cref="BmpInfoHeader"/> from the stream and sets the corresponding fields.
/// </summary>
private void ReadImageHeaders(Stream stream, out bool inverted, out byte[] palette)
{
this.currentStream = stream;

try
{
this.ReadFileHeader();
this.ReadInfoHeader();

// see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517
// If the height is negative, then this is a Windows bitmap whose origin
// is the upper-left corner and not the lower-left.The inverted flag
// indicates a lower-left origin.Our code will be outputting an
// upper-left origin pixel array.
inverted = false;
if (this.infoHeader.Height < 0)
{
inverted = true;
this.infoHeader.Height = -this.infoHeader.Height;
}

int colorMapSize = -1;

if (this.infoHeader.ClrUsed == 0)
{
if (this.infoHeader.BitsPerPixel == 1 ||
this.infoHeader.BitsPerPixel == 4 ||
this.infoHeader.BitsPerPixel == 8)
{
colorMapSize = (int)Math.Pow(2, this.infoHeader.BitsPerPixel) * 4;
}
}
else
{
colorMapSize = this.infoHeader.ClrUsed * 4;
}

palette = null;

if (colorMapSize > 0)
{
// 256 * 4
if (colorMapSize > 1024)
{
throw new ImageFormatException($"Invalid bmp colormap size '{colorMapSize}'");
}

palette = new byte[colorMapSize];

this.currentStream.Read(palette, 0, colorMapSize);
}

if (this.infoHeader.Width > int.MaxValue || this.infoHeader.Height > int.MaxValue)
{
throw new ArgumentOutOfRangeException(
$"The input bitmap '{this.infoHeader.Width}x{this.infoHeader.Height}' is "
+ $"bigger then the max allowed size '{int.MaxValue}x{int.MaxValue}'");
}
}
catch (IndexOutOfRangeException e)
{
throw new ImageFormatException("Bitmap does not have a valid format.", e);
}
}
}
}
17 changes: 12 additions & 5 deletions src/ImageSharp/Formats/Gif/GifDecoder.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using SixLabors.ImageSharp.PixelFormats;
Expand All @@ -12,7 +10,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Decoder for generating an image out of a gif encoded stream.
/// </summary>
public sealed class GifDecoder : IImageDecoder, IGifDecoderOptions
public sealed class GifDecoder : IImageDecoder, IGifDecoderOptions, IImageInfoDetector
{
/// <summary>
/// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
Expand All @@ -33,8 +31,17 @@ public sealed class GifDecoder : IImageDecoder, IGifDecoderOptions
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream)
where TPixel : struct, IPixel<TPixel>
{
var decoder = new GifDecoderCore<TPixel>(configuration, this);
return decoder.Decode(stream);
var decoder = new GifDecoderCore(configuration, this);
return decoder.Decode<TPixel>(stream);
}

/// <inheritdoc/>
public IImage Identify(Configuration configuration, Stream stream)
{
Guard.NotNull(stream, "stream");

var decoder = new GifDecoderCore(configuration, this);
return decoder.Identify(stream);
}
}
}
Loading