/// <summary> /// Performs logical AND operation on this <see cref="Image"/> and the specified <see cref="Image"/>. /// </summary> /// <param name="dst">The destination <see cref="Image"/>. Can be <b>null</b>.</param> /// <param name="src">The right-side operand of this operation.</param> /// <returns> /// The destination <see cref="Image"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// <para><paramref name="src"/> is <b>null</b>.</para> /// </exception> /// <exception cref="ArgumentException"> /// The images have a different depth. /// The <see cref="Image{T}.BitsPerPixel"/> properties of <paramref name="src"/> and this <see cref="Image"/> are not the same. /// </exception> /// <remarks> /// <para> /// <paramref name="src"/> and this <see cref="Image"/> do not have to have the same width and height. /// If image sizes are different, the operation is performed in this <see cref="Image"/> upper-left corner. /// </para> /// </remarks> public Image And(Image dst, Image src) { if (src == null) { throw new ArgumentNullException(nameof(src)); } int bitsPerPixel = this.BitsPerPixel; if (src.BitsPerPixel != bitsPerPixel) { throw new ArgumentException(Properties.Resources.E_DepthNotTheSame); } int width = Math.Min(this.Width, src.Width); int height = Math.Min(this.Height, src.Height); // copy this image to destination dst = this.Copy(dst, true); ulong[] bitssrc = src.Bits; ulong[] bitsdst = dst.Bits; if (width == dst.Width && src.Stride == dst.Stride) { // operation is performed on entire image // do all lines at once Vectors.And(dst.Stride * height, bitssrc, 0, bitsdst, 0); } else { int stridesrc = src.Stride1; int stridedst = dst.Stride1; int count = width * bitsPerPixel; for (int iy = 0, possrc = 0, posdst = 0; iy < height; iy++, possrc += stridesrc, posdst += stridedst) { BitUtils.And(count, bitssrc, possrc, bitsdst, posdst); } } return(dst); }
/// <summary> /// Performs logical AND operation on a rectangular block of pixels from this <see cref="Image"/> and the specified <see cref="Image"/>. /// </summary> /// <param name="x">The x-coordinate of the upper-left corner of the destination rectangle.</param> /// <param name="y">The y-coordinate of the upper-left corner of the destination rectangle.</param> /// <param name="width">The width of the source and destination rectangles.</param> /// <param name="height">The height of the source and destination rectangles.</param> /// <param name="src">The right-side operand of this operation.</param> /// <param name="xsrc">The x-coordinate of the upper-left corner of the source rectangle.</param> /// <param name="ysrc">The y-coordinate of the upper-left corner of the source rectangle.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="src"/> is <b>null</b>. /// </exception> /// <exception cref="ArgumentException"> /// The images have a different depth. /// The <see cref="Image{T}.BitsPerPixel"/> properties of <paramref name="src"/> and this <see cref="Image"/> are not the same. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// <para>The rectangular area described by <paramref name="x"/>, <paramref name="y"/>, <paramref name="width"/> and <paramref name="height"/> is outside of this <see cref="Image"/> bounds.</para> /// <para>-or-</para> /// <para>The rectangular area described by <paramref name="xsrc"/>, <paramref name="ysrc"/>, <paramref name="width"/> and <paramref name="height"/> is outside of <paramref name="src"/> bounds.</para> /// </exception> public void And(int x, int y, int width, int height, Image src, int xsrc, int ysrc) { if (src == null) { throw new ArgumentNullException(nameof(src)); } this.ValidateArea(x, y, width, height); src.ValidateArea(xsrc, ysrc, width, height); int bitsPerPixel = this.BitsPerPixel; if (src.BitsPerPixel != bitsPerPixel) { throw new ArgumentException(Properties.Resources.E_DepthNotTheSame); } int stridedst = this.Stride1; int stridesrc = src.Stride1; ulong[] bitsdst = this.Bits; ulong[] bitssrc = src.Bits; int posdst = (y * stridedst) + (x * bitsPerPixel); int possrc = (ysrc * stridesrc) + (xsrc * bitsPerPixel); if (x == 0 && xsrc == 0 && width == this.Width && stridesrc == stridedst) { // operation is performed on entire area // do all lines at once Vectors.And(stridedst * height / 64, bitssrc, possrc / 64, bitsdst, posdst / 64); } else { int count = width * bitsPerPixel; for (int iy = 0; iy < height; iy++, possrc += stridesrc, posdst += stridedst) { BitUtils.And(count, bitssrc, possrc, bitsdst, posdst); } } }
public void BitsAndTest() { const int Size = 3 * 64; ulong[] x = new ulong[3]; ulong[] y = new ulong[3]; for (int count = 1; count < Size; count++) { for (int pos = 0; pos < count; pos++) { // shift left for (int posy = 0; posy < Size - count; posy++) { int posx = Size - count; x[0] = x[1] = x[2] = ulong.MaxValue; BitUtils.ResetBits(1, x, posx + pos); y[0] = y[1] = y[2] = ulong.MaxValue; BitUtils.And(count, x, posx, y, posy); Assert.AreEqual(posy + pos, BitUtils.BitScanZeroForward(Size, y, 0)); } // shift right for (int posx = 0; posx < Size - count; posx++) { x[0] = x[1] = x[2] = ulong.MaxValue; BitUtils.ResetBits(1, x, posx + pos); int posy = Size - count; y[0] = y[1] = y[2] = ulong.MaxValue; BitUtils.And(count, x, posx, y, posy); Assert.AreEqual(posy + pos, BitUtils.BitScanZeroForward(Size, y, 0)); } } } }
public void AndTest() { Assert.Equal <uint>(0x0, BitUtils.And(0x0, 0x0, 0x0)); Assert.Equal <uint>(0x80000008, BitUtils.And(0x80080008, 0x80000008)); Assert.Equal <uint>(0x0, BitUtils.And(Enumerable.Range(0, 32).Select(val => (uint)0x1 << val).ToArray())); }