Объект C# Bitmap, цвет выглядит прозрачным

Я работаю над программой на С#, которая делает скриншоты экрана пользователя. Для большинства дерзких он работает как надо, но недавно я столкнулся с одной проблемой. Кажется, что есть (по крайней мере) один цвет пикселя, который всегда выглядит прозрачным в выходном изображении. Любой экземпляр цвета #0D0B0C (RGB 13, 11, 12) отображается прозрачным в сохраненном png. Это с PixelFormat, установленным на Format32bppArgb. Если я установлю его на Format32bppRgb или Format24bppRgb, тот же цвет пикселя будет отображаться как черный в сохраненном png.

Я понятия не имею, что может быть причиной этого, но единственное, что я смог сделать, чтобы «исправить», это очистить графический объект до этого цвета перед выполнением CopyFromScreen(). Я ненавижу это делать, хотя по нескольким причинам. Во-первых, я не знаю, единственный ли это цвет, у которого есть проблема (что с 16 777 216 цветами есть довольно много возможностей), и, во-вторых, я ненавижу хакерские исправления, это похоже на хакерское исправление.

Может ли кто-нибудь пролить свет на то, что может быть причиной этой проблемы? Я возился с PixelFormat при создании растрового изображения и с CopyPixelOperation в методе CopyFromScreen, похоже, ничего не работает. Тот факт, что очистка графического объекта до этого цвета «исправляет», кажется, говорит мне, что прозрачность исходит из самих данных экрана, но это не имеет смысла. Я слишком долго смотрел на это, я думаю, мне нужен свежий взгляд на это. Если у кого-то есть какие-либо идеи, почему это может происходить, я хотел бы услышать это. Спасибо.


person HaLo2FrEeEk    schedule 08.03.2012    source источник


Ответы (3)


Мне просто нужно было запросить CopyFromScreen в растровое изображение, которое вообще НЕ имеет альфа-канала, например:

Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height,     System.Drawing.Imaging.PixelFormat.Format32bppRgb);
Graphics graphics = Graphics.FromImage(bitmap as Image);
graphics.CopyFromScreen(bounds.Location, new Point(0, 0), bitmap.Size);

Я подтвердил, что у этого есть прозрачные пиксельные отверстия с Format32bppArgb, но не с Format32bppRgb.

person Dave    schedule 11.05.2016

Возможно, альфа-значение равно 0? вы проверили?

Потому что большая разница между Format32bppArgb и Format32bppRgb заключается в том, что второй формат не знает альфа-канал.

person cansik    schedule 08.03.2012
comment
Экран печати дает правильное изображение, и, как я сказал в ОП, когда я устанавливаю для него значение Format32bppRgb, те же пиксели отображаются черными (когда они должны быть # 0D0B0C). Ни один из других пикселей не кажется прозрачным, и это звучит так же, как и на экране печати. - person HaLo2FrEeEk; 08.03.2012
comment
как вы делаете скриншоты? - person cansik; 08.03.2012
comment
Как я уже сказал в OP, я использую графический объект и CopyFromScreen(). - person HaLo2FrEeEk; 09.03.2012
comment
Изменение new Bitmap(width, height, PixelFormat.Format32bppArgb) на new Bitmap(width, height, PixelFormat.Format32bppRgb) устранило эту проблему для меня. - person ghord; 05.02.2016

Была точно такая же проблема при рендеринге элемента управления в растровое изображение. Удалось исправить это, создав еще одно растровое изображение с PixelFormat.Format32bppRgb и применив к нему BitBlt. Надеюсь это поможет!

public class ScreenCapture
{
    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
    private static extern bool BitBlt(
        IntPtr hdcDest, // handle to destination DC
        int nXDest, // x-coord of destination upper-left corner
        int nYDest, // y-coord of destination upper-left corner
        int nWidth, // width of destination rectangle
        int nHeight, // height of destination rectangle
        IntPtr hdcSrc, // handle to source DC
        int nXSrc, // x-coordinate of source upper-left corner
        int nYSrc, // y-coordinate of source upper-left corner
        System.Int32 dwRop // raster operation code
        );


    /// <summary>
    /// Returns an image of the control
    /// </summary>
    /// <param name="control">The control object whose image is wanted</param>
    /// <returns>Image of the control</returns>
    /// <remarks>This is based on code from 
    /// http://www.dotnet247.com/247reference/a.aspx?u=http://www.c-sharpcorner.com/Code/2002/April/ScreenCaptureUtility.asp 
    /// with changes made to prevent 0D0B0C transparency issues</remarks>
    public static Image GetControlImage(Control control)
    {
        Graphics g1 = control.CreateGraphics();

        // Create a bitmap the same size as the control
        Image MyImage = new Bitmap(control.ClientRectangle.Width, control.ClientRectangle.Height, PixelFormat.Format32bppRgb);
        (MyImage as Bitmap).SetResolution(g1.DpiX, g1.DpiY);

        Graphics g2 = Graphics.FromImage(MyImage);

        IntPtr dc1 = g1.GetHdc();
        IntPtr dc2 = g2.GetHdc();

        // BitBlt from one DC to the other
        BitBlt(dc2, 0, 0, control.ClientRectangle.Width, control.ClientRectangle.Height, dc1, 0, 0, 13369376);

        // Release Device Contexts
        g1.ReleaseHdc(dc1);
        g2.ReleaseHdc(dc2);

        // This statement runs the garbage collector manually
        // (If not present, uses up large amounts of memory...)
        GC.Collect();

        return MyImage;
    }
}
person Community    schedule 18.04.2012