/// <summary> /// Initializes a new instance of the <see cref="DynamicImage"/> struct. /// </summary> /// <param name="fileName">The file name of the image excluding any part of the path.</param> /// <param name="resizeMethod">The resize method.</param> public DynamicImage(string fileName, DynamicResizeMethod resizeMethod) { FileName = fileName; ResizeMethod = resizeMethod; }
// create a NinePatch from file public NinePatchImage(string fileName, DynamicResizeMethod DynamicResizeMethod) { if (String.IsNullOrWhiteSpace(fileName)) { _DynamicResizeMethod = DynamicResizeMethod.Tile; } else { _DynamicResizeMethod = DynamicResizeMethod; const uint BLACK_PIXEL_FULL_ALPHA = 0xFF000000; Bitmap npi = null; try { npi = new Bitmap(String.Format("{0}\\{1}", System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), fileName)); } catch (Exception ex) { throw new Exception("Bitmap could not be created from PNG. The PNG file may be missing from the container.", ex); } npi.SetResolution(72, 72); var bitmapData = npi.LockBits(new Rectangle(0, 0, npi.Width, npi.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); IntPtr dataPointer = bitmapData.Scan0; int topStart = 0; int topEnd = npi.Width; int leftStart = 0; int leftEnd = npi.Height; int bottomStart = 0; int bottomEnd = npi.Width; int rightStart = 0; int rightEnd = npi.Height; bool noPaddingSpecified = false; int centerHeight = 0; int centerWidth = 0; unsafe { // calculate top stretch line int firstPixel = npi.Width; int lastPixel = 0; uint *imagePointer = (uint *)(void *)dataPointer; for (int xx = 0; xx < npi.Width; xx++, imagePointer++) { uint thisValue = *imagePointer; if (*imagePointer == BLACK_PIXEL_FULL_ALPHA) { if (xx < firstPixel) { firstPixel = xx; } if (xx > lastPixel) { lastPixel = xx; } } } topStart = firstPixel; topEnd = lastPixel; _leftWidth = topStart - 1; _rightWidth = (npi.Width - 2) - topEnd; // assumes padding lines (-1 if not)! centerWidth = (npi.Width - 2) - (_leftWidth + _rightWidth); // calculate left side stretch line firstPixel = npi.Height; lastPixel = 0; imagePointer = (uint *)(void *)dataPointer; for (int xx = 0; xx < npi.Height; xx++, imagePointer += npi.Width) { uint thisValue = *imagePointer; if (thisValue == BLACK_PIXEL_FULL_ALPHA) { if (xx < firstPixel) { firstPixel = xx; } if (xx > lastPixel) { lastPixel = xx; } } } leftStart = firstPixel; leftEnd = lastPixel; _upperHeight = leftStart - 1; _lowerHeight = (npi.Height - 2) - leftEnd; centerHeight = (npi.Height - 2) - (_upperHeight + _lowerHeight); // calculate right side padding line firstPixel = npi.Height; lastPixel = 0; imagePointer = ((uint *)(void *)dataPointer) + (npi.Width - 1); for (int xx = 0; xx < npi.Height; xx++, imagePointer += npi.Width) { uint thisValue = *imagePointer; if (thisValue == BLACK_PIXEL_FULL_ALPHA) { if (xx < firstPixel) { firstPixel = xx; } if (xx > lastPixel) { lastPixel = xx; } } } if (lastPixel == 0) { noPaddingSpecified = true; } rightStart = firstPixel; rightEnd = lastPixel; // calculate bottom padding line firstPixel = npi.Width; lastPixel = 0; imagePointer = ((uint *)(void *)dataPointer) + (npi.Width * (npi.Height - 1)); for (int xx = 0; xx < npi.Width; xx++, imagePointer++) { uint thisValue = *imagePointer; if (*imagePointer == BLACK_PIXEL_FULL_ALPHA) { if (xx < firstPixel) { firstPixel = xx; } if (xx > lastPixel) { lastPixel = xx; } } } if (lastPixel == 0) { noPaddingSpecified = true; } bottomStart = firstPixel; bottomEnd = lastPixel; } npi.UnlockBits(bitmapData); _IsEmpty = true; // upper section bitmaps Rectangle imageRect = new Rectangle(1, 1, _leftWidth, _upperHeight); //Debug.WriteLine("Upper Left: " + imageRect.ToString()); _upperLeft = IsRect(imageRect) ? npi.Crop(imageRect) : null; if (_upperLeft != null) { _IsEmpty = false; } imageRect = new Rectangle(topStart, 1, centerWidth, _upperHeight); //Debug.WriteLine("Upper: " + imageRect.ToString()); _upper = IsRect(imageRect) ? npi.Crop(imageRect) : null; if (_upper != null) { _IsEmpty = false; } imageRect = new Rectangle(topEnd + 1, 1, _rightWidth, _upperHeight); //Debug.WriteLine("Upper Right: " + imageRect.ToString()); _upperRight = IsRect(imageRect) ? npi.Crop(imageRect) : null; if (_upperRight != null) { _IsEmpty = false; } // center section bitmaps imageRect = new Rectangle(1, leftStart, _leftWidth, centerHeight); //Debug.WriteLine("Left: " + imageRect.ToString()); _left = IsRect(imageRect) ? npi.Crop(imageRect) : null; if (_left != null) { _IsEmpty = false; } imageRect = new Rectangle(topStart, leftStart, centerWidth, centerHeight); //Debug.WriteLine("Center: " + imageRect.ToString()); _center = IsRect(imageRect) ? npi.Crop(imageRect) : null; if (_center != null) { _IsEmpty = false; } imageRect = new Rectangle(topEnd + 1, leftStart, _rightWidth, centerHeight); //Debug.WriteLine("Right: " + imageRect.ToString()); _right = IsRect(imageRect) ? npi.Crop(imageRect) : null; if (_right != null) { _IsEmpty = false; } // lower section bitmaps imageRect = new Rectangle(1, leftEnd + 1, _leftWidth, _lowerHeight); //Debug.WriteLine("Lower Left: " + imageRect.ToString()); _lowerLeft = IsRect(imageRect) ? npi.Crop(imageRect) : null; if (_lowerLeft != null) { _IsEmpty = false; } imageRect = new Rectangle(topStart, leftEnd + 1, centerWidth, _lowerHeight); //Debug.WriteLine("Lower: " + imageRect.ToString()); _lower = IsRect(imageRect) ? npi.Crop(imageRect) : null; if (_lower != null) { _IsEmpty = false; } imageRect = new Rectangle(topEnd + 1, leftEnd + 1, _rightWidth, _lowerHeight); //Debug.WriteLine("Lower Right: " + imageRect.ToString()); _lowerRight = IsRect(imageRect) ? npi.Crop(imageRect) : null; if (_lowerRight != null) { _IsEmpty = false; } #if DEBUG // Debugging code to check that the 9 images are correctly sliced out of the original image. // Writes out a [Guid.NewGuid().ToString()].png to the app container root (check bin/Debug). //Bitmap bmp = new Bitmap(_upperLeft.Width + _upper.Width + _upperRight.Width, _upperLeft.Height + _left.Height + _lowerLeft.Height); //bmp.SetResolution(72, 72); //Graphics g = Graphics.FromImage(bmp); //g.DrawImage(_upperLeft, 0, 0); //g.DrawImage(_upper, _upperLeft.Width, 0); //g.DrawImage(_upperRight, _upperLeft.Width + _upper.Width, 0); //g.DrawImage(_left, 0, _upperLeft.Height); //g.DrawImage(_center, _left.Width, _upper.Height); //g.DrawImage(_right, _left.Width + _center.Width, _upperRight.Height); //g.DrawImage(_lowerLeft, 0, _upperLeft.Height + _left.Height); //g.DrawImage(_lower, _lowerLeft.Width, _upper.Height + _center.Height); //g.DrawImage(_lowerRight, _lowerLeft.Width + _lower.Width, _upperRight.Height + _right.Height); //bmp.Save(String.Format("{0}\\{1}.png", System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), Guid.NewGuid().ToString()), System.Drawing.Imaging.ImageFormat.Png); #endif if (noPaddingSpecified) { // uses the center area defined by the top and left margins _paddingBounds = new Rectangle(_upperLeft.Width, _upperLeft.Height, _center.Width, _center.Height); } else { // uses the area defined by the bottom and right margins _paddingBounds = new Rectangle(bottomStart - 1, rightStart - 1, bottomEnd - bottomStart, rightEnd - rightStart); } //Debug.WriteLine("Content/Padding: " + _paddingBounds.ToString()); } }