久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

自動將位圖修剪到最小尺寸?

Automatically trim a bitmap to minimum size?(自動將位圖修剪到最小尺寸?)
本文介紹了自動將位圖修剪到最小尺寸?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

假設我有一個 32bpp ARGB 模式的 System.Drawing.Bitmap.這是一個大的位圖,但它主要是完全透明的像素,中間有一個相對較小的圖像.

Suppose I have a System.Drawing.Bitmap in 32bpp ARGB mode. It's a large bitmap, but it's mostly fully transparent pixels with a relatively small image somewhere in the middle.

檢測真實"圖像邊界的快速算法是什么,這樣我就可以剪掉它周圍的所有透明像素?

What is a fast algorithm to detect the borders of the "real" image, so I can crop away all the transparent pixels from around it?

或者,.Net 中是否已經有一個函數可以用于此目的?

Alternatively, is there a function already in .Net that I can use for this?

推薦答案

基本思想是檢查圖像的每個像素點,找到圖像的上、左、右、下邊界.要有效地執行此操作,請不要使用速度很慢的 GetPixel 方法.改用 LockBits.

The basic idea is to check every pixel of the image to find the top, left, right and bottom bounds of the image. To do this efficiently, don't use the GetPixel method, which is pretty slow. Use LockBits instead.

這是我想出的實現:

static Bitmap TrimBitmap(Bitmap source)
{
    Rectangle srcRect = default(Rectangle);
    BitmapData data = null;
    try
    {
        data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        byte[] buffer = new byte[data.Height * data.Stride];
        Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);
        int xMin = int.MaxValue;
        int xMax = 0;
        int yMin = int.MaxValue;
        int yMax = 0;
        for (int y = 0; y < data.Height; y++)
        {
            for (int x = 0; x < data.Width; x++)
            {
                byte alpha = buffer[y * data.Stride + 4 * x + 3];
                if (alpha != 0)
                {
                    if (x < xMin) xMin = x;
                    if (x > xMax) xMax = x;
                    if (y < yMin) yMin = y;
                    if (y > yMax) yMax = y;
                }
            }
        }
        if (xMax < xMin || yMax < yMin)
        {
            // Image is empty...
            return null;
        }
        srcRect = Rectangle.FromLTRB(xMin, yMin, xMax, yMax);
    }
    finally
    {
        if (data != null)
            source.UnlockBits(data);
    }

    Bitmap dest = new Bitmap(srcRect.Width, srcRect.Height);
    Rectangle destRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height);
    using (Graphics graphics = Graphics.FromImage(dest))
    {
        graphics.DrawImage(source, destRect, srcRect, GraphicsUnit.Pixel);
    }
    return dest;
}

它可能可以優化,但我不是 GDI+ 專家,所以這是我能做的最好的,無需進一步研究...

It can probably be optimized, but I'm not a GDI+ expert, so it's the best I can do without further research...

實際上,有一種簡單的方法可以優化它,即不掃描圖像的某些部分:

actually, there's a simple way to optimize it, by not scanning some parts of the image :

  1. 從左到右掃描,直到找到一個不透明的像素;將 (x, y) 存入 (xMin, yMin)
  2. 從上到下掃描,直到找到一個不透明的像素(僅適用于 x >= xMin);將 y 存入 yMin
  3. 從右向左掃描,直到找到一個不透明的像素(僅適用于 y >= yMin);將 x 存入 xMax
  4. 從下往上掃描,直到找到一個不透明的像素(僅適用于 xMin <= x <= xMax);將 y 存入 yMax

<小時>

這是上述方法的實現:


here's an implementation of the approach above:

static Bitmap TrimBitmap(Bitmap source)
{
    Rectangle srcRect = default(Rectangle);
    BitmapData data = null;
    try
    {
        data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        byte[] buffer = new byte[data.Height * data.Stride];
        Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);

        int xMin = int.MaxValue,
            xMax = int.MinValue,
            yMin = int.MaxValue,
            yMax = int.MinValue;

        bool foundPixel = false;

        // Find xMin
        for (int x = 0; x < data.Width; x++)
        {
            bool stop = false;
            for (int y = 0; y < data.Height; y++)
            {
                byte alpha = buffer[y * data.Stride + 4 * x + 3];
                if (alpha != 0)
                {
                    xMin = x;
                    stop = true;
                    foundPixel = true;
                    break;
                }
            }
            if (stop)
                break;
        }

        // Image is empty...
        if (!foundPixel)
            return null;

        // Find yMin
        for (int y = 0; y < data.Height; y++)
        {
            bool stop = false;
            for (int x = xMin; x < data.Width; x++)
            {
                byte alpha = buffer[y * data.Stride + 4 * x + 3];
                if (alpha != 0)
                {
                    yMin = y;
                    stop = true;
                    break;
                }
            }
            if (stop)
                break;
        }

        // Find xMax
        for (int x = data.Width - 1; x >= xMin; x--)
        {
            bool stop = false;
            for (int y = yMin; y < data.Height; y++)
            {
                byte alpha = buffer[y * data.Stride + 4 * x + 3];
                if (alpha != 0)
                {
                    xMax = x;
                    stop = true;
                    break;
                }
            }
            if (stop)
                break;
        }

        // Find yMax
        for (int y = data.Height - 1; y >= yMin; y--)
        {
            bool stop = false;
            for (int x = xMin; x <= xMax; x++)
            {
                byte alpha = buffer[y * data.Stride + 4 * x + 3];
                if (alpha != 0)
                {
                    yMax = y;
                    stop = true;
                    break;
                }
            }
            if (stop)
                break;
        }

        srcRect = Rectangle.FromLTRB(xMin, yMin, xMax, yMax);
    }
    finally
    {
        if (data != null)
            source.UnlockBits(data);
    }

    Bitmap dest = new Bitmap(srcRect.Width, srcRect.Height);
    Rectangle destRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height);
    using (Graphics graphics = Graphics.FromImage(dest))
    {
        graphics.DrawImage(source, destRect, srcRect, GraphicsUnit.Pixel);
    }
    return dest;
}

當然,如果非透明部分很小,則不會有明顯的增益,因為它仍然會掃描大部分像素.但如果它很大,則只會掃描不透明部分周圍的矩形.

There won't be a significant gain if the non-transparent part is small of course, since it will still scan most of the pixels. But if it's big, only the rectangles around the non-transparent part will be scanned.

這篇關于自動將位圖修剪到最小尺寸?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

Right-click on a Listbox in a Silverlight 4 app(右鍵單擊 Silverlight 4 應用程序中的列表框)
WPF c# webbrowser scrolls over top menu(WPF c# webbrowser 在頂部菜單上滾動)
C# Console app - How do I make an interactive menu?(C# 控制臺應用程序 - 如何制作交互式菜單?)
How to avoid duplicate form creation in .NET Windows Forms?(如何避免在 .NET Windows Forms 中創建重復的表單?)
UI Automation Control Desktop Application and Click on Menu Strip(UI自動化控制桌面應用程序并單擊菜單條)
Removing thin border around the menuitems(刪除菜單項周圍的細邊框)
主站蜘蛛池模板: 国产午夜影院 | 欧美超碰在线 | 91av在线看 | 国产亚洲天堂 | 麻豆三级视频 | 国产成人免费在线视频 | 成人aaa| 欧美精品一级片 | 日韩欧美国产精品 | 国产永久视频 | 欧美xx孕妇 | 国产aⅴ爽av久久久久成人 | 福利小视频在线观看 | 一级黄色片免费看 | 天天射天天 | 欧美色综合天天久久综合精品 | 亚洲免费视频网站 | 四虎永久在线视频 | 国产成人精品一区二区三区四区 | 亚洲成人二区 | 欧美精品在线播放 | 中文字幕综合网 | 一级片日韩 | 男女啪啪免费 | 亚洲激情在线视频 | 日日干天天射 | 日韩av在线影院 | 欧美日韩一区二区三区视频 | 国产午夜一区二区 | 亚洲综合精品 | 天天爽天天爽 | 亚洲狠狠干| 国产自产21区 | 午夜在线小视频 | 精品欧美黑人一区二区三区 | 国产成人综合视频 | 欧美日韩综合网 | 麻豆亚洲一区 | 黄色高清网站 | 看免费毛片 | 九九久久精品视频 |