Skip to content

Instantly share code, notes, and snippets.

@arviedelgado
Created April 20, 2020 05:12
Show Gist options
  • Select an option

  • Save arviedelgado/05a94a06e99f915484354e0036123fc9 to your computer and use it in GitHub Desktop.

Select an option

Save arviedelgado/05a94a06e99f915484354e0036123fc9 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
public class TiffImage : ObservableCollection<Image>
{
public TiffImage(Image image)
{
Add(image);
}
public TiffImage(IEnumerable<Image> images)
{
images.ToList().ForEach(image => Add(image));
}
public TiffImage(byte[] bytes)
{
Add(FromBytes(bytes));
}
public TiffImage(string base64)
{
Add(FromBytes(Convert.FromBase64String(base64)));
}
protected override void InsertItem(int index, Image item)
{
Split(item).ToList().ForEach(page => base.InsertItem(index++, FromBytes(page)));
}
public byte[] ToBytes()
{
return Merge(Items);
}
public string ToBase64()
{
return Convert.ToBase64String(ToBytes());
}
public string ToBase64DataUrl()
{
return "data:" + GetMimeType() + ";base64," + ToBase64();
}
public string GetMimeType()
{
return ImageCodecInfo.GetImageEncoders()
.First(x => x.FormatID == ImageFormat.Tiff.Guid).MimeType;
}
public IReadOnlyList<string> GetFileExtensions()
{
return ImageCodecInfo.GetImageEncoders()
.First(x => x.FormatID == ImageFormat.Tiff.Guid).FilenameExtension
.Replace("*", "").ToLower().Split(';');
}
public Image ToImage()
{
return FromBytes(ToBytes());
}
public TiffImage Clone()
{
return new TiffImage(Items.Select(item => (Image)item.Clone()));
}
public async Task SaveAsync(string path, CancellationToken cancellationToken = default)
{
await File.WriteAllBytesAsync(path, Merge(Items), cancellationToken);
}
public async Task SaveAsync(Stream stream, CancellationToken cancellationToken = default)
{
await stream.WriteAsync(Merge(Items), cancellationToken);
}
// PRIVATE
private Image FromBytes(byte[] bytes)
{
return Image.FromStream(new MemoryStream(bytes)); // no "using"
}
private IEnumerable<byte[]> Split(Image originalImage)
{
var pages = new List<byte[]>();
var image = (Image)originalImage.Clone();
var count = image.GetFrameCount(FrameDimension.Page);
var encoder = ImageCodecInfo.GetImageEncoders().First(x => x.FormatID == ImageFormat.Tiff.Guid);
using var encoderParams = new EncoderParameters(2);
encoderParams.Param[0] = new EncoderParameter(Encoder.Compression, (Int64)EncoderValue.CompressionLZW);
encoderParams.Param[1] = new EncoderParameter(Encoder.SaveFlag, (Int64)EncoderValue.FrameDimensionPage);
for (var index = 0; index < count; index++)
{
image.SelectActiveFrame(FrameDimension.Page, index);
using var stream = new MemoryStream();
image.Save(stream, encoder, encoderParams);
pages.Add(stream.ToArray());
}
return pages.AsReadOnly();
}
private byte[] Merge(IEnumerable<Image> orignalImages)
{
using var stream = new MemoryStream();
var pages = orignalImages.ToList().SelectMany(page => Split(page)).Select(x => FromBytes(x)).ToList();
var encoder = ImageCodecInfo.GetImageEncoders().First(x => x.FormatID == ImageFormat.Tiff.Guid);
using var encoderParams = new EncoderParameters(2);
encoderParams.Param[0] = new EncoderParameter(Encoder.Compression, (Int64)EncoderValue.CompressionLZW);
var image = (Image)pages.First().Clone();
// add first page
encoderParams.Param[1] = new EncoderParameter(Encoder.SaveFlag, (Int64)EncoderValue.MultiFrame);
image.Save(stream, encoder, encoderParams);
// add next pages
encoderParams.Param[1] = new EncoderParameter(Encoder.SaveFlag, (Int64)EncoderValue.FrameDimensionPage);
pages.Skip(1).ToList().ForEach(page => image.SaveAdd(page, encoderParams));
// close
encoderParams.Param[1] = new EncoderParameter(Encoder.SaveFlag, (Int64)EncoderValue.Flush);
image.SaveAdd(encoderParams);
image.Dispose();
pages.ForEach(page => page.Dispose());
return stream.ToArray();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment