public static Texture2D CreateTexture2DFromBitmap(Device device, BitmapSource bitmapSource) { // Allocate DataStream to receive the WIC image pixels int stride = bitmapSource.Size.Width * 4; using (var buffer = new SharpDX.DataStream(bitmapSource.Size.Height * stride, true, true)) { // Copy the content of the WIC to the buffer bitmapSource.CopyPixels(stride, buffer); return new SharpDX.Direct3D11.Texture2D(device, new SharpDX.Direct3D11.Texture2DDescription() { Width = bitmapSource.Size.Width, Height = bitmapSource.Size.Height, ArraySize = 1, BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource, Usage = SharpDX.Direct3D11.ResourceUsage.Immutable, CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None, Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm, MipLevels = 1, OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None, SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), }, new SharpDX.DataRectangle(buffer.DataPointer, stride)); } }
//縮小拡大対応完成版 /// <summary> /// 画像の拡大縮小、バイリニア法で補完(PixelFormats.Bgr24専用) /// </summary> /// <param name="source">PixelFormats.Bgr24のBitmap</param> /// <param name="yoko">横ピクセル数を指定</param> /// <param name="tate">縦ピクセル数を指定</param> /// <returns></returns> private BitmapSource BilinearBgr24専用(BitmapSource source, int yoko, int tate) { //元画像の画素値の配列作成 int sourceWidth = source.PixelWidth; int sourceHeight = source.PixelHeight; int stride = (sourceWidth * source.Format.BitsPerPixel + 7) / 8; byte[] pixels = new byte[sourceHeight * stride]; source.CopyPixels(pixels, stride, 0); //縮小後の画像の画素値の配列用 double yokoScale = (double)sourceWidth / yoko;//横倍率 double tateScale = (double)sourceHeight / tate; //1ピクセルあたりのバイト数、Byte / Pixel int pByte = (source.Format.BitsPerPixel + 7) / 8; int scaledStride = yoko * pByte; byte[] resultPixels = new byte[tate * scaledStride]; _ = Parallel.For(0, tate, y => { for (int x = 0; x < yoko; x++) { //参照範囲の左上座標bp double bpX = ((x + 0.5) * yokoScale) - 0.5; //画像範囲内チェック、参照範囲が画像から外れていたら修正(収める) if (bpX < 0) { bpX = 0; } if (bpX > sourceWidth - 1) { bpX = sourceWidth - 1; } double bpY = (y + 0.5) * tateScale - 0.5; if (bpY < 0) { bpY = 0; } if (bpY > sourceHeight - 1) { bpY = sourceHeight - 1; } //小数部分s double sx = bpX % 1; double sy = bpY % 1; //面積 double d = sx * sy; double c = (1 - sx) * sy; double b = sx * (1 - sy); double a = 1 - (d + c + b);// (1 - sx) * (1 - sy) //左上ピクセルの座標は //参照範囲の左上座標の小数部分を切り捨て(整数部分) //左上ピクセルのIndex int i = ((int)bpY * stride) + ((int)bpX * pByte); //値*面積 double aBlue = pixels[i] * a; double aGreen = pixels[i + 1] * a; double aRed = pixels[i + 2] * a; double bBlue = 0; double bGreen = 0; double bRed = 0; double cBlue = 0; double cGreen = 0; double cRed = 0; double dBlue = 0; double dGreen = 0; double dRed = 0; //B区以降は面積が0より大きいときだけ計算 if (b != 0) { //Aの右ピクセル*Bの面積 bBlue = pixels[i + pByte] * b; bGreen = pixels[i + pByte + 1] * b; bRed = pixels[i + pByte + 2] * b; } if (c != 0) { cBlue = pixels[i + stride] * c; cGreen = pixels[i + stride + 1] * c; cRed = pixels[i + stride + 2] * c; } if (d != 0) { //Aの右下ピクセル、仮にAが画像右下ピクセルだったとしても //そのときは面積が0のはずだからここは計算されない dBlue = pixels[i + stride + pByte] * d; dGreen = pixels[i + stride + pByte + 1] * d; dRed = pixels[i + stride + pByte + 2] * d; } //4区を合計して四捨五入で完成 resultPixels[y * scaledStride + x * pByte] = (byte)(aBlue + bBlue + cBlue + dBlue + 0.5); resultPixels[y * scaledStride + x * pByte + 1] = (byte)(aGreen + bGreen + cGreen + dGreen + 0.5); resultPixels[y * scaledStride + x * pByte + 2] = (byte)(aRed + bRed + cRed + dRed + 0.5); } }); BitmapSource bitmap = BitmapSource.Create(yoko, tate, 96, 96, source.Format, null, resultPixels, scaledStride); return(bitmap); }
/// <summary> /// Loads an image, checks if it is a PNG containing palette transparency, and if so, ensures it loads correctly. /// The theory can be found at http://www.libpng.org/pub/png/book/chapter08.html /// </summary> /// <param name="data">File data to load</param> /// <param name="paletteLength">Palette length in the original image. The palette format of .net is not adjustable in size, so it'll be the max size. This value can be used to adjust that.</param> /// <returns>The loaded image</returns> public static Bitmap LoadBitmap(Byte[] data, out Int32 paletteLength) { Bitmap loadedImage; if (data.Length > PNG_IDENTIFIER.Length && data.Take(PNG_IDENTIFIER.Length).SequenceEqual(PNG_IDENTIFIER)) { Byte[] transparencyData = null; // Check if it contains a palette. // I'm sure it can be looked up in the header somehow, but meh. Int32 plteOffset = FindChunk(data, "PLTE"); if (plteOffset != -1) { // Check if it contains a palette transparency chunk. Int32 trnsOffset = FindChunk(data, "tRNS"); if (trnsOffset != -1) { // Get chunk Int32 trnsLength = GetChunkDataLength(data, trnsOffset); transparencyData = new Byte[trnsLength]; Array.Copy(data, trnsOffset + 8, transparencyData, 0, trnsLength); // filter out the palette alpha chunk, make new data array Byte[] data2 = new Byte[data.Length - (trnsLength + 12)]; Array.Copy(data, 0, data2, 0, trnsOffset); Int32 trnsEnd = trnsOffset + trnsLength + 12; Array.Copy(data, trnsEnd, data2, trnsOffset, data.Length - trnsEnd); data = data2; } } // Open a Stream and decode a PNG image using (MemoryStream imageStreamSource = new MemoryStream(data)) { PngBitmapDecoder decoder = new PngBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); BitmapSource bitmapSource = decoder.Frames[0]; Int32 width = bitmapSource.PixelWidth; Int32 height = bitmapSource.PixelHeight; Int32 stride = ImageUtils.GetMinimumStride(width, bitmapSource.Format.BitsPerPixel); Byte[] pixel = new Byte[height * stride]; bitmapSource.CopyPixels(pixel, stride, 0); WriteableBitmap myBitmap = new WriteableBitmap(width, height, 96, 96, bitmapSource.Format, bitmapSource.Palette); myBitmap.WritePixels(new Int32Rect(0, 0, width, height), pixel, stride, 0); // Convert WPF BitmapSource to GDI+ Bitmap Bitmap newBitmap = BitmapFromSource(myBitmap); System.Drawing.Color[] colpal = newBitmap.Palette.Entries; Boolean hasTransparency = false; if (colpal.Length != 0 && transparencyData != null) { for (Int32 i = 0; i < colpal.Length; i++) { if (i >= transparencyData.Length) { break; } System.Drawing.Color col = colpal[i]; colpal[i] = System.Drawing.Color.FromArgb(transparencyData[i], col.R, col.G, col.B); if (!hasTransparency) { hasTransparency = transparencyData[i] == 0; } } } paletteLength = colpal.Length; if (!hasTransparency) { return(newBitmap); } Byte[] imageData = ImageUtils.GetImageData(newBitmap, out stride); return(ImageUtils.BuildImage(imageData, newBitmap.Width, newBitmap.Height, stride, newBitmap.PixelFormat, colpal, System.Drawing.Color.Empty)); } } using (MemoryStream ms = new MemoryStream(data)) { // Prevents the image from breaking when the underlying stream is disposed. loadedImage = ImageUtils.CloneImage(new Bitmap(ms)); ms.Close(); paletteLength = loadedImage.Palette.Entries.Length; } return(loadedImage); }
//変換直前に個別にガンマ補正、可変ガンマ値 private BitmapSource D7(BitmapSource source, int colorsCount) { Dictionary <int, byte> convertTable = MakeTable(colorsCount); double stepRange = 1.0 / colorsCount;//0.333 //画素値の配列作成 int width = source.PixelWidth; int height = source.PixelHeight; int stride = width; byte[] pixels = new byte[height * stride];//もとの値Pixels source.CopyPixels(pixels, stride, 0); //誤差拡散計算用 double gamma = 2.2; var gosaPixels = GammaCorrect2(pixels, colorsCount, gamma); var localGamma = MakeLocalGamma5(colorsCount, gamma); int p; //座標を配列のインデックスに変換した値用 double gosa; //誤差(変換前 - 変換後) int splitCount = colorsCount - 1; //分割数 double stepTone = 1.0 / splitCount; //1階調 //(128*x/65536/255)^(1/2.2)=(100/255)^(1/2.2) //(128*x/65536/255)=(100/255) //128*x/65536=100 //128*x=100*65536 //x=100*65536/128 for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { p = y * stride + x; double gp = gosaPixels[p] / 255.0; if (gp < 0) { gp = 0.0; //マイナスになる場合もある、そのときは0に強制変換 } if (gp > 1) { gp = 1.0; } int index = (int)(gp / stepTone); double begin = stepTone * index; double gg = (gp - begin) * splitCount; gg = Math.Pow(gg, localGamma[index]); //ガンマ補正 gg /= splitCount; gg += begin; //補正後出力値 = 開始値+((入力値-開始値)*分割数)^(γ値)/分割数 //変換 double neko = gg / stepRange; //0.333 //int inu = (int)(neko + 0.5);//四捨五入 int inu = (int)neko; //切り捨て if (inu == 2) { var uu = 0; } pixels[p] = convertTable[inu]; //誤差拡散 gosa = (gosaPixels[p] - pixels[p]) / 16.0; if (x != width - 1) { gosaPixels[p + 1] += gosa * 7;//右 } if (y < height - 1) { p += stride; gosaPixels[p] += gosa * 5;//下 if (x != 0) { gosaPixels[p - 1] += gosa * 3;//左下 } if (x != width - 1) { gosaPixels[p + 1] += gosa * 1;//右下 } } } } return(BitmapSource.Create(width, height, 96, 96, PixelFormats.Gray8, null, pixels, stride)); }
//public static BitmapSource loadBitmap(Bitmap source) //{ // IntPtr hBitmap = source.GetHbitmap(); // //Memory Leak fixes, for more info : http://social.msdn.microsoft.com/forums/en-US/wpf/thread/edcf2482-b931-4939-9415-15b3515ddac6/ // try // { // BitmapSource retVal = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, // BitmapSizeOptions.FromEmptyOptions()); // if (retVal.CanFreeze) // retVal.Freeze(); // else if (Debugger.IsAttached) // Debugger.Break(); // return retVal; // } // catch // { // return new BitmapImage(); // } // finally // { // DeleteObject(hBitmap); // } //} private static void copyBitmap(BitmapSource source, WriteableBitmap target, bool dispatcher, int spacing, bool freezeBitmap) { int width = source.PixelWidth; int height = source.PixelHeight; int stride = width * ((source.Format.BitsPerPixel + 7) / 8); byte[] bits = new byte[height * stride]; source.CopyPixels(bits, stride, 0); source = null; //original code. //writeBitmap.Dispatcher.Invoke(DispatcherPriority.Background, // new ThreadStart(delegate // { // //UI Thread // Int32Rect outRect = new Int32Rect(0, (int)(writeBitmap.Height - height) / 2, width, height); // writeBitmap.WritePixels(outRect, bits, stride, 0); // })); //Bugfixes by h32 if (dispatcher) { target.Dispatcher.BeginInvoke(DispatcherPriority.Background, new ThreadStart(delegate { //UI Thread var delta = target.Height - height; var newWidth = width > target.Width ? (int)target.Width : width; var newHeight = height > target.Height ? (int)target.Height : height; Int32Rect outRect = new Int32Rect((int)((target.Width - newWidth) / 2), (int)(delta >= 0 ? delta : 0) / 2 + spacing, newWidth - (spacing * 2), newWidth - (spacing * 2)); try { target.WritePixels(outRect, bits, stride, 0); if (freezeBitmap) { target.Freeze(); } } catch (Exception e) { Debug.WriteLine(e); System.Diagnostics.Debugger.Break(); } })); } else { var delta = target.Height - height; var newWidth = width > target.Width ? (int)target.Width : width; var newHeight = height > target.Height ? (int)target.Height : height; Int32Rect outRect = new Int32Rect(spacing, (int)(delta >= 0 ? delta : 0) / 2 + spacing, newWidth - (spacing * 2), newWidth - (spacing * 2)); try { target.WritePixels(outRect, bits, stride, 0); if (freezeBitmap) { target.Freeze(); } } catch (Exception e) { Debug.WriteLine(e); System.Diagnostics.Debugger.Break(); } } }
public void setPixelDataRGB() { mySourceBitmap.CopyPixels(pixelDataRGB, rawStride, 0); /* possible ArgumentOutOfRangeException */ }
private Rect DetectInnerRectFromPixels(BitmapSource bitmap, Rect outerRect) { int stride = bitmap.PixelWidth * 4; int size = bitmap.PixelHeight * stride; byte[] pixels = new byte[size]; bitmap.CopyPixels(pixels, stride, 0); int lowX = -1; int lowY = int.MaxValue; int highX = -1; int highY = -1; for (int x = 0; x < bitmap.PixelWidth; x++) { for (int y = 0; y < bitmap.PixelHeight; y++) { int index = (y * stride) + (4 * x); byte blue = pixels[index]; byte green = pixels[index + 1]; byte red = pixels[index + 2]; //byte alpha = pixels[index + 3]; if (red != 0 || blue != 0) { if (lowX == -1) { lowX = x; } if (y < lowY) { lowY = y; } highX = x; if (y > highY) { highY = y; } } if (green != 0) { MessageBox.Show("Green!?"); return(Rect.Empty); } } } // Some glyphs may not be rendered at all in the selected font if (lowX == -1) { return(outerRect); } Point upperLeft = new Point(outerRect.X + lowX, outerRect.Y + lowY); Point lowerRight = new Point(outerRect.X + highX + SpacingAdjustment + 1, outerRect.Y + highY + 2); // TODO: Why is +1/+2 needed? return(new Rect(upperLeft, lowerRight)); }
public override BitmapSource ExecuteFilter(BitmapSource inputImage) { int width = inputImage.PixelWidth; int height = inputImage.PixelHeight; int arrayLens = 1 + Coarseness; int[] intensityCount; uint[] avgRed; uint[] avgGreen; uint[] avgBlue; uint[] avgAlpha; byte[] sourceBytes = new byte[inputImage.PixelWidth * inputImage.PixelHeight * 4]; byte[] destBytes = new byte[inputImage.PixelWidth * inputImage.PixelHeight * 4]; inputImage.CopyPixels(sourceBytes, inputImage.PixelWidth * 4, 0); byte maxIntensity = Coarseness; double scaleFactor = (double)maxIntensity / 255.0; for (int y = 0; y < height; y++) { int top = y - BrushSize; int bottom = y + BrushSize + 1; if (top < 0) { top = 0; } if (bottom > height) { bottom = height; } for (int x = 0; x < width; x++) { int index = y * width * 4 + x * 4; intensityCount = new int[arrayLens]; avgRed = new uint[arrayLens]; avgGreen = new uint[arrayLens]; avgBlue = new uint[arrayLens]; avgAlpha = new uint[arrayLens]; int left = x - BrushSize; int right = x + BrushSize + 1; if (left < 0) { left = 0; } if (right > width) { right = width; } int numInt = 0; for (int j = top; j < bottom; j++) { int sourceIndex = j * width * 4 + left * 4; for (int i = left; i < right; i++) { byte srcA = sourceBytes[sourceIndex + 3]; byte srcR = sourceBytes[sourceIndex + 2]; byte srcG = sourceBytes[sourceIndex + 1]; byte srcB = sourceBytes[sourceIndex]; double iDouble = srcB * 0.11 + srcG * 0.59 + srcR * 0.30; //byte iByte = (byte)iDouble; //byte intensity = Utility.FastScaleByteByByte(iByte, maxIntensity); byte intensity = (byte)(iDouble * scaleFactor); intensityCount[intensity]++; numInt++; avgRed[intensity] += srcR; avgGreen[intensity] += srcG; avgBlue[intensity] += srcB; avgAlpha[intensity] += srcA; } } byte chosenIntensity = 0; int maxInstance = 0; for (int i = 0; i <= maxIntensity; ++i) { if (intensityCount[i] > maxInstance) { chosenIntensity = (byte)i; maxInstance = intensityCount[i]; } } // TODO: correct handling of alpha values? destBytes[index + 2] = (byte)(avgRed[chosenIntensity] / maxInstance); destBytes[index + 1] = (byte)(avgGreen[chosenIntensity] / maxInstance); destBytes[index] = (byte)(avgBlue[chosenIntensity] / maxInstance); destBytes[index + 3] = (byte)(avgAlpha[chosenIntensity] / maxInstance); } } return(BitmapSource.Create(inputImage.PixelWidth, inputImage.PixelHeight, 96, 96, inputImage.Format, null, destBytes, inputImage.PixelWidth * 4)); }
public BitmapSource DecryptImg(BitmapSource inputImg) { int bytesPerPixel = (inputImg.Format.BitsPerPixel + 7) / 8; if (inBlock && bytesPerPixel > 1 && (alphaK == null || redK == null || greenK == null || blueK == null || alphaWays == null || redWays == null || greenWays == null || blueWays == null)) { MessageBox.Show("Ви не згенерували ключі!", "Застереження", MessageBoxButton.OK, MessageBoxImage.Warning); return(null); } else if (inBlock && (alphaK == null || alphaWays == null)) { MessageBox.Show("Ви не згенерували ключі!", "Застереження", MessageBoxButton.OK, MessageBoxImage.Warning); return(null); } List <byte[]> blocks = new List <byte[]>(); int blocksCount = (inputImg.PixelWidth * inputImg.PixelHeight) / (int)(Math.Pow(lenth, 2)); for (int yI = 0; yI < inputImg.PixelHeight / lenth; yI++) { for (int xI = 0; xI < inputImg.PixelWidth / lenth; xI++) { byte[] pixels = new byte[(int)(Math.Pow(lenth, 2)) * bytesPerPixel]; Int32Rect rect = new Int32Rect(xI * lenth, yI * lenth, lenth, lenth); inputImg.CopyPixels(rect, pixels, lenth * bytesPerPixel, 0); if (inBlock) { pixels = DecryptBlocks(pixels, bytesPerPixel); } blocks.Add(pixels); } } int n = 1; while (n < blocks.Count) { int k = ways[(blocks.Count - 1) - n]; byte[] temp = blocks[n]; blocks[n] = blocks[k]; blocks[k] = temp; n++; } var result = new WriteableBitmap(inputImg); int blockI = 0; for (int yI = 0; yI < result.PixelHeight / lenth; yI++) { for (int xI = 0; xI < result.PixelWidth / lenth; xI++) { Int32Rect rect = new Int32Rect(xI * lenth, yI * lenth, lenth, lenth); result.WritePixels(rect, blocks[blockI], lenth * bytesPerPixel, 0); blockI++; } } if (resized == true) { byte[] bytes = new byte[inputImg.PixelWidth * inputImg.PixelHeight * bytesPerPixel]; result.CopyPixels(bytes, inputImg.PixelWidth * bytesPerPixel, 0); byte[] pixels = new byte[width * height * bytesPerPixel]; int row = 0, col = 0, iteration = 1; for (int i = 0; i < pixels.Length; i++) { pixels[i] = bytes[row * inputImg.PixelWidth * bytesPerPixel + col]; col++; if (i == (width * iteration * bytesPerPixel) - 1) { row++; iteration++; col = 0; } } BitmapSource resizedImg = BitmapSource.Create(width, height, inputImg.DpiX, inputImg.DpiY, inputImg.Format, inputImg.Palette, pixels, width * bytesPerPixel); return(resizedImg); } return(result); }
public static BitmapSource CutImageBlank(BitmapSource source) { int keep = 4; BitmapSource bitmap = source; //DrawingImageToBitmapSource((DrawingImage)source); int RectX = 0; int RectY = 0; int RectRight = 0; int RectBottom = 0; int width = bitmap.PixelWidth; int height = bitmap.PixelHeight; int bstride = Math.Abs(width * 4); int byteSize = bstride * height; byte[] array = new byte[byteSize]; bitmap.CopyPixels(array, bstride, 0); for (int i = 0; i < bstride; i += 4) { bool flag = false; for (int j = 0; j < height - 1; j++) { if (array[bstride * j + i + 3] != 0) { RectX = i / 4; flag = true; break; } } if (flag) { break; } } for (int k = 0; k < height; k++) { bool flag2 = false; for (int l = 0; l < bstride - 1; l += 4) { if (array[bstride * k + l + 3] != 0) { RectY = k; flag2 = true; break; } } if (flag2) { break; } } for (int num6 = bstride; num6 > 0; num6 -= 4) { bool flag3 = false; for (int num7 = height - 1; num7 > 0; num7--) { if (array[bstride * num7 + num6 - 1] != 0) { RectRight = num6 / 4; flag3 = true; break; } } if (flag3) { break; } } for (int num8 = height - 1; num8 > 0; num8--) { bool flag4 = false; for (int num9 = bstride; num9 > 0; num9 -= 4) { if (array[bstride * num8 + num9 - 1] != 0) { RectBottom = num8 + 1; flag4 = true; break; } } if (flag4) { break; } } Int32Rect result = default; if (RectX >= keep) { result.X = RectX - keep; } else { result.X = RectX; } if (RectY >= keep) { result.Y = RectY - keep; } else { result.Y = RectY; } if (RectRight >= width - keep) { result.Width = RectRight - result.X; } else { result.Width = RectRight - result.X + keep; } if (RectBottom >= height - keep) { result.Height = RectBottom - result.Y; } else { result.Height = RectBottom - result.Y + keep; } return(new CroppedBitmap(bitmap, result)); }
/// <summary> /// Creates a new surface based on the PixelFormat of the BitmapSource. /// </summary> /// <param name="bitmap">The input BitmapSource.</param> /// <param name="imageMode">The ImageMode of the current surface.</param> /// <returns></returns> internal static unsafe SurfaceBase CreateFromBitmapSource(BitmapSource bitmap, out ImageModes imageMode) { PixelFormat format = bitmap.Format; int width = bitmap.PixelWidth; int height = bitmap.PixelHeight; if (format == PixelFormats.BlackWhite || format == PixelFormats.Gray2 || format == PixelFormats.Gray4 || format == PixelFormats.Gray8) { imageMode = ImageModes.GrayScale; SurfaceGray8 surface = new SurfaceGray8(width, height, bitmap.DpiX, bitmap.DpiY); if (format != PixelFormats.Gray8) { FormatConvertedBitmap conv = new FormatConvertedBitmap(bitmap, PixelFormats.Gray8, null, 0.0); conv.CopyPixels(Int32Rect.Empty, surface.Scan0.Pointer, (int)surface.Scan0.Length, width); } else { bitmap.CopyPixels(Int32Rect.Empty, surface.Scan0.Pointer, (int)surface.Scan0.Length, width); } return(surface); } else if (format == PixelFormats.Gray16 || format == PixelFormats.Gray32Float) { imageMode = ImageModes.Gray16; SurfaceGray16 surface = new SurfaceGray16(width, height, bitmap.DpiX, bitmap.DpiY); if (format == PixelFormats.Gray32Float) { FormatConvertedBitmap conv = new FormatConvertedBitmap(bitmap, PixelFormats.Gray16, null, 0.0); conv.CopyPixels(Int32Rect.Empty, surface.Scan0.Pointer, (int)surface.Scan0.Length, width * 2); } else { bitmap.CopyPixels(Int32Rect.Empty, surface.Scan0.Pointer, (int)surface.Scan0.Length, width * 2); } surface.ScaleToPhotoshop16BitRange(); return(surface); } else if (format == PixelFormats.Rgb48 || format == PixelFormats.Rgba64 || format == PixelFormats.Rgba128Float || format == PixelFormats.Rgb128Float || format == PixelFormats.Prgba128Float || format == PixelFormats.Prgba64) { int bpp, stride; ushort[] pixels = null; if (format == PixelFormats.Rgba128Float || format == PixelFormats.Rgb128Float || format == PixelFormats.Prgba128Float || format == PixelFormats.Prgba64) { PixelFormat dstFormat = format == PixelFormats.Rgb128Float ? PixelFormats.Rgb48 : PixelFormats.Rgba64; FormatConvertedBitmap conv = new FormatConvertedBitmap(bitmap, dstFormat, null, 0.0); bpp = dstFormat.BitsPerPixel / 16; stride = width * bpp; pixels = new ushort[stride * height]; conv.CopyPixels(pixels, stride * 2, 0); } else { bpp = format.BitsPerPixel / 16; stride = width * bpp; pixels = new ushort[stride * height]; bitmap.CopyPixels(pixels, stride * 2, 0); } imageMode = ImageModes.RGB48; SurfaceBGRA64 surface = new SurfaceBGRA64(width, height, bitmap.DpiX, bitmap.DpiY); fixed(ushort *ptr = pixels) { for (int y = 0; y < height; y++) { ushort * src = ptr + (y * stride); ColorBgra16 *dst = (ColorBgra16 *)surface.GetRowAddressUnchecked(y); for (int x = 0; x < width; x++) { dst->R = src[0]; dst->G = src[1]; dst->B = src[2]; if (format == PixelFormats.Rgba64) { dst->A = src[3]; } else { dst->A = 65535; } src += bpp; dst++; } } } surface.ScaleToPhotoshop16BitRange(); return(surface); } else { imageMode = ImageModes.RGB; SurfaceBGRA32 surface = new SurfaceBGRA32(width, height, bitmap.DpiX, bitmap.DpiY); if (format != PixelFormats.Bgra32) { FormatConvertedBitmap conv = new FormatConvertedBitmap(bitmap, PixelFormats.Bgra32, null, 0.0); conv.CopyPixels(Int32Rect.Empty, surface.Scan0.Pointer, (int)surface.Scan0.Length, width * 4); } else { bitmap.CopyPixels(Int32Rect.Empty, surface.Scan0.Pointer, (int)surface.Scan0.Length, width * 4); } return(surface); } }
// Invert the original image. private void btnInvert_Click(object sender, RoutedEventArgs e) { // Get the bitmap source. BitmapSource bms_old = (BitmapSource)imgOld.Source; // Get the size in pixels. int wid = (int)bms_old.PixelWidth; int hgt = (int)bms_old.PixelHeight; // Make room for the pixel bytes. int bytes_per_pixel = (int)(bms_old.Format.BitsPerPixel / 8); int stride = (int)(wid * bytes_per_pixel); byte[] pixels_old = new byte[hgt * stride]; // Get the pixel data. try { bms_old.CopyPixels(pixels_old, stride, 0); } catch (Exception ex) { MessageBox.Show(ex.Message); return; } // Make room for the output pixel data. byte[] pixels_new = new byte[hgt * stride]; // Transform the pixel data. for (int y = 0; y < hgt; y++) // For each row... { for (int x = 0; x < wid; x++) // For each column... { // Get the pixel's old value. byte a = 0, r = 0, g = 0, b = 0; GetPixel(pixels_old, stride, bytes_per_pixel, x, y, ref a, ref r, ref g, ref b); // Invert. r = (byte)(255 - r); g = (byte)(255 - g); b = (byte)(255 - b); SetPixel(pixels_new, stride, bytes_per_pixel, x, y, a, r, g, b); } } pixels_old.CopyTo(pixels_new, 0); for (int i = 0; i < hgt * stride; i++) { pixels_new[i] = (byte)(255 - pixels_new[i]); } // Display the result. BitmapSource bms_new = BitmapSource.Create(wid, hgt, bms_old.DpiX, bms_old.DpiY, bms_old.Format, null, pixels_new, stride); imgNew.Source = bms_new; }
// Copy red, green, or blue color components. private void CopyColors(bool copy_a, bool copy_r, bool copy_g, bool copy_b) { // Get the bitmap source. BitmapSource bms_old = (BitmapSource)imgOld.Source; // Get the size in pixels. int wid = (int)bms_old.PixelWidth; int hgt = (int)bms_old.PixelHeight; // Make room for the pixel bytes. int bytes_per_pixel = (int)(bms_old.Format.BitsPerPixel / 8); int stride = (int)(wid * bytes_per_pixel); byte[] pixels_old = new byte[hgt * stride]; // Get the pixel data. try { bms_old.CopyPixels(pixels_old, stride, 0); } catch (Exception ex) { MessageBox.Show(ex.Message); } // Make room for the output pixel data. byte[] pixels_new = new byte[hgt * stride]; // Transform the pixel data. for (int y = 0; y < hgt; y++) // For each row... { for (int x = 0; x < wid; x++) // For each column... { // Get the pixel's old value. byte a = 0, r = 0, g = 0, b = 0; GetPixel(pixels_old, stride, bytes_per_pixel, x, y, ref a, ref r, ref g, ref b); // Save only the selected components. if (!copy_a) { a = 0; } if (!copy_r) { r = 0; } if (!copy_g) { g = 0; } if (!copy_b) { b = 0; } // Save the result. SetPixel(pixels_new, stride, bytes_per_pixel, x, y, a, r, g, b); } } // Display the result. BitmapSource bms_new = BitmapSource.Create(wid, hgt, bms_old.DpiX, bms_old.DpiY, bms_old.Format, null, pixels_new, stride); imgNew.Source = bms_new; }
public static BitmapSource MakeTransparent(this BitmapSource bitmap, Xe.Graphics.Color[] colors) { BitmapSource newBitmap = null; // patch for 24-bit bitmaps if (bitmap.Format == PixelFormats.Bgr32) { var formatter = new FormatConvertedBitmap(); formatter.BeginInit(); formatter.Source = bitmap; formatter.DestinationFormat = PixelFormats.Bgra32; formatter.EndInit(); bitmap = formatter; } var bytesPerPixel = (bitmap.Format.BitsPerPixel + 7) / 8; var stride = bytesPerPixel * bitmap.PixelWidth; var length = stride * bitmap.PixelHeight; var processPixels = true; var palette = bitmap.Palette; if (bitmap.Format == PixelFormats.Indexed1 || bitmap.Format == PixelFormats.Indexed2 || bitmap.Format == PixelFormats.Indexed4 || bitmap.Format == PixelFormats.Indexed8) { var srcColors = bitmap.Palette.Colors.ToList(); for (int i = 0; i < srcColors.Count; i++) { var color = srcColors[i]; for (int j = 0; j < colors.Length; j++) { var c = colors[j]; if (color.R == c.r || color.G == c.g || color.B == c.b) { color.A = 0; } } srcColors[i] = color; } palette = new BitmapPalette(srcColors); processPixels = false; } IntPtr data = Marshal.AllocHGlobal(length); try { var rect = new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight); bitmap.CopyPixels(rect, data, length, stride); var pixelFormat = bitmap.Format; if (processPixels) { MakeTransparent(data, stride, bitmap.PixelHeight, bitmap.Format, colors); } newBitmap = BitmapSource.Create(bitmap.PixelWidth, bitmap.PixelHeight, bitmap.DpiX, bitmap.DpiY, pixelFormat, palette, data, length, stride); } finally { Marshal.FreeHGlobal(data); } return(newBitmap); }
private static DataStream GetPixels(BitmapSource source, int stride) { var pixels = new DataStream(source.Size.Height * stride, true, true); source.CopyPixels(stride, pixels); return pixels; }
private System.Windows.Media.Color PickColor(double x, double y) { BitmapSource bitmapSource = ImageViewer.Source as BitmapSource; if (bitmapSource != null) { // Get color from bitmap pixel. // Convert coopdinates from WPF pixels to Bitmap pixels // and restrict them by the Bitmap bounds. x *= bitmapSource.PixelWidth / ActualWidth; if ((int)x > bitmapSource.PixelWidth - 1) { x = bitmapSource.PixelWidth - 1; } else if (x < 0) { x = 0; } y *= bitmapSource.PixelHeight / ActualHeight; if ((int)y > bitmapSource.PixelHeight - 1) { y = bitmapSource.PixelHeight - 1; } else if (y < 0) { y = 0; } // Lee Brimelow approach (http://thewpfblog.com/?p=62). //byte[] pixels = new byte[4]; //CroppedBitmap cb = new CroppedBitmap(bitmapSource, // new Int32Rect((int)x, (int)y, 1, 1)); //cb.CopyPixels(pixels, 4, 0); //return Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0]); // Alternative approach if (bitmapSource.Format == PixelFormats.Indexed4) { byte[] pixels = new byte[1]; int stride = (bitmapSource.PixelWidth * bitmapSource.Format.BitsPerPixel + 3) / 4; bitmapSource.CopyPixels(new Int32Rect((int)x, (int)y, 1, 1), pixels, stride, 0); return(bitmapSource.Palette.Colors[pixels[0] >> 4]); } else if (bitmapSource.Format == PixelFormats.Indexed8) { byte[] pixels = new byte[1]; int stride = (bitmapSource.PixelWidth * bitmapSource.Format.BitsPerPixel + 7) / 8; bitmapSource.CopyPixels(new Int32Rect((int)x, (int)y, 1, 1), pixels, stride, 0); return(bitmapSource.Palette.Colors[pixels[0]]); } else { byte[] pixels = new byte[4]; int stride = (bitmapSource.PixelWidth * bitmapSource.Format.BitsPerPixel + 7) / 8; bitmapSource.CopyPixels(new Int32Rect((int)x, (int)y, 1, 1), pixels, stride, 0); return(System.Windows.Media.Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0])); } } return(System.Windows.Media.Color.FromArgb(255, 0, 0, 0)); }
public static BitmapSource InversEncryption(BitmapSource inputImg) { int bytesPerPixel = (inputImg.Format.BitsPerPixel + 7) / 8; List <byte[]> blocks = new List <byte[]>(); int blocksCount = (inputImg.PixelWidth * inputImg.PixelHeight) / (int)(Math.Pow(lenth, 2)); for (int yI = 0; yI < inputImg.PixelHeight / lenth; yI++) { for (int xI = 0; xI < inputImg.PixelWidth / lenth; xI++) { byte[] pixels = new byte[(int)(Math.Pow(lenth, 2)) * bytesPerPixel]; Int32Rect rect = new Int32Rect(xI * lenth, yI * lenth, lenth, lenth); inputImg.CopyPixels(rect, pixels, lenth * bytesPerPixel, 0); if (inBlock) { pixels = DecryptBlocks(pixels); } blocks.Add(pixels); } } int n = 1; while (n < blocks.Count) { int k = ways[(blocks.Count - 1) - n]; byte[] temp = blocks[n]; blocks[n] = blocks[k]; blocks[k] = temp; n++; } var result = new WriteableBitmap(inputImg); int blockI = 0; for (int yI = 0; yI < result.PixelHeight / lenth; yI++) { for (int xI = 0; xI < result.PixelWidth / lenth; xI++) { Int32Rect rect = new Int32Rect(xI * lenth, yI * lenth, lenth, lenth); result.WritePixels(rect, blocks[blockI], lenth * bytesPerPixel, 0); blockI++; } } if (resized == true) { byte[] bytes = new byte[inputImg.PixelWidth * inputImg.PixelHeight * bytesPerPixel]; result.CopyPixels(bytes, inputImg.PixelWidth * bytesPerPixel, 0); byte[] pixels = new byte[exportInfo[1] * exportInfo[2] * bytesPerPixel]; int row = 0, col = 0, iteration = 1; for (int i = 0; i < pixels.Length; i++) { pixels[i] = bytes[row * inputImg.PixelWidth * bytesPerPixel + col]; col++; if (i == (exportInfo[1] * iteration * bytesPerPixel) - 1) { row++; iteration++; col = 0; } } BitmapSource resizedImg = BitmapSource.Create(exportInfo[1], exportInfo[2], inputImg.DpiX, inputImg.DpiY, inputImg.Format, inputImg.Palette, pixels, exportInfo[1] * bytesPerPixel); return(resizedImg); } return(result); }
public static void ReadGrayImage(byte[] intermediateImage, BitmapSource src, int srcX, int srcY, int stride, int width, int height) { System.Diagnostics.Debug.Assert(src.Format == PixelFormats.Gray8); src.CopyPixels(new Int32Rect(srcX, srcY, width, height), intermediateImage, stride, 0); }
public static BitmapSource EncryptImg(BitmapSource inputImg, int method) { if (inBlock && alphaK.Length != lenth) { MessageBox.Show("Довжина згенерованих ключів менша за розміри блока!", "Застереження", MessageBoxButton.OK, MessageBoxImage.Error); return(null); } exportInfo = new List <int>(); exportInfo.Add(lenth); resized = false; bytesPerPixel = (inputImg.Format.BitsPerPixel + 7) / 8; if ((inputImg.PixelWidth % lenth) != 0 || (inputImg.PixelHeight % lenth) != 0) { exportInfo.Add(inputImg.PixelWidth); exportInfo.Add(inputImg.PixelHeight); int Width = 0, Height = 0; resized = true; if (inputImg.PixelWidth > inputImg.PixelHeight) { if ((inputImg.PixelWidth % lenth) != 0) { int newSize = (inputImg.PixelWidth / lenth + 1) * lenth; Width = newSize; Height = newSize; } else { Width = inputImg.PixelWidth; Height = inputImg.PixelWidth; } } else if (inputImg.PixelWidth < inputImg.PixelHeight) { if ((inputImg.PixelHeight % lenth) != 0) { int newSize = (inputImg.PixelHeight / lenth + 1) * lenth; Width = newSize; Height = newSize; } else { Width = inputImg.PixelHeight; Height = inputImg.PixelHeight; } } else if (inputImg.PixelWidth == inputImg.PixelHeight) { int newSize = (inputImg.PixelWidth / lenth + 1) * lenth; Width = newSize; Height = newSize; } int neededBytes = Width * Height * bytesPerPixel; byte[] originalPixels = new byte[inputImg.PixelWidth * inputImg.PixelHeight * bytesPerPixel]; inputImg.CopyPixels(originalPixels, inputImg.PixelWidth * bytesPerPixel, 0); byte[] pixels = new byte[neededBytes]; int row = 0, col = 0, iteration = 1; for (int i = 0; i < originalPixels.Length; i++) { pixels[row * Width * bytesPerPixel + col] = originalPixels[i]; col++; if (i == (inputImg.PixelWidth * iteration * bytesPerPixel) - 1) { row++; iteration++; col = 0; } } BitmapSource resizedImg = BitmapSource.Create(Width, Height, inputImg.DpiX, inputImg.DpiY, inputImg.Format, inputImg.Palette, pixels, Width * bytesPerPixel); inputImg = resizedImg; } List <byte[]> blocks = new List <byte[]>(); int blocksCount = (inputImg.PixelWidth * inputImg.PixelHeight) / (int)(Math.Pow(lenth, 2)); IV = GetWays(0, lenth, lenth); for (int yI = 0; yI < inputImg.PixelHeight / lenth; yI++) { for (int xI = 0; xI < inputImg.PixelWidth / lenth; xI++) { byte[] pixels = new byte[(int)(Math.Pow(lenth, 2)) * bytesPerPixel]; Int32Rect rect = new Int32Rect(xI * lenth, yI * lenth, lenth, lenth); inputImg.CopyPixels(rect, pixels, lenth * bytesPerPixel, 0); if (inBlock) { pixels = EncryptBlocks(pixels); } blocks.Add(pixels); } } Random rng = new Random(); int n = blocks.Count; ways = new List <int>(); while (n > 1) { int k = rng.Next(n--); ways.Add(k); byte[] temp = blocks[n]; blocks[n] = blocks[k]; blocks[k] = temp; } var result = new WriteableBitmap(inputImg); int blockI = 0; for (int yI = 0; yI < result.PixelHeight / lenth; yI++) { for (int xI = 0; xI < result.PixelWidth / lenth; xI++) { Int32Rect rect = new Int32Rect(xI * lenth, yI * lenth, lenth, lenth); result.WritePixels(rect, blocks[blockI], lenth * bytesPerPixel, 0); blockI++; } } return(result); }
//画像の上にカーソル画像を合成 private BitmapSource CursorOnScreen()//(BitmapSource source, BitmapSource cursor, POINT cursorLocate, int hotspotX, int hotspotY) { int width, height, stride; byte[] pixels; //マスクが必要なカーソルの場合 if (IsMaskUse == true) { //カーソルマスク画像と合成 //マスク画像の2枚は上下に連結された状態なので、上下に分割 int maskWidth = MyBitmapCursorMask.PixelWidth; int maskHeight = MyBitmapCursorMask.PixelHeight / 2; //分割 var mask1Bitmap = new CroppedBitmap(MyBitmapCursorMask, new Int32Rect(0, 0, maskWidth, maskHeight)); var mask2Bitmap = new CroppedBitmap(MyBitmapCursorMask, new Int32Rect(0, maskHeight, maskWidth, maskHeight)); //画素をbyte配列で取得 int maskStride = (maskWidth * 32 + 7) / 8; byte[] mask1Pixels = new byte[maskHeight * maskStride]; byte[] mask2Pixels = new byte[maskHeight * maskStride]; mask1Bitmap.CopyPixels(mask1Pixels, maskStride, 0); mask2Bitmap.CopyPixels(mask2Pixels, maskStride, 0); //キャプチャ画像をbyte配列で取得 width = MyBitmap.PixelWidth; height = MyBitmap.PixelHeight; stride = (width * 32 + 7) / 8; pixels = new byte[height * stride]; MyBitmap.CopyPixels(pixels, stride, 0); //処理範囲の開始点と終了点設定、開始点はカーソルのホットスポットでオフセット int beginX = MyCursorPoint.X - MyCursorHotspotX; int beginY = MyCursorPoint.Y - MyCursorHotspotY; int endX = beginX + maskWidth; int endY = beginY + maskHeight; if (endX > width) { endX = width; } if (endY > height) { endY = height; } //最初にマスク画像上とAND合成、続けてマスク画像下とXOR int yCount = 0; for (int y = beginY; y < endY; y++) { int xCount = 0; for (int x = beginX; x < endX; x++) { int p = (y * stride) + (x * 4); int pp = (yCount * maskStride) + (xCount * 4); //AND pixels[p] &= mask1Pixels[pp]; pixels[p + 1] &= mask1Pixels[pp + 1]; pixels[p + 2] &= mask1Pixels[pp + 2]; //XOR pixels[p] ^= mask2Pixels[pp]; pixels[p + 1] ^= mask2Pixels[pp + 1]; pixels[p + 2] ^= mask2Pixels[pp + 2]; xCount++; } yCount++; } } //マスクが必要ない場合はアルファブレンドする else { //カーソル画像 int cWidth = MyBitmapCursor.PixelWidth; int cHeight = MyBitmapCursor.PixelHeight; int maskStride = (cWidth * 32 + 7) / 8; byte[] cursorPixels = new byte[cHeight * maskStride]; MyBitmapCursor.CopyPixels(cursorPixels, maskStride, 0); //キャプチャ画像 width = MyBitmap.PixelWidth; height = MyBitmap.PixelHeight; stride = (width * 32 + 7) / 8; pixels = new byte[height * stride]; MyBitmap.CopyPixels(pixels, stride, 0); //処理範囲の開始点と終了点設定 int beginX = MyCursorPoint.X - MyCursorHotspotX; int beginY = MyCursorPoint.Y - MyCursorHotspotY; int endX = beginX + cWidth; int endY = beginY + cHeight; if (endX > width) { endX = width; } if (endY > height) { endY = height; } int yCount = 0; for (int y = beginY; y < endY; y++) { int xCount = 0; for (int x = beginX; x < endX; x++) { int p = (y * stride) + (x * 4); int pp = (yCount * maskStride) + (xCount * 4); //アルファブレンド // 効果 //http://www.charatsoft.com/develop/otogema/page/05d3d/effect.html //求める画素値 = もとの画素値 + ((カーソル画素値 - もとの画素値) * (カーソルのアルファ値 / 255)) double alpha = cursorPixels[pp + 3] / 255.0; byte r = pixels[p + 2]; byte g = pixels[p + 1]; byte b = pixels[p]; pixels[p + 2] = (byte)(r + ((cursorPixels[pp + 2] - r) * alpha)); pixels[p + 1] = (byte)(g + ((cursorPixels[pp + 1] - g) * alpha)); pixels[p] = (byte)(b + ((cursorPixels[pp] - b) * alpha)); xCount++; } yCount++; } } return(BitmapSource.Create(width, height, MyBitmap.DpiX, MyBitmap.DpiY, MyBitmap.Format, MyBitmap.Palette, pixels, stride)); }
public void AffectImage(Dictionary <String, Object> args) { BitmapSource bitmapSource = (BitmapSource)args["BitmapSource"]; int mouseX = (int)((int)args["MouseX"] * bitmapSource.DpiX / 96); int mouseY = (int)((int)args["MouseY"] * bitmapSource.DpiY / 96); double scale = (double)args["Scale"]; Thickness imagePosition = (Thickness)args["ImagePosition"]; var targetBitmap = new TransformedBitmap(bitmapSource, new ScaleTransform(scale, scale)); bitmapSource = targetBitmap; try { int stride = (int)(bitmapSource.PixelWidth * 4); int size = (int)(bitmapSource.PixelHeight * stride); byte[] pixels = new byte[size]; bitmapSource.CopyPixels(pixels, stride, 0); int row = mouseY - (int)(imagePosition.Top * bitmapSource.DpiY / 96); int column = mouseX - (int)(imagePosition.Left * bitmapSource.DpiX / 96); int index = row * stride + 4 * column; byte red; byte green; byte blue; byte alpha; Dictionary <string, int> pixelInformation = new Dictionary <string, int>(); if (row >= bitmapSource.PixelHeight || row < 0 || column >= bitmapSource.PixelWidth || column < 0) { red = 0; green = 0; blue = 0; alpha = 0; pixelInformation.Add("MouseX", -1); pixelInformation.Add("MouseY", -1); } else { red = pixels[index + 2]; green = pixels[index + 1]; blue = pixels[index]; alpha = pixels[index + 3]; pixelInformation.Add("MouseX", (int)((mouseX - (int)(imagePosition.Left * bitmapSource.DpiX / 96)) / scale)); pixelInformation.Add("MouseY", (int)((mouseY - (int)(imagePosition.Top * bitmapSource.DpiY / 96)) / scale)); } pixelInformation.Add("Alpha", alpha); pixelInformation.Add("Red", red); pixelInformation.Add("Green", green); pixelInformation.Add("Blue", blue); IEventAggregator aggregator = GlobalEvent.GetEventAggregator(); aggregator.GetEvent <SendPixelInformationEvent>().Publish(pixelInformation); } catch (KeyNotFoundException) { throw; } catch (IndexOutOfRangeException) { } }
} // CloneBms static public byte[] ToMainColors() { byte[] rgb = new byte[dataLength]; parentBms.CopyPixels(rgb, stride, 0); return(rgb); }
static public ICaptureProcessor createCaptureProcessor(string a_FilePath) { if (MainWindow.mCaptureManager == null) { return(null); } string lPresentationDescriptor = "<?xml version='1.0' encoding='UTF-8'?>" + "<PresentationDescriptor StreamCount='1'>" + "<PresentationDescriptor.Attributes Title='Attributes of Presentation'>" + "<Attribute Name='MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK' GUID='{58F0AAD8-22BF-4F8A-BB3D-D2C4978C6E2F}' Title='The symbolic link for a video capture driver.' Description='Contains the unique symbolic link for a video capture driver.'>" + "<SingleValue Value='ImageCaptureProcessor' />" + "</Attribute>" + "<Attribute Name='MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME' GUID='{60D0E559-52F8-4FA2-BBCE-ACDB34A8EC01}' Title='The display name for a device.' Description='The display name is a human-readable string, suitable for display in a user interface.'>" + "<SingleValue Value='Image Capture Processor' />" + "</Attribute>" + "</PresentationDescriptor.Attributes>" + "<StreamDescriptor Index='0' MajorType='MFMediaType_Video' MajorTypeGUID='{73646976-0000-0010-8000-00AA00389B71}'>" + "<MediaTypes TypeCount='1'>" + "<MediaType Index='0'>" + "<MediaTypeItem Name='MF_MT_FRAME_SIZE' GUID='{1652C33D-D6B2-4012-B834-72030849A37D}' Title='Width and height of the video frame.' Description='Width and height of a video frame, in pixels.'>" + "<Value.ValueParts>" + "<ValuePart Title='Width' Value='Temp_Width' />" + "<ValuePart Title='Height' Value='Temp_Height' />" + "</Value.ValueParts>" + "</MediaTypeItem>" + "<MediaTypeItem Name='MF_MT_AVG_BITRATE' GUID='{20332624-FB0D-4D9E-BD0D-CBF6786C102E}' Title='Approximate data rate of the video stream.' Description='Approximate data rate of the video stream, in bits per second, for a video media type.'>" + "<SingleValue Value='33570816' />" + "</MediaTypeItem>" + "<MediaTypeItem Name='MF_MT_MAJOR_TYPE' GUID='{48EBA18E-F8C9-4687-BF11-0A74C9F96A8F}' Title='Major type GUID for a media type.' Description='The major type defines the overall category of the media data.'>" + "<SingleValue Value='MFMediaType_Video' GUID='{73646976-0000-0010-8000-00AA00389B71}' />" + "</MediaTypeItem>" + //"<MediaTypeItem Name='MF_MT_DEFAULT_STRIDE' GUID='{644B4E48-1E02-4516-B0EB-C01CA9D49AC6}' Title='Default surface stride.' Description='Default surface stride, for an uncompressed video media type. Stride is the number of bytes needed to go from one row of pixels to the next.'>" + // "<SingleValue Value='Temp_Stride' />" + //"</MediaTypeItem>" + "<MediaTypeItem Name='MF_MT_FIXED_SIZE_SAMPLES' GUID='{B8EBEFAF-B718-4E04-B0A9-116775E3321B}' Title='The fixed size of samples in stream.' Description='Specifies for a media type whether the samples have a fixed size.'>" + "<SingleValue Value='True' />" + "</MediaTypeItem>" + "<MediaTypeItem Name='MF_MT_FRAME_RATE' GUID='{C459A2E8-3D2C-4E44-B132-FEE5156C7BB0}' Title='Frame rate.' Description='Frame rate of a video media type, in frames per second.'>" + "<RatioValue Value='10.0'>" + "<Value.ValueParts>" + "<ValuePart Title='Numerator' Value='20' />" + "<ValuePart Title='Denominator' Value='1' />" + "</Value.ValueParts>" + "</RatioValue>" + "</MediaTypeItem>" + "<MediaTypeItem Name='MF_MT_PIXEL_ASPECT_RATIO' GUID='{C6376A1E-8D0A-4027-BE45-6D9A0AD39BB6}' Title='Pixel aspect ratio.' Description='Pixel aspect ratio for a video media type.'>" + "<RatioValue Value='1'>" + "<Value.ValueParts>" + "<ValuePart Title='Numerator' Value='1' />" + "<ValuePart Title='Denominator' Value='1' />" + "</Value.ValueParts>" + "</RatioValue>" + "</MediaTypeItem>" + "<MediaTypeItem Name='MF_MT_ALL_SAMPLES_INDEPENDENT' GUID='{C9173739-5E56-461C-B713-46FB995CB95F}' Title='Independent of samples.' Description='Specifies for a media type whether each sample is independent of the other samples in the stream.'>" + "<SingleValue Value='True' />" + "</MediaTypeItem>" + "<MediaTypeItem Name='MF_MT_SAMPLE_SIZE' GUID='{DAD3AB78-1990-408B-BCE2-EBA673DACC10}' Title='The fixed size of each sample in stream.' Description='Specifies the size of each sample, in bytes, in a media type.'>" + "<SingleValue Value='Temp_SampleSize' />" + "</MediaTypeItem>" + "<MediaTypeItem Name='MF_MT_INTERLACE_MODE' GUID='{E2724BB8-E676-4806-B4B2-A8D6EFB44CCD}' Title='Describes how the frames are interlaced.' Description='Describes how the frames in a video media type are interlaced.'>" + "<SingleValue Value='MFVideoInterlace_Progressive' />" + "</MediaTypeItem>" + "<MediaTypeItem Name='MF_MT_SUBTYPE' GUID='{F7E34C9A-42E8-4714-B74B-CB29D72C35E5}' Title='Subtype GUID for a media type.' Description='The subtype GUID defines a specific media format type within a major type.'>" + "<SingleValue GUID='{Temp_SubTypeGUID}' />" + "</MediaTypeItem>" + "</MediaType>" + "</MediaTypes>" + "</StreamDescriptor>" + "</PresentationDescriptor>"; ImageCaptureProcessor lICaptureProcessor = new ImageCaptureProcessor(); using (var lImageStream = File.Open(a_FilePath, FileMode.Open)) { if (lImageStream == null) { return(null); } var lBitmap = BitmapDecoder.Create(lImageStream, BitmapCreateOptions.None, BitmapCacheOption.None); if (lBitmap == null) { return(null); } if (lBitmap.Frames == null || lBitmap.Frames.Count == 0) { return(null); } BitmapSource bitmapSource = lBitmap.Frames[0]; int lStride = 0; Guid lMFVideoFormat_RGBFormat = MFVideoFormat_ARGB32; MainWindow.mCaptureManager.getStrideForBitmapInfoHeader(lMFVideoFormat_RGBFormat, (uint)bitmapSource.PixelWidth, out lStride); int width = bitmapSource.PixelWidth; int height = bitmapSource.PixelHeight; int stride = (int)Math.Abs(lStride); lPresentationDescriptor = lPresentationDescriptor.Replace("Temp_Width", ((uint)bitmapSource.PixelWidth).ToString()); lPresentationDescriptor = lPresentationDescriptor.Replace("Temp_Height", ((uint)bitmapSource.PixelHeight).ToString()); lPresentationDescriptor = lPresentationDescriptor.Replace("Temp_Stride", lStride.ToString()); lPresentationDescriptor = lPresentationDescriptor.Replace("Temp_SampleSize", ((uint)(Math.Abs(lStride) * bitmapSource.PixelHeight * 3)).ToString()); lPresentationDescriptor = lPresentationDescriptor.Replace("Temp_SubTypeGUID", lMFVideoFormat_RGBFormat.ToString()); lICaptureProcessor.mPresentationDescriptor = lPresentationDescriptor; foreach (var litem in lBitmap.Frames) { bitmapSource = litem; if (bitmapSource.Format != System.Windows.Media.PixelFormats.Bgra32) { FormatConvertedBitmap newFormatedBitmapSource = new FormatConvertedBitmap(); newFormatedBitmapSource.BeginInit(); newFormatedBitmapSource.Source = litem; newFormatedBitmapSource.DestinationFormat = System.Windows.Media.PixelFormats.Bgra32; newFormatedBitmapSource.EndInit(); bitmapSource = newFormatedBitmapSource; } byte[] lPixels = new byte[height * stride]; bitmapSource.CopyPixels(lPixels, stride, 0); lICaptureProcessor.mRawDataFrames.Add(new RawDataFrame(lPixels)); } } return(lICaptureProcessor); }
/// <summary> /// Converts BitmapSource to Mat /// </summary> /// <param name="src">Input BitmapSource</param> /// <param name="dst">Output Mat</param> public static void ToMat(this BitmapSource src, Mat dst) { if (src == null) { throw new ArgumentNullException(nameof(src)); } if (dst == null) { throw new ArgumentNullException(nameof(dst)); } if (src.PixelWidth != dst.Width || src.PixelHeight != dst.Height) { throw new ArgumentException("size of src must be equal to size of dst"); } if (dst.Dims > 2) { throw new ArgumentException("Mat dimensions must be 2"); } int w = src.PixelWidth; int h = src.PixelHeight; int bpp = src.Format.BitsPerPixel; int channels = WriteableBitmapConverter.GetOptimumChannels(src.Format); if (dst.Channels() != channels) { throw new ArgumentException("nChannels of dst is invalid", nameof(dst)); } bool submat = dst.IsSubmatrix(); bool continuous = dst.IsContinuous(); unsafe { byte *p = (byte *)(dst.Data); long step = dst.Step(); // 1bppは手作業でコピー if (bpp == 1) { if (submat) { throw new NotImplementedException("submatrix not supported"); } // BitmapImageのデータを配列にコピー // 要素1つに横8ピクセル分のデータが入っている。 int stride = (w / 8) + 1; byte[] pixels = new byte[h * stride]; src.CopyPixels(pixels, stride, 0); int x = 0; for (int y = 0; y < h; y++) { int offset = y * stride; // この行の各バイトを調べていく for (int bytePos = 0; bytePos < stride; bytePos++) { if (x < w) { // 現在の位置のバイトからそれぞれのビット8つを取り出す byte b = pixels[offset + bytePos]; for (int i = 0; i < 8; i++) { if (x >= w) { break; } p[step * y + x] = ((b & 0x80) == 0x80) ? (byte)255 : (byte)0; b <<= 1; x++; } } } // 次の行へ x = 0; } } // 8bpp /*else if (bpp == 8) * { * int stride = w; * byte[] pixels = new byte[h * stride]; * src.CopyPixels(pixels, stride, 0); * for (int y = 0; y < h; y++) * { * for (int x = 0; x < w; x++) * { * p[step * y + x] = pixels[y * stride + x]; * } * } * }*/ // 24bpp, 32bpp, ... else { int stride = w * ((bpp + 7) / 8); if (!submat && continuous) { long imageSize = dst.DataEnd.ToInt64() - dst.Data.ToInt64(); if (imageSize < 0) { throw new OpenCvSharpException("The mat has invalid data pointer"); } if (imageSize > int.MaxValue) { throw new OpenCvSharpException("Too big mat data"); } src.CopyPixels(Int32Rect.Empty, dst.Data, (int)imageSize, stride); } else { // 高さ1pxの矩形ごと(≒1行ごと)にコピー var roi = new Int32Rect { X = 0, Y = 0, Width = w, Height = 1 }; IntPtr dstData = dst.Data; for (int y = 0; y < h; y++) { roi.Y = y; src.CopyPixels(roi, dstData, stride, stride); dstData = new IntPtr(dstData.ToInt64() + stride); } } } } }
public static BitmapSource SoftenEdges(BitmapSource original, int softedgex, int softedgey) { if (softedgex <= 0 && softedgey <= 0) { return(original); } try { //System.Windows.Forms.MessageBox.Show(string.Format("SoftenEdges,soft={0},bpp={1}", softedge, original.Format.BitsPerPixel)); //32bit assumption if (original.Format.BitsPerPixel != 32) { return(original); } //limit softedge range by half image size softedgex = Math.Min(softedgex, (int)(original.Width / 2)); softedgey = Math.Min(softedgey, (int)(original.Height / 2)); int height = original.PixelHeight; int width = original.PixelWidth; int bytesPerPixel = (original.Format.BitsPerPixel + 7) / 8; int nStride = width * bytesPerPixel; pixelByteArray = new byte[height * nStride]; original.CopyPixels(pixelByteArray, nStride, 0); //alpha and color for (int y = 0; y < height; y++) { float fAlphaByY = 1f; int nDistToEdgeY = Math.Min(y, height - 1 - y); fAlphaByY = (float)nDistToEdgeY / softedgey; fAlphaByY = Math.Min(fAlphaByY, 1.0f); for (int x = 0; x < width; x++) { float fAlphaByX = 1f; int nDistToEdgeX = Math.Min(x, width - 1 - x); fAlphaByX = (float)nDistToEdgeX / softedgex; fAlphaByX = Math.Min(fAlphaByX, 1.0f); for (int iPix = 0; iPix < 4; iPix++) { int alpha_offset_in_array = bytesPerPixel * (x + y * width) + iPix; int alphaOld = (int)pixelByteArray[alpha_offset_in_array]; int alphaNew = (int)Math.Floor(alphaOld * fAlphaByX * fAlphaByY); pixelByteArray[alpha_offset_in_array] = (byte)alphaNew; } } } WriteableBitmap newbm = new WriteableBitmap(width, height, original.DpiX, original.DpiY, PixelFormats.Pbgra32, null); newbm.WritePixels(new System.Windows.Int32Rect(0, 0, width, height), pixelByteArray, nStride, 0); return(newbm); } catch (System.Exception exp) { System.Windows.Forms.MessageBox.Show(exp.ToString() + exp.StackTrace); } return(original); }
//0~1に変換してから計算、ガンマ補正あり private BitmapSource D11(BitmapSource source, int colorsCount) { double[] palette = MakePalette(colorsCount); double stepColor = 1.0 / colorsCount;//1範囲値 var localGamma = MakeGammaTable1(colorsCount); //画素値の配列作成 int width = source.PixelWidth; int height = source.PixelHeight; int stride = width; byte[] pixels = new byte[height * stride];//もとの値Pixels source.CopyPixels(pixels, stride, 0); //誤差拡散計算用 double[] gosaPixels = pixels.Select(x => x / 255.0).ToArray(); //ガンマ補正 GammaCorrect1(gosaPixels, colorsCount, MakeGammaTable1(colorsCount)); double[] normPixels = new double[pixels.Length]; int p; //座標を配列のインデックスに変換した値用 double gosa; //誤差(変換前 - 変換後) for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { p = y * stride + x; //変換 if (y == 128) { var tako = 0; } var neko = gosaPixels[p] / stepColor; int inu = (int)neko; double uma = palette[inu]; normPixels[p] = uma; //誤差拡散 gosa = (gosaPixels[p] - normPixels[p]) / 16.0; if (x != width - 1) { gosaPixels[p + 1] += gosa * 7;//右 } if (y < height - 1) { p += stride; gosaPixels[p] += gosa * 5;//下 if (x != 0) { gosaPixels[p - 1] += gosa * 3;//左下 } if (x != width - 1) { gosaPixels[p + 1] += gosa * 1;//右下 } } } } //pixels = normPixels.Select(x => (byte)(x * 255)).ToArray(); pixels = normPixels.Select(x => (byte)((x * 255) + 0.5)).ToArray();//四捨五入 return(BitmapSource.Create(width, height, 96, 96, PixelFormats.Gray8, null, pixels, stride)); }
public static BitmapSource ResizeImg(BitmapSource inputImg, int lenght) { int bytesPerPixel = CountBytesPerPixel(inputImg); algParams.Add(inputImg.PixelWidth); algParams.Add(inputImg.PixelHeight); int Width = 0, Height = 0; if (inputImg.PixelWidth > inputImg.PixelHeight) { if ((inputImg.PixelWidth % lenght) != 0) { int newSize = (inputImg.PixelWidth / lenght + 1) * lenght; Width = newSize; Height = newSize; } else { Width = inputImg.PixelWidth; Height = inputImg.PixelWidth; } } else if (inputImg.PixelWidth < inputImg.PixelHeight) { if ((inputImg.PixelHeight % lenght) != 0) { int newSize = (inputImg.PixelHeight / lenght + 1) * lenght; Width = newSize; Height = newSize; } else { Width = inputImg.PixelHeight; Height = inputImg.PixelHeight; } } else if (inputImg.PixelWidth == inputImg.PixelHeight) { int newSize = (inputImg.PixelWidth / lenght + 1) * lenght; Width = newSize; Height = newSize; } int neededBytes = Width * Height * bytesPerPixel; byte[] originalPixels = new byte[inputImg.PixelWidth * inputImg.PixelHeight * bytesPerPixel]; inputImg.CopyPixels(originalPixels, inputImg.PixelWidth * bytesPerPixel, 0); byte[] pixels = new byte[neededBytes]; int row = 0, col = 0, iteration = 1; for (int i = 0; i < originalPixels.Length; i++) { pixels[row * Width * bytesPerPixel + col] = originalPixels[i]; col++; if (i == (inputImg.PixelWidth * iteration * bytesPerPixel) - 1) { row++; iteration++; col = 0; } } BitmapSource resizedImg = BitmapSource.Create(Width, Height, inputImg.DpiX, inputImg.DpiY, inputImg.Format, inputImg.Palette, pixels, Width * bytesPerPixel); return(resizedImg); }
//E:\オレ\エクセル\画像処理.xlsm_バイリニア法_$A$599 //縮小専用 /// <summary> /// 画像の縮小、バイリニア法で補完、PixelFormats.Bgr24専用) /// </summary> /// <param name="source">PixelFormats.Bgr24のBitmap</param> /// <param name="yoko">変換後の横ピクセル数を指定</param> /// <param name="tate">変換後の縦ピクセル数を指定</param> /// <returns></returns> private BitmapSource BilinearBgr24縮小専用(BitmapSource source, int yoko, int tate) { //元画像の画素値の配列作成 int sourceWidth = source.PixelWidth; int sourceHeight = source.PixelHeight; int stride = (sourceWidth * source.Format.BitsPerPixel + 7) / 8; byte[] pixels = new byte[sourceHeight * stride]; source.CopyPixels(pixels, stride, 0); //変換後の画像の画素値の配列用 double yokoScale = (double)sourceWidth / yoko;//横倍率 double tateScale = (double)sourceHeight / tate; //1ピクセルあたりのバイト数、Byte / Pixel int pByte = (source.Format.BitsPerPixel + 7) / 8; int scaledStride = yoko * pByte; byte[] resultPixels = new byte[tate * scaledStride]; _ = Parallel.For(0, tate, y => { for (int x = 0; x < yoko; x++) { //参照範囲の左上座標bp double bpX = ((x + 0.5) * yokoScale) - 0.5; double bpY = ((y + 0.5) * tateScale) - 0.5; //小数部分s double sx = bpX % 1; double sy = bpY % 1; //面積 double d = sx * sy; double c = (1 - sx) * sy; double b = sx * (1 - sy); double a = 1 - (d + c + b); // (1 - sx) * (1 - sy) //左上ピクセルの座標は //参照範囲の左上座標の小数部分を切り捨て(整数部分) //左上ピクセルのIndex int i = ((int)bpY * stride) + ((int)bpX * pByte); //各区の値*面積の合計を四捨五入して完成 //Blue resultPixels[y * scaledStride + x * pByte] = (byte)(pixels[i] * a + pixels[i + pByte] * b + pixels[i + stride] * c + pixels[i + stride + pByte] * d + 0.5); //Green resultPixels[y * scaledStride + x * pByte + 1] = (byte)(pixels[i + 1] * a + pixels[i + pByte + 1] * b + pixels[i + stride + 1] * c + pixels[i + stride + pByte + 1] * d + 0.5); //Red resultPixels[y * scaledStride + x * pByte + 2] = (byte)(pixels[i + 2] * a + pixels[i + pByte + 2] * b + pixels[i + stride + 2] * c + pixels[i + stride + pByte + 2] * d + 0.5); } }); BitmapSource bitmap = BitmapSource.Create(yoko, tate, 96, 96, source.Format, null, resultPixels, scaledStride); return(bitmap); }
public static BitmapSource CropBitmapSource( BitmapSource source, int sourceX, int sourceY, int width, int height, byte[] cachedSourcePixels = null ) { // A couple things are hardcoded to expect 4 bytes per pixel. if (source.Format != PixelFormats.Bgra32) { throw new Exception("Unexpected Bitmap format."); } var bytesPerPixel = source.Format.BitsPerPixel / 8; var sourceWidth = source.PixelWidth; var sourceHeight = source.PixelHeight; var sourceStride = sourceWidth * bytesPerPixel; var sourceBuffer = cachedSourcePixels; if (cachedSourcePixels == null) { sourceBuffer = new byte[sourceStride * sourceHeight]; source.CopyPixels(sourceBuffer, sourceStride, 0); } var outputWidth = width; var outputHeight = height; var outputStride = outputWidth * bytesPerPixel; var outputBuffer = new byte[outputStride * outputHeight]; // Fill the crop with black for (var x = 0; x < outputWidth; x++) { for (var y = 0; y < outputHeight; y++) { var offset = (outputStride * y) + (x * bytesPerPixel); outputBuffer[offset] = 0; // B outputBuffer[offset + 1] = 0; // G outputBuffer[offset + 2] = 0; // R outputBuffer[offset + 3] = 255; // A } } // Copy the crop-area pixels from the source to the output bitmap. for (var y = 0; y < height; y++) { // Ignore out-of-range pixels. if (sourceY + y < 0 || sourceY + y > sourceHeight - 1) { continue; } var rowOffset = (sourceY + y) * sourceStride; if (rowOffset < 0 || rowOffset >= sourceBuffer.Length) { continue; } for (var x = 0; x < width; x++) { // Ignore out-of-range pixels. if (sourceX + x < 0 || sourceX + x > sourceWidth - 1) { continue; } var sourceOffset = rowOffset + (sourceX + x) * bytesPerPixel; var outputOffset = y * outputStride + x * bytesPerPixel; if (sourceOffset < 0 || sourceOffset >= sourceBuffer.Length) { continue; } outputBuffer[outputOffset] = sourceBuffer[sourceOffset]; outputBuffer[outputOffset + 1] = sourceBuffer[sourceOffset + 1]; outputBuffer[outputOffset + 2] = sourceBuffer[sourceOffset + 2]; outputBuffer[outputOffset + 3] = 255; } } return(BitmapSource.Create( width, height, 96, 96, source.Format, null, outputBuffer, outputStride )); }
private static Texture2D CreateTexture2DFromBitmapSource(Device device, BitmapSource bitmapSource, TextureLoadOptions options) { // Allocate DataStream to receive the WIC image pixels var stride = bitmapSource.Size.Width * 4; using (var buffer = new DataStream(bitmapSource.Size.Height * stride, true, true)) { // Copy the content of the WIC to the buffer bitmapSource.CopyPixels(stride, buffer); var texture2DDescription = new Texture2DDescription() { Width = bitmapSource.Size.Width, Height = bitmapSource.Size.Height, ArraySize = 1, BindFlags = options.BindFlags, Usage = options.ResourceUsage, CpuAccessFlags = options.CpuAccessFlags, Format = options.Format, MipLevels = options.MipLevels, OptionFlags = ResourceOptionFlags.None, SampleDescription = new SampleDescription(1, 0), }; bitmapSource.Dispose(); var dataRectangle = new DataRectangle(buffer.DataPointer, stride); return new Texture2D(device, texture2DDescription, dataRectangle); } }
//E:\オレ\エクセル\画像処理.xlsm_バイリニア法_$A$599 //縮小専用 /// <summary> /// 画像の縮小、バイリニア法で補完、PixelFormats.Bgra32専用) /// </summary> /// <param name="source">PixelFormats.Bgra32のBitmap</param> /// <param name="yoko">変換後の横ピクセル数を指定</param> /// <param name="tate">変換後の縦ピクセル数を指定</param> /// <returns></returns> private BitmapSource BilinearBgra32縮小専用(BitmapSource source, int yoko, int tate) { //元画像の画素値の配列作成 int sourceWidth = source.PixelWidth; int sourceHeight = source.PixelHeight; int stride = (sourceWidth * source.Format.BitsPerPixel + 7) / 8; byte[] pixels = new byte[sourceHeight * stride]; source.CopyPixels(pixels, stride, 0); //変換後の画像の画素値の配列用 double yokoScale = (double)sourceWidth / yoko;//横倍率 double tateScale = (double)sourceHeight / tate; int scaledStride = (yoko * source.Format.BitsPerPixel + 7) / 8; byte[] resultPixels = new byte[tate * scaledStride]; int pByte = (source.Format.BitsPerPixel + 7) / 8;//1ピクセルあたりのバイト数、Byte / Pixel _ = Parallel.For(0, tate, y => { for (int x = 0; x < yoko; x++) { //参照範囲の左上座標bp double bpX = ((x + 0.5) * yokoScale) - 0.5; double bpY = ((y + 0.5) * tateScale) - 0.5; //小数部分s double sx = bpX % 1; double sy = bpY % 1; //面積 double d = sx * sy; double c = (1 - sx) * sy; double b = sx * (1 - sy); double a = 1 - (d + c + b); // (1 - sx) * (1 - sy) //左上ピクセルの座標は //参照範囲の左上座標の小数部分を切り捨て(整数部分) //左上ピクセルのIndex int ia = ((int)bpY * stride) + ((int)bpX * pByte); int ib = ia + 1; int ic = ((int)bpY * stride + stride) + ((int)bpX * pByte); int id = ((int)bpY * stride + stride) + ((int)bpX * pByte) + 1; //Alphaが0の区画のRGB値は無視したいので初期値1.0から面積を引き算して //有効面積率を計算 byte aAlpha = pixels[ia + 3]; byte bAlpha = pixels[ia + pByte + 3]; byte cAlpha = pixels[ia + stride + 3]; byte dAlpha = pixels[ia + stride + pByte + 3]; //有効面積率 double effectiveAreaRatio = 1.0; if (aAlpha == 0) { effectiveAreaRatio -= a; } if (bAlpha == 0) { effectiveAreaRatio -= b; } if (cAlpha == 0) { effectiveAreaRatio -= c; } if (dAlpha == 0) { effectiveAreaRatio -= d; } //1.0/有効面積率、これをRGB合計値に掛け算 effectiveAreaRatio = 1.0 / effectiveAreaRatio; //各区の値*面積の合計に有効面積倍率を掛け算してから四捨五入して完成 //Blue resultPixels[y * scaledStride + x * pByte] = (byte)((( pixels[ia] * a + pixels[ia + pByte] * b + pixels[ia + stride] * c + pixels[ia + stride + pByte] * d ) * effectiveAreaRatio ) + 0.5); //Green resultPixels[y * scaledStride + x * pByte + 1] = (byte)(((pixels[ia + 1] * a + pixels[ia + pByte + 1] * b + pixels[ia + stride + 1] * c + pixels[ia + stride + pByte + 1] * d) * effectiveAreaRatio) + 0.5); //Red resultPixels[y * scaledStride + x * pByte + 2] = (byte)(((pixels[ia + 2] * a + pixels[ia + pByte + 2] * b + pixels[ia + stride + 2] * c + pixels[ia + stride + pByte + 2] * d) * effectiveAreaRatio) + 0.5); //Alpha resultPixels[y * scaledStride + x * pByte + 3] = (byte)((aAlpha * a) + (bAlpha * b) + (cAlpha * c) + (dAlpha * d) + 0.5); } }); BitmapSource bitmap = BitmapSource.Create(yoko, tate, 96, 96, source.Format, null, resultPixels, scaledStride); return(bitmap); }
//縮小拡大対応完成版 /// <summary> /// 画像の拡大縮小、バイリニア法で補完(PixelFormats.Bgra32専用) /// </summary> /// <param name="source">PixelFormats.Bgra32のBitmap</param> /// <param name="yoko">横ピクセル数を指定</param> /// <param name="tate">縦ピクセル数を指定</param> /// <returns></returns> private BitmapSource BilinearBgra32専用(BitmapSource source, int yoko, int tate) { //元画像の画素値の配列作成 int sourceWidth = source.PixelWidth; int sourceHeight = source.PixelHeight; int stride = (sourceWidth * source.Format.BitsPerPixel + 7) / 8; byte[] pixels = new byte[sourceHeight * stride]; source.CopyPixels(pixels, stride, 0); //縮小後の画像の画素値の配列用 double yokoScale = (double)sourceWidth / yoko;//横倍率 double tateScale = (double)sourceHeight / tate; //1ピクセルあたりのバイト数、Byte / Pixel int pByte = (source.Format.BitsPerPixel + 7) / 8; int scaledStride = yoko * pByte; byte[] resultPixels = new byte[tate * scaledStride]; Parallel.For(0, tate, y => { for (int x = 0; x < yoko; x++) { //参照範囲の左上座標bp double bpX = ((x + 0.5) * yokoScale) - 0.5; //画像範囲内チェック、参照範囲が画像から外れていたら修正(収める) if (bpX < 0) { bpX = 0; } if (bpX > sourceWidth - 1) { bpX = sourceWidth - 1; } double bpY = (y + 0.5) * tateScale - 0.5; if (bpY < 0) { bpY = 0; } if (bpY > sourceHeight - 1) { bpY = sourceHeight - 1; } //小数部分s double sx = bpX % 1; double sy = bpY % 1; //面積 double d = sx * sy; double c = (1 - sx) * sy; double b = sx * (1 - sy); double a = 1 - (d + c + b);// (1 - sx) * (1 - sy) //左上ピクセルの座標は //参照範囲の左上座標の小数部分を切り捨て(整数部分) //左上ピクセルのIndex int i = ((int)bpY * stride) + ((int)bpX * pByte); //値*面積 double aBlue = pixels[i] * a; double aGreen = pixels[i + 1] * a; double aRed = pixels[i + 2] * a; double aAlpha = pixels[i + 3] * a; //Alphaが0の区画のRGB値は無視したいので初期値1.0から面積を引き算して //有効面積率を計算 double effectiveAreaRatio = 1.0; if (pixels[i + 3] == 0) { effectiveAreaRatio -= a; } double bB = 0; double bG = 0; double bR = 0; double bA = 0; double cB = 0; double cG = 0; double cR = 0; double cA = 0; double dB = 0; double dG = 0; double dR = 0; double dA = 0; int pp; //B区以降は面積が0より大きいときだけ計算 if (b != 0) { //Aの右ピクセル*Bの面積 pp = i + pByte; bB = pixels[pp] * b; bG = pixels[pp + 1] * b; bR = pixels[pp + 2] * b; bA = pixels[pp + 3] * b; if (pixels[pp + 3] == 0) { effectiveAreaRatio -= b; } } if (c != 0) { //下側ピクセル pp = i + stride; cB = pixels[pp] * c; cG = pixels[pp + 1] * c; cR = pixels[pp + 2] * c; cA = pixels[pp + 3] * c; if (pixels[pp + 3] == 0) { effectiveAreaRatio -= c; } } if (d != 0) { //Aの右下ピクセル、仮にAが画像右下ピクセルだったとしても //そのときは面積が0のはずだからここは計算されない pp = i + stride + pByte; dB = pixels[pp] * d; dG = pixels[pp + 1] * d; dR = pixels[pp + 2] * d; dA = pixels[pp + 3] * d; if (pixels[pp + 3] == 0) { effectiveAreaRatio -= d; } } //Alpha0の面積によって倍率変更 //有効面積率はRGBそれぞれに掛け算 effectiveAreaRatio = 1 / effectiveAreaRatio; //4区を合計して四捨五入で完成 resultPixels[(y * scaledStride) + (x * pByte)] = (byte)(((aBlue + bB + cB + dB) * effectiveAreaRatio) + 0.5); resultPixels[(y * scaledStride) + (x * pByte) + 1] = (byte)(((aGreen + bG + cG + dG) * effectiveAreaRatio) + 0.5); resultPixels[(y * scaledStride) + (x * pByte) + 2] = (byte)(((aRed + bR + cR + dR) * effectiveAreaRatio) + 0.5); resultPixels[(y * scaledStride) + (x * pByte) + 3] = (byte)(aAlpha + bA + cA + dA + 0.5); } }); BitmapSource bitmap = BitmapSource.Create(yoko, tate, 96, 96, source.Format, null, resultPixels, scaledStride); return(bitmap); }
/// <summary> /// Cretae the member variable _bitmap for the photo to eet /// DPI and format requirements /// </summary> /// <param name="filename">Path to photo</param> /// <returns>Array of Images representing the iameg</returns> private Dpu.ImageProcessing.Image[] CreateMainBitMap(string filename) { Uri uri = new Uri("file:" + filename); if (false == System.IO.File.Exists(uri.LocalPath)) { throw new Exception("Cannot find photo file " + filename); } BitmapImage bitmapImage = new BitmapImage(); bitmapImage.BeginInit(); bitmapImage.UriSource = uri; bitmapImage.EndInit(); if (PixelFormats.Rgb24 != bitmapImage.Format) { _bitmap = new FormatConvertedBitmap(bitmapImage, PixelFormats.Rgb24, null, 0.0) as BitmapSource; } else { _bitmap = bitmapImage as BitmapSource; } if (null == _bitmap) { throw new Exception("Bitmap is null"); } int bytePerPixel = _bitmap.Format.BitsPerPixel / 8; int stride = _bitmap.PixelWidth * bytePerPixel; _originalRect = new Rect(0, 0, _bitmap.PixelWidth, _bitmap.PixelHeight); byte[] dataPixs = new byte[stride * _bitmap.PixelHeight]; _bitmap.CopyPixels(dataPixs, stride, 0); Dpu.ImageProcessing.Image [] dataImages = ImageUtils.ConvertByteArrayToImageArray(dataPixs, _originalRect, bytePerPixel); _targetRect = new Rect(); _targetRect.Width = (_mainCanvas.OptionDialog.PhotoWidth * _mainCanvas.DisplayWidth); _targetRect.Height = (_mainCanvas.OptionDialog.PhotoWidth * _mainCanvas.DisplayHeight); byte[] displayPix; //Downscale large images if (_bitmap.PixelWidth > _targetRect.Width && _bitmap.PixelHeight > _targetRect.Height) { if (_bitmap.PixelWidth / _targetRect.Width > _bitmap.PixelHeight / _targetRect.Height) { _targetRect.Height = _bitmap.PixelHeight * _targetRect.Width / _bitmap.PixelWidth; } else { _targetRect.Width = _bitmap.PixelWidth * _targetRect.Height / _bitmap.PixelHeight; } Rect sourceRect = new Rect(0, 0, _bitmap.PixelWidth, _bitmap.PixelHeight); Dpu.ImageProcessing.Image[] displayImages = ImageUtils.ScaleImage(dataImages, sourceRect, _targetRect, bytePerPixel); displayPix = ImageUtils.ConvertImageArrayToByteArray(displayImages); stride = (int)_targetRect.Width * bytePerPixel; _bitmap = (BitmapSource)BitmapImage.Create((int)_targetRect.Width, (int)_targetRect.Height, _defaultDPI, _defaultDPI, _bitmap.Format, null, displayPix, stride); } else { displayPix = dataPixs; } if (_bitmap.DpiX != _defaultDPI || _bitmap.DpiY != _defaultDPI) { _bitmap = BitmapImage.Create(_bitmap.PixelWidth, _bitmap.PixelHeight, _defaultDPI, _defaultDPI, _bitmap.Format, null, displayPix, stride); } return(dataImages); }