Created
April 20, 2020 05:12
-
-
Save arviedelgado/05a94a06e99f915484354e0036123fc9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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