使用JPEG压缩.NET创建多页Tiff [英] Create multipage Tiff with JPEG compression .NET

查看:92
本文介绍了使用JPEG压缩.NET创建多页Tiff的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以使用.NET通过jpeg压缩创建多页tiff? 我可以使用LZW压缩创建tiff,但是文件非常大.看起来EncoderValue枚举(我用来设置压缩)甚至没有合适的成员.

Is there any way to create multipage tiff with jpeg compression using .NET? I can create tiff's with LZW compression, but files are extremely big. Looks like EncoderValue enumeration (which I use to set up compression) doesn't even have suitable member.

推荐答案

您可以查看 >> ,在这里我将说明如何将现有的JPEG包装在一个简单的多页TIFF容器中.

You can have a look at >> this post, where I explain how to wrap existing JPEGs in a simple multi-page TIFF container.

但是还有其他多种可能性. FreeImage.Net (freeimage.sourceforge.net)是一个非常强大的库.您可以像这样创建一个简单的JPEG压缩TIFF:

But there's a variety of other possibilities. FreeImage.Net (freeimage.sourceforge.net) is a very powerful library. You can create a simple JPEG-compressed TIFF like this:

using FreeImageAPI;
// [...]
FIBITMAP image = FreeImage.Load(FREE_IMAGE_FORMAT.FIF_UNKNOWN, "filename", FREE_IMAGE_LOAD_FLAGS.DEFAULT);
FreeImage.Save(FREE_IMAGE_FORMAT.FIF_TIFF, image, "filename", FREE_IMAGE_SAVE_FLAGS.TIFF_JPEG)

创建多页TIFF有点棘手.据我所知,多页编辑只能在硬盘上进行. (尽管我听说过较新版本中还有另一种方式,所以也许可以尝试一下.)但是,您可以使用如下方式:

Creating multi-page TIFFs is a little more tricky. As far as I know, multi-page editing is only possible on the harddrive. (I've heard there's another way in a newer version though, so maybe play around with it a little bit.) However, you may use sth like this:

using System.IO;
using FreeImageAPI;

// [...]

public byte[] MergeTiffs(List<byte[]> tiffs)
{
    byte[] multiPageTiff = null;
    string tmpfile = "... chose any file name ...";
    MemoryStream singleStream = null;
    FIBITMAP fib = FIBITMAP.Zero;
    FIMULTIBITMAP fmb = FIMULTIBITMAP.Zero;

    using (singleStream = new MemoryStream(tiffs[0])
    {
        fib = FreeImage.LoadFromStream(singleStream);
        FreeImage.SaveEx(fib, dateiname, FREE_IMAGE_FORMAT.FIF_TIFF, FREE_IMAGE_SAVE_FLAGS.TIFF_JPEG);
        FreeImage.UnloadEx(ref fib);
    }

    fmb = FreeImage.OpenMultiBitmap(
        FREE_IMAGE_FORMAT.FIF_TIFF,
        tmpfile,
        false,
        false,
        false,
        FREE_IMAGE_LOAD_FLAGS.TIFF_JPEG);

    for (int i = 1; i < tiffs.Count; i++)
    {
        using (singleStream = new MemoryStream(tiffs[i])
        {
            fib = FreeImage.LoadFromStream(singleStream);
            FreeImage.AppendPage(fmb, fib);
        }
    }

    FreeImage.CloseMultiBitmapEx(ref fmb);
    multiPageTiff = File.ReadAllBytes(tmpfile);
    File.Delete(tmpfile);

    return file;
}

除此之外,我最近发现了一种简单的方法,可以将现有的TIFF与 LibTiff.Net (bitmiracle.com)合并,而无需更改其原始数据(因此您既不会失去质量,也不增加尺寸).可能有一种更简单的方法(也许您找到了一种方法),但是我使用了以下代码(基于

Apart from that, I recently found a simple way to merge existing TIFFs with LibTiff.Net (bitmiracle.com), without changing their raw data (so you neither lose quality nor increase their sizes). There might be an easier way (maybe you find one), but I used the following code (based on this example):

using System.IO
using BitMiracle.LibTiff.Classic;

// [...]

/// <summary>
/// Merges multiple TIFFs into one multi-page TIFF
/// </summary>
/// <param name="tiffs">The TIFFs' raw data (can also be multi-page)</param>
/// <returns></returns>
public static byte[] MergeTiffs(List<byte[]> tiffs)
{
    // the byteStream will contain the merged tiff's raw data
    MemoryStream byteStream = new MemoryStream();
    // create the output-TIFF (empty stream)
    using (Tiff output = Tiff.ClientOpen("InMemory", "w", byteStream, new TiffStream()))
    {
        for (short i = 0; i < tiffs.Count; i++)
        {
            // provide input-TIFF as custom TiffStream, with byteStream (output-TIFF) as output
            TiffStreamForBytes tiffStream = new TiffStreamForBytes(tiffs[i]);
            using (Tiff input = Tiff.ClientOpen("bytes", "r", null, tiffStream))
            {
                // *** now copy all the TIFF-data: ***

                // copy all directories (= all pages)
                int numberOfDirectories = input.NumberOfDirectories();
                for (short d = 0; d < numberOfDirectories; ++d)
                {
                    // set this as the current directory (to work in)
                    input.SetDirectory(d);

                    // copy all tags
                    for (ushort t = ushort.MinValue; t < ushort.MaxValue; ++t)
                    {
                        TiffTag tag = (TiffTag)t;
                        FieldValue[] tagValue = input.GetField(tag);
                        if (tagValue != null)
                            output.GetTagMethods().SetField(output, tag, tagValue);
                    }

                    // copy all strips
                    int numberOfStrips = input.NumberOfStrips();
                    int stripSize = input.StripSize();
                    for (int s = 0; s < numberOfStrips; ++s)
                    {
                        // buffer for the current strip
                        byte[] stripData = new byte[stripSize];
                        // read strip from input image (not decompressed)
                        int length = input.ReadRawStrip(s, stripData, 0, stripData.Length);
                        // write strip to output image (uncompressed)
                        output.WriteRawStrip(s, stripData, 0, length);
                    }

                    // add the new directory to output image
                    output.WriteDirectory();
                }
            }
        }
    }
    // return the new TIFF as byte array
    return byteStream.ToArray();
}

/// <summary>
/// Custom read-only stream for byte buffer that can be used
/// with Tiff.ClientOpen method.
/// </summary>
private class TiffStreamForBytes : TiffStream
{
    private byte[] m_bytes;
    private int m_position;

    public TiffStreamForBytes(byte[] bytes)
    {
        m_bytes = bytes;
        m_position = 0;
    }

    public override int Read(object clientData, byte[] buffer, int offset, int count)
    {
        if ((m_position + count) > m_bytes.Length)
            return -1;

        Buffer.BlockCopy(m_bytes, m_position, buffer, offset, count);
        m_position += count;
        return count;
    }

    public override void Write(object clientData, byte[] buffer, int offset, int count)
    {
        throw new InvalidOperationException("This stream is read-only");
    }

    public override long Seek(object clientData, long offset, SeekOrigin origin)
    {
        switch (origin)
        {
            case SeekOrigin.Begin:
                if (offset > m_bytes.Length)
                    return -1;

                m_position = (int)offset;
                return m_position;

            case SeekOrigin.Current:
                if ((offset + m_position) > m_bytes.Length)
                    return -1;

                m_position += (int)offset;
                return m_position;

            case SeekOrigin.End:
                if ((m_bytes.Length - offset) < 0)
                    return -1;

                m_position = (int)(m_bytes.Length - offset);
                return m_position;
        }

        return -1;
    }

    public override void Close(object clientData)
    {
        // nothing to do
    }

    public override long Size(object clientData)
    {
        return m_bytes.Length;
    }
}

这篇关于使用JPEG压缩.NET创建多页Tiff的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆