久久久久久久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 中是否已經(jīng)有一個函數(shù)可以用于此目的?

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

推薦答案

基本思想是檢查圖像的每個像素點,找到圖像的上、左、右、下邊界.要有效地執(zhí)行此操作,請不要使用速度很慢的 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.

這是我想出的實現(xiàn):

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;
}

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

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

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

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

<小時>

這是上述方法的實現(xiàn):


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.

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

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

相關(guān)文檔推薦

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 中創(chuàng)建重復的表單?)
UI Automation Control Desktop Application and Click on Menu Strip(UI自動化控制桌面應用程序并單擊菜單條)
Removing thin border around the menuitems(刪除菜單項周圍的細邊框)
主站蜘蛛池模板: 亚洲国产精品99久久久久久久久 | 99国产精品99久久久久久 | 欧美精品一区二区免费 | 二区久久| 日本亚洲欧美 | 日韩精品免费在线 | 中文字幕视频在线看5 | 国产一区二区影院 | 婷婷色国产偷v国产偷v小说 | 亚洲品质自拍视频 | 伊人欧美视频 | 中文字幕精品一区 | 日韩视频―中文字幕 | 国产成在线观看免费视频 | 国产91丝袜在线播放 | 国产日韩欧美在线播放 | 密桃av| 成人国产一区二区三区精品麻豆 | 久久噜噜噜精品国产亚洲综合 | 自拍偷拍第一页 | 色.com| 国产免费观看视频 | 欧美在线一区二区三区 | 久久久久久久av | 成人久久久 | 成人不卡视频 | 亚洲精品91 | 一级a性色生活片久久毛片波多野 | 久久99精品久久久久久国产越南 | 精品成人| 中文字幕加勒比 | 久久国产成人 | 欧美日韩精品 | 91视频入口 | 97视频精品 | 超碰日韩 | 久久99精品久久久水蜜桃 | 一区二区三区高清在线观看 | 久热9| 色网站视频 | 亚洲精品乱码久久久久久9色 |