c# - How to effectively crop and scale image data -
i need operate on pixel values in images. therefore wrote such class:
public class image_class { #region property public int width { get; private set; } public int height { get; private set; } byte[] buffer; #endregion #region constructors public image_class() { ; } public image_class(int width, int height, byte[] data) { if (data.count() == (width * height * 3)) { this.width = width; this.height = height; this.buffer = data; } else throw new exception(); } #endregion #region bitmap public imagesource bmp { { try { var pixelformat = pixelformats.rgb24; var bytesperpixel = (pixelformat.bitsperpixel + 7) / 8; var stride = bytesperpixel * width; var bitmap = bitmapsource.create(width, height, 96d, 96d, pixelformat, null, buffer, stride); return bitmap; } catch { return null; } } } #endregion #region methods public void load_from_file(string path) { var bmp = new bitmapimage(); bmp.begininit(); bmp.urisource = new uri(ofd.filename, urikind.absolute); bmp.endinit(); height = (int)bmp.height; width = (int)bmp.width; int stride = width * ((bmp.format.bitsperpixel + 7) / 8); int size = height * stride; var buffer2 = new byte[size]; bmp.copypixels(buffer2, stride, 0); buffer = new byte[size * 3 / 4]; (int = 0, j = 0; < size; += 4, j += 3) { buffer[j] = buffer2[i + 2]; buffer[j + 1] = buffer2[i + 1]; buffer[j + 2] = buffer2[i]; } } public void load_from_file(string path, int width, int height) { this.width = width; this.height = height; var bmp = new bitmapimage(); bmp.begininit(); bmp.decodepixelheight = height; bmp.decodepixelwidth = width; bmp.urisource = new uri(path, urikind.absolute); bmp.endinit(); int stride = width * ((bmp.format.bitsperpixel + 7) / 8); int size = height * stride; var buffer2 = new byte[size]; bmp.copypixels(buffer2, stride, 0); buffer = new byte[size * 3 / 4]; (int = 0, j = 0; < size; += 4, j += 3) { buffer[j] = buffer2[i + 2]; buffer[j + 1] = buffer2[i + 1]; buffer[j + 2] = buffer2[i]; } } public void save_to_file(string path) { var pixelformat = pixelformats.rgb24; var bytesperpixel = (pixelformat.bitsperpixel + 7) / 8; var stride = bytesperpixel * width; var encoder = new jpegbitmapencoder(); encoder.frames.add(bitmapframe.create(bitmapsource.create(width, height, 96d, 96d, pixelformat, null, buffer, stride))); filestream fs = new filestream(path, filemode.openorcreate, fileaccess.readwrite); encoder.save(fs); fs.close(); } public image_class cut(int x0, int y0, int dx, int dy) { if (x0 >= 0 & y0 >= 0 & x0 + dx <= width & y0 + dy <= height) { byte[] buffer3 = new byte[dx * dy * 3]; (int y = 0, = 0, j = -1; y < height; y++) (int x = 0; x < width; x++, += 3) if (x >= x0 & x < x0 + dx & y >= y0 & y < y0 + dy) { buffer3[++j] = buffer[i]; buffer3[++j] = buffer[i + 1]; buffer3[++j] = buffer[i + 2]; } return new image_class(dx, dy, buffer3); } else throw new exception(); } #endregion }
the buffer array 1 use.
this class works fine. when need operate on data fragment of image, use method cut, example:
image_class img1=new image_class(); image_class img2=img1.cut(5,5,20,20);
what need scale cut image other values , maintain format of pixel data. example want 50x50 square picture, scaled 20x20. do:
image_class img1=new image_class(); image_class img2=img1.cut(5,5,50,50); img2.save_to_file(path); image_class img3=new image_class(); img3.load_from_file(path, 20,20);
it works, of course uneffective. can show me better solution?
you don't need this. in order copy rectangular part source bitmap, , subsequently scale it, might use croppedbitmap
, transformedbitmap
:
bitmapsource original = ... var crop = new croppedbitmap(original, new int32rect(5, 5, 50, 50)); var result = new transformedbitmap(crop, new scaletransform(0.4, 0.4));
Comments
Post a Comment