/// <summary> /// Draw the specified x, y, source and considerAlpha. /// </summary> /// <param name="x">The x coordinate.</param> /// <param name="y">The y coordinate.</param> /// <param name="source">Source.</param> /// <param name="considerAlpha">If set to <c>true</c> consider alpha.</param> public void Draw(int x, int y, Image8i source, bool considerAlpha) { if (!considerAlpha || source.ChannelFormat == ChannelFormat.BGR || source.ChannelFormat == ChannelFormat.RGB || source.ChannelFormat == ChannelFormat.Gray) { Draw(x, y, source); return; } if (x >= Width || y >= Height) throw new ArgumentOutOfRangeException("x or y", "Out of image."); if (x + source.Width < 0 || y + source.Height < 0) throw new ArgumentOutOfRangeException("x or y", "Out of image."); Image8i sourceImage = null; switch (ChannelFormat) { case ChannelFormat.Gray: { sourceImage = source.ToChannelFormatGrayAlpha(); break; } case ChannelFormat.GrayAlpha: { sourceImage = source.ToChannelFormatGrayAlpha(); break; } case ChannelFormat.RGB: { sourceImage = source.ToChannelFormatRGBA(); break; } case ChannelFormat.RGBA: { sourceImage = source.ToChannelFormatRGBA(); break; } case ChannelFormat.BGR: { sourceImage = source.ToChannelFormatBGRA(); break; } case ChannelFormat.BGRA: { sourceImage = source.ToChannelFormatBGRA(); break; } } uint bpp = GetBytePerPixelFromChannelFormat(source.ChannelFormat); unsafe { fixed(byte* src_=sourceImage.imageData, dst_=imageData) { uint start = (uint)System.Math.Max(-x, 0); uint end = (uint)System.Math.Min(source.Width, Width - x); uint jstart = (uint)System.Math.Max(-y, 0); uint jend = (uint)System.Math.Min(source.Height, Height - y); if (ChannelFormat == ChannelFormat.BGR || ChannelFormat == ChannelFormat.RGB || ChannelFormat == ChannelFormat.Gray) { uint dbpp = GetBytePerPixelFromChannelFormat(ChannelFormat); byte* src__ = src_ + start * bpp; byte* dst__ = dst_ + x * dbpp + start * dbpp; uint sw = source.Width * bpp; uint dw = Width * dbpp; if (ChannelFormat == ChannelFormat.BGR || ChannelFormat == ChannelFormat.RGB) { for (uint j = jstart; j < jend; j++) { byte* src = src__ + sw * j; byte* dst = dst__ + dw * (y + j); for (uint i = start; i < end; i++) { byte sr = *src++; byte sg = *src++; byte sb = *src++; byte sa = *src++; if (sa != 0) { byte dr = *dst++; byte dg = *dst++; byte db = *dst++; dst -= 3; double a2 = sa / 255.0; double a1 = 1 - a2; *dst++ = (byte)(dr * a1 + sr * a2); *dst++ = (byte)(dg * a1 + sg * a2); *dst++ = (byte)(db * a1 + sb * a2); } else dst += 3; } } } else // GRAY { for (uint j = jstart; j < jend; j++) { byte* src = src__ + sw * j; byte* dst = dst__ + dw * (y + j); for (uint i = start; i < end; i++) { byte sg = *src++; byte sa = *src++; if (sa != 0) { byte dg = *dst; double a2 = sa / 255.0; double a1 = 1 - a2; *dst++ = (byte)(dg * a1 + sg * a2); } else dst++; } } } // end if RGB || BGR } else // 2x alpha image { byte* src__ = src_ + start * bpp; byte* dst__ = dst_ + x * bpp + start * bpp; uint sw = source.Width * bpp; uint dw = Width * bpp; if (ChannelFormat == ChannelFormat.BGRA || ChannelFormat == ChannelFormat.RGBA) { for (uint j = jstart; j < jend; j++) { byte* src = src__ + sw * j; byte* dst = dst__ + dw * (y + j); for (uint i = start; i < end; i++) { byte sr = *src++; byte sg = *src++; byte sb = *src++; byte sa = *src++; if (sa != 0) { byte dr = *dst++; byte dg = *dst++; byte db = *dst++; byte da = *dst++; dst -= 4; double a2 = sa / 255.0; double a1 = 1 - a2; *dst++ = (byte)(dr * a1 + sr * a2); *dst++ = (byte)(dg * a1 + sg * a2); *dst++ = (byte)(db * a1 + sb * a2); *dst++ = da; } else dst += 4; } } } else // GRAYALPHA { for (uint j = jstart; j < jend; j++) { byte* src = src__ + sw * j; byte* dst = dst__ + dw * (y + j); for (uint i = start; i < end; i++) { byte sg = *src++; byte sa = *src++; if (sa != 0) { byte dg = *dst++; byte da = *dst++; dst -= 2; double a2 = sa / 255.0; double a1 = 1 - a2; *dst++ = (byte)(dg * a1 + sg * a2); *dst++ = da; } else dst += 2; } } } // end if RGBA || BGRA } // end if 2x Alpha-Bild } // fixed } // unsafe }
public static void ToFile(string filename, Image8i image) { if (filename == null) throw new Exception(); if (filename == "") throw new Exception(); if (image.Width == 0 || image.Height == 0) throw new Exception(); if (image.Width > 0xFFFF || image.Height > 0xFFFF) throw new Exception(); if (image.ChannelFormat == ChannelFormat.BGR) { ToFile(filename, image.ToChannelFormatRGB()); return; } if (image.ChannelFormat == ChannelFormat.BGRA) { ToFile(filename, image.ToChannelFormatRGBA()); return; } bool isRGB = (image.ChannelFormat == ChannelFormat.BGR || image.ChannelFormat == ChannelFormat.RGB || image.ChannelFormat == ChannelFormat.BGRA || image.ChannelFormat == ChannelFormat.RGBA); bool isAlpha = (image.ChannelFormat == ChannelFormat.BGRA || image.ChannelFormat == ChannelFormat.RGBA || image.ChannelFormat == ChannelFormat.GrayAlpha); ulong size = (ulong)(18 + ((isRGB) ? (isAlpha ? 4 : 3) : (isAlpha ? 2 : 1)) * image.Width * image.Height); // Length of data if (size > 0xFFFFFFFF) throw new Exception(); // image is to big using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write)) { BinaryWriter bw = new BinaryWriter(fs); byte Pixel_Depth = (byte)(isRGB ? (isAlpha ? 32 : 24) : (isAlpha ? 16 : 8)); byte Image_Descriptor = (byte)(isAlpha ? 0x28 : 0x20); // Field 5.6 // Write header (18 bytes) bw.Write((byte)0); // ID_Length bw.Write((byte)0); // Color_Map_Type bw.Write((byte)(isRGB ? 2 : 3)); // Image_Type bw.Write((ushort)0); // First_Entry_Index bw.Write((ushort)0); // Color_Map_Length bw.Write((byte)0); // Color_Map_Entry_Size bw.Write((ushort)0); // X_Origin bw.Write((ushort)0); // Y_Origin bw.Write((ushort)image.Width); // Width bw.Write((ushort)image.Height); // Height bw.Write(Pixel_Depth); // Pixel_Depth bw.Write(Image_Descriptor); // Image_Descriptor bw.Write(image.ImageData); bw.Close(); fs.Close(); } }