【问题标题】:Reducing an image size for compact framework减少紧凑框架的图像大小
【发布时间】:2017-05-19 14:06:29
【问题描述】:

我正在寻找一种方法,它可以让我减小从屏幕捕获的图像的大小(以字节为单位),而不是像远程桌面一样发送到另一台电脑(顺便说一句,这实际上是我的项目目的这部分已经完成,我只是在压缩图像时遇到了一些麻烦)。
该程序必须运行的计算机具有 Compact Framework 2.0 (Windows CE 6.0),我无法更改(@工作我们在某些机器上使用这些计算机,因此更改操作系统和框架有点困难)。
不管怎样,这是我用来捕捉屏幕的方法,然后是我用来改变像素颜色深度的实际方法。

    int DefaultMaxScreenDiskSize = 212500;

    private bool StreamScreen()
    {
        Rectangle bounds = Screen.PrimaryScreen.Bounds;
        IntPtr hdc = GetDC(IntPtr.Zero);

        Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format16bppRgb555);

        using (MemoryStream ms = new MemoryStream())
        {
            using (Graphics graphics = Graphics.FromImage(bitmap))
            {
                IntPtr dstHdc = graphics.GetHdc();
                BitBlt(dstHdc, 0, 0, bounds.Width, bounds.Height, hdc, 0, 0, Enums.RasterOperation.SRC_COPY);
                graphics.ReleaseHdc(dstHdc);
            }

            bitmap.Save(ms, ImageFormat.Png);
            int length = ms.ToArray().Length;

            if (length > DefaultMaxScreenDiskSize)
            {
                Bitmap nBitmap = ApplyDecreaseColourDepth(128, bitmap);
                nBitmap.Save(ms, ImageFormat.Png);
            }

            using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
                currentImgHash = Convert.ToBase64String(sha1.ComputeHash(ms.ToArray()));

            if (oldImgHash != currentImgHash || ForceScreenRefresh)
            {
                ReleaseDC(IntPtr.Zero, hdc);

                if (ms.ToArray() != null)
                {
                    while (!SendScreen(ZlibStream.CompressBuffer(ms.ToArray()))) ;

                    oldImgHash = currentImgHash;

                    ForceScreenRefresh = false;

                    return true;
                }
            }
        }

        return false;
    }

这是我使用的另一种方法,即改变像素深度的方法。但是,它在系统上有点慢和沉重,所以我不知道如何改变它。

    public Bitmap ApplyDecreaseColourDepth(int offset, Bitmap bitmapImage)
    {
        for (int y = 0; y < bitmapImage.Height; y++)
        {
            for (int x = 0; x < bitmapImage.Width; x++)
            {
                Color pixelColor = bitmapImage.GetPixel(x, y);

                int R = Math.Max(0, (pixelColor.R + offset / 2) / offset * offset - 1);
                int G = Math.Max(0, (pixelColor.G + offset / 2) / offset * offset - 1);
                int B = Math.Max(0, (pixelColor.B + offset / 2) / offset * offset - 1);

                bitmapImage.SetPixel(x, y, Color.FromArgb(R, G, B));
            }
        }

        return bitmapImage;
    }

知道如何更改深度像素或压缩位图吗?我尝试压缩图像,但(这是一个 .PNG)它只改变几个字节(例如正常大小 ms.length = 38689,压缩它 ms.length = 38489)

【问题讨论】:

  • 使用 GIF 或 8 位 PNG 等索引格式,创建调色板,用索引替换像素并保存。它会减少很多。
  • @Gusman 嗯,这是一个有趣的解决方案,但它是紧凑的框架,缺少这些东西。我已经想到了,但它不可行

标签: c# windows-ce image-compression compact-framework2.0


【解决方案1】:

很遗憾,我还没有解决压缩问题的方法。但我记得我不久前看到的 CodeProject 的一篇文章准确描述了 GetPixel()SetPixel() 非常慢的问题。可以通过以下代码克服此限制。 为了使其编译,您需要在相应项目的构建选项中允许不安全代码。

public unsafe Bitmap ApplyDecreaseColourDepth(int offset, Bitmap bitmapImage)
{
  BitmapData data = bitmapImage.LockBits(
    new Rectangle(0, 0, bitmapImage.Width, bitmapImage.Height),
    ImageLockMode.ReadWrite,
    PixelFormat.Format24bppRgb);
  const int bytesPerPixel = 3;

  Byte* scan0 = (Byte*)data.Scan0.ToPointer();
  Int32 stride = data.Stride;

  for (int y = 0; y < bitmapImage.Height; y++)
  {
    Byte* row = scan0 + (y * stride);
    for (int x = 0; x < bitmapImage.Width; x++)
    {
      Int32 bIndex = x * bytesPerPixel;
      Int32 gIndex = bIndex + 1;
      Int32 rIndex = bIndex + 2;

      Byte pixelR = row[rIndex];
      Byte pixelG = row[gIndex];
      Byte pixelB = row[bIndex];

      row[rIndex] = (Byte)Math.Max(0, (pixelR + offset / 2) / offset * offset - 1);
      row[gIndex] = (Byte)Math.Max(0, (pixelG + offset / 2) / offset * offset - 1);
      row[bIndex] = (Byte)Math.Max(0, (pixelB + offset / 2) / offset * offset - 1);
    }
  }

  bitmapImage.UnlockBits(data);
  return bitmapImage;
}

这是未经测试的,因此请在将其发布到生产环境之前进行测试!我正在谈论的文章(以及我曾经更改过您的代码)可以在https://www.codeproject.com/Articles/617613/Fast-pixel-operations-in-NET-with-and-without-unsa

下找到

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多