TIFFのビットの深さを変更できません

タグの編集
投稿者 snowmansnow  (社会人) 投稿日時 2021/8/28 21:05:14
こんばんは
 先日のkazu様と魔界の仮面弁士様とのやりとりに関連しまして
 TIFFのビット深度、圧縮を変更しようと思いました
  C#で作ってみました

using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Drawing.Imaging;


namespace WindowsFormsAppTIFF_1L
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Bitmap bmp = new Bitmap("C:/hoge/example.tiff");

            ImageCodecInfo[] enc = ImageCodecInfo.GetImageEncoders();
            ImageCodecInfo tiffICI = enc.First(p => p.MimeType == "image/tiff");

            EncoderParameters epMultiFrame = new EncoderParameters(2);
            // 1.の画像
            string tif = "C:/hoge/example_1L.tiff";
            epMultiFrame.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionLZW);
            epMultiFrame.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 1L);
    
            bmp.Save(tif, tiffICI, epMultiFrame);

        }
    }
}

圧縮は、変更されるのですが、ビット深度は、変更されません。
このやり方ではビット深度は変更できないのでしょうか?
ビット深度の変更の仕方を知りたいです。(今回はモノクロ2値)
よろしくお願いします




投稿者 snowmansnow  (社会人) 投稿日時 2021/8/29 17:16:47
こんばんは、
 魔界の仮面弁士様の紹介していた
  https://dobon.net/vb/dotnet/graphics/createmultitiff.htmlに載っていた
  https://www.codeproject.com/Articles/16904/Save-images-into-a-multi-page-TIFF-file-or-add-imaをフォームアプリケーションのクラスライブラリにしてみました
  文字数が多いので分けます
  
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.IO;

namespace WindowsFormsAppTiffTo1L_CL
{
    [Guid(TiffTo1L.ClassId)]
    public class  TiffTo1L
    {
        //  COM用のGUID値
        public const string ClassId = "14BC0BB5-22E6-45C8-8656-45D84E25F60D";

        //https://www.codeproject.com/Articles/16904/Save-images-into-a-multi-page-TIFF-file-or-add-ima
        //This function can save newly scanned images on existing single page or multipage file
        public String OriginDest(string fileName, string type,long col,string orig,float dpi)
        {
            Image origionalFile = null;
            FileStream fr = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite);
            origionalFile = Image.FromStream(fr);
            int PageNumber = getPageNumber(origionalFile);

            if (PageNumber > 1)//Existing File is multi page tiff file
            {
                saveImageExistingMultiplePage(origionalFile, type, PageNumber, orig, col,dpi);
            }
            else if (PageNumber == 1)//Existing file is single page file
            {
                saveImageExistingSinglePage(origionalFile, type, orig, col,dpi);
            }
            fr.Flush();
            fr.Close();
           // System.IO.File.Replace("shreeTemp.tif", fileName, "Backup.tif", true);
            return "ok";
        }

        public ImageCodecInfo getCodecForstring(string type)
        {
            ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();

            for (int i = 0; i < info.Length; i++)
            {
                string EnumName = type.ToString();
                if (info[i].FormatDescription.Equals(EnumName))
                {
                    return info[i];
                }
            }
            return null;

        }
    
        public void saveImageExistingSinglePage(Image origionalFile, string type, string location,long col1,float dpi)
        {
            //Now load the Codecs 
            ImageCodecInfo codecInfo = getCodecForstring(type);

            EncoderParameter SaveEncodeParam;
            EncoderParameter CompressionEncodeParam;
            EncoderParameters EncoderParams = new EncoderParameters(3);
            EncoderParameter ColorEncodeParam;

            // Save the first page (frame).
            SaveEncodeParam = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.MultiFrame);
            CompressionEncodeParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionNone);
            // Save the image with a color depth of 24 bits per pixel.
            ColorEncodeParam = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth,col1);
            EncoderParams.Param[0] = CompressionEncodeParam;
            EncoderParams.Param[1] = SaveEncodeParam;
            EncoderParams.Param[2] = ColorEncodeParam;

            origionalFile = ConvertToBitonal((Bitmap)origionalFile,dpi);
            origionalFile.Save(location, codecInfo, EncoderParams);

            SaveEncodeParam = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.Flush);
            EncoderParams.Param[0] = SaveEncodeParam;
            origionalFile.SaveAdd(EncoderParams);
        }
   
投稿者 snowmansnow  (社会人) 投稿日時 2021/8/29 17:17:51
   その2
    
        public void saveImageExistingMultiplePage(Image origionalFile, string type, int PageNumber, string location,long col1,float dpi)
        {
            //Now load the Codecs 
            ImageCodecInfo codecInfo = getCodecForstring(type);

            EncoderParameter SaveEncodeParam;
            EncoderParameter CompressionEncodeParam;
            EncoderParameters EncoderParams = new EncoderParameters(3);
            EncoderParameter ColorEncodeParam;

            Bitmap pages;
            Bitmap NextPage;

            origionalFile.SelectActiveFrame(FrameDimension.Page, 0);
            pages = new Bitmap(origionalFile);
            pages = ConvertToBitonal(pages,dpi);

            // Save the first page (frame).
            SaveEncodeParam = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.MultiFrame);
            CompressionEncodeParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionNone);
            // Save the image with a color depth of 24 bits per pixel.
            ColorEncodeParam = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, col1);
            EncoderParams.Param[0] = CompressionEncodeParam;
            EncoderParams.Param[1] = SaveEncodeParam;
            EncoderParams.Param[2] = ColorEncodeParam;

            pages.Save(location, codecInfo, EncoderParams);

            for (int i = 1; i < PageNumber; i++)
            {
                SaveEncodeParam = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.FrameDimensionPage);
                CompressionEncodeParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionNone);
                EncoderParams.Param[0] = CompressionEncodeParam;
                EncoderParams.Param[1] = SaveEncodeParam;
                EncoderParams.Param[2] = ColorEncodeParam;

                origionalFile.SelectActiveFrame(FrameDimension.Page, i);
                NextPage = new Bitmap(origionalFile);
                NextPage = ConvertToBitonal(NextPage,dpi);
                pages.SaveAdd(NextPage, EncoderParams);
            }
            SaveEncodeParam = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.Flush);
            EncoderParams.Param[0] = SaveEncodeParam;
            pages.SaveAdd(EncoderParams);
        }

        public int getPageNumber(Image img)
        {
            Guid objGuid = img.FrameDimensionsList[0];
            FrameDimension objDimension = new FrameDimension(objGuid);

            //Gets the total number of frames in the .tiff file
            int PageNumber = img.GetFrameCount(objDimension);

            return PageNumber;
        }
  

  
 
投稿者 snowmansnow  (社会人) 投稿日時 2021/8/29 17:19:00
  その3
    
        public Bitmap ConvertToBitonal(Bitmap original,float dpi)
        {
            Bitmap source = null;

            // If original bitmap is not already in 32 BPP, ARGB format, then convert
            if (original.PixelFormat != PixelFormat.Format32bppArgb)
            {
                source = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
                source.SetResolution(original.HorizontalResolution, original.VerticalResolution);

                //   source.SetResolution(dpi, dpi );

                using (Graphics g = Graphics.FromImage(source))
                {
                    g.DrawImageUnscaled(original, 0, 0);
                }
            }
            else
            {
                source = original;
            }

            // Lock source bitmap in memory
            BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            // Copy image data to binary array
            int imageSize = sourceData.Stride * sourceData.Height;
            byte[] sourceBuffer = new byte[imageSize];
            Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);

            // Unlock source bitmap
            source.UnlockBits(sourceData);

            // Create destination bitmap
            Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed);

            // Lock destination bitmap in memory
            BitmapData destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);

            // Create destination buffer
            imageSize = destinationData.Stride * destinationData.Height;
            byte[] destinationBuffer = new byte[imageSize];

            int sourceIndex = 0;
            int destinationIndex = 0;
            int pixelTotal = 0;
            byte destinationValue = 0;
            int pixelValue = 128;
            int height = source.Height;
            int width = source.Width;
            int threshold = 500;

            // Iterate lines
            for (int y = 0; y < height; y++)
            {
                sourceIndex = y * sourceData.Stride;
                destinationIndex = y * destinationData.Stride;
                destinationValue = 0;
                pixelValue = 128;

                // Iterate pixels
                for (int x = 0; x < width; x++)
                {
                    // Compute pixel brightness (i.e. total of Red, Green, and Blue values)
                    pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] + sourceBuffer[sourceIndex + 3];
                    if (pixelTotal > threshold)
                    {
                        destinationValue += (byte)pixelValue;
                    }
                    if (pixelValue == 1)
                    {
                        destinationBuffer[destinationIndex] = destinationValue;
                        destinationIndex++;
                        destinationValue = 0;
                        pixelValue = 128;
                    }
                    else
                    {
                        pixelValue >>= 1;
                    }
                    sourceIndex += 4;
                }
                if (pixelValue != 128)
                {
                    destinationBuffer[destinationIndex] = destinationValue;
                }
            }

            // Copy binary image data to destination bitmap
            Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);

            // Unlock destination bitmap
            destination.UnlockBits(destinationData);

            // Return
            return destination;
        }
    }
}
投稿者 snowmansnow  (社会人) 投稿日時 2021/8/29 17:27:54
その4

でも、ビット深度とサイズは、エクスプローラで、
 プロパティ上変わっているようでしたが、見た目はモノクロのみです。
 解像度は、元のファイルなのか何なのか?なようでした。
 指定した、正しいビット深度と解像度になるのでしょうか?
 モノクロっぽいですが、カラーのマークが全くなくなったりも(2値の境界以下?)しています。

 複合機でスキャンする時に、カラー、300DPIにしていたのですが、
 ファイルが大きすぎて、モノクロ(ビット下げたカラー?)でも、いいものは
 ビット深度を下げようと思いました。
 先日のpdfからtiffを介して2段階で、再pdfにするのも大変なので、
 直接tiffからtiffでビット深度を下げてみたかったです。
 
 C#でクラスライブラリで
 WIN10PRO excel2016_64bitです
 クラスライブラリは
 
Sub Tiff()
 
  ' .NETライブラリのクラスをインスタンス化 
  Dim wp As New WindowsFormsAppTiffTo1L_CL.TiffTo1L
  ' .NETクラスのメソッドを呼び出す 
  
' Set wp = ClassLibraryCS_itext7Margin.Margin 
  Dim html As String
  Dim col As Long
  Dim dpi As Single
  col = 8
  dpi = 200#
  html = wp.OriginDest("C:\hoge\sample.tiff""TIFF", col, "C:\hoge\sample2.tiff", dpi)
  MsgBox html
End Sub

です
よろしくお願いします
投稿者 snowmansnow  (社会人) 投稿日時 2021/9/4 20:14:29
こんばんは
 tiffの色変換などが、webで皆さん苦労してるのに気づきませんでした。
 魔界の仮面弁士様の変換が綺麗だったので、tiffからtiffの変換も簡単なのかと思いました。

 他の方の例を色々参考に見ていったのですが、こんがらがる一方で、
 先の2つが少し動くだけで、それ以上のものはできませんでした。

 魔界の仮面弁士様の例をクラスライブラリにしたものが、やっと動くようになり、
 tiff⇒pdf⇒tiff⇒pdfで、変換できそうです。
 何か、気に障る投稿だったのか、誰も返事をくれなくて、寂しい限りでした。
 前回もwebのググり方が足りない投稿でしたが、今回もそのせいだったのかなぁ?
 と思いました。
 皆さん、またよろしくお願いします。

 
 
投稿者 るきお  (社会人) 投稿日時 2021/9/5 19:53:47
snowmansnowさん、こんにちは。

画像処理分野はプログラマーの人口が比較的少ない分野で、その中でもTIFFという切り口だと、ほとんど回答できる人がいないのです。何か書き込みたくても書き込めないという感じだと思います。

魔界の仮面弁士さんの守備範囲のすごさは稀有なものなのです。
投稿者 snowmansnow  (社会人) 投稿日時 2021/9/7 21:08:51
こんばんは、るきお様
 お返事ありがとうございます!
 魔界の仮面弁士様も、るきお様も、他の方々もすごいと思います。
 気をつけて質問しますので、
 皆さんまたよろしくお願いします。