Zauge
Zauge

Reputation: 1

Copy a bitmap keeping same file size and bit depth in C#

I have a Windows service application that I have developed. When I am testing it local everything works perfect, but when I put the files on the server its failing.

The application is taking tiff files from the faxserver, one file can have many pages. the application takes one file and splits it to get all the pages in a file and save them to the database.

The problem is BITMAP, I have to copy the bitmap image to a new bitmap if I save it to the original bitmap the application fails. when I save it to the new bitmap the file size changes it becomes big, the bit depth changes from 1 to 32. I want it to remain the same.

There is a solution i got from my friend google it converts the bitmap from 32 to one, the problem with this solution is sometimes it does not copy some parts of the file.

My ultimate goal is to be able to save the bitmap to Memorystream and I do not want the file size to change.

I am saving the files as PNG. JPG and TIFF formats work perfect. I want to use PNG because when I save the file as PNG the file size is very small compared to JPG and TIFF

Here is my code

    public static Bitmap GetImage(Bitmap image, int index, ImageFormat imageFormat, ref byte[] imageStream)
    {
        Bitmap newImage=null;

        try
        {
            int imageWidth = int.Parse(ConfigurationManager.AppSettings["ImageWidth"]);
            int imageHeight = int.Parse(ConfigurationManager.AppSettings["ImageHeight"]);

            if (image == null) return null;

            image.SelectActiveFrame(FrameDimension.Page, index);

            newImage = new Bitmap(image);
            newImage = BitmapTo1Bpp(newImage); // i do not want to use this method its not reliable. sometimes it does not copy some parts of the file

            using (var byteStream = new MemoryStream())
            {

              //image.Save(byteStream,imageFormat) this one if failing on the server.
                newImage.Save(byteStream, imageFormat);  // the file size is changing it becomes big.
                imageStream = byteStream.ToArray();
            }

            return newImage;

        }
        catch (Exception ex)
        {
            Logger.Error(ex.ToString(), "Class : " + MethodBase.GetCurrentMethod().DeclaringType.FullName + ", Method : " + MethodBase.GetCurrentMethod().Name);
            return null;
        }
    }


    public static Bitmap BitmapTo1Bpp(Bitmap img)
    {

        int w = img.Width;
        int h = img.Height;
        Bitmap bmp = new Bitmap(w, h, PixelFormat.Format1bppIndexed);
        try
        {
            BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed);
            byte[] scan = new byte[(w + 7) / 8];
            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    if (x % 8 == 0) scan[x / 8] = 0;
                    Color c = img.GetPixel(x, y);
                    if (c.GetBrightness() >= 0.5) scan[x / 8] |= (byte)(0x80 >> (x % 8));
                }
                Marshal.Copy(scan, 0, (IntPtr)((long)data.Scan0 + data.Stride * y), scan.Length);
            }

            bmp.UnlockBits(data);
        }
        catch (Exception ex)
        {
            Logger.Error(ex.ToString(), "Class : " + MethodBase.GetCurrentMethod().DeclaringType.FullName + ", Method : " + MethodBase.GetCurrentMethod().Name);
            return null;
        }

        return bmp;
    }

Upvotes: 0

Views: 3002

Answers (2)

Joel Legaspi Enriquez
Joel Legaspi Enriquez

Reputation: 1236

You can also try cloning the image via GDI+'s DrawImage:

Bitmap clone = new Bitmap(srcWidth, srcHeight, srcPixelFormat );
Graphics g = Graphics.FromImage(clone);
Rectangle srcRect = new Rectangle(0, 0, srcWidth, srcHeight);
Rectangle dstRect = new Rectangle(0, 0, srcWidth, srcHeight);
g.DrawImage(bitmap, dstRect, srcRect, GraphicsUnit.Pixel);

You can play around with the following values if it affects your image's size (below is usually the settings for copying an exact image):

g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;

Upvotes: 0

Veverke
Veverke

Reputation: 11358

Did you try using Bitmap's Clone implementation ?

Cloning seems to create a clone with the same exact size, pixel format, and all remaining settings...

class Program
{
    static void Main(string[] args)
    {
        Bitmap b = Bitmap.FromFile(Path.Combine(Environment.CurrentDirectory, "test.bmp")) as Bitmap;
        Bitmap b2 = b.Clone() as Bitmap;

        Console.WriteLine("Height: original: {0}, clone: {1}",b.Size.Height, b2.Size.Height);
        Console.WriteLine("Width: original: {0}, clone: {1}",b.Size.Width, b2.Size.Width);

    }
}

Upvotes: 3

Related Questions