Tuesday, November 15, 2011

C#: Slice a Bitmap horizontally with a specified maximum (physical) size per slice

I will explain the problem in detail once I find some time... but here is the code for now:

Sample code to call the slicer class (using a PNG image in this example)
******************************************************
Bitmap baseBitmap = Bitmap.FromFile("c:\\mybitmap.png");
ImageSlicer slicer = new ImageSlicer();
List<Bitmap> slicedBitmaps = slicer.SliceImage(baseBitmap, 20000, ImageFormat.Png);

Code for the class
**************

using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace KodeSharp.ImageSlicer
{
    class ImageSlicer
    {
        public List<Bitmap> SliceImage(Bitmap baseBitmap, int maxSizeInBytes, ImageFormat imageType)
        {
            return GetSlicedImages(new List<Bitmap>() { baseBitmap }, maxSizeInBytes, imageType);
        }

        private List<Bitmap> GetSlicedImages(List<Bitmap> baseBitmaps, int maxSizeInBytes, ImageFormat imageType)
        {
            List<Bitmap> bmpOut = new List<Bitmap>();
            foreach (Bitmap bmp in baseBitmaps)
            {
                if (IsSliceTooBig(bmp, maxSizeInBytes, imageType))
                {
                    List<Bitmap> bmps = SliceImageInHalf(bmp);
                    bmpOut.AddRange(GetSlicedImages(new List<Bitmap>() { bmps[0] }, maxSizeInBytes, imageType));
                    bmpOut.AddRange(GetSlicedImages(new List<Bitmap>() { bmps[1] }, maxSizeInBytes, imageType));
                }
                else
                {
                    bmpOut.Add(bmp);
                }
            }
            return bmpOut;
        }

        private bool IsSliceTooBig(Bitmap bmp, int maxSizeInBytes, ImageFormat imageType)
        {
            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, imageType);
            if (ms.Length > maxSizeInBytes)
                return true;
            else
                return false;
        }

        private List<Bitmap> SliceImageInHalf(Bitmap sourceImage)
        {
            int slice1Height = sourceImage.Height / 2;
            int slice2Height = sourceImage.Height - slice1Height;
            int sliceWidth = sourceImage.Width;

            Bitmap slice1 = sourceImage.Clone(new Rectangle(0, 0, sliceWidth, slice1Height), sourceImage.PixelFormat);
            Bitmap slice2 = sourceImage.Clone(new Rectangle(0, slice1Height, sliceWidth, slice2Height), sourceImage.PixelFormat);

            return new List<Bitmap>() { slice1, slice2 };
        }
    }
}

No comments:

Post a Comment

Please use your common sense before making a comment, and I truly appreciate your constructive criticisms.