private static void Copy8BitDataToImage(ImageBuffer destImage, Bitmap m_WidowsBitmap) { destImage.Allocate(m_WidowsBitmap.Width, m_WidowsBitmap.Height, m_WidowsBitmap.Width * 4, 32); BitmapData bitmapData = m_WidowsBitmap.LockBits(new Rectangle(0, 0, m_WidowsBitmap.Width, m_WidowsBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, m_WidowsBitmap.PixelFormat); int sourceIndex = 0; int destIndex = 0; unsafe { int offset; byte[] destBuffer = destImage.GetBuffer(out offset); byte * pSourceBuffer = (byte *)bitmapData.Scan0; Color[] colors = m_WidowsBitmap.Palette.Entries; for (int y = 0; y < destImage.Height; y++) { sourceIndex = y * bitmapData.Stride; destIndex = destImage.GetBufferOffsetY(destImage.Height - 1 - y); for (int x = 0; x < destImage.Width; x++) { Color color = colors[pSourceBuffer[sourceIndex++]]; destBuffer[destIndex++] = color.B; destBuffer[destIndex++] = color.G; destBuffer[destIndex++] = color.R; destBuffer[destIndex++] = color.A; } } } m_WidowsBitmap.UnlockBits(bitmapData); }
public static void DoYBlur(ImageBuffer sourceDest) { if (sourceDest.BitDepth != 8) { throw new NotImplementedException("We only work with 8 bit at the moment."); } int height = sourceDest.Height; int width = sourceDest.Width; byte[] buffer = sourceDest.GetBuffer(); int strideInBytes = sourceDest.StrideInBytes(); byte[] cache = new byte[height]; for (int x = 0; x < width; x++) { int offset = x; for (int y = 0; y < height; y++) { cache[y] = buffer[offset]; offset += strideInBytes; } offset = x; for (int y = 1; y < height - 1; y++) { int newValue = (cache[y - 1] + cache[y] * 2 + cache[y + 1] + 2) / 4; // the + 2 is so that we will round correctly buffer[offset] = (byte)newValue; offset += strideInBytes; } } }
internal static void DoXBlur(ImageBuffer sourceDest) { if (sourceDest.BitDepth != 8) { throw new NotImplementedException("We only work with 8 bit at the moment."); } int height = sourceDest.Height; int width = sourceDest.Width; byte[] buffer = sourceDest.GetBuffer(); byte[] cache = new byte[width]; for (int y = 0; y < height; y++) { int offset = sourceDest.GetBufferOffsetY(y); for (int x = 0; x < width; x++) { cache[x] = buffer[offset + x]; } for (int x = 1; x < width - 1; x++) { int newValue = (cache[x - 1] + cache[x] * 2 + cache[x + 1] + 2) / 4; // the + 2 is so that we will round correctly buffer[offset + x] = (byte)newValue; } } }
public static void DoErode3x3MinValue(ImageBuffer source, ImageBuffer dest) { if (source.BitDepth != 32 || dest.BitDepth != 32) { throw new NotImplementedException("We only work with 32 bit at the moment."); } if (source.Width != dest.Width || source.Height != dest.Height) { throw new NotImplementedException("Source and Dest have to be the same size"); } int height = source.Height; int width = source.Width; int sourceStrideInBytes = source.StrideInBytes(); int destStrideInBytes = dest.StrideInBytes(); byte[] sourceBuffer = source.GetBuffer(); byte[] destBuffer = dest.GetBuffer(); // This can be made much faster by holding the buffer pointer and offsets better // LBB 2013 06 09 for (int testY = 1; testY < height - 1; testY++) { for (int testX = 1; testX < width - 1; testX++) { RGBA_Bytes minColor = RGBA_Bytes.White; int sourceOffset = source.GetBufferOffsetXY(testX, testY - 1); // x-1, y-1 //minColor = MinColor(sourceBuffer, minColor, sourceOffset - 4); // x0, y-1 minColor = MinColor(sourceBuffer, minColor, sourceOffset + 0); // x1, y-1 //minColor = MinColor(sourceBuffer, minColor, sourceOffset + 4); // x-1, y0 minColor = MinColor(sourceBuffer, minColor, sourceOffset + sourceStrideInBytes - 4); // x0, y0 minColor = MinColor(sourceBuffer, minColor, sourceOffset + sourceStrideInBytes + 0); // x+1, y0 minColor = MinColor(sourceBuffer, minColor, sourceOffset + sourceStrideInBytes + 4); // x-1, y+1 //minColor = MinColor(sourceBuffer, minColor, sourceOffset + sourceStrideInBytes * 2 - 4); // x0, y+1 minColor = MinColor(sourceBuffer, minColor, sourceOffset + sourceStrideInBytes * 2 + 0); // x+1, y+1 //minColor = MinColor(sourceBuffer, minColor, sourceOffset + sourceStrideInBytes * 2 + 4); int destOffset = dest.GetBufferOffsetXY(testX, testY); destBuffer[destOffset + 2] = minColor.red; destBuffer[destOffset + 1] = minColor.green; destBuffer[destOffset + 0] = minColor.blue; destBuffer[destOffset + 3] = 255; } } }
public static void DoDilate3x3MaxValue(ImageBuffer source, ImageBuffer dest) { if (source.BitDepth != 32 || dest.BitDepth != 32) { throw new NotImplementedException("We only work with 32 bit at the moment."); } if (source.Width != dest.Width || source.Height != dest.Height) { throw new NotImplementedException("Source and Dest have to be the same size"); } int height = source.Height; int width = source.Width; int sourceStrideInBytes = source.StrideInBytes(); int destStrideInBytes = dest.StrideInBytes(); byte[] sourceBuffer = source.GetBuffer(); byte[] destBuffer = dest.GetBuffer(); for (int testY = 1; testY < height - 1; testY++) { for (int testX = 1; testX < width - 1; testX++) { RGBA_Bytes maxColor = RGBA_Bytes.Black; int sourceOffset = source.GetBufferOffsetXY(testX, testY -1); // x-1, y-1 //maxColor = MaxColor(sourceBuffer, maxColor, sourceOffset - 4); // x0, y-1 maxColor = MaxColor(sourceBuffer, maxColor, sourceOffset + 0); // x1, y-1 //maxColor = MaxColor(sourceBuffer, maxColor, sourceOffset + 4); // x-1, y0 maxColor = MaxColor(sourceBuffer, maxColor, sourceOffset + sourceStrideInBytes - 4); // x0, y0 maxColor = MaxColor(sourceBuffer, maxColor, sourceOffset + sourceStrideInBytes + 0); // x+1, y0 maxColor = MaxColor(sourceBuffer, maxColor, sourceOffset + sourceStrideInBytes + 4); // x-1, y+1 //maxColor = MaxColor(sourceBuffer, maxColor, sourceOffset + sourceStrideInBytes * 2 - 4); // x0, y+1 maxColor = MaxColor(sourceBuffer, maxColor, sourceOffset + sourceStrideInBytes * 2 + 0); // x+1, y+1 //maxColor = MaxColor(sourceBuffer, maxColor, sourceOffset + sourceStrideInBytes * 2 + 4); int destOffset = dest.GetBufferOffsetXY(testX, testY); destBuffer[destOffset + 2] = maxColor.red; destBuffer[destOffset + 1] = maxColor.green; destBuffer[destOffset + 0] = maxColor.blue; destBuffer[destOffset + 3] = 255; } } }
public ImageBuffer(ImageBuffer sourceImage) { SetDimmensionAndFormat(sourceImage.Width, sourceImage.Height, sourceImage.StrideInBytes(), sourceImage.BitDepth, sourceImage.GetBytesBetweenPixelsInclusive(), true); int offset = sourceImage.GetBufferOffsetXY(0, 0); byte[] buffer = sourceImage.GetBuffer(); byte[] newBuffer = new byte[buffer.Length]; agg_basics.memcpy(newBuffer, offset, buffer, offset, buffer.Length - offset); SetBuffer(newBuffer, offset); SetRecieveBlender(sourceImage.GetRecieveBlender()); }
public bool FindLeastSquaresMatch(ImageBuffer imageToFind, out Vector2 bestPosition, out double bestLeastSquares, double maxError = double.MaxValue) { bestPosition = Vector2.Zero; bestLeastSquares = double.MaxValue; if (Width >= imageToFind.Width && Height >= imageToFind.Height && BitDepth == imageToFind.BitDepth) { int bytesPerPixel = BitDepth / 8; int aDistanceBetweenPixels = GetBytesBetweenPixelsInclusive(); int bDistanceBetweenPixels = imageToFind.GetBytesBetweenPixelsInclusive(); byte[] thisBuffer = GetBuffer(); byte[] containedBuffer = imageToFind.GetBuffer(); for (int matchY = 0; matchY <= Height - imageToFind.Height; matchY++) { for (int matchX = 0; matchX <= Width - imageToFind.Width; matchX++) { double currentLeastSquares = 0; for (int imageToFindY = 0; imageToFindY < imageToFind.Height; imageToFindY++) { int thisBufferOffset = GetBufferOffsetXY(matchX, matchY + imageToFindY); int imageToFindBufferOffset = imageToFind.GetBufferOffsetY(imageToFindY); for (int imageToFindX = 0; imageToFindX < imageToFind.Width; imageToFindX++) { for (int byteIndex = 0; byteIndex < bytesPerPixel; byteIndex++) { byte aByte = thisBuffer[thisBufferOffset + byteIndex]; byte bByte = containedBuffer[imageToFindBufferOffset + byteIndex]; int difference = (int)aByte - (int)bByte; currentLeastSquares += difference * difference; } thisBufferOffset += aDistanceBetweenPixels; imageToFindBufferOffset += bDistanceBetweenPixels; } if (currentLeastSquares > maxError) { // stop checking we have too much error. imageToFindY = imageToFind.Height; } } if (currentLeastSquares < bestLeastSquares) { bestPosition = new Vector2(matchX, matchY); bestLeastSquares = currentLeastSquares; } } } } return(bestLeastSquares <= maxError); }
public bool Contains(ImageBuffer imageToFind, out int matchX, out int matchY, int maxError = 0) { matchX = 0; matchY = 0; if (Width >= imageToFind.Width && Height >= imageToFind.Height && BitDepth == imageToFind.BitDepth) { int bytesPerPixel = BitDepth / 8; int aDistanceBetweenPixels = GetBytesBetweenPixelsInclusive(); int bDistanceBetweenPixels = imageToFind.GetBytesBetweenPixelsInclusive(); byte[] thisBuffer = GetBuffer(); byte[] containedBuffer = imageToFind.GetBuffer(); for (matchY = 0; matchY <= Height - imageToFind.Height; matchY++) { for (matchX = 0; matchX <= Width - imageToFind.Width; matchX++) { bool foundBadMatch = false; for (int imageToFindY = 0; imageToFindY < imageToFind.Height; imageToFindY++) { int thisBufferOffset = GetBufferOffsetXY(matchX, matchY + imageToFindY); int imageToFindBufferOffset = imageToFind.GetBufferOffsetY(imageToFindY); for (int imageToFindX = 0; imageToFindX < imageToFind.Width; imageToFindX++) { for (int byteIndex = 0; byteIndex < bytesPerPixel; byteIndex++) { byte aByte = thisBuffer[thisBufferOffset + byteIndex]; byte bByte = containedBuffer[imageToFindBufferOffset + byteIndex]; if (aByte < (bByte - maxError) || aByte > (bByte + maxError)) { foundBadMatch = true; byteIndex = bytesPerPixel; imageToFindX = imageToFind.Width; imageToFindY = imageToFind.Height; } } thisBufferOffset += aDistanceBetweenPixels; imageToFindBufferOffset += bDistanceBetweenPixels; } } if (!foundBadMatch) { return(true); } } } } return(false); }
public static void DoSubtract(ImageBuffer result, ImageBuffer imageToSubtractFrom, ImageBuffer imageToSubtract) { if (lookupSubtractAndClamp == null) { CreateLookup(); } if (imageToSubtractFrom.BitDepth != imageToSubtract.BitDepth || imageToSubtract.BitDepth != result.BitDepth) { throw new NotImplementedException("All the images have to be the same bit depth."); } if (imageToSubtractFrom.Width != imageToSubtract.Width || imageToSubtractFrom.Height != imageToSubtract.Height || imageToSubtractFrom.Width != result.Width || imageToSubtractFrom.Height != result.Height) { throw new Exception("All images must be the same size."); } switch (imageToSubtractFrom.BitDepth) { case 32: { int height = imageToSubtractFrom.Height; int width = imageToSubtractFrom.Width; byte[] resultBuffer = result.GetBuffer(); byte[] imageABuffer = imageToSubtractFrom.GetBuffer(); byte[] imageBBuffer = imageToSubtract.GetBuffer(); for (int y = 0; y < height; y++) { int offset = imageToSubtractFrom.GetBufferOffsetY(y); for (int x = 0; x < width; x++) { resultBuffer[offset] = (byte)lookupSubtractAndClamp[imageABuffer[offset] - imageBBuffer[offset] + 255]; // add 255 to make sure not < 0 offset++; resultBuffer[offset] = (byte)lookupSubtractAndClamp[imageABuffer[offset] - imageBBuffer[offset] + 255]; offset++; resultBuffer[offset] = (byte)lookupSubtractAndClamp[imageABuffer[offset] - imageBBuffer[offset] + 255]; offset++; resultBuffer[offset] = 255; offset++; } } } break; default: throw new NotImplementedException(); } }
public static void DoThreshold(ImageBuffer result, ImageBuffer sourceImage, int threshold, TestThreshold testFunction) { if (sourceImage.BitDepth != result.BitDepth) { throw new NotImplementedException("All the images have to be the same bit depth."); } if (sourceImage.Width != result.Width || sourceImage.Height != result.Height) { throw new Exception("All images must be the same size."); } switch (sourceImage.BitDepth) { case 32: { int height = sourceImage.Height; int width = sourceImage.Width; byte[] resultBuffer = result.GetBuffer(); byte[] sourceBuffer = sourceImage.GetBuffer(); for (int y = 0; y < height; y++) { int offset = sourceImage.GetBufferOffsetY(y); for (int x = 0; x < width; x++) { if (testFunction(sourceBuffer, offset, threshold)) { resultBuffer[offset + 0] = (byte)255; resultBuffer[offset + 1] = (byte)255; resultBuffer[offset + 2] = (byte)255; resultBuffer[offset + 3] = (byte)255; } else { resultBuffer[offset + 0] = (byte)0; resultBuffer[offset + 1] = (byte)0; resultBuffer[offset + 2] = (byte)0; resultBuffer[offset + 3] = (byte)0; } offset += 4; } } } break; default: throw new NotImplementedException(); } }
public static void DoInvertLightness(ImageBuffer result, ImageBuffer sourceImage) { if (sourceImage.BitDepth != result.BitDepth) { throw new NotImplementedException("All the images have to be the same bit depth."); } if (sourceImage.Width != result.Width || sourceImage.Height != result.Height) { throw new Exception("All images must be the same size."); } switch (sourceImage.BitDepth) { case 32: { int height = sourceImage.Height; int width = sourceImage.Width; byte[] resultBuffer = result.GetBuffer(); byte[] sourceBuffer = sourceImage.GetBuffer(); for (int y = 0; y < height; y++) { int offset = sourceImage.GetBufferOffsetY(y); for (int x = 0; x < width; x++) { RGBA_Bytes color = new RGBA_Bytes(resultBuffer[offset + 2], resultBuffer[offset + 1], resultBuffer[offset + 0], resultBuffer[offset + 3]); RGBA_Bytes invertedColor = InvertColor(color); resultBuffer[offset + 0] = invertedColor.blue; resultBuffer[offset + 1] = invertedColor.green; resultBuffer[offset + 2] = invertedColor.blue; resultBuffer[offset + 3] = invertedColor.alpha; offset += 4; } } } break; default: throw new NotImplementedException(); } }
public static void DoMultiply(ImageBuffer result, ImageBuffer imageA, ImageBuffer imageB) { if (imageA.BitDepth != imageB.BitDepth || imageB.BitDepth != result.BitDepth) { throw new NotImplementedException("All the images have to be the same bit depth."); } if (imageA.Width != imageB.Width || imageA.Height != imageB.Height || imageA.Width != result.Width || imageA.Height != result.Height) { throw new Exception("All images must be the same size."); } switch (imageA.BitDepth) { case 32: { int height = imageA.Height; int width = imageA.Width; byte[] resultBuffer = result.GetBuffer(); byte[] imageABuffer = imageA.GetBuffer(); byte[] imageBBuffer = imageB.GetBuffer(); for (int y = 0; y < height; y++) { int offsetA = imageA.GetBufferOffsetY(y); int offsetB = imageB.GetBufferOffsetY(y); int offsetResult = result.GetBufferOffsetY(y); for (int x = 0; x < width; x++) { resultBuffer[offsetResult++] = (byte)((imageABuffer[offsetA++] * imageBBuffer[offsetB++]) / 255); resultBuffer[offsetResult++] = (byte)((imageABuffer[offsetA++] * imageBBuffer[offsetB++]) / 255); resultBuffer[offsetResult++] = (byte)((imageABuffer[offsetA++] * imageBBuffer[offsetB++]) / 255); resultBuffer[offsetResult++] = 255; offsetA++; offsetB++; } } } break; default: throw new NotImplementedException(); } }
public void CompareToLionTGA() { LionShape lionShape = new LionShape(); ImageBuffer renderedImage = new ImageBuffer(512, 400, 24, new BlenderBGR()); byte alpha = (byte)(.1 * 255); for (int i = 0; i < lionShape.NumPaths; i++) { lionShape.Colors[i].Alpha0To255 = alpha; } Affine transform = Affine.NewIdentity(); transform *= Affine.NewTranslation(-lionShape.Center.x, -lionShape.Center.y); transform *= Affine.NewTranslation(renderedImage.Width / 2, renderedImage.Height / 2); // This code renders the lion: VertexSourceApplyTransform transformedPathStorage = new VertexSourceApplyTransform(lionShape.Path, transform); Graphics2D renderer = renderedImage.NewGraphics2D(); renderer.Clear(new RGBA_Floats(1.0, 1.0, 1.0, 1.0)); renderer.Render(transformedPathStorage, lionShape.Colors, lionShape.PathIndex, lionShape.NumPaths); ImageTgaIO.Save(renderedImage, "TestOutput.tga"); Stream imageStream = File.Open("LionRenderMaster.tga", FileMode.Open); ImageBuffer masterImage = new ImageBuffer(); ImageTgaIO.LoadImageData(masterImage, imageStream, 24); bool sameWidth = masterImage.Width == renderedImage.Width; bool sameHeight = masterImage.Height == renderedImage.Height; Assert.IsTrue(sameWidth && sameHeight); Assert.IsTrue(masterImage.BitDepth == renderedImage.BitDepth); int unused; byte[] masterBuffer = masterImage.GetBuffer(out unused); byte[] renderedBuffer = renderedImage.GetBuffer(out unused); Assert.IsTrue(masterBuffer.Length == renderedBuffer.Length); for (int i = 0; i < masterBuffer.Length; i++) { if (masterBuffer[i] != renderedBuffer[i]) { Assert.IsTrue(false); } } }
public static void DoDilate3x3Binary(ImageBuffer source, ImageBuffer dest, int threshold) { if (source.BitDepth != 32 || dest.BitDepth != 32) { throw new NotImplementedException("We only work with 32 bit at the moment."); } if (source.Width != dest.Width || source.Height != dest.Height) { throw new NotImplementedException("Source and Dest have to be the same size"); } int height = source.Height; int width = source.Width; int sourceStrideInBytes = source.StrideInBytes(); int destStrideInBytes = dest.StrideInBytes(); byte[] sourceBuffer = source.GetBuffer(); byte[] destBuffer = dest.GetBuffer(); for (int testY = 1; testY < height-1; testY++) { for (int testX = 1; testX < width - 1; testX++) { for (int sourceY = -1; sourceY <= 1; sourceY++) { for (int sourceX = -1; sourceX <= 1; sourceX++) { int sourceOffset = source.GetBufferOffsetXY(testX + sourceX, testY + sourceY); if (sourceBuffer[sourceOffset] > threshold) { int destOffset = dest.GetBufferOffsetXY(testX, testY); destBuffer[destOffset++] = 255; destBuffer[destOffset++] = 255; destBuffer[destOffset++] = 255; destBuffer[destOffset++] = 255; } } } } } }
public static void DoWhiteToColor(ImageBuffer result, ImageBuffer imageA, RGBA_Bytes color) { if (imageA.BitDepth != result.BitDepth) { throw new NotImplementedException("All the images have to be the same bit depth."); } if (imageA.Width != result.Width || imageA.Height != result.Height) { throw new Exception("All images must be the same size."); } switch (imageA.BitDepth) { case 32: { int height = imageA.Height; int width = imageA.Width; byte[] resultBuffer = result.GetBuffer(); byte[] imageABuffer = imageA.GetBuffer(); for (int y = 0; y < height; y++) { int offsetA = imageA.GetBufferOffsetY(y); int offsetResult = result.GetBufferOffsetY(y); byte amoutOfWhite = imageABuffer[offsetA]; for (int x = 0; x < width; x++) { resultBuffer[offsetResult++] = (byte)(color.blue * amoutOfWhite / 255); offsetA++; resultBuffer[offsetResult++] = (byte)(color.green * amoutOfWhite / 255); offsetA++; resultBuffer[offsetResult++] = (byte)(color.red * amoutOfWhite / 255); offsetA++; resultBuffer[offsetResult++] = imageABuffer[offsetA++]; } } } break; default: throw new NotImplementedException(); } }
public bool Equals(ImageBuffer b, int maxError = 0) { if (Width == b.Width && Height == b.Height && BitDepth == b.BitDepth && StrideInBytes() == b.StrideInBytes() && m_OriginOffset == b.m_OriginOffset) { int bytesPerPixel = BitDepth / 8; int aDistanceBetweenPixels = GetBytesBetweenPixelsInclusive(); int bDistanceBetweenPixels = b.GetBytesBetweenPixelsInclusive(); byte[] aBuffer = GetBuffer(); byte[] bBuffer = b.GetBuffer(); for (int y = 0; y < Height; y++) { int aBufferOffset = GetBufferOffsetY(y); int bBufferOffset = b.GetBufferOffsetY(y); for (int x = 0; x < Width; x++) { for (int byteIndex = 0; byteIndex < bytesPerPixel; byteIndex++) { byte aByte = aBuffer[aBufferOffset + byteIndex]; byte bByte = bBuffer[bBufferOffset + byteIndex]; if (aByte < (bByte - maxError) || aByte > (bByte + maxError)) { return(false); } } aBufferOffset += aDistanceBetweenPixels; bBufferOffset += bDistanceBetweenPixels; } } return(true); } return(false); }
private static int LowLevelReadTGABitsFromBuffer(ImageBuffer imageToReadTo, byte[] wholeFileBuffer, int DestBitDepth) { STargaHeader TargaHeader = new STargaHeader(); int FileReadOffset; if (!ReadTGAInfo(wholeFileBuffer, out TargaHeader)) { return(0); } // if the frame we are loading is different then the one we have allocated // or we don't have any bits allocated if ((imageToReadTo.Width * imageToReadTo.Height) != (TargaHeader.Width * TargaHeader.Height)) { imageToReadTo.Allocate(TargaHeader.Width, TargaHeader.Height, TargaHeader.Width * DestBitDepth / 8, DestBitDepth); } // work out the line width switch (imageToReadTo.BitDepth) { case 24: TGABytesPerLine = imageToReadTo.Width * 3; if (imageToReadTo.GetRecieveBlender() == null) { imageToReadTo.SetRecieveBlender(new BlenderBGR()); } break; case 32: TGABytesPerLine = imageToReadTo.Width * 4; if (imageToReadTo.GetRecieveBlender() == null) { imageToReadTo.SetRecieveBlender(new BlenderBGRA()); } break; default: throw new System.Exception("Bad bit depth."); } if (TGABytesPerLine > 0) { byte[] BufferToDecompressTo = null; FileReadOffset = TargaHeaderSize + TargaHeader.PostHeaderSkip; if (TargaHeader.ImageType == 10) // 10 is RLE compressed { BufferToDecompressTo = new byte[TGABytesPerLine * 2]; } // read all the lines * for (int i = 0; i < imageToReadTo.Height; i++) { byte[] BufferToCopyFrom; int CopyOffset = 0; int CurReadLine; // bit 5 tells us if the image is stored top to bottom or bottom to top if ((TargaHeader.Descriptor & 0x20) != 0) { // bottom to top CurReadLine = imageToReadTo.Height - i - 1; } else { // top to bottom CurReadLine = i; } if (TargaHeader.ImageType == 10) // 10 is RLE compressed { FileReadOffset = Decompress(BufferToDecompressTo, wholeFileBuffer, FileReadOffset, imageToReadTo.Width, TargaHeader.BPP, CurReadLine); BufferToCopyFrom = BufferToDecompressTo; } else { BufferToCopyFrom = wholeFileBuffer; CopyOffset = FileReadOffset; } int bufferOffset; byte[] imageBuffer = imageToReadTo.GetBuffer(out bufferOffset); switch (imageToReadTo.BitDepth) { case 8: switch (TargaHeader.BPP) { case 24: Do24To8Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; case 32: Do32To8Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; } break; case 24: switch (TargaHeader.BPP) { case 24: Do24To24Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; case 32: Do32To24Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; } break; case 32: switch (TargaHeader.BPP) { case 24: Do24To32Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; case 32: Do32To32Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; } break; default: throw new System.Exception("Bad bit depth"); } if (TargaHeader.ImageType != 10) // 10 is RLE compressed { FileReadOffset += TGABytesPerLine; } } } return(TargaHeader.Width); }
internal void UpdateImageBuffer(ImageBuffer destImageBuffer, Bitmap sourceBitmap) { BitmapData bitmapData = null; bool isLocked = false; if (destImageBuffer != null) { if (!isLocked) { bitmapData = sourceBitmap.LockBits(new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, sourceBitmap.PixelFormat); } int destBufferStrideInBytes = destImageBuffer.StrideInBytes(); int destBufferHeight = destImageBuffer.Height; int destBufferWidth = destImageBuffer.Width; int destBufferHeightMinusOne = destBufferHeight - 1; int bitmapDataStride = bitmapData.Stride; int offset; byte[] buffer = destImageBuffer.GetBuffer(out offset); if (flipY) { unsafe { byte* bitmapDataScan0 = (byte*)bitmapData.Scan0; fixed (byte* pDestFixed = &buffer[offset]) { byte* pSource = bitmapDataScan0; for (int y = 0; y < destBufferHeight; y++) { byte* pDest = pDestFixed + destBufferStrideInBytes * (destBufferHeight - 1 - y); for (int x = 0; x < destBufferWidth; x++) { pDest[x * 4 + 0] = pSource[x * 3 + 0]; pDest[x * 4 + 1] = pSource[x * 3 + 1]; pDest[x * 4 + 2] = pSource[x * 3 + 2]; pDest[x * 4 + 3] = 255; } pSource += bitmapDataStride; } } } } else { unsafe { byte* bitmapDataScan0 = (byte*)bitmapData.Scan0; fixed (byte* pDestFixed = &buffer[offset]) { byte* pSource = bitmapDataScan0; for (int y = 0; y < destBufferHeight; y++) { byte* pDest = pDestFixed + destBufferStrideInBytes * (y); for (int x = 0; x < destBufferWidth; x++) { pDest[x * 4 + 0] = pSource[x * 3 + 0]; pDest[x * 4 + 1] = pSource[x * 3 + 1]; pDest[x * 4 + 2] = pSource[x * 3 + 2]; pDest[x * 4 + 3] = 255; } pSource += bitmapDataStride; } } } } if (!isLocked) { sourceBitmap.UnlockBits(bitmapData); } } }
public static ImageBuffer GetCurrentScreen() { ImageBuffer screenCapture = new ImageBuffer(); Size sz = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Size; IntPtr hDesk = GetDesktopWindow(); IntPtr hSrce = GetWindowDC(hDesk); IntPtr hDest = CreateCompatibleDC(hSrce); IntPtr hBmp = CreateCompatibleBitmap(hSrce, sz.Width, sz.Height); IntPtr hOldBmp = SelectObject(hDest, hBmp); bool b = BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, 0, 0, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt); Bitmap bmpScreenCapture = Bitmap.FromHbitmap(hBmp); SelectObject(hDest, hOldBmp); DeleteObject(hBmp); DeleteDC(hDest); ReleaseDC(hDesk, hSrce); //bmpScreenCapture.Save("bitmapsave.png"); screenCapture = new ImageBuffer(bmpScreenCapture.Width, bmpScreenCapture.Height, 32, new BlenderBGRA()); BitmapData bitmapData = bmpScreenCapture.LockBits(new Rectangle(0, 0, bmpScreenCapture.Width, bmpScreenCapture.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmpScreenCapture.PixelFormat); int offset; byte[] buffer = screenCapture.GetBuffer(out offset); int bitmapDataStride = bitmapData.Stride; int backBufferStrideInBytes = screenCapture.StrideInBytes(); int backBufferHeight = screenCapture.Height; int backBufferHeightMinusOne = backBufferHeight - 1; unsafe { byte* bitmapDataScan0 = (byte*)bitmapData.Scan0; fixed (byte* pSourceFixed = &buffer[offset]) { byte* pSource = bitmapDataScan0 + bitmapDataStride * backBufferHeightMinusOne; byte* pDestBuffer = pSourceFixed; for (int y = 0; y < screenCapture.Height; y++) { int* pSourceInt = (int*)pSource; pSourceInt -= (bitmapDataStride * y / 4); int* pDestBufferInt = (int*)pDestBuffer; pDestBufferInt += (backBufferStrideInBytes * y / 4); for (int x = 0; x < screenCapture.Width; x++) { pDestBufferInt[x] = pSourceInt[x]; } } } } bmpScreenCapture.UnlockBits(bitmapData); bmpScreenCapture.Dispose(); return screenCapture; }
//圆形 public static CCSprite CreateEllipse( double width, double height, CCColor4B fill, CCColor4B stroke, double strokeThickness = 1 ) { ImageBuffer buffer = new ImageBuffer((int)width, (int)height, 32, new BlenderRGBA()); Graphics2D g = buffer.NewGraphics2D(); MatterHackers.Agg.VertexSource.Ellipse path; if (stroke.A > 0) //有border { //border是以线的中间对齐,所以转换成int,如果是1个像素,正好变成零 int halfThickness = (int)(strokeThickness / 2); path = new MatterHackers.Agg.VertexSource.Ellipse(width / 2, height / 2, width / 2 - halfThickness, height / 2 - halfThickness); } else { path = new MatterHackers.Agg.VertexSource.Ellipse(width / 2, height / 2, width / 2, height / 2); } if (fill.A > 0) g.Render(path, new RGBA_Bytes(fill.R, fill.G, fill.B, fill.A)); if (stroke.A > 0) g.Render(new Stroke(path, strokeThickness), new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A)); Texture2D xnaTexture = XnaTexture((int)width, (int)height); xnaTexture.SetData<byte>(buffer.GetBuffer()); CCTexture2D ccTexture = new CCTexture2D(); ccTexture.InitWithTexture(xnaTexture); return new CCSprite(ccTexture); }
//矩形 public static CCSprite CreateRectangle( double width, double height, double radiusX, double radiusY, CCColor4B fill, CCColor4B stroke, double strokeThickness = 1 ) { ImageBuffer buffer = new ImageBuffer((int)width, (int)height, 32, new BlenderRGBA()); Graphics2D g = buffer.NewGraphics2D(); RoundedRect path; if (stroke.A > 0) //有border { //border是以线的中间对齐,所以转换成int,如果是1个像素,正好变成零 int halfThickness = (int)(strokeThickness / 2); path = new RoundedRect(halfThickness, halfThickness, width - halfThickness, height - halfThickness, Math.Min(radiusX, radiusY)); } else { path = new RoundedRect(0, 0, width, height, Math.Min(radiusX, radiusY)); } if (fill.A > 0) g.Render(path, new RGBA_Bytes(fill.R, fill.G, fill.B, fill.A)); if (stroke.A > 0) g.Render(new Stroke(path, strokeThickness), new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A)); Texture2D xnaTexture = XnaTexture((int)width, (int)height); xnaTexture.SetData<byte>(buffer.GetBuffer()); CCTexture2D ccTexture = new CCTexture2D(); ccTexture.InitWithTexture(xnaTexture); return new CCSprite(ccTexture); }
public bool FindLeastSquaresMatch(ImageBuffer imageToFind, out Vector2 bestPosition, out double bestLeastSquares, double maxError = double.MaxValue) { bestPosition = Vector2.Zero; bestLeastSquares = double.MaxValue; if (Width >= imageToFind.Width && Height >= imageToFind.Height && BitDepth == imageToFind.BitDepth) { int bytesPerPixel = BitDepth / 8; int aDistanceBetweenPixels = GetBytesBetweenPixelsInclusive(); int bDistanceBetweenPixels = imageToFind.GetBytesBetweenPixelsInclusive(); byte[] thisBuffer = GetBuffer(); byte[] containedBuffer = imageToFind.GetBuffer(); for (int matchY = 0; matchY <= Height - imageToFind.Height; matchY++) { for (int matchX = 0; matchX <= Width - imageToFind.Width; matchX++) { double currentLeastSquares = 0; for (int imageToFindY = 0; imageToFindY < imageToFind.Height; imageToFindY++) { int thisBufferOffset = GetBufferOffsetXY(matchX, matchY + imageToFindY); int imageToFindBufferOffset = imageToFind.GetBufferOffsetY(imageToFindY); for (int imageToFindX = 0; imageToFindX < imageToFind.Width; imageToFindX++) { for (int byteIndex = 0; byteIndex < bytesPerPixel; byteIndex++) { byte aByte = thisBuffer[thisBufferOffset + byteIndex]; byte bByte = containedBuffer[imageToFindBufferOffset + byteIndex]; int difference = (int)aByte - (int)bByte; currentLeastSquares += difference * difference; } thisBufferOffset += aDistanceBetweenPixels; imageToFindBufferOffset += bDistanceBetweenPixels; if (currentLeastSquares > maxError) { // stop checking we have too much error. imageToFindX = imageToFind.Width; imageToFindY = imageToFind.Height; } } } if (currentLeastSquares < bestLeastSquares) { bestPosition = new Vector2(matchX, matchY); bestLeastSquares = currentLeastSquares; if (maxError > currentLeastSquares) { maxError = currentLeastSquares; if (currentLeastSquares == 0) { return true; } } } } } } return bestLeastSquares <= maxError; }
internal static bool ConvertBitmapToImage(ImageBuffer destImage, Bitmap m_WidowsBitmap) { if (m_WidowsBitmap != null) { switch (m_WidowsBitmap.PixelFormat) { case System.Drawing.Imaging.PixelFormat.Format32bppArgb: { destImage.Allocate(m_WidowsBitmap.Width, m_WidowsBitmap.Height, m_WidowsBitmap.Width * 4, 32); if (destImage.GetRecieveBlender() == null) { destImage.SetRecieveBlender(new BlenderBGRA()); } BitmapData bitmapData = m_WidowsBitmap.LockBits(new Rectangle(0, 0, m_WidowsBitmap.Width, m_WidowsBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, m_WidowsBitmap.PixelFormat); int sourceIndex = 0; int destIndex = 0; unsafe { int offset; byte[] destBuffer = destImage.GetBuffer(out offset); byte * pSourceBuffer = (byte *)bitmapData.Scan0; for (int y = 0; y < destImage.Height; y++) { destIndex = destImage.GetBufferOffsetXY(0, destImage.Height - 1 - y); for (int x = 0; x < destImage.Width; x++) { #if true destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; #else RGBA_Bytes notPreMultiplied = new RGBA_Bytes(pSourceBuffer[sourceIndex + 0], pSourceBuffer[sourceIndex + 1], pSourceBuffer[sourceIndex + 2], pSourceBuffer[sourceIndex + 3]); sourceIndex += 4; RGBA_Bytes preMultiplied = notPreMultiplied.GetAsRGBA_Floats().premultiply().GetAsRGBA_Bytes(); destBuffer[destIndex++] = preMultiplied.blue; destBuffer[destIndex++] = preMultiplied.green; destBuffer[destIndex++] = preMultiplied.red; destBuffer[destIndex++] = preMultiplied.alpha; #endif } } } m_WidowsBitmap.UnlockBits(bitmapData); return(true); } case System.Drawing.Imaging.PixelFormat.Format24bppRgb: { destImage.Allocate(m_WidowsBitmap.Width, m_WidowsBitmap.Height, m_WidowsBitmap.Width * 4, 32); BitmapData bitmapData = m_WidowsBitmap.LockBits(new Rectangle(0, 0, m_WidowsBitmap.Width, m_WidowsBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, m_WidowsBitmap.PixelFormat); int sourceIndex = 0; int destIndex = 0; unsafe { int offset; byte[] destBuffer = destImage.GetBuffer(out offset); byte * pSourceBuffer = (byte *)bitmapData.Scan0; for (int y = 0; y < destImage.Height; y++) { sourceIndex = y * bitmapData.Stride; destIndex = destImage.GetBufferOffsetXY(0, destImage.Height - 1 - y); for (int x = 0; x < destImage.Width; x++) { destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = 255; } } } m_WidowsBitmap.UnlockBits(bitmapData); return(true); } case System.Drawing.Imaging.PixelFormat.Format8bppIndexed: { Copy8BitDataToImage(destImage, m_WidowsBitmap); return(true); } default: throw new System.NotImplementedException(); } } return(false); }
public bool Equals(ImageBuffer b, int maxError = 0) { if (Width == b.Width && Height == b.Height && BitDepth == b.BitDepth && StrideInBytes() == b.StrideInBytes() && m_OriginOffset == b.m_OriginOffset) { int bytesPerPixel = BitDepth / 8; int aDistanceBetweenPixels = GetBytesBetweenPixelsInclusive(); int bDistanceBetweenPixels = b.GetBytesBetweenPixelsInclusive(); byte[] aBuffer = GetBuffer(); byte[] bBuffer = b.GetBuffer(); for (int y = 0; y < Height; y++) { int aBufferOffset = GetBufferOffsetY(y); int bBufferOffset = b.GetBufferOffsetY(y); for (int x = 0; x < Width; x++) { for (int byteIndex = 0; byteIndex < bytesPerPixel; byteIndex++) { byte aByte = aBuffer[aBufferOffset + byteIndex]; byte bByte = bBuffer[bBufferOffset + byteIndex]; if (aByte < (bByte - maxError) || aByte > (bByte + maxError)) { return false; } } aBufferOffset += aDistanceBetweenPixels; bBufferOffset += bDistanceBetweenPixels; } } return true; } return false; }
public bool Contains(ImageBuffer imageToFind, out int matchX, out int matchY, int maxError = 0) { matchX = 0; matchY = 0; if (Width >= imageToFind.Width && Height >= imageToFind.Height && BitDepth == imageToFind.BitDepth) { int bytesPerPixel = BitDepth / 8; int aDistanceBetweenPixels = GetBytesBetweenPixelsInclusive(); int bDistanceBetweenPixels = imageToFind.GetBytesBetweenPixelsInclusive(); byte[] thisBuffer = GetBuffer(); byte[] containedBuffer = imageToFind.GetBuffer(); for (matchY = 0; matchY <= Height - imageToFind.Height; matchY++) { for (matchX = 0; matchX <= Width - imageToFind.Width; matchX++) { bool foundBadMatch = false; for (int imageToFindY = 0; imageToFindY < imageToFind.Height; imageToFindY++) { int thisBufferOffset = GetBufferOffsetXY(matchX, matchY + imageToFindY); int imageToFindBufferOffset = imageToFind.GetBufferOffsetY(imageToFindY); for (int imageToFindX = 0; imageToFindX < imageToFind.Width; imageToFindX++) { for (int byteIndex = 0; byteIndex < bytesPerPixel; byteIndex++) { byte aByte = thisBuffer[thisBufferOffset + byteIndex]; byte bByte = containedBuffer[imageToFindBufferOffset + byteIndex]; if (aByte < (bByte - maxError) || aByte > (bByte + maxError)) { foundBadMatch = true; byteIndex = bytesPerPixel; imageToFindX = imageToFind.Width; imageToFindY = imageToFind.Height; } } thisBufferOffset += aDistanceBetweenPixels; imageToFindBufferOffset += bDistanceBetweenPixels; } } if (!foundBadMatch) { return true; } } } } return false; }
public static CCSprite CreateLine( int width, int height, CCColor4B stroke, double strokeThickness = 1 ) { ImageBuffer buffer = new ImageBuffer(width, height, 32, new BlenderRGBA()); Graphics2D g = buffer.NewGraphics2D(); if (stroke.A > 0) { //g.Line没有厚度 PathStorage linesToDraw = new PathStorage(); linesToDraw.remove_all(); linesToDraw.MoveTo(0, 0); linesToDraw.LineTo(width, height); Stroke StrockedLineToDraw = new Stroke(linesToDraw, strokeThickness); g.Render(StrockedLineToDraw, new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A)); } Texture2D xnaTexture = XnaTexture((int)width, (int)height); xnaTexture.SetData<byte>(buffer.GetBuffer()); CCTexture2D ccTexture = new CCTexture2D(); ccTexture.InitWithTexture(xnaTexture); return new CCSprite(ccTexture); }
static public ImageGlPlugin GetImageGlPlugin(ImageBuffer imageToGetDisplayListFor, bool createAndUseMipMaps, bool TextureMagFilterLinear = true) { ImageGlPlugin plugin; imagesWithCacheData.TryGetValue(imageToGetDisplayListFor.GetBuffer(), out plugin); using (TimedLock.Lock(glDataNeedingToBeDeleted, "GetImageGlPlugin")) { // We run this in here to ensure that we are on the correct thread and have the correct // glcontext realized. for (int i = glDataNeedingToBeDeleted.Count - 1; i >= 0; i--) { int textureToDelete = glDataNeedingToBeDeleted[i].glTextureHandle; if (glDataNeedingToBeDeleted[i].refreshCountCreatedOn == currentGlobalRefreshCount) { GL.DeleteTextures(1, ref textureToDelete); } glDataNeedingToBeDeleted.RemoveAt(i); } } #if ON_IMAGE_CHANGED_ALWAYS_CREATE_IMAGE if (plugin != null && (imageToGetDisplayListFor.ChangedCount != plugin.imageUpdateCount || plugin.glData.refreshCountCreatedOn != currentGlobalRefreshCount)) { int textureToDelete = plugin.GLTextureHandle; if (plugin.glData.refreshCountCreatedOn == currentGlobalRefreshCount) { GL.DeleteTextures(1, ref textureToDelete); } plugin.glData.glTextureHandle = 0; imagesWithCacheData.Remove(imageToGetDisplayListFor.GetBuffer()); plugin = null; } if (plugin == null) { ImageGlPlugin newPlugin = new ImageGlPlugin(); imagesWithCacheData.Add(imageToGetDisplayListFor.GetBuffer(), newPlugin); newPlugin.createdWithMipMaps = createAndUseMipMaps; newPlugin.CreateGlDataForImage(imageToGetDisplayListFor, TextureMagFilterLinear); newPlugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount; newPlugin.glData.refreshCountCreatedOn = currentGlobalRefreshCount; return newPlugin; } #else if (plugin == null) { ImageGlPlugin newPlugin = new ImageGlPlugin(); imagesWithCacheData.Add(imageToGetDisplayListFor.GetBuffer(), newPlugin); newPlugin.createdWithMipMaps = createAndUseMipMaps; newPlugin.CreateGlDataForImage(imageToGetDisplayListFor, TextureMagFilterLinear); newPlugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount; newPlugin.refreshCountCreatedOn = currentGlobalRefreshCount; return newPlugin; } if(imageToGetDisplayListFor.ChangedCount != plugin.imageUpdateCount || plugin.refreshCountCreatedOn != currentGlobalRefreshCount) { plugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount; plugin.refreshCountCreatedOn = currentGlobalRefreshCount; GL.BindTexture(TextureTarget.Texture2D, plugin.GLTextureHandle); // Create the texture switch (imageToGetDisplayListFor.BitDepth) { case 8: GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height, PixelFormat.Luminance, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer()); break; case 24: // our bitmaps are not padded and GL is having a problem with them so don't use 24 bit unless you fix this. GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height, PixelFormat.Bgr, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer()); break; case 32: GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height, PixelFormat.Bgra, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer()); break; default: throw new NotImplementedException(); } if (plugin.createdWithMipMaps) { if (GLMajorVersion < 3) { switch (imageToGetDisplayListFor.BitDepth) { case 32: { ImageBuffer sourceImage = new ImageBuffer(imageToGetDisplayListFor); ImageBuffer tempImage = new ImageBuffer(sourceImage.Width / 2, sourceImage.Height / 2, 32, new BlenderBGRA()); tempImage.NewGraphics2D().Render(sourceImage, 0, 0, 0, .5, .5); int mipLevel = 1; while (sourceImage.Width > 1 && sourceImage.Height > 1) { GL.TexSubImage2D(TextureTarget.Texture2D, mipLevel++, 0, 0, tempImage.Width, tempImage.Height, PixelFormat.Bgra, PixelType.UnsignedByte, tempImage.GetBuffer()); sourceImage = new ImageBuffer(tempImage); tempImage = new ImageBuffer(Math.Max(1, sourceImage.Width / 2), Math.Max(1, sourceImage.Height / 2), 32, new BlenderBGRA()); tempImage.NewGraphics2D().Render(sourceImage, 0, 0, 0, (double)tempImage.Width / (double)sourceImage.Width, (double)tempImage.Height / (double)sourceImage.Height); } } break; default: throw new NotImplementedException(); } } else { GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); } } } #endif return plugin; }
public override void OnParentChanged(EventArgs e) { AnchorAll(); string img_name = "spheres.bmp"; if (!ImageIO.LoadImageData(img_name, image_resample.m_SourceImage)) { string buf; buf = "File not found: " + img_name + ".bmp" + ". Download http://www.antigrain.com/" + img_name + ".bmp" + "\n" + "or copy it from another directory if available."; throw new NotImplementedException(buf); } else { if (image_resample.m_SourceImage.BitDepth != 32) { throw new Exception("we are expecting 32 bit source."); } // give the image some alpha. [4/6/2009 lbrubaker] ImageBuffer image32 = new ImageBuffer(image_resample.m_SourceImage.Width, image_resample.m_SourceImage.Height, 32, new BlenderBGRA()); int offset; byte[] source = image_resample.m_SourceImage.GetBuffer(out offset); byte[] dest = image32.GetBuffer(out offset); for (int y = 0; y < image32.Height; y++) for (int x = 0; x < image32.Width; x++) { int i = y * image32.Width + x; dest[i * 4 + 0] = source[i * 4 + 0]; dest[i * 4 + 1] = source[i * 4 + 1]; dest[i * 4 + 2] = source[i * 4 + 2]; Vector2 pixel = new Vector2(x, y); Vector2 center = new Vector2(image32.Width / 2, image32.Height / 2); Vector2 delta = pixel - center; int length = (int)Math.Min(delta.Length * 3, 255); dest[i * 4 + 3] = (byte)length; } // and set our new image with alpha image_resample.m_SourceImage = image32; //image_resample_application.m_SourceImage.SetBlender(new BlenderBGR()); } base.OnParentChanged(e); }
private static void Copy8BitDataToImage(ImageBuffer destImage, Bitmap m_WidowsBitmap) { destImage.Allocate(m_WidowsBitmap.Width, m_WidowsBitmap.Height, m_WidowsBitmap.Width * 4, 32); BitmapData bitmapData = m_WidowsBitmap.LockBits(new Rectangle(0, 0, m_WidowsBitmap.Width, m_WidowsBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, m_WidowsBitmap.PixelFormat); int sourceIndex = 0; int destIndex = 0; unsafe { int offset; byte[] destBuffer = destImage.GetBuffer(out offset); byte* pSourceBuffer = (byte*)bitmapData.Scan0; Color[] colors = m_WidowsBitmap.Palette.Entries; for (int y = 0; y < destImage.Height; y++) { sourceIndex = y * bitmapData.Stride; destIndex = destImage.GetBufferOffsetY(destImage.Height - 1 - y); for (int x = 0; x < destImage.Width; x++) { Color color = colors[pSourceBuffer[sourceIndex++]]; destBuffer[destIndex++] = color.B; destBuffer[destIndex++] = color.G; destBuffer[destIndex++] = color.R; destBuffer[destIndex++] = color.A; } } } m_WidowsBitmap.UnlockBits(bitmapData); }
private static unsafe int LowLevelReadTGABitsFromBuffer(ImageBuffer imageToReadTo, byte[] wholeFileBuffer, int DestBitDepth) { STargaHeader TargaHeader = new STargaHeader(); int FileReadOffset; if (!ReadTGAInfo(wholeFileBuffer, out TargaHeader)) { return 0; } // if the frame we are loading is different then the one we have allocated // or we don't have any bits allocated if ((imageToReadTo.Width * imageToReadTo.Height) != (TargaHeader.Width * TargaHeader.Height)) { imageToReadTo.Allocate(TargaHeader.Width, TargaHeader.Height, TargaHeader.Width * DestBitDepth / 8, DestBitDepth); } // work out the line width switch (imageToReadTo.BitDepth) { case 24: TGABytesPerLine = imageToReadTo.Width * 3; if (imageToReadTo.GetRecieveBlender() == null) { imageToReadTo.SetRecieveBlender(new BlenderBGR()); } break; case 32: TGABytesPerLine = imageToReadTo.Width * 4; if (imageToReadTo.GetRecieveBlender() == null) { imageToReadTo.SetRecieveBlender(new BlenderBGRA()); } break; default: throw new System.Exception("Bad bit depth."); } if (TGABytesPerLine > 0) { byte[] BufferToDecompressTo = null; FileReadOffset = TargaHeaderSize + TargaHeader.PostHeaderSkip; if (TargaHeader.ImageType == 10) // 10 is RLE compressed { BufferToDecompressTo = new byte[TGABytesPerLine * 2]; } // read all the lines * for (int i = 0; i < imageToReadTo.Height; i++) { byte[] BufferToCopyFrom; int CopyOffset = 0; int CurReadLine; // bit 5 tells us if the image is stored top to bottom or bottom to top if ((TargaHeader.Descriptor & 0x20) != 0) { // bottom to top CurReadLine = imageToReadTo.Height - i - 1; } else { // top to bottom CurReadLine = i; } if (TargaHeader.ImageType == 10) // 10 is RLE compressed { FileReadOffset = Decompress(BufferToDecompressTo, wholeFileBuffer, FileReadOffset, imageToReadTo.Width, TargaHeader.BPP, CurReadLine); BufferToCopyFrom = BufferToDecompressTo; } else { BufferToCopyFrom = wholeFileBuffer; CopyOffset = FileReadOffset; } int bufferOffset; byte[] imageBuffer = imageToReadTo.GetBuffer(out bufferOffset); switch (imageToReadTo.BitDepth) { case 8: switch (TargaHeader.BPP) { case 24: Do24To8Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; case 32: Do32To8Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; } break; case 24: switch (TargaHeader.BPP) { case 24: Do24To24Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; case 32: Do32To24Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; } break; case 32: switch (TargaHeader.BPP) { case 24: Do24To32Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; case 32: Do32To32Bit(imageBuffer, BufferToCopyFrom, CopyOffset, imageToReadTo.Width, CurReadLine); break; } break; default: throw new System.Exception("Bad bit depth"); } if (TargaHeader.ImageType != 10) // 10 is RLE compressed { FileReadOffset += TGABytesPerLine; } } } return TargaHeader.Width; }
private static bool ConvertBitmapToImage(ImageBuffer destImage, Bitmap m_WidowsBitmap) { if (m_WidowsBitmap != null) { switch (m_WidowsBitmap.PixelFormat) { case System.Drawing.Imaging.PixelFormat.Format32bppArgb: { destImage.Allocate(m_WidowsBitmap.Width, m_WidowsBitmap.Height, m_WidowsBitmap.Width * 4, 32); if (destImage.GetRecieveBlender() == null) { destImage.SetRecieveBlender(new BlenderBGRA()); } BitmapData bitmapData = m_WidowsBitmap.LockBits(new Rectangle(0, 0, m_WidowsBitmap.Width, m_WidowsBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, m_WidowsBitmap.PixelFormat); int sourceIndex = 0; int destIndex = 0; unsafe { int offset; byte[] destBuffer = destImage.GetBuffer(out offset); byte* pSourceBuffer = (byte*)bitmapData.Scan0; for (int y = 0; y < destImage.Height; y++) { destIndex = destImage.GetBufferOffsetXY(0, destImage.Height - 1 - y); for (int x = 0; x < destImage.Width; x++) { #if true destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; #else RGBA_Bytes notPreMultiplied = new RGBA_Bytes(pSourceBuffer[sourceIndex + 0], pSourceBuffer[sourceIndex + 1], pSourceBuffer[sourceIndex + 2], pSourceBuffer[sourceIndex + 3]); sourceIndex += 4; RGBA_Bytes preMultiplied = notPreMultiplied.GetAsRGBA_Floats().premultiply().GetAsRGBA_Bytes(); destBuffer[destIndex++] = preMultiplied.blue; destBuffer[destIndex++] = preMultiplied.green; destBuffer[destIndex++] = preMultiplied.red; destBuffer[destIndex++] = preMultiplied.alpha; #endif } } } m_WidowsBitmap.UnlockBits(bitmapData); return true; } case System.Drawing.Imaging.PixelFormat.Format24bppRgb: { destImage.Allocate(m_WidowsBitmap.Width, m_WidowsBitmap.Height, m_WidowsBitmap.Width * 4, 32); BitmapData bitmapData = m_WidowsBitmap.LockBits(new Rectangle(0, 0, m_WidowsBitmap.Width, m_WidowsBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, m_WidowsBitmap.PixelFormat); int sourceIndex = 0; int destIndex = 0; unsafe { int offset; byte[] destBuffer = destImage.GetBuffer(out offset); byte* pSourceBuffer = (byte*)bitmapData.Scan0; for (int y = 0; y < destImage.Height; y++) { sourceIndex = y * bitmapData.Stride; destIndex = destImage.GetBufferOffsetXY(0, destImage.Height - 1 - y); for (int x = 0; x < destImage.Width; x++) { destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = 255; } } } m_WidowsBitmap.UnlockBits(bitmapData); return true; } case System.Drawing.Imaging.PixelFormat.Format8bppIndexed: { Copy8BitDataToImage(destImage, m_WidowsBitmap); return true; } default: throw new System.NotImplementedException(); } } return false; }
public static void DoAllWhite(ImageBuffer result, ImageBuffer imageA) { if (imageA.BitDepth != result.BitDepth) { throw new NotImplementedException("All the images have to be the same bit depth."); } if (imageA.Width != result.Width || imageA.Height != result.Height) { throw new Exception("All images must be the same size."); } switch (imageA.BitDepth) { case 32: { int height = imageA.Height; int width = imageA.Width; byte[] resultBuffer = result.GetBuffer(); byte[] imageABuffer = imageA.GetBuffer(); for (int y = 0; y < height; y++) { int offsetA = imageA.GetBufferOffsetY(y); int offsetResult = result.GetBufferOffsetY(y); for (int x = 0; x < width; x++) { int alpha = imageABuffer[offsetA+3]; if (alpha > 0) { resultBuffer[offsetResult++] = (byte)255; offsetA++; resultBuffer[offsetResult++] = (byte)255; offsetA++; resultBuffer[offsetResult++] = (byte)255; offsetA++; resultBuffer[offsetResult++] = (byte)alpha; offsetA++; } else { resultBuffer[offsetResult++] = (byte)0; offsetA++; resultBuffer[offsetResult++] = (byte)0; offsetA++; resultBuffer[offsetResult++] = (byte)0; offsetA++; resultBuffer[offsetResult++] = (byte)0; offsetA++; } } } result.SetRecieveBlender(new BlenderPreMultBGRA()); } break; default: throw new NotImplementedException(); } }
public static CCSprite CreateText(string text, CCColor4B fill, CCColor4B stroke, TypeFace font, double emSizeInPoints, bool underline = false, bool flatenCurves = true, double strokeThickness = 1) { TypeFacePrinter printer = new TypeFacePrinter(text, new StyledTypeFace(font, emSizeInPoints, underline, flatenCurves)); double width = printer.LocalBounds.Width; double height = printer.LocalBounds.Height; RectangleDouble rect = new RectangleDouble(); bounding_rect.bounding_rect_single(printer, 0, ref rect); VertexSourceApplyTransform path = new VertexSourceApplyTransform(printer, Affine.NewTranslation(-rect.Left, -rect.Bottom)); ImageBuffer buffer = new ImageBuffer((int)width, (int)height, 32, new BlenderRGBA()); Graphics2D g = buffer.NewGraphics2D(); if (fill.A > 0) g.Render(path, new RGBA_Bytes(fill.R, fill.G, fill.B, fill.A)); if (stroke.A > 0) g.Render(new Stroke(path, strokeThickness), new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A)); Texture2D xnaTexture = XnaTexture((int)width, (int)height); xnaTexture.SetData<byte>(buffer.GetBuffer()); CCTexture2D ccTexture = new CCTexture2D(); ccTexture.InitWithTexture(xnaTexture); return new CCSprite(ccTexture); }
//路径 public static CCSprite CreatePath( double width, double height, string[] paths, double contentX, double contentY, double contentWidth, double contentHeight, CCColor4B fill, CCColor4B stroke, double strokeThickness = 1, UIGraphic.Stretch stretch = UIGraphic.Stretch.StretchNone ) { if (width == 0) width = contentWidth; if (height == 0) height = contentHeight; ImageBuffer buffer = new ImageBuffer((int)width, (int)height, 32, new BlenderRGBA()); Graphics2D g = buffer.NewGraphics2D(); double scalex = 0; double scaley = 0; //if (stretch == Stretch.StretchNone) { } else if (stretch == UIGraphic.Stretch.StretchFill) { if (width != contentWidth || height != contentHeight) { scalex = width / contentWidth; scaley = height / contentHeight; } } else if (stretch == UIGraphic.Stretch.StretchUniformToFill) { scalex = scaley = Math.Min(width / contentWidth, height / contentHeight); } foreach (string path in paths) { IVertexSource vertexs = MiniLanguage.CreatePathStorage(path); if (contentX != 0 || contentY != 0) vertexs = new VertexSourceApplyTransform(vertexs, Affine.NewTranslation(-contentX, -contentY)); if (scalex != 0 || scaley != 0) vertexs = new VertexSourceApplyTransform(vertexs, Affine.NewScaling(scalex, scaley)); if (fill.A > 0) g.Render(vertexs, new RGBA_Bytes(fill.R, fill.G, fill.B, fill.A)); if (stroke.A > 0) g.Render(new Stroke(vertexs, strokeThickness), new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A)); } Texture2D xnaTexture = XnaTexture((int)width, (int)height); xnaTexture.SetData<byte>(buffer.GetBuffer()); CCTexture2D ccTexture = new CCTexture2D(); ccTexture.InitWithTexture(xnaTexture); return new CCSprite(ccTexture); }
private void CreateGlDataForImage(ImageBuffer bufferedImage, bool TextureMagFilterLinear) { //Next we expand the image into an openGL texture int imageWidth = bufferedImage.Width; int imageHeight = bufferedImage.Height; int bufferOffset; byte[] imageBuffer = bufferedImage.GetBuffer(out bufferOffset); int hardwareWidth = SmallestHardwareCompatibleTextureSize(imageWidth); int hardwareHeight = SmallestHardwareCompatibleTextureSize(imageHeight); byte[] hardwareExpandedPixelBuffer = imageBuffer; if (hardwareWidth != imageWidth || hardwareHeight != imageHeight) { // we have to put the data on a buffer that GL can handle. hardwareExpandedPixelBuffer = new byte[4 * hardwareWidth * hardwareHeight]; switch (bufferedImage.BitDepth) { case 32: for (int y = 0; y < hardwareHeight; y++) { for (int x = 0; x < hardwareWidth; x++) { int pixelIndex = 4 * (x + y * hardwareWidth); if (x >= imageWidth || y >= imageHeight) { hardwareExpandedPixelBuffer[pixelIndex + 0] = 0; hardwareExpandedPixelBuffer[pixelIndex + 1] = 0; hardwareExpandedPixelBuffer[pixelIndex + 2] = 0; hardwareExpandedPixelBuffer[pixelIndex + 3] = 0; } else { hardwareExpandedPixelBuffer[pixelIndex + 0] = imageBuffer[4 * (x + y * imageWidth) + 2]; hardwareExpandedPixelBuffer[pixelIndex + 1] = imageBuffer[4 * (x + y * imageWidth) + 1]; hardwareExpandedPixelBuffer[pixelIndex + 2] = imageBuffer[4 * (x + y * imageWidth) + 0]; hardwareExpandedPixelBuffer[pixelIndex + 3] = imageBuffer[4 * (x + y * imageWidth) + 3]; } } } break; default: throw new NotImplementedException(); } } GL.Enable(EnableCap.Texture2D); // Create the texture handle GL.GenTextures(1, out glData.glTextureHandle); // Set up some texture parameters for openGL GL.BindTexture(TextureTarget.Texture2D, glData.glTextureHandle); if (TextureMagFilterLinear) { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); } else { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); } if (createdWithMipMaps) { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); } else { GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); } GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge); // Create the texture switch (bufferedImage.BitDepth) { #if false // not implemented in our gl wrapper and never used in our current code case 8: GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Luminance, hardwareWidth, hardwareHeight, 0, PixelFormat.Luminance, PixelType.UnsignedByte, hardwareExpandedPixelBuffer); break; case 24: GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, hardwareWidth, hardwareHeight, 0, PixelFormat.Rgb, PixelType.UnsignedByte, hardwareExpandedPixelBuffer); break; #endif case 32: #if __ANDROID__ GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, hardwareWidth, hardwareHeight, 0, PixelFormat.Rgba, PixelType.UnsignedByte, hardwareExpandedPixelBuffer); #else GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, hardwareWidth, hardwareHeight, 0, PixelFormat.Bgra, PixelType.UnsignedByte, hardwareExpandedPixelBuffer); #endif break; default: throw new NotImplementedException(); } hardwareExpandedPixelBuffer = null; if (createdWithMipMaps) { switch (bufferedImage.BitDepth) { case 32: { ImageBuffer sourceImage = new ImageBuffer(bufferedImage); ImageBuffer tempImage = new ImageBuffer(sourceImage.Width / 2, sourceImage.Height / 2, 32, new BlenderBGRA()); tempImage.NewGraphics2D().Render(sourceImage, 0, 0, 0, .5, .5); int mipLevel = 1; while (sourceImage.Width > 1 && sourceImage.Height > 1) { #if __ANDROID__ GL.TexImage2D(TextureTarget.Texture2D, mipLevel++, PixelInternalFormat.Rgba, tempImage.Width, tempImage.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, tempImage.GetBuffer()); #else GL.TexImage2D(TextureTarget.Texture2D, mipLevel++, PixelInternalFormat.Rgba, tempImage.Width, tempImage.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, tempImage.GetBuffer()); #endif sourceImage = new ImageBuffer(tempImage); tempImage = new ImageBuffer(Math.Max(1, sourceImage.Width / 2), Math.Max(1, sourceImage.Height / 2), 32, new BlenderBGRA()); tempImage.NewGraphics2D().Render(sourceImage, 0, 0, 0, (double)tempImage.Width / (double)sourceImage.Width, (double)tempImage.Height / (double)sourceImage.Height); } } break; default: throw new NotImplementedException(); } } float texCoordX = imageWidth / (float)hardwareWidth; float texCoordY = imageHeight / (float)hardwareHeight; float OffsetX = (float)bufferedImage.OriginOffset.x; float OffsetY = (float)bufferedImage.OriginOffset.y; glData.textureUVs = new float[8]; glData.positions = new float[8]; glData.textureUVs[0] = 0; glData.textureUVs[1] = 0; glData.positions[0] = 0 - OffsetX; glData.positions[1] = 0 - OffsetY; glData.textureUVs[2] = 0; glData.textureUVs[3] = texCoordY; glData.positions[2] = 0 - OffsetX; glData.positions[3] = imageHeight - OffsetY; glData.textureUVs[4] = texCoordX; glData.textureUVs[5] = texCoordY; glData.positions[4] = imageWidth - OffsetX; glData.positions[5] = imageHeight - OffsetY; glData.textureUVs[6] = texCoordX; glData.textureUVs[7] = 0; glData.positions[6] = imageWidth - OffsetX; glData.positions[7] = 0 - OffsetY; }
internal static bool ConvertBitmapToImage(ImageBuffer destImage, Bitmap bitmap) { if (bitmap != null) { switch (bitmap.PixelFormat) { case System.Drawing.Imaging.PixelFormat.Format32bppArgb: { destImage.Allocate(bitmap.Width, bitmap.Height, bitmap.Width * 4, 32); if (destImage.GetRecieveBlender() == null) { destImage.SetRecieveBlender(new BlenderBGRA()); } BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat); int sourceIndex = 0; int destIndex = 0; unsafe { int offset; byte[] destBuffer = destImage.GetBuffer(out offset); byte * pSourceBuffer = (byte *)bitmapData.Scan0; for (int y = 0; y < destImage.Height; y++) { destIndex = destImage.GetBufferOffsetXY(0, destImage.Height - 1 - y); for (int x = 0; x < destImage.Width; x++) { #if true destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; #else Color notPreMultiplied = new Color(pSourceBuffer[sourceIndex + 0], pSourceBuffer[sourceIndex + 1], pSourceBuffer[sourceIndex + 2], pSourceBuffer[sourceIndex + 3]); sourceIndex += 4; Color preMultiplied = notPreMultiplied.ToColorF().premultiply().ToColor(); destBuffer[destIndex++] = preMultiplied.blue; destBuffer[destIndex++] = preMultiplied.green; destBuffer[destIndex++] = preMultiplied.red; destBuffer[destIndex++] = preMultiplied.alpha; #endif } } } bitmap.UnlockBits(bitmapData); return(true); } case System.Drawing.Imaging.PixelFormat.Format24bppRgb: { destImage.Allocate(bitmap.Width, bitmap.Height, bitmap.Width * 4, 32); if (destImage.GetRecieveBlender() == null) { destImage.SetRecieveBlender(new BlenderBGRA()); } BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat); int sourceIndex = 0; int destIndex = 0; unsafe { int offset; byte[] destBuffer = destImage.GetBuffer(out offset); byte * pSourceBuffer = (byte *)bitmapData.Scan0; for (int y = 0; y < destImage.Height; y++) { sourceIndex = y * bitmapData.Stride; destIndex = destImage.GetBufferOffsetXY(0, destImage.Height - 1 - y); for (int x = 0; x < destImage.Width; x++) { destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = pSourceBuffer[sourceIndex++]; destBuffer[destIndex++] = 255; } } } bitmap.UnlockBits(bitmapData); return(true); } case System.Drawing.Imaging.PixelFormat.Format8bppIndexed: { Copy8BitDataToImage(destImage, bitmap); return(true); } default: // let this code fall through and return false break; } } return(false); }
private void AddText(string tabText, GuiWidget widgetState, RGBA_Bytes textColor, RGBA_Bytes backgroundColor, double pointSize) { leftToRight = new FlowLayoutWidget(); tabTitle = new TextWidget(tabText, pointSize: pointSize, textColor: textColor); tabTitle.AutoExpandBoundsToText = true; leftToRight.AddChild(tabTitle); ImageBuffer popOutImageClick = StaticData.Instance.LoadIcon(Path.Combine("icon_pop_out_32x32.png")); if (ActiveTheme.Instance.IsDarkTheme) { InvertLightness.DoInvertLightness(popOutImageClick); } ImageBuffer popOutImage = new ImageBuffer(popOutImageClick); byte[] buffer = popOutImage.GetBuffer(); for (int i = 0; i < buffer.Length; i++) { if ((i & 3) != 3) { buffer[i] = textColor.red; } } Button popOut = new Button(0, 0, new ButtonViewStates(new ImageWidget(popOutImage), new ImageWidget(popOutImage), new ImageWidget(popOutImageClick), new ImageWidget(popOutImageClick))); popOut.ToolTipText = "Pop This Tab out into its own Window".Localize(); popOut.Click += (sender, e) => { popOutManager.ShowContentInWindow(); }; popOut.Margin = new BorderDouble(3, 0); popOut.VAnchor = VAnchor.ParentTop; leftToRight.AddChild(popOut); widgetState.AddChild(leftToRight); widgetState.SetBoundsToEncloseChildren(); widgetState.BackgroundColor = backgroundColor; }