Hi there,
I found a way of doing this.
Here the code:
private void ResaveTiffBlackWhite(FileStream fs, string destPath)
{
// FileStream fs = File.Open(sourcePath, FileMode.Open, FileAccess.Read);
Bitmap srcBmp = new Bitmap(fs);// (Bitmap)Bitmap.FromStream(fs);
int totalPages = (int)(srcBmp.GetFrameCount(FrameDimension.Page));
ImageCodecInfo ici = GetTiffCodec();
EncoderParameters ep = GetBWEncoderParams();
Bitmap destFile = null;
int currentPage = 0;
for (currentPage = 0; currentPage < totalPages; currentPage++)
{
srcBmp.SelectActiveFrame(FrameDimension.Page, currentPage);
Bitmap tempBmp = GetRGBPage(srcBmp, 1652, 2352);
Bitmap destPage = new Bitmap(tempBmp.Width, tempBmp.Height, PixelFormat.Format1bppIndexed);//.Format16bppGrayScale);
destPage.SetResolution(200, 200);
destPage = Get1BppImage(tempBmp);
if (currentPage == 0)
{
if (destPage.Width > destPage.Height) { destPage.RotateFlip(RotateFlipType.Rotate90FlipNone); }
destFile = destPage;
destFile.Save(destPath, ici, ep);
}
else
{
if (destPage.Width > destPage.Height) { destPage.RotateFlip(RotateFlipType.Rotate90FlipNone); }
ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)(EncoderValue.FrameDimensionPage));
destFile.SaveAdd(destPage, ep);
}
if (currentPage == (int)(srcBmp.GetFrameCount(FrameDimension.Page) - 1))
{
ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)(EncoderValue.Flush));
destFile.SaveAdd(ep);
}
}
destFile.Dispose();
fs.Close();
}
private System.Drawing.Imaging.ImageCodecInfo GetTiffCodec()
{
foreach (ImageCodecInfo ici in ImageCodecInfo.GetImageEncoders())
{
if (ici.MimeType == "image/tiff")
{
return ici;
}
}
return null;
}
private System.Drawing.Imaging.EncoderParameters GetBWEncoderParams()
{
EncoderParameters ep = new EncoderParameters(2);
ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, Convert.ToInt32(EncoderValue.MultiFrame));
ep.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, Convert.ToInt32(EncoderValue.CompressionCCITT3));
// ep.Param[2] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 1L);
return ep;
}
private Bitmap GetRGBPage(Bitmap srcBmp, int newWidth, int newHeight)
{
if (srcBmp.Width > srcBmp.Height)
{
int tempHeight = newHeight;
newHeight = newWidth;
newWidth = tempHeight;
}
Bitmap tempBmp = new Bitmap(newWidth, newHeight, PixelFormat.Format32bppArgb);//((int)(resizeRatio * srcBmp.Width), (int)(resizeRatio * srcBmp.Height), PixelFormat.Format32bppArgb);
tempBmp.SetResolution(200, 200);
Graphics g = Graphics.FromImage(tempBmp);
g.DrawImage(srcBmp, new Rectangle(0, 0, tempBmp.Width, tempBmp.Height), 0, 0, srcBmp.Width, srcBmp.Height, GraphicsUnit.Pixel);
g.Dispose();
return tempBmp;
}
private Bitmap Get1BppImage(Bitmap srcBitmap)
{
//Be sure to have / create a Format32bppPArgb bitmap and resize it
if (srcBitmap.PixelFormat != PixelFormat.Format32bppPArgb)
{
Bitmap temp = new Bitmap(srcBitmap.Width, srcBitmap.Height, PixelFormat.Format32bppPArgb);
temp.SetResolution(200, 200);
Graphics g = Graphics.FromImage(temp);
g.DrawImage(srcBitmap, new Rectangle(0, 0, temp.Width, temp.Height), 0, 0, srcBitmap.Width, srcBitmap.Height, GraphicsUnit.Pixel);
srcBitmap.Dispose();
g.Dispose();
srcBitmap = temp;
}
//lock the bits of the original bitmap
BitmapData bmdo = srcBitmap.LockBits(new Rectangle(0, 0, srcBitmap.Width, srcBitmap.Height), ImageLockMode.ReadOnly, srcBitmap.PixelFormat);
//and the new 1bpp bitmap
Bitmap destBitmap = new Bitmap(srcBitmap.Width, srcBitmap.Height, PixelFormat.Format1bppIndexed);
BitmapData bmdn = destBitmap.LockBits(new Rectangle(0, 0, destBitmap.Width, destBitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed);
destBitmap.SetResolution(200, 200); //I want a resolution of 200dpi x 200dpi
//scan through the pixels Y by X
int x, y;
for (x = 0; x < srcBitmap.Width; x++)
{
for (y = 0; y < srcBitmap.Height; y++)
{
//generate the address of the colour pixel
int index = y * bmdo.Stride + (x * 4);
float myBrigthness = Color.FromArgb(Marshal.ReadByte(bmdo.Scan0, index + 2),
Marshal.ReadByte(bmdo.Scan0, index + 1),
Marshal.ReadByte(bmdo.Scan0, index)).GetBrightness();
//check its brightness and if between 0.33f and 0.67f create fake gray by alternating black and white (note that you have to cross depending on x-y position)
if (myBrigthness < 0.33f)
{
//Black thus do nothing
}
else if (myBrigthness < 0.67f)
{
if ((x + (y % 2)) % 2 == 1)
{
//Black thus do nothing
}
else
{
//White
this.SetIndexedPixel(x, y, bmdn, true); //set it if its bright.
}
}
else
{
//White
this.SetIndexedPixel(x, y, bmdn, true); //set it if its bright.
}
}
}
//tidy up
destBitmap.UnlockBits(bmdn);
srcBitmap.UnlockBits(bmdo);
return destBitmap;
}
protected void SetIndexedPixel(int x, int y, BitmapData bmd, bool pixel)
{
int index = y * bmd.Stride + (x >> 3);
byte p = Marshal.ReadByte(bmd.Scan0, index);
byte mask = (byte)(0x80 >> (x & 0x7));
if (pixel)
p |= mask;
else
p &= (byte)(mask ^ 0xff);
Marshal.WriteByte(bmd.Scan0, index, p);
}