private protected void AllocateBits(int width, int height, int bitsPerPixel) { if (width <= 0) { throw new ArgumentException(Properties.Resources.E_InvalidWidth, nameof(width)); } if (height <= 0) { throw new ArgumentException(Properties.Resources.E_InvalidHeight, nameof(height)); } if (this.Width == width && this.Height == height && this.BitsPerPixel == bitsPerPixel) { // nothing to do // already allocated return; } this.Width = width; this.Height = height; this.BitsPerPixel = bitsPerPixel; this.Stride = Image <T> .CalculateStride(width, bitsPerPixel); int length = this.Stride * height; if (this.Bits?.Length != length) { this.Bits = new T[length]; } }
public void SetColor(uint color) { if (this.BitsPerPixel == 24) { byte bcolor = (byte)(color & 0xff); if (bcolor == (byte)((color >> 8) & 0xff) && bcolor == (byte)((color >> 16) & 0xff)) { // all components are the same - set bytes unsafe { fixed(ulong *bits = this.Bits) { Vectors.Set(this.Height * this.Stride8, bcolor, (byte *)bits); } } } else { ulong[] colors = this.ColorScanline(Image.CalculateStride(this.Width, 24), color); Vectors.Tile(this.Stride, this.Height, colors, 0, this.Bits, 0); } } else { Vectors.Set(this.Bits.Length, this.ColorBits(color), this.Bits, 0); } }
public void DrawRectangle(int x, int y, int width, int height, uint color) { this.ValidateArea(x, y, width, height); if (width == 0 || height == 0) { // nothing to draw return; } ulong[] bits = this.Bits; int bitsPerPixel = this.BitsPerPixel; if (bitsPerPixel == 24) { ulong[] colors = this.ColorScanline(Image.CalculateStride(width, 24), color); int stride8 = this.Stride8; unsafe { fixed(ulong *ubits = &bits[y * this.Stride], ucolors = colors) { byte *ptrcolors = (byte *)ucolors; byte *ptrbits = (byte *)ubits + (x * 3); // draw top Vectors.Copy(width * 3, ptrcolors, ptrbits); ptrbits += stride8; // draw left and right for (int i = 1, ii = height - 1; i < ii; i++, ptrbits += stride8) { Vectors.Copy(3, ptrcolors, ptrbits); Vectors.Copy(3, ptrcolors, ptrbits + (width * 3)); } // draw bottom Vectors.Copy(width * 3, ptrcolors, ptrbits); } } } else { int stride1 = this.Stride1; ulong colorbits = this.ColorBits(color); // draw top int pos = (y * stride1) + (x * bitsPerPixel); BitUtils.SetBits(width * bitsPerPixel, colorbits, bits, pos); pos += stride1; // draw left and right int posend = pos + (width * bitsPerPixel); for (int i = 1, ii = height - 1; i < ii; i++, pos += stride1, posend += stride1) { BitUtils.SetBits(bitsPerPixel, colorbits, bits, pos); BitUtils.SetBits(bitsPerPixel, colorbits, bits, posend); } // draw bottom BitUtils.SetBits(width * bitsPerPixel, colorbits, bits, pos); } }
public void SetBorder(int x, int y, int width, int height, BorderType borderType, uint borderValue) { this.ValidateArea(x, y, width, height); if (x == 0 && y == 0 && width == this.Width && height == this.Height) { // nothing to set return; } if (borderType == BorderType.BorderRepl) { if (width == 0 || height == 0) { // if border occupies entire image - set entire image to color of the pixel at specified origin this.SetColor(this.GetPixel(x, y)); return; } ulong[] bits = this.Bits; int stride = this.Stride; int stride1 = this.Stride1; int bitsPerPixel = this.BitsPerPixel; if (bitsPerPixel == 24) { // fill left and right sides int x2 = x + width; if (x > 0 || x2 < this.Width) { unsafe { fixed(ulong *ubits = &bits[y *stride]) { byte *bbits = (byte *)ubits; for (int i = 0, count2 = this.Width - x2, stride8 = this.Stride8; i < height; i++, bbits += stride8) { if (x > 0) { Vectors.Tile(3, x, bbits + (x * 3), bbits); } if (count2 > 0) { Vectors.Tile(3, count2, bbits + (x2 * 3) - 3, bbits + (x2 * 3)); } } } } } } else { // fill left side if (x > 0) { // sets all pixels on the left to first row pixel within the area int count = x * bitsPerPixel; for (int i = y, ii = y + height, pos = y * stride1; i < ii; i++, pos += stride1) { ulong ucolor = this.ColorBits(this.GetPixel(x, i)); BitUtils.SetBits(count, ucolor, bits, pos); } } // fill right side int x2 = x + width; if (x2 < this.Width) { // sets all pixels on the left to last row pixel within the area int count = (this.Width - x2) * bitsPerPixel; for (int i = y, ii = y + height, pos = (y * stride1) + (x2 * bitsPerPixel); i < ii; i++, pos += stride1) { ulong ucolor = this.ColorBits(this.GetPixel(x2 - 1, i)); BitUtils.SetBits(count, ucolor, bits, pos); } } } // fill top if (y > 0) { // copy first area row to all rows above Vectors.Tile(stride, y, bits, y * stride, bits, 0); } // fill bottom int y2 = y + height; if (y2 < this.Height) { // copy last area row to all rows below Vectors.Tile(stride, this.Height - y2, bits, (y2 - 1) * stride, bits, y2 * stride); } } else if (borderType == BorderType.BorderConst) { if (width == 0 || height == 0) { // if border occupies entire image - set entire image to specified color this.SetColor(borderValue); return; } ulong[] bits = this.Bits; int stride = this.Stride; int bitsPerPixel = this.BitsPerPixel; if (bitsPerPixel == 24) { ulong[] colors = this.ColorScanline(Image.CalculateStride(this.Width, 24), borderValue); // fill top if (y > 0) { Vectors.Tile(stride, y, colors, 0, bits, 0); } // fill left and right int x2 = x + width; if (x > 0 || x2 < this.Width) { unsafe { fixed(ulong *ubits = &bits[y *stride], ucolors = colors) { byte *bbits = (byte *)ubits; byte *bcolors = (byte *)ucolors; for (int i = 0, count1 = x * 3, count2 = (this.Width - x2) * 3, stride8 = this.Stride8; i < height; i++, bbits += stride8) { if (count1 > 0) { Vectors.Copy(count1, bcolors, bbits); } if (count2 > 0) { Vectors.Copy(count2, bcolors + (x2 * 3), bbits + (x2 * 3)); } } } } } // fill bottom int y2 = y + height; if (y2 < this.Height) { Vectors.Tile(stride, this.Height - y2, colors, 0, bits, y2 * stride); } } else { int stride1 = this.Stride1; ulong color = this.ColorBits(borderValue); int x2 = x + width; int y2 = y + height; // fill top area and the left part of first partial stride int count = (y * stride1) + (x * bitsPerPixel); int pos = 0; if (count > 0) { BitUtils.SetBits(count, color, bits, pos); } // fill partial strides (together right part and left part of the next line) if (height > 1) { count = stride1 - (width * bitsPerPixel); if (count > 0) { pos = (y * stride1) + (x2 * bitsPerPixel); for (int i = 1; i < height; i++, pos += stride1) { BitUtils.SetBits(count, color, bits, pos); } } } // fill bottom area and the right part of last partial stride pos = ((y2 - 1) * stride1) + (x2 * bitsPerPixel); count = (this.Height * stride1) - pos; if (count > 0) { BitUtils.SetBits(count, color, bits, pos); } } } }
public void SetColor(int x, int y, int width, int height, uint color) { this.ValidateArea(x, y, width, height); if (this.BitsPerPixel == 24) { byte bcolor = (byte)(color & 0xff); if (bcolor == (byte)((color >> 8) & 0xff) && bcolor == (byte)((color >> 16) & 0xff)) { // all components are the same - set bytes unsafe { fixed(ulong *bits = &this.Bits[y * this.Stride]) { byte *bbits = (byte *)bits; if (x == 0 && width == this.Width) { // set multiple scan lines at once // if entire image width has to be set Vectors.Set(height * this.Stride8, bcolor, bbits); } else { bbits += x * 3; for (int i = 0, count = width * 3, stride8 = this.Stride8; i < height; i++, bbits += stride8) { Vectors.Set(count, bcolor, bbits); } } } } } else { ulong[] colors = this.ColorScanline(Image.CalculateStride(width, 24), color); if (x == 0 && width == this.Width) { // set multiple scan lines at once // if entire image width has to be set Vectors.Tile(this.Stride, height, colors, 0, this.Bits, y * this.Stride); } else { unsafe { fixed(ulong *bits = &this.Bits[y * this.Stride], ucolors = colors) { byte *bbits = (byte *)bits + (x * 3); byte *bcolors = (byte *)ucolors; for (int i = 0, count = width * 3, stride8 = this.Stride8; i < height; i++, bbits += stride8) { Vectors.Copy(count, bcolors, bbits); } } } } } } else { ulong colorbits = this.ColorBits(color); ulong[] bits = this.Bits; if (x == 0 && width == this.Width) { // set multiple scan lines at once // if entire image width has to be set Vectors.Set(height * this.Stride, colorbits, bits, y * this.Stride); } else { int stride1 = this.Stride1; int count = width * this.BitsPerPixel; int off = (y * stride1) + (x * this.BitsPerPixel); if (colorbits == 0) { for (int i = 0; i < height; i++, off += stride1) { BitUtils.ResetBits(count, bits, off); } } else if (colorbits == ulong.MaxValue) { for (int i = 0; i < height; i++, off += stride1) { BitUtils.SetBits(count, bits, off); } } else { for (int i = 0; i < height; i++, off += stride1) { BitUtils.SetBits(count, colorbits, bits, off); } } } } }
public void MinC(int x, int y, int width, int height, uint color) { color &= this.MaxColor; if (color == this.MaxColor) { // nothing to set return; } if (color == 0) { // set to maximum value this.SetToZero(x, y, width, height); return; } this.ValidateArea(x, y, width, height); if (width == 0 || height == 0) { // nothing to set return; } unsafe { fixed(ulong *bits = &this.Bits[y * this.Stride]) { switch (this.BitsPerPixel) { case 8: { byte *ptr = (byte *)bits + x; int stride8 = this.Stride8; if (x == 0 && width == this.Width) { Vectors.MinC(height * stride8, (byte)color, ptr); } else { for (int i = 0; i < height; i++, ptr += stride8) { Vectors.MinC(width, (byte)color, ptr); } } } break; case 16: { ushort *ptr = (ushort *)bits + x; int stride16 = this.Stride8 / sizeof(ushort); if (x == 0 && width == this.Width) { Vectors.MinC(height * stride16, (ushort)color, ptr); } else { for (int i = 0; i < height; i++, ptr += stride16) { Vectors.MinC(width, (ushort)color, ptr); } } } break; case 24: case 32: { int bytesPerPixel = this.BitsPerPixel / 8; byte *ptr = (byte *)bits + (x * bytesPerPixel); int stride8 = this.Stride8; fixed(ulong *mask = this.ColorScanline(Image.CalculateStride(width, this.BitsPerPixel), color)) { for (int i = 0, count = width * bytesPerPixel; i < height; i++, ptr += stride8) { Vectors.Min(count, (byte *)mask, ptr); } } } break; default: throw new NotSupportedException(string.Format( CultureInfo.InvariantCulture, Properties.Resources.E_UnsupportedDepth, this.BitsPerPixel)); } } } }