Sunday, June 20, 2010

Collocation or Tessellation of incongruent right angles quadrilateral onto a plane / Making sprite image for CSS Sprite technique- A Greedy Approach.

It’s easy to combine small images to make one giant image, but if there is certain constraint like you have fixed width of the resulting image and you have to make the best use of your space so that things can get in order then there is an opportunity for little brainstorming. Here is a sample code to serve the purpose written in C#. Somebody can use better search and sorting technique according to their need.

using System;

using System.Collections.Generic;

using System.Text;

using System.IO;

using System.Drawing;

namespace SpriteImage

{

class Program

{

public List<System.Drawing.Bitmap> images = new

List<System.Drawing.Bitmap>();

public int MaxWidth = 90, _index = 0;

public bool[] IsImageSet;

public int[] imageWidth;

Dictionary<int, List<int>> _recordes;

public Dictionary<int, List<int>> Recordes

{

get { return _recordes; }

}

static void Main(string[] args)

{

string[] files = Directory.GetFiles(@"C:\Img\");

Program p = new Program();

System.Drawing.Bitmap combinedImage = p.Combine(files);

combinedImage.Save(@"C:\stitchedImage.Png",

System.Drawing.Imaging.ImageFormat.Png);

}

public void MarkImageAsSet(int index)

{

IsImageSet[index] = true;

}

public Bitmap SearchNextFitImage(int Offset)

{

int[] temp = new int[imageWidth.Length]; int j = 0;

for (int i = 0; i < imageWidth.Length; i++)

{

if (imageWidth[i] <= Offset)

{

if (!IsImageSet[i])

{

temp[j++] = imageWidth[i];

}

}

}

int bigValue = 0;

// find the highest magnitude

for (int i = 0; i < j; i++)

{

bigValue = temp[i] > bigValue ? temp[i] : bigValue;

}

bool IsFound = false;

for (int i = 0; i < imageWidth.Length; i++)

{

if (imageWidth[i] == bigValue)

{

if (!IsImageSet[i])

{

IsFound = true; _index = i;

break;

}

}

}

if (IsFound)

{

return images[_index];

}

else

return null;

}

public Bitmap Combine(string[] files)

{

System.Drawing.Bitmap finalImage = null;

try

{

foreach (string image in files)

{

if (String.Compare("C:\\Img\\Thumbs.db", image) != 0)

{

System.Drawing.Bitmap bitmap = new

System.Drawing.Bitmap(image);

images.Add(bitmap);

}

}

int[] ImageId = new int[images.Count];

for (int i = 0; i < ImageId.Length; i++)

{

ImageId[i] = i;

}

Bitmap temp; int t;

// sort in descending order according to image height.

for (int i = 0; i < images.Count; i++)

{

for (int j = 0; j < images.Count; j++)

{

if (images[i].Height > images[j].Height)

{

temp = images[i];

images[i] = images[j];

images[j] = temp;

t = ImageId[i];

ImageId[i] = ImageId[j];

ImageId[j] = t;

}

}

}

IsImageSet = new bool[images.Count];

imageWidth = new int[images.Count];

// set image width

for (int i = 0; i < images.Count; i++)

{

imageWidth[i] = images[i].Width;

}

//// simulate the possible height

int count = 0, indexTop = 0, offset = 0, width = 0, height =

0;

while (count != images.Count)

{

if (count == 0)

{

// set 1st image

width = images[0].Width;

offset = MaxWidth - width;

MarkImageAsSet(count);

count++; continue;

}

Bitmap nextFitImage = SearchNextFitImage(offset);

if (nextFitImage != null)

{

MarkImageAsSet(_index);

count++;

offset = offset - nextFitImage.Width;

// offsetX = MaxWidth - offset;

Cordinate(offsetX,images[indexTop].Height)

}

else

{

if (!IsImageSet[indexTop + 1])

{

height += images[indexTop].Height;

indexTop++;

offset = MaxWidth - images[indexTop].Width;

count++;

MarkImageAsSet(indexTop);

//Cordinate(0,images[indexTop].Height)

}

// find next available image

else

{

for (int i = 0; i < IsImageSet.Length; i++)

{

if (!IsImageSet[i])

{

height += images[indexTop].Height;

indexTop = i;

offset = MaxWidth - images[i].Width;

count++;

MarkImageAsSet(i);

break;

}

}

}

}

}

height += images[indexTop].Height;

//////////////////

///// now set the images

finalImage = new System.Drawing.Bitmap(MaxWidth, height);

_recordes = new Dictionary<int, List<int>>();

using (System.Drawing.Graphics g =

System.Drawing.Graphics.FromImage(finalImage))

{

g.Clear(System.Drawing.Color.Transparent);

IsImageSet = new bool[images.Count];

count = 0; indexTop = 0; offset = 0; width = 0; height =

0; _index = 0;

int offsetX = 0;

while (count != images.Count)

{

if (count == 0)

{

// set 1st image

width = images[0].Width;

offset = MaxWidth - width;

g.DrawImage(images[0],

new System.Drawing.Rectangle(0, 0,

images[0].Width, images[0].Height));

// set cordinate into dictionary

List<int> point = new List<int>();

point.Add(0); point.Add(0);

_recordes.Add(ImageId[0], point);

//-----------------------

MarkImageAsSet(count);

count++; continue;

}

Bitmap nextFitImage = SearchNextFitImage(offset);

if (nextFitImage != null)

{

MarkImageAsSet(_index);

count++;

offsetX = MaxWidth - offset;

offset = offset - nextFitImage.Width;

if (indexTop == 0)

{

g.DrawImage(images[_index],

new System.Drawing.Rectangle(offsetX, 0,

images[_index].Width, images[_index].Height));

// set cordinate into dictionary

List<int> point = new List<int>();

point.Add(offsetX); point.Add(0);

_recordes.Add(ImageId[_index], point);

//-----------------------

}

else

{

g.DrawImage(images[_index],

new System.Drawing.Rectangle(offsetX,

height, images[_index].Width, images[_index].Height));

// set cordinate into dictionary

List<int> point = new List<int>();

point.Add(offsetX); point.Add(height);

_recordes.Add(ImageId[_index], point);

//-----------------------

}

// Cordinate(offsetX,images[indexTop].Height)

}

else

{

if (!IsImageSet[indexTop + 1])

{

height += images[indexTop].Height;

indexTop++;

offset = MaxWidth - images[indexTop].Width;

g.DrawImage(images[indexTop],

new System.Drawing.Rectangle(0, height,

images[indexTop].Width, images[indexTop].Height));

// set cordinate into dictionary

List<int> point = new List<int>();

point.Add(0); point.Add(height);

_recordes.Add(ImageId[indexTop], point);

//-----------------------

count++;

MarkImageAsSet(indexTop);

//Cordinate(0,images[indexTop].Height)

}

// find next available image

else

{

for (int i = 0; i < IsImageSet.Length; i++)

{

if (!IsImageSet[i])

{

height += images[indexTop].Height;

indexTop = i;

offset = MaxWidth - images[i].Width;

g.DrawImage(images[i],

new System.Drawing.Rectangle(0,

height, images[i].Width, images[i].Height));

// set cordinate into dictionary

List<int> point = new List<int>();

point.Add(0); point.Add(height);

_recordes.Add(ImageId[i], point);

//-----------------------

count++;

MarkImageAsSet(i);

break;

}

}

}

}

}

}

return finalImage;

}

catch (Exception ex)

{

if (finalImage != null)

finalImage.Dispose();

throw ex;

}

finally

{

//clean up memory

foreach (System.Drawing.Bitmap image in images)

{

image.Dispose();

}

}

}

}

}

No comments:

Post a Comment