Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VS2015 icon guide - color inversion

I downloaded the set of VS2015 icons and reading through the MSDN guide

Under "Using color in images", it is stated that "In order to make icons appear with the correct contrast ratio in the Visual Studio dark theme, an inversion is applied programmatically."

I'm trying to mimic this behavior in my application but when I apply a color inversion to the image, it doesn't come out the way it looks in VS's dark theme:

enter image description here

Does anyone know how exactly VS inverts the colors so I can mimic this?

EDIT: This is the inversion code I'm using - the issue appear to be the edges with transparency/alpha:

        public static void InvertColors(Bitmap bitmapImage)
    {
        var bitmapRead = bitmapImage.LockBits(new Rectangle(0, 0, bitmapImage.Width, bitmapImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb);
        var bitmapLength = bitmapRead.Stride * bitmapRead.Height;
        var bitmapBGRA = new byte[bitmapLength];
        Marshal.Copy(bitmapRead.Scan0, bitmapBGRA, 0, bitmapLength);
        bitmapImage.UnlockBits(bitmapRead);

        for (int i = 0; i < bitmapLength; i += 4)
        {
            bitmapBGRA[i] = (byte)(255 - bitmapBGRA[i]);
            bitmapBGRA[i + 1] = (byte)(255 - bitmapBGRA[i + 1]);
            bitmapBGRA[i + 2] = (byte)(255 - bitmapBGRA[i + 2]);
        }

        var bitmapWrite = bitmapImage.LockBits(new Rectangle(0, 0, bitmapImage.Width, bitmapImage.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppPArgb);
        Marshal.Copy(bitmapBGRA, 0, bitmapWrite.Scan0, bitmapLength);
        bitmapImage.UnlockBits(bitmapWrite);
    }
like image 522
TJF Avatar asked Apr 21 '16 19:04

TJF


2 Answers

You can use the IVsUIShell5.ThemeDIBits method to apply in-place inversion. There is also ThemedImageSourceConverter WPF helper class to create an inverted image.

like image 80
Sergey Vlasov Avatar answered Oct 19 '22 18:10

Sergey Vlasov


The color is adjusted via its luminosity as stated in the documentation for the method IVsUIShell5.ThemeDIBits:

The luminosity of the image is transformed so that the constant "halo" luminosity blends in with the background. This has the effect of eliminating the halo visually. The "halo" luminosity is an immutable constant, and is not calculated from the input image.

So you have to convert the pixels into HSL color space, adjust the color and convert it back. I stumbled across this somewhere:

private double TransformLuminosity(double luminosity)
{
    double haloLuminosity = HaloLuminosity; //Color.FromArgb(255, 246, 246, 246)
    double themeBackgroundLuminosity = ThemeBackgroundColor.L;

    if (themeBackgroundLuminosity < LuminosityInversionThreshold) //LuminosityInversionThreshold = 0.5
    {
        haloLuminosity = 1.0 - haloLuminosity;
        luminosity = 1.0 - luminosity;
    }

    if (luminosity < haloLuminosity)
    {
        return themeBackgroundLuminosity * luminosity / haloLuminosity;
    }

    return (1.0 - themeBackgroundLuminosity) * (luminosity - 1.0) / (1.0 - haloLuminosity) + 1.0;
}

I based the halo luminosity on what the gray color is around most of the icons Color.FromArgb(255, 246, 246, 246). It does not give the exact same results but it is pleasing enough and suits my purpose currently. Some examples:

Without transformationWith transformation

like image 4
dfkeenan Avatar answered Oct 19 '22 18:10

dfkeenan