3

私は現在、ファイルやフォルダーからアイコンを取得できる小さなライブラリに取り組んでいます。今、それがwin8 +でのみ動作するかどうかは気にしません(私が使用する場所だからです)が、透過性に関して小さな問題に遭遇しました. 次の画像を見てください。

違い

私が (私のライブラリから) 生成したものは左側にあり、Windows エクスプローラーは右側にあります。
ご覧のとおり、最初に生成したものの右上に 2 本の黒い線があり、次に背景色に違いがあります。私が疑問に思っているのはこれです。Windowsエクスプローラーで使用されているのとまったく同じ画像を取得する方法はありませんか、それとも単に間違っていますか?

私のコード(構造体/externsなどを除いて短くするため)以下、コード全体.

public static class Icon
{
    public static Image GetIcon(string fileName, int size)
    {
        IShellItem shellItem;
        Shell32.SHCreateItemFromParsingName(fileName, IntPtr.Zero, Shell32.IShellItem_GUID, out shellItem);

        IntPtr hbitmap;
        ((IShellItemImageFactory)shellItem).GetImage(new SIZE(size, size), 0x0, out hbitmap);

        // get the info about the HBITMAP inside the IPictureDisp
        DIBSECTION dibsection = new DIBSECTION();
        Gdi32.GetObjectDIBSection(hbitmap, Marshal.SizeOf(dibsection), ref dibsection);
        int width = dibsection.dsBm.bmWidth;
        int height = dibsection.dsBm.bmHeight;

        // zero out the RGB values for all pixels with A == 0 
        // (AlphaBlend expects them to all be zero)
        for (int i = 0; i < dibsection.dsBmih.biWidth * dibsection.dsBmih.biHeight; i++)
        {
            IntPtr ptr = dibsection.dsBm.bmBits + (i * Marshal.SizeOf(typeof(RGBQUAD)));
            var rgbquad = (RGBQUAD)Marshal.PtrToStructure(ptr, typeof(RGBQUAD));
            if (rgbquad.rgbReserved == 0)
            {
                rgbquad.rgbBlue = 0;
                rgbquad.rgbGreen = 0;
                rgbquad.rgbRed = 0;
            }
            else
            {
                ;
            }
            Marshal.StructureToPtr(rgbquad, ptr, false);
        }

        // create the destination Bitmap object
        Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);

        // get the HDCs and select the HBITMAP
        Graphics graphics = Graphics.FromImage(bitmap);

        IntPtr hdcDest = graphics.GetHdc();
        IntPtr hdcSrc = Gdi32.CreateCompatibleDC(hdcDest);
        IntPtr hobjOriginal = Gdi32.SelectObject(hdcSrc, hbitmap);

        // render the bitmap using AlphaBlend
        BLENDFUNCTION blendfunction = new BLENDFUNCTION(BLENDFUNCTION.AC_SRC_OVER, 0, 0xFF, BLENDFUNCTION.AC_SRC_ALPHA);
        Gdi32.AlphaBlend(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, width, height, blendfunction);

        // clean up
        Gdi32.SelectObject(hdcSrc, hobjOriginal);
        Gdi32.DeleteDC(hdcSrc);
        graphics.ReleaseHdc(hdcDest);
        graphics.Dispose();
        Gdi32.DeleteObject(hbitmap);

        return bitmap;
    }
}
4

1 に答える 1

3

ピクセルごとにコピーすることが解決策だったようです。以下は、エクスプローラーのものと同等のピクセルパーフェクトのようです。

    public static Image GetIcon(string fileName, int size)
    {
        IShellItem shellItem;
        Shell32.SHCreateItemFromParsingName(fileName, IntPtr.Zero, Shell32.IShellItem_GUID, out shellItem);

        IntPtr hbitmap;
        ((IShellItemImageFactory)shellItem).GetImage(new SIZE(size, size), 0x0, out hbitmap);

        // get the info about the HBITMAP inside the IPictureDisp
        DIBSECTION dibsection = new DIBSECTION();
        Gdi32.GetObjectDIBSection(hbitmap, Marshal.SizeOf(dibsection), ref dibsection);
        int width = dibsection.dsBm.bmWidth;
        int height = dibsection.dsBm.bmHeight;

        // create the destination Bitmap object
        Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);

        for (int x = 0; x < dibsection.dsBmih.biWidth; x++)
        {
            for (int y = 0; y < dibsection.dsBmih.biHeight; y++)
            {
                int i = y * dibsection.dsBmih.biWidth + x;
                IntPtr ptr = dibsection.dsBm.bmBits + (i * Marshal.SizeOf(typeof(RGBQUAD)));
                var rgbquad = (RGBQUAD)Marshal.PtrToStructure(ptr, typeof(RGBQUAD));

                if (rgbquad.rgbReserved != 0)
                    bitmap.SetPixel(x, y, Color.FromArgb(rgbquad.rgbReserved, rgbquad.rgbRed, rgbquad.rgbGreen, rgbquad.rgbBlue));
            }
        }

        Gdi32.DeleteObject(hbitmap);

        return bitmap;
    }
于 2012-11-13T21:45:41.160 に答える