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

自動(dòng)將位圖修剪到最小尺寸?

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

問題描述

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

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.

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

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)有一個(gè)函數(shù)可以用于此目的?

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

推薦答案

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

這是我想出的實(shí)現(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+ 專家,所以這是我能做的最好的,無需進(jìn)一步研究...

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

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

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

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

<小時(shí)>

這是上述方法的實(shí)現(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;
}

當(dāng)然,如果非透明部分很小,則不會(huì)有明顯的增益,因?yàn)樗匀粫?huì)掃描大部分像素.但如果它很大,則只會(huì)掃描不透明部分周圍的矩形.

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)于自動(dòng)將位圖修剪到最小尺寸?的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

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

相關(guān)文檔推薦

Right-click on a Listbox in a Silverlight 4 app(右鍵單擊 Silverlight 4 應(yīng)用程序中的列表框)
WPF c# webbrowser scrolls over top menu(WPF c# webbrowser 在頂部菜單上滾動(dòng))
C# Console app - How do I make an interactive menu?(C# 控制臺(tái)應(yīng)用程序 - 如何制作交互式菜單?)
How to avoid duplicate form creation in .NET Windows Forms?(如何避免在 .NET Windows Forms 中創(chuàng)建重復(fù)的表單?)
UI Automation Control Desktop Application and Click on Menu Strip(UI自動(dòng)化控制桌面應(yīng)用程序并單擊菜單條)
Removing thin border around the menuitems(刪除菜單項(xiàng)周圍的細(xì)邊框)
主站蜘蛛池模板: 亚洲视频www| 人人干人人干人人干 | 国产一区二区三区四区五区加勒比 | www亚洲免费国内精品 | 91久久久久| 国内精品久久久久久 | 国产区在线 | www国产成人免费观看视频 | 欧美在线亚洲 | 91精品综合久久久久久五月天 | 在线观看亚洲精品 | 岛国av免费在线观看 | 亚洲精品一区二区三区在线 | 国产视频在线观看一区二区三区 | 欧美一级大片免费看 | 97精品超碰一区二区三区 | 亚洲三级在线观看 | 91精品国产乱码久久久 | 一级黄色毛片免费 | 91免费版在线观看 | 91精品国产91久久综合桃花 | 精品欧美二区 | 国产一区二区三区精品久久久 | 国产午夜精品一区二区三区 | 亚洲视频在线观看 | 亚洲精品免费看 | 美女视频一区二区三区 | 精品国产一区二区三区久久狼黑人 | 国产情侣在线看 | 精品伊人 | 国产日韩欧美在线观看 | 免费黄网站在线观看 | 亚洲一区精品视频 | 国产精品视频导航 | 日韩在线视频免费观看 | 国产精品久久国产精品 | 毛片在线免费 | 国产精品福利网站 | 日韩精品一区二区三区中文字幕 | 视频在线一区二区 | 日韩av美女电影 |