Image8i ToReducedByImageHorizontal(uint m) { if ((Width * Height) == 0) return new Image8i(0, 0, ChannelFormat); uint w = Width / m; uint wh = w * Height; if (ChannelFormat == ChannelFormat.Gray) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; byte[] dst = ret.imageData; uint ind = 0; byte[] src = imageData; uint inds = 0; for (uint y = 0; y < wh; y++) { uint sum = 0; for (uint z = 0; z < m; z++) sum += src[inds++]; dst[ind++] = (byte)(sum / m); } return ret; } if (ChannelFormat == ChannelFormat.RGB || ChannelFormat == ChannelFormat.BGR) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; byte[] dst = ret.imageData; uint ind = 0; byte[] src = imageData; uint inds = 0; for (uint y = 0; y < wh; y++) { uint sumr = 0, sumg = 0, sumb = 0; for (uint z = 0; z < m; z++) { sumr += src[inds++]; sumg += src[inds++]; sumb += src[inds++]; } dst[ind++] = (byte)(sumr / m); dst[ind++] = (byte)(sumg / m); dst[ind++] = (byte)(sumb / m); } return ret; } if (ChannelFormat == ChannelFormat.RGBA || ChannelFormat == ChannelFormat.BGRA) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; byte[] dst = ret.imageData; uint ind = 0; byte[] src = imageData; uint inds = 0; for (uint y = 0; y < wh; y++) { uint sumr = 0, sumg = 0, sumb = 0, suma = 0; for (uint z = 0; z < m; z++) { byte r = src[inds++]; byte g = src[inds++]; byte b = src[inds++]; uint a = src[inds++]; sumr += r * a; sumg += g * a; sumb += b * a; suma += a; } if (suma == 0) { dst[ind++] = 0; dst[ind++] = 0; dst[ind++] = 0; dst[ind++] = 0; } else { dst[ind++] = (byte)(sumr / suma); dst[ind++] = (byte)(sumg / suma); dst[ind++] = (byte)(sumb / suma); dst[ind++] = (byte)(suma / m); } } return ret; } if (ChannelFormat == ChannelFormat.GrayAlpha) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; byte[] dst = ret.imageData; uint ind = 0; byte[] src = imageData; uint inds = 0; for (uint y = 0; y < wh; y++) { uint sumg = 0, suma = 0; for (uint z = 0; z < m; z++) { byte g = src[inds++]; uint a = src[inds++]; sumg += g * a; suma += a; } if (suma == 0) { dst[ind++] = 0; dst[ind++] = 0; } else { dst[ind++] = (byte)(sumg / suma); dst[ind++] = (byte)(suma / m); } } return ret; } return new Image8i(0, 0, ChannelFormat); }
Image8i ToReducedByImageVertical(uint n) { if ((Width * Height) == 0) return new Image8i(0, 0, ChannelFormat); uint h = Height / n; if (ChannelFormat == ChannelFormat.Gray) { Image8i ret = new Image8i(Width, h, ChannelFormat); if (ret.imageData == null) return ret; for (uint x = 0; x < Width; x++) { byte[] dst = ret.imageData; uint ind = x; byte[] src = imageData; uint inds = x; for (uint y = 0; y < h; y++) { uint sum = 0; for (uint z = 0; z < n; z++) { sum += src[inds]; inds += Width; } dst[ind] = (byte)(sum / n); ind += Width; } } return ret; } if (ChannelFormat == ChannelFormat.RGB || ChannelFormat == ChannelFormat.BGR) { Image8i ret = new Image8i(Width, h, ChannelFormat); if (ret.imageData == null) return ret; uint wb = 3 * Width - 2; for (uint x = 0; x < Width; x++) { byte[] dst = ret.imageData; uint ind = x * 3; byte[] src = imageData; uint inds = x * 3; for (uint y = 0; y < h; y++) { uint sumr = 0, sumg = 0, sumb = 0; for (uint z = 0; z < n; z++) { sumr += src[inds++]; sumg += src[inds++]; sumb += src[inds]; inds += wb; } dst[ind++] = (byte)(sumr / n); dst[ind++] = (byte)(sumg / n); dst[ind] = (byte)(sumb / n); ind += wb; } } return ret; } if (ChannelFormat == ChannelFormat.RGBA || ChannelFormat == ChannelFormat.BGRA) { Image8i ret = new Image8i(Width, h, ChannelFormat); if (ret.imageData == null) return ret; uint wb = 4 * Width - 3; for (uint x = 0; x < Width; x++) { byte[] dst = ret.imageData; uint ind = x * 4; byte[] src = imageData; uint inds = x * 4; for (uint y = 0; y < h; y++) { uint sumr = 0, sumg = 0, sumb = 0, suma = 0; for (uint z = 0; z < n; z++) { byte r = src[inds++]; byte g = src[inds++]; byte b = src[inds++]; uint a = src[inds]; inds += wb; sumr += r * a; sumg += g * a; sumb += b * a; suma += a; } if (suma == 0) { dst[ind++] = 0; dst[ind++] = 0; dst[ind++] = 0; dst[ind] = 0; } else { dst[ind++] = (byte)(sumr / suma); dst[ind++] = (byte)(sumg / suma); dst[ind++] = (byte)(sumb / suma); dst[ind] = (byte)(suma / n); } ind += wb; } } return ret; } if (ChannelFormat == ChannelFormat.GrayAlpha) { Image8i ret = new Image8i(Width, h, ChannelFormat); if (ret.imageData == null) return ret; uint wb = 2 * Width - 1; for (uint x = 0; x < Width; x++) { byte[] dst = ret.imageData; uint ind = x * 2; byte[] src = imageData; uint inds = x * 2; for (uint y = 0; y < h; y++) { uint sumg = 0, suma = 0; for (uint z = 0; z < n; z++) { byte g = src[inds++]; uint a = src[inds]; inds += wb; sumg += g * a; suma += a; } if (suma == 0) { dst[ind++] = 0; dst[ind] = 0; } else { dst[ind++] = (byte)(sumg / suma); dst[ind] = (byte)(suma / n); } ind += wb; } } return ret; } return new Image8i(0, 0, ChannelFormat); }
/// <summary> /// Converts to gray. /// </summary> /// <returns>The to gray.</returns> public Image8i ToChannelFormatGray() { if (ChannelFormat == ChannelFormat.Gray) return this; Image8i ret = new Image8i(Width, Height, ChannelFormat.Gray); if (ret.imageData == null) return ret; uint count = Width * Height; byte[] src = imageData; uint ind = 0; byte[] dst = ret.imageData; uint inds = 0; switch (ChannelFormat) { case ChannelFormat.GrayAlpha: { for (uint i = 0; i < count; i++) { dst[ind++] = src[inds++]; inds++; } break; } case ChannelFormat.BGR: { for (uint i = 0; i < count; i++) { byte r = src[inds++]; byte g = src[inds++]; byte b = src[inds++]; dst[ind++] = (byte)(0.299 * r + 0.587 * g + 0.114 * b); } break; } case ChannelFormat.RGB: { for (uint i = 0; i < count; i++) { byte b = src[inds++]; byte g = src[inds++]; byte r = src[inds++]; dst[ind++] = (byte)(0.299 * r + 0.587 * g + 0.114 * b); } break; } case ChannelFormat.BGRA: { for (uint i = 0; i < count; i++) { byte r = src[inds++]; byte g = src[inds++]; byte b = src[inds++]; inds++; dst[ind++] = (byte)(0.299 * r + 0.587 * g + 0.114 * b); } break; } case ChannelFormat.RGBA: { for (uint i = 0; i < count; i++) { byte b = src[inds++]; byte g = src[inds++]; byte r = src[inds++]; inds++; dst[ind++] = (byte)(0.299 * r + 0.587 * g + 0.114 * b); } break; } } return ret; }
/// <summary> /// Converts ToBGR /// </summary> /// <returns>The to BGR.</returns> public Image8i ToChannelFormatBGRA() { if (ChannelFormat == ChannelFormat.BGRA) return this; Image8i ret = new Image8i(Width, Height, ChannelFormat.BGRA); if (ret.imageData == null) return ret; uint count = Width * Height; byte[] src = imageData; uint ind = 0; byte[] dst = ret.imageData; uint inds = 0; switch (ChannelFormat) { case ChannelFormat.Gray: { for (uint i = 0; i < count; i++) { byte g = src[inds++]; dst[ind++] = g; dst[ind++] = g; dst[ind++] = g; dst[ind++] = 255; } break; } case ChannelFormat.GrayAlpha: { for (uint i = 0; i < count; i++) { byte g = src[inds++]; dst[ind++] = g; dst[ind++] = g; dst[ind++] = g; dst[ind++] = src[inds++]; } break; } case ChannelFormat.RGB: { for (uint i = 0; i < count; i++) { byte r = src[inds++]; byte g = src[inds++]; dst[ind++] = src[inds++]; dst[ind++] = g; dst[ind++] = r; dst[ind++] = 255; } break; } case ChannelFormat.RGBA: { for (uint i = 0; i < count; i++) { byte r = src[inds++]; byte g = src[inds++]; dst[ind++] = src[inds++]; dst[ind++] = g; dst[ind++] = r; dst[ind++] = src[inds++]; } break; } case ChannelFormat.BGR: { for (uint i = 0; i < count; i++) { dst[ind++] = src[inds++]; dst[ind++] = src[inds++]; dst[ind++] = src[inds++]; dst[ind++] = 255; } break; } } return ret; }
private Image8i Render(int width, int height, string onlyLayer) { Image8i ret = new Image8i((uint)width, (uint)height, ChannelFormat.RGBA); ret = ret.ToAlphaInvertedImage(); foreach (LayerData i in Layers) { if (onlyLayer == "") { if (i.name == "Collision") continue; } else { if (i.name != onlyLayer) continue; } for (int y = 0; y < i.height; y++) { for (int x = 0; x < i.width; x++) { int number = i.data[x, y]; if (number <= 0) continue; Image8i Tile = GetTile(number); int CorFactorX = 0; int CorFactorY = (int)(Tile.Height - TileHeight); ret.Draw(x * TileWidth - CorFactorX, y * TileHeight - CorFactorY, Tile, true); } } } return ret; }
public Image8i ToFlippedImageCounterDiagonal() { Image8i ret = new Image8i(Height, Width, ChannelFormat); if (ret.imageData == null) return ret; uint bpp = GetBytePerPixelFromChannelFormat(ChannelFormat); uint bw = Height * bpp; uint src = 0; uint dst = Width * bw - bpp; for (uint y = 0; y < Height; y++) { uint tmp = dst; for (uint x = 0; x < Width; x++) { for (uint i = 0; i < bpp; i++) ret.imageData[dst++] = imageData[src++]; dst -= bw + bpp; } dst = tmp - bpp; } return ret; }
public Image8i To180DegreeRotatedImage() { Image8i ret = new Image8i(Width, Height, ChannelFormat); if (ret.imageData == null) return ret; uint bpp = GetBytePerPixelFromChannelFormat(ChannelFormat); uint bw = Width * bpp; uint src = 0; uint dst = Height * bw; dst -= bpp; for (uint y = 0; y < Height; y++) { for (uint x = 0; x < Width; x++) { for (uint i = 0; i < bpp; i++) ret.imageData[dst++] = imageData[src++]; dst -= 2 * bpp; } } return ret; }
/// <summary> /// Gets a subimage from the image. /// </summary> /// <returns>The sub image.</returns> /// <param name="x">The x coordinate.</param> /// <param name="y">The y coordinate.</param> /// <param name="w">The width.</param> /// <param name="h">The height.</param> public Image8i GetSubimage(uint x, uint y, uint w, uint h) { if (x >= Width || y >= Height) throw new ArgumentOutOfRangeException("x or y", "Out of image."); Image8i ret = new Image8i(w, h, ChannelFormat); ret.Draw(-(int)x, -(int)y, this); return ret; }
/// <summary> /// Compare the specified compareImage with a threshold. /// Returns similartiy in percent (100 % == similar images) /// </summary> /// <param name="compareImage">Compare image.</param> /// <param name="threshold">Threshold.</param> public double Compare(Image8i compareImage, uint threshold) { if (compareImage == null) throw new Exception("Image is null"); if (Width != compareImage.Width) throw new Exception("Image have different sizes"); if (Height != compareImage.Height) throw new Exception("Image have different sizes"); if (ChannelFormat != compareImage.ChannelFormat) throw new Exception("Image have different formats"); uint divergency = 0; for (uint y = 0; y < Width; y++) { for (uint x = 0; x < Height; x++) { Color8i picA = GetPixel(x, y); Color8i picB = compareImage.GetPixel(x, y); int dif = 0; dif += System.Math.Abs(picA.R - picB.R); dif += System.Math.Abs(picA.G - picB.G); dif += System.Math.Abs(picA.B - picB.B); dif /= 3; if (dif > threshold) divergency++; } } return (double)(100 * (divergency / (double)(Width * Height))); }
/// <summary> /// Draw the specified x, y and source. /// </summary> /// <param name="x">The x coordinate.</param> /// <param name="y">The y coordinate.</param> /// <param name="source">Source.</param> public void Draw(int x, int y, Image8i sourceImage) { if (x >= Width || y >= Height) throw new ArgumentOutOfRangeException("x or y", "Out of image."); if (x + sourceImage.Width < 0 || y + sourceImage.Height < 0) throw new ArgumentOutOfRangeException("x or y", "Out of image."); Image8i srcimg = sourceImage.ToChannelFormat(ChannelFormat); if (srcimg == null) return; uint bytePerPixel = GetBytePerPixelFromChannelFormat(ChannelFormat); unsafe { fixed(byte* src_=srcimg.imageData, dst_=imageData) { uint start = (uint)System.Math.Max(-x, 0) * bytePerPixel; uint end = (uint)System.Math.Min(sourceImage.Width, Width - x) * bytePerPixel; uint jstart = (uint)System.Math.Max(-y, 0); uint jend = (uint)System.Math.Min(sourceImage.Height, Height - y); byte* src__ = src_ + start; byte* dst__ = dst_ + x * bytePerPixel + start; uint sw = sourceImage.Width * bytePerPixel; uint dw = Width * bytePerPixel; 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++) *dst++ = *src++; } } } }
/// <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 }
unsafe Image8i ToDownsampledImageHorizontal(uint w) { if ((Width * Height) == 0) return new Image8i(0, 0, ChannelFormat); if (w == 0) return new Image8i(0, 0, ChannelFormat); if (Width > w && Width % w == 0) return ToReducedByImageHorizontal(Width / w); double delta = ((double)Width) / w; if (ChannelFormat == ChannelFormat.Gray) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; fixed(byte* _dst=ret.imageData, _src=imageData) { byte* dst = _dst; for (uint y = 0; y < Height; y++) { byte* src = _src + y * Width; for (uint x = 0; x < w; x++) { double deltax = x * delta; double dx = 1 - (deltax - ((uint)deltax)); byte* s = src + ((uint)deltax); double deltasum = dx; double gsum = *(s++) * dx; while ((delta - deltasum) > 0.0001) { dx = delta - deltasum; if (dx >= 1) { deltasum += 1; gsum += *(s++); } else { gsum += *s * dx; break; } } *(dst++) = (byte)(gsum / delta + 0.5); } } } return ret; } if (ChannelFormat == ChannelFormat.RGB || ChannelFormat == ChannelFormat.BGR) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; fixed(byte* _dst=ret.imageData, _src=imageData) { byte* dst = _dst; uint wb = Width * 3; for (uint y = 0; y < Height; y++) { byte* src = _src + y * wb; for (uint x = 0; x < w; x++) { double deltax = x * delta; double dx = 1 - (deltax - ((uint)deltax)); byte* s = src + ((uint)deltax) * 3; double deltasum = dx; double rsum = *(s++) * dx; double gsum = *(s++) * dx; double bsum = *(s++) * dx; while ((delta - deltasum) > 0.0001) { dx = delta - deltasum; if (dx >= 1) { deltasum += 1; rsum += *(s++); gsum += *(s++); bsum += *(s++); } else { rsum += *(s++) * dx; gsum += *(s++) * dx; bsum += *s * dx; break; } } *(dst++) = (byte)(rsum / delta + 0.5); *(dst++) = (byte)(gsum / delta + 0.5); *(dst++) = (byte)(bsum / delta + 0.5); } } } return ret; } if (ChannelFormat == ChannelFormat.RGBA || ChannelFormat == ChannelFormat.BGRA) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; fixed(byte* _dst=ret.imageData, _src=imageData) { byte* dst = _dst; uint wb = Width * 4; for (uint y = 0; y < Height; y++) { byte* src = _src + y * wb; for (uint x = 0; x < w; x++) { double deltax = x * delta; double dx = 1 - (deltax - ((uint)deltax)); byte* s = src + ((uint)deltax) * 4; double deltasum = dx; byte r = *(s++), g = *(s++), b = *(s++); uint a = *(s++); double adx = a * dx; double rsum = r * adx; double gsum = g * adx; double bsum = b * adx; double asum = adx; while ((delta - deltasum) > 0.0001) { dx = delta - deltasum; r = *(s++); g = *(s++); b = *(s++); a = *(s++); if (dx >= 1) { deltasum += 1; rsum += r * a; gsum += g * a; bsum += b * a; asum += a; } else { adx = a * dx; rsum += r * adx; gsum += g * adx; bsum += b * adx; asum += adx; break; } } *(dst++) = (byte)(rsum / asum + 0.5); *(dst++) = (byte)(gsum / asum + 0.5); *(dst++) = (byte)(bsum / asum + 0.5); *(dst++) = (byte)(asum / delta + 0.5); } } } return ret; } if (ChannelFormat == ChannelFormat.GrayAlpha) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; fixed(byte* _dst=ret.imageData, _src=imageData) { byte* dst = _dst; uint wb = Width * 2; for (uint y = 0; y < Height; y++) { byte* src = _src + y * wb; for (uint x = 0; x < w; x++) { double deltax = x * delta; double dx = 1 - (deltax - ((uint)deltax)); byte* s = src + ((uint)deltax) * 2; double deltasum = dx; byte g = *(s++); uint a = *(s++); double gsum = g * dx * a; double asum = a * dx; while ((delta - deltasum) > 0.0001) { dx = delta - deltasum; g = *(s++); a = *(s++); if (dx >= 1) { deltasum += 1; gsum += g * a; asum += a; } else { double adx = a * dx; gsum += g * adx; asum += adx; break; } } *(dst++) = (byte)(gsum / asum + 0.5); *(dst++) = (byte)(asum / delta + 0.5); } } } return ret; } return new Image8i(0, 0, ChannelFormat); }
public static Image8i FromBitmap(Bitmap bmp) { Image8i ret = null; uint width = (uint)bmp.Width; uint height = (uint)bmp.Height; if ((bmp.PixelFormat & PixelFormat.Alpha) == PixelFormat.Alpha) { ret = new Image8i(width, height, ChannelFormat.RGBA); BitmapData data = bmp.LockBits(new Rectangle(0, 0, (int)width, (int)height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); Marshal.Copy(data.Scan0, ret.imageData, 0, (int)(width * height * 4)); bmp.UnlockBits(data); } else { ret = new Image8i(width, height, ChannelFormat.RGB); BitmapData data = bmp.LockBits(new Rectangle(0, 0, (int)width, (int)height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); if (((int)width * 3) == data.Stride) { Marshal.Copy(data.Scan0, ret.imageData, 0, (int)(width * height * 3)); } else { if (IntPtr.Size == 4) { for (uint i = 0; i < height; i++) { Marshal.Copy((IntPtr)(data.Scan0.ToInt32() + (int)(i * data.Stride)), ret.imageData, (int)(width * 3 * i), (int)(width * 3)); } } else if (IntPtr.Size == 8) { for (uint i = 0; i < height; i++) { Marshal.Copy((IntPtr)(data.Scan0.ToInt64() + (long)(i * data.Stride)), ret.imageData, (int)(width * 3 * i), (int)(width * 3)); } } } bmp.UnlockBits(data); data = null; bmp.Dispose(); bmp = null; } return ret; }
unsafe Image8i ToDownsampledImageVertical(uint h) { if ((Width * Height) == 0) return new Image8i(0, 0, ChannelFormat); if (h == 0) return new Image8i(0, 0, ChannelFormat); if (Height > h && Height % h == 0) return ToReducedByImageVertical(Height / h); double delta = ((double)Height) / h; if (ChannelFormat == ChannelFormat.Gray) { Image8i ret = new Image8i(Width, h, ChannelFormat); if (ret.imageData == null) return ret; for (uint x = 0; x < Width; x++) { fixed(byte* _dst=ret.imageData, _src=imageData) { byte* dst = _dst + x; byte* src = _src + x; for (uint y = 0; y < h; y++) { double deltay = y * delta; double dy = 1 - (deltay - ((uint)deltay)); byte* s = src + ((uint)deltay) * Width; double deltasum = dy; double gsum = *s * dy; s += Width; while ((delta - deltasum) > 0.0001) { dy = delta - deltasum; if (dy >= 1) { deltasum += 1; gsum += *s; s += Width; } else { gsum += *s * dy; break; } } *dst = (byte)(gsum / delta + 0.5); dst += Width; } } } return ret; } if (ChannelFormat == ChannelFormat.RGB || ChannelFormat == ChannelFormat.BGR) { Image8i ret = new Image8i(Width, h, ChannelFormat); if (ret.imageData == null) return ret; int wb = (int)Width * 3; int wb2 = wb - 2; for (uint x = 0; x < Width; x++) { fixed(byte* _dst=ret.imageData, _src=imageData) { byte* dst = _dst + x * 3; byte* src = _src + x * 3; for (uint y = 0; y < h; y++) { double deltay = y * delta; double dy = 1 - (deltay - ((uint)deltay)); byte* s = src + ((uint)deltay) * wb; double deltasum = dy; double rsum = *(s++) * dy; double gsum = *(s++) * dy; double bsum = *s * dy; s += wb2; while ((delta - deltasum) > 0.0001) { dy = delta - deltasum; if (dy >= 1) { deltasum += 1; rsum += *(s++); gsum += *(s++); bsum += *s; s += wb2; } else { rsum += *(s++) * dy; gsum += *(s++) * dy; bsum += *s * dy; break; } } *(dst++) = (byte)(rsum / delta + 0.5); *(dst++) = (byte)(gsum / delta + 0.5); *dst = (byte)(bsum / delta + 0.5); dst += wb2; } } } return ret; } if (ChannelFormat == ChannelFormat.RGBA || ChannelFormat == ChannelFormat.BGRA) { Image8i ret = new Image8i(Width, h, ChannelFormat); if (ret.imageData == null) return ret; int wb = (int)Width * 4; int wb3 = wb - 3; for (uint x = 0; x < Width; x++) { fixed(byte* _dst=ret.imageData, _src=imageData) { byte* dst = _dst + x * 4; byte* src = _src + x * 4; for (uint y = 0; y < h; y++) { double deltay = y * delta; double dy = 1 - (deltay - ((uint)deltay)); byte* s = src + ((uint)deltay) * wb; double deltasum = dy; byte r = *(s++), g = *(s++), b = *(s++); uint a = *s; s += wb3; double ady = a * dy; double rsum = r * ady; double gsum = g * ady; double bsum = b * ady; double asum = ady; while ((delta - deltasum) > 0.0001) { r = *(s++); g = *(s++); b = *(s++); a = *s; s += wb3; dy = delta - deltasum; if (dy >= 1) { deltasum += 1; rsum += r * a; gsum += g * a; bsum += b * a; asum += a; } else { ady = a * dy; rsum += r * ady; gsum += g * ady; bsum += b * ady; asum += ady; break; } } *(dst++) = (byte)(rsum / asum + 0.5); *(dst++) = (byte)(gsum / asum + 0.5); *(dst++) = (byte)(bsum / asum + 0.5); *dst = (byte)(asum / delta + 0.5); dst += wb3; } } } return ret; } if (ChannelFormat == ChannelFormat.GrayAlpha) { Image8i ret = new Image8i(Width, h, ChannelFormat); if (ret.imageData == null) return ret; int wb = (int)Width * 2; int wb1 = wb - 1; for (uint x = 0; x < Width; x++) { fixed(byte* _dst=ret.imageData, _src=imageData) { byte* dst = _dst + x * 2; byte* src = _src + x * 2; for (uint y = 0; y < h; y++) { double deltay = y * delta; double dy = 1 - (deltay - ((uint)deltay)); byte* s = src + ((uint)deltay) * wb; double deltasum = dy; byte g = *(s++); uint a = *s; s += wb1; double ady = a * dy; double gsum = g * ady; double asum = ady; while ((delta - deltasum) > 0.0001) { g = *(s++); a = *s; s += wb1; dy = delta - deltasum; if (dy >= 1) { deltasum += 1; gsum += g * a; asum += a; } else { ady = a * dy; gsum += g * ady; asum += ady; break; } } *(dst++) = (byte)(gsum / asum + 0.5); *dst = (byte)(asum / delta + 0.5); dst += wb1; } } } return ret; } return new Image8i(0, 0, ChannelFormat); }
public Image8i ToFlippedImageHorizontal() { Image8i ret = new Image8i(Width, Height, ChannelFormat); if (ret.imageData == null) return ret; uint bw = Width * GetBytePerPixelFromChannelFormat(ChannelFormat); uint src = 0; uint dst = Height * bw; for (uint y = 0; y < Height; y++) { dst -= bw; for (uint x = 0; x < bw; x++) ret.imageData[dst++] = imageData[src++]; dst -= bw; } return ret; }
public Image8i ToAlphaInvertedImage() { if (ChannelFormat != ChannelFormat.RGBA && ChannelFormat != ChannelFormat.BGRA && ChannelFormat != ChannelFormat.GrayAlpha) return this; Image8i ret = new Image8i(Width, Height, ChannelFormat); if (ret.ImageData == null) return ret; uint count = Width * Height * GetBytePerPixelFromChannelFormat(ChannelFormat); if (ChannelFormat == ChannelFormat.BGRA || ChannelFormat == ChannelFormat.RGBA) { for (uint i = 0; i < count; i += 4) { ret.imageData[i] = (byte)(imageData[i]); ret.imageData[i + 1] = (byte)(imageData[i + 1]); ret.imageData[i + 2] = (byte)(imageData[i + 2]); ret.imageData[i + 3] = (byte)(255 - imageData[i + 3]); } } else if (ChannelFormat == ChannelFormat.GrayAlpha) { for (uint i = 0; i < count; i += 2) { ret.imageData[i] = (byte)(imageData[i]); ret.imageData[i + 1] = (byte)(255 - imageData[i + 1]); } } return ret; }
public Image8i ToFlippedImageDiagonal() { Image8i ret = new Image8i(Height, Width, ChannelFormat); uint bpp = GetBytePerPixelFromChannelFormat(ChannelFormat); uint bw = Height * bpp; uint src = 0; uint dst = 0; for (uint y = 0; y < Height; y++) { for (uint x = 0; x < Width; x++) { for (uint i = 0; i < bpp; i++) ret.imageData[dst++] = imageData[src++]; dst += bw - bpp; } dst = y * bpp; } return ret; }
Image8i ToNearestPixelResizedImageVertical(uint h) { double delta = (double)Height / h; Image8i ret = new Image8i(Width, h, ChannelFormat); if (ret.imageData == null) return ret; uint bpp = GetBytePerPixelFromChannelFormat(ChannelFormat); uint bw = Width * bpp; uint dst = 0; for (uint y = 0; y < h; y++) { uint src = ((uint)(y * delta + delta / 2)) * bw; for (uint i = 0; i < bw; i++) ret.imageData[dst++] = imageData[src++]; } return ret; }
public Image8i To90DegreeRotatedImage() { Image8i ret = new Image8i(Height, Width, ChannelFormat); if (ret.imageData == null) return ret; uint bpp = GetBytePerPixelFromChannelFormat(ChannelFormat); uint bw = Height * bpp; uint src = 0; uint dst_ = (Width - 1) * bw; for (uint y = 0; y < Height; y++) { uint dst = dst_; for (uint x = 0; x < Width; x++) { for (uint i = 0; i < bpp; i++) ret.imageData[dst++] = imageData[src++]; dst -= bw + bpp; } dst_ += bpp; } return ret; }
Image8i ToNearestPixelResizedImageHorizontal(uint w) { double delta = (double)Width / w; uint bpp = GetBytePerPixelFromChannelFormat(ChannelFormat); uint[] dx = new uint[w]; for (uint x = 0; x < w; x++) dx[x] = (uint)(x * delta + delta / 2); if (bpp == 1) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; uint dst = 0; for (uint y = 0; y < Height; y++) { uint src = y * Width; for (uint x = 0; x < w; x++) ret.imageData[dst++] = imageData[src + dx[x]]; } return ret; } if (bpp == 4) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; uint bw = Width * 4; uint dst = 0; for (uint y = 0; y < Height; y++) { uint src = y * bw; for (uint x = 0; x < w; x++) { uint s = src + dx[x] * 4; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s]; } } return ret; } if (bpp == 3) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; uint bw = Width * 3; uint dst = 0; for (uint y = 0; y < Height; y++) { uint src = y * bw; for (uint x = 0; x < w; x++) { uint s = src + dx[x] * 3; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s]; } } return ret; } if (bpp == 2) { Image8i ret = new Image8i(w, Height, ChannelFormat); if (ret.imageData == null) return ret; uint bw = Width * 2; uint dst = 0; for (uint y = 0; y < Height; y++) { uint src = y * bw; for (uint x = 0; x < w; x++) { uint s = src + dx[x] * 2; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s]; } } return ret; } return new Image8i(0, 0, ChannelFormat); }
public Image8i To270DegreeRotatedImage() { Image8i ret = new Image8i(Height, Width, ChannelFormat); if (ret.imageData == null) return ret; uint bpp = GetBytePerPixelFromChannelFormat(ChannelFormat); uint bw = Width * bpp; uint dst = 0; uint src_ = (Height - 1) * bw; for (uint y = 0; y < Width; y++) { uint src = src_; for (uint x = 0; x < Height; x++) { for (uint i = 0; i < bpp; i++) ret.imageData[dst++] = imageData[src++]; src -= bw + bpp; } src_ += bpp; } return ret; }
Image8i ToNearestPixelResizedImageVerticalHorizontal(uint w, uint h) { double deltah = (double)Height / h; double deltaw = (double)Width / w; uint bpp = GetBytePerPixelFromChannelFormat(ChannelFormat); uint[] dx = new uint[w]; for (uint x = 0; x < w; x++) dx[x] = (uint)(x * deltaw + deltaw / 2); if (bpp == 1) { Image8i ret = new Image8i(w, h, ChannelFormat); if (ret.imageData == null) return ret; uint dst = 0; for (uint y = 0; y < h; y++) { uint src = (uint)(y * deltah + deltah / 2) * Width; for (uint x = 0; x < w; x++) ret.imageData[dst++] = imageData[src + dx[x]]; } return ret; } if (bpp == 4) { Image8i ret = new Image8i(w, h, ChannelFormat); if (ret.imageData == null) return ret; uint dst = 0; uint w4 = Width * 4; for (uint y = 0; y < h; y++) { uint src = (uint)(y * deltah + deltah / 2) * w4; for (uint x = 0; x < w; x++) { uint s = src + dx[x] * 4; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s]; } } return ret; } if (bpp == 3) { Image8i ret = new Image8i(w, h, ChannelFormat); if (ret.imageData == null) return ret; uint dst = 0; uint w3 = Width * 3; for (uint y = 0; y < h; y++) { uint src = (uint)(y * deltah + deltah / 2) * w3; for (uint x = 0; x < w; x++) { uint s = src + dx[x] * 3; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s]; } } return ret; } if (bpp == 2) { Image8i ret = new Image8i(w, h, ChannelFormat); if (ret.imageData == null) return ret; uint dst = 0; uint w2 = Width * 2; for (uint y = 0; y < h; y++) { uint src = (uint)(y * deltah + deltah / 2) * w2; for (uint x = 0; x < w; x++) { uint s = src + dx[x] * 2; ret.imageData[dst++] = imageData[s++]; ret.imageData[dst++] = imageData[s]; } } return ret; } return new Image8i(0, 0, ChannelFormat); }
/// <summary> /// Swaps the channels to GBR; /// </summary> /// <returns>The channels to GB.</returns> public Image8i ToGBRSwappedChannels() { if (ChannelFormat != ChannelFormat.RGB) return this.ToChannelFormatRGB().ToBGRSwappedChannels(); Image8i ret = new Image8i(Width, Height, ChannelFormat.RGB); if (ret.imageData == null) return ret; uint count = Width * Height; byte[] src = imageData; uint ind = 0; byte[] dst = ret.imageData; uint inds = 0; // Channel Swap RGB for (uint i = 0; i < count; i++) { byte r = src[inds++]; byte g = src[inds++]; byte b = src[inds++]; dst[ind++] = g; dst[ind++] = b; dst[ind++] = r; } return ret; }
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(); } }