public static Bitmap ToGdiBitmap(BitmapSource bmp) { // below code refernces blog entry by luche: // http://www.ruche-home.net/%A4%DC%A4%E4%A4%AD%A4%B4%A4%C8/2011-08-02/CopyPixels%20%A5%E1%A5%BD%A5%C3%A5%C9%A4%F2%CD%D1%A4%A4%A4%BF%20WPF%20BitmapSource%20%A4%AB%A4%E9%20GDI%20Bitmap%20%A4%D8%A4%CE%CA%D1%B4%B9 if (bmp.Format != PixelFormats.Bgra32) { // convert format bmp = new FormatConvertedBitmap(bmp, PixelFormats.Bgra32, null, 0); bmp.Freeze(); } // prepare values var width = (int)bmp.Width; var height = (int)bmp.Height; var stride = width * 4; // prepare buffer var buffer = new byte[stride * height]; // copy to byte array bmp.CopyPixels(buffer, stride, 0); // create bitmap var result = new Bitmap(width, height, SDI::PixelFormat.Format32bppArgb); // set bitmap content try { // locking bits SDI::BitmapData bd = null; try { bd = result.LockBits(new Rectangle(0, 0, width, height), SDI::ImageLockMode.WriteOnly, SDI::PixelFormat.Format32bppArgb); Marshal.Copy(buffer, 0, bd.Scan0, buffer.Length); } finally { if (bd != null) { result.UnlockBits(bd); } } } catch { result.Dispose(); throw; } return result; }
/// <summary> /// 从图片中获取背景颜色 /// </summary> /// <param name="image">图片</param> /// <param name="callback">计算完成后调用的委托</param> public static void GetImageColorForBackgroundAsync(BitmapSource image, ComputeCompleteCallback callback) { FormatConvertedBitmap bitmap = null; const int bytesPerPixel = 3; byte[] pixels = null; int width = 0; int height = 0; bool isFrozen = image.IsFrozen; if (!isFrozen) { //由于image没有冻结,所以image不能跨线程使用,这时要在当前线程中将image转换为另一个位图 bitmap = new FormatConvertedBitmap(image, PixelFormats.Rgb24, BitmapPalettes.WebPalette, 0); if (bitmap.CanFreeze) bitmap.Freeze(); pixels = new byte[bitmap.PixelHeight * bitmap.PixelWidth * bytesPerPixel]; bitmap.CopyPixels(pixels, bitmap.PixelWidth * bytesPerPixel, 0); width = bitmap.PixelWidth; height = bitmap.PixelHeight; } ThreadPool.QueueUserWorkItem(new WaitCallback((state) => { if (isFrozen) { //由于image已经冻结,所以image可以跨线程使用,这时在新线程中将image转换为另一个位图 bitmap = new FormatConvertedBitmap(image, PixelFormats.Rgb24, BitmapPalettes.WebPalette, 0); if (bitmap.CanFreeze) bitmap.Freeze(); pixels = new byte[bitmap.PixelHeight * bitmap.PixelWidth * bytesPerPixel]; bitmap.CopyPixels(pixels, bitmap.PixelWidth * bytesPerPixel, 0); width = bitmap.PixelWidth; height = bitmap.PixelHeight; } //计算颜色的均值 int sum = width * height; int r = 0, g = 0, b = 0; int offset = 0; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { r += pixels[offset++]; g += pixels[offset++]; b += pixels[offset++]; } } r = r / sum; g = g / sum; b = b / sum; Color color1 = Color.FromRgb((byte)r, (byte)g, (byte)b); //计算图片右部的颜色均值 r = 0; g = 0; b = 0; int jstart = (int)(width * (1 - RightSideWidth)); sum = (width - jstart) * width; for (int i = 0; i < height; i++) { for (int j = jstart; j < width; j++) { r += pixels[(i * width + j) * bytesPerPixel + 0]; g += pixels[(i * width + j) * bytesPerPixel + 1]; b += pixels[(i * width + j) * bytesPerPixel + 2]; } } r = r / sum; g = g / sum; b = b / sum; Color color2 = Color.FromRgb((byte)r, (byte)g, (byte)b); //根据上面计算出来的两个颜色计算最终颜色 HSLColor hsl1 = new HSLColor(color1); HSLColor hsl2 = new HSLColor(color2); hsl1.Hue += 10; if (IsNotSaturateEnough(hsl1) && !IsAlmostZeroSaturation(hsl1)) hsl1.Saturation += 0.2; callback(Revise(hsl1, hsl2).ToRGB()); })); }
/// キャプチャしたHBitmapをBitmapSource(Freezed)にして返す /// @param request スクリーンキャプチャ設定をまとめたリクエスト /// @return スクリーンキャプチャ結果が格納されたBitmapSource private BitmapSource Capture(ScreenCaptureRequest request) { if (request.ClippingWidth <= 0 || request.ClippingHeight <= 0) { // Debug.WriteLine("Invalid clipping size", "ScreenCaptureTimer.CaptureByGetDIBits"); return null; } // HBitmapからBitmapSourceを作成 BitmapSource bitmap = null; using (var result = request.Execute()) { if (result == null) return bitmap; // HBitmapからBitmapSourceに変換 bitmap = Imaging.CreateBitmapSourceFromHBitmap( result.Bitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); // Debug.WriteLine(string.Format("Captured: {0:D}x{1:D}", // bitmap.PixelWidth, bitmap.PixelHeight), // "ScreenCapture"); } // Alphaチャンネル情報を削除 bitmap = new FormatConvertedBitmap(bitmap, PixelFormats.Bgr32, null, 0.0); /// @todo(me) あまり大きな画像をメモリにおいておきたくない。 /// とはいえ、TransformedBitmapはちょっと重過ぎる。 /// メモリよりもCPUリソースを残しておきたいのでこのままでいいかも。 //bitmap = this.Resize(bitmap); // スレッド越しにアクセスされるためFreeze bitmap.Freeze(); return bitmap; }
/// <summary> /// 从图片中获取背景颜色 /// </summary> /// <param name="bitmap">图片</param> public static Color GetImageColorForBackground(FormatConvertedBitmap bitmap) { const int bytesPerPixel = 3; if (bitmap.CanFreeze) bitmap.Freeze(); var pixels = new byte[bitmap.PixelHeight * bitmap.PixelWidth * bytesPerPixel]; bitmap.CopyPixels(pixels, bitmap.PixelWidth * bytesPerPixel, 0); var width = bitmap.PixelWidth; var height = bitmap.PixelHeight; //计算颜色的均值 Color color = GetColorOfRegion(pixels, width, height, 0, width, 0, height); var hsl = new HslColor(color); if (IsNotSaturateEnough(hsl) && !IsAlmostZeroSaturation(hsl)) hsl.Saturation += 0.2; return Revise(hsl).ToRgb(); }
private BitmapSource ConvertToBgra32(BitmapSource src) { if (src.Format == PixelFormats.Bgra32) return src; var s = new FormatConvertedBitmap( src, PixelFormats.Bgra32, null, 0); s.Freeze(); return s; }