unsafe private static void Resample1D(BitmapBase bmpDest, BitmapBase bmpSrc, int transparentOffset, ContributorEntry[] contrib, int alongSize, int crossSize, bool horz) { using (bmpSrc.UseRead()) using (bmpDest.UseWrite()) { byte *srcBytes = bmpSrc.Data + transparentOffset; for (int crossCoord = 0; crossCoord < crossSize; ++crossCoord) { for (int alongCoord = 0; alongCoord < alongSize; ++alongCoord) { for (int channel = 0; channel < 4; ++channel) { double intensity = 0; double wsum = 0; for (int j = 0; j < contrib[alongCoord].SrcPixelCount; j++) { int contribCoord = contrib[alongCoord].SrcPixel[j].Coord; int contribOffset = (horz ? contribCoord : crossCoord) * 4 + (horz ? crossCoord : contribCoord) * bmpSrc.Stride; double weight = contrib[alongCoord].SrcPixel[j].Weight; if (channel != 3) { weight *= srcBytes[contribOffset + 3] / 255d; } if (weight == 0) { continue; } wsum += weight; intensity += srcBytes[contribOffset + channel] * weight; } bmpDest.Data[(horz ? alongCoord : crossCoord) * 4 + (horz ? crossCoord : alongCoord) * bmpDest.Stride + channel] = (byte)Math.Min(Math.Max(intensity / wsum, byte.MinValue), byte.MaxValue); } } } } }
/// <summary>A convenience method to save a GDI image directly to a .tga file.</summary> public static unsafe void Save(BitmapBase image, string filename) { using (image.UseRead()) using (var file = File.Open(filename, FileMode.Create, FileAccess.Write, FileShare.Read)) { var header = new byte[18]; header[2] = 2; header[12] = (byte) (image.Width); header[13] = (byte) (image.Width >> 8); header[14] = (byte) (image.Height); header[15] = (byte) (image.Height >> 8); header[16] = 32; header[17] = 32; file.Write(header); byte[] dummy = new byte[image.Width * 4]; for (int y = 0; y < image.Height; y++) { Ut.MemCpy(dummy, image.Data + y * image.Stride, image.Width * 4); file.Write(dummy); } } }
/// <summary>A convenience method to save a GDI image directly to a .tga file.</summary> public static unsafe void Save(BitmapBase image, string filename) { using (image.UseRead()) using (var file = File.Open(filename, FileMode.Create, FileAccess.Write, FileShare.Read)) { var header = new byte[18]; header[2] = 2; header[12] = (byte)(image.Width); header[13] = (byte)(image.Width >> 8); header[14] = (byte)(image.Height); header[15] = (byte)(image.Height >> 8); header[16] = 32; header[17] = 32; file.Write(header); byte[] dummy = new byte[image.Width * 4]; for (int y = 0; y < image.Height; y++) { Ut.MemCpy(dummy, image.Data + y * image.Stride, image.Width * 4); file.Write(dummy); } } }
public void DrawImage(BitmapBase image, int destX, int destY, int srcX, int srcY, int width, int height, bool below) { using (UseWrite()) using (image.UseRead()) { if (width <= 0 || height <= 0) { return; } if (destX < 0) { srcX -= destX; width += destX; destX = 0; } if (destY < 0) { srcY -= destY; height += destY; destY = 0; } if (srcX >= image.Width || srcY >= image.Height) { return; } if (srcX < 0) { destX -= srcX; width += srcX; srcX = 0; } if (srcY < 0) { destY -= srcY; height += srcY; srcY = 0; } if (destX >= Width || destY >= Height) { return; } if (destX + width > Width) { width = Width - destX; } if (destY + height > Height) { height = Height - destY; } if (srcX + width > image.Width) { width = image.Width - srcX; } if (srcY + height > image.Height) { height = image.Height - srcY; } if (width <= 0 || height <= 0) // cannot be negative at this stage, but just in case... { return; } byte *dest = Data + destY * Stride + destX * 4; byte *src = image.Data + srcY * image.Stride + srcX * 4; for (int y = 0; y < height; y++, dest += Stride, src += image.Stride) { byte *tgt = dest; byte *btm = below ? src : dest; byte *top = below ? dest : src; byte *end = tgt + width * 4; do { byte topA = *(top + 3); byte btmA = *(btm + 3); if (topA == 255 || btmA == 0) { *(int *)tgt = *(int *)top; } else if (topA == 0) { *(int *)tgt = *(int *)btm; } else if (btmA == 255) { // green *(tgt + 1) = (byte)((*(top + 1) * topA + *(btm + 1) * (255 - topA)) >> 8); // red and blue *(uint *)tgt = (*(uint *)tgt & 0xFF00FF00u) | (((((*(uint *)top) & 0x00FF00FFu) * topA + ((*(uint *)btm) & 0x00FF00FFu) * (uint)(255 - topA)) >> 8) & 0x00FF00FFu); // alpha (only needed when "below" is true) *(tgt + 3) = 255; } else // topA and btmA both >0 and <255 { byte tgtAA = *(tgt + 3) = (byte)(topA + (btmA * (255 - topA) >> 8)); int btmAA = (btmA * (255 - topA)) / 255; tgtAA += 1; // ensures the division below never results in a value greater than 255 *(tgt + 0) = (byte)((*(top + 0) * topA + *(btm + 0) * btmAA) / tgtAA); *(tgt + 1) = (byte)((*(top + 1) * topA + *(btm + 1) * btmAA) / tgtAA); *(tgt + 2) = (byte)((*(top + 2) * topA + *(btm + 2) * btmAA) / tgtAA); } tgt += 4; btm += 4; top += 4; }while (tgt < end); } } }
public void CopyPixelsFrom(BitmapBase source) { using (source.UseRead()) CopyPixelsFrom(source.Data, source.Width, source.Height, source.Stride); }
public void DrawImage(BitmapBase image, int destX, int destY, int srcX, int srcY, int width, int height, bool below) { using (UseWrite()) using (image.UseRead()) { if (width <= 0 || height <= 0) return; if (destX < 0) { srcX -= destX; width += destX; destX = 0; } if (destY < 0) { srcY -= destY; height += destY; destY = 0; } if (srcX >= image.Width || srcY >= image.Height) return; if (srcX < 0) { destX -= srcX; width += srcX; srcX = 0; } if (srcY < 0) { destY -= srcY; height += srcY; srcY = 0; } if (destX >= Width || destY >= Height) return; if (destX + width > Width) width = Width - destX; if (destY + height > Height) height = Height - destY; if (srcX + width > image.Width) width = image.Width - srcX; if (srcY + height > image.Height) height = image.Height - srcY; if (width <= 0 || height <= 0) // cannot be negative at this stage, but just in case... return; byte* dest = Data + destY * Stride + destX * 4; byte* src = image.Data + srcY * image.Stride + srcX * 4; for (int y = 0; y < height; y++, dest += Stride, src += image.Stride) { byte* tgt = dest; byte* btm = below ? src : dest; byte* top = below ? dest : src; byte* end = tgt + width * 4; do { byte topA = *(top + 3); byte btmA = *(btm + 3); if (topA == 255 || btmA == 0) *(int*) tgt = *(int*) top; else if (topA == 0) *(int*) tgt = *(int*) btm; else if (btmA == 255) { // green *(tgt + 1) = (byte) ((*(top + 1) * topA + *(btm + 1) * (255 - topA)) >> 8); // red and blue *(uint*) tgt = (*(uint*) tgt & 0xFF00FF00u) | (((((*(uint*) top) & 0x00FF00FFu) * topA + ((*(uint*) btm) & 0x00FF00FFu) * (uint) (255 - topA)) >> 8) & 0x00FF00FFu); // alpha (only needed when "below" is true) *(tgt + 3) = 255; } else // topA and btmA both >0 and <255 { byte tgtAA = *(tgt + 3) = (byte) (topA + (btmA * (255 - topA) >> 8)); int btmAA = (btmA * (255 - topA)) / 255; tgtAA += 1; // ensures the division below never results in a value greater than 255 *(tgt + 0) = (byte) ((*(top + 0) * topA + *(btm + 0) * btmAA) / tgtAA); *(tgt + 1) = (byte) ((*(top + 1) * topA + *(btm + 1) * btmAA) / tgtAA); *(tgt + 2) = (byte) ((*(top + 2) * topA + *(btm + 2) * btmAA) / tgtAA); } tgt += 4; btm += 4; top += 4; } while (tgt < end); } } }
public void CopyPixelsFrom(BitmapBase source) { using (source.UseRead()) CopyPixelsFrom(source.Data, source.Width, source.Height, source.Stride); }