BoltBait

Black and White+ plugin v1.1 Updated Nov 10, 2018

Recommended Posts

Black and White+

version 1.1

 

Black and White+ includes 3 different algorithms to convert a color image into a black-and-white image.
 

  • Luminosity Method

    Shade of Gray = 0.299 * Red + 0.587 * Green + 0.114 * Blue

    This is the default method.  This is how the built-in Black-and-White effect converts a color image to black-and-white.  This method gives different weights to Red, Green, and Blue.  Other methods treat each color equally.
     
  • Average Method

    Shade of Gray = (Red + Green + Blue) / 3
     
  • Lightness Method

    Shade of Gray = [Max(Red,Green,Blue) + Min(Red,Green,Blue)] / 2
     

Every color photograph is different. You'll just need to try each method to see which one works best for your specific photograph.

 

Brightness/Contrast

 

In addition to converting your photograph to black-and-white, I've also provided access to the Brightness and Contrast adjustments.  For a more dramatic effect, decrease the brightness (try -10) and increase the contrast (try +10).
 

BandWPlusUI.png

 

BWDifferences.pngBWResults.png

 

Download

 

Download this effect as part of my plugin pack: https://forums.getpaint.net/topic/113220-b

 

 

 

 

Source Code

 

Here is the icon: BandWPlus.png and here is the CodeLab source:

// Name: Black and White+
// Author: BoltBait
// Submenu: Adjustments
// Title: BoltBait's Black and White+ v1.1
// Version: 1.1
// Desc: Convert image to Black and White
// Keywords: Black and White|B&W
// URL: http://BoltBait.com/pdn
#region UICode
ListBoxControl Amount1 = 0; // |Luminosity Method|Average Method|Lightness Method
IntSliderControl Amount2 = 0; // [-100,100] Brightness/Contrast
IntSliderControl Amount3 = 0; // [-100,100]
#endregion

BrightnessAndContrastAdjustment bacAdjustment = new BrightnessAndContrastAdjustment();
PropertyCollection bacProps;

private double Max3(double x, double y, double z)
{
    return (x > y) ? ((x > z) ? x : z) : ((y > z) ? y : z);
}

private double Min3(double x, double y, double z)
{
    return (x < y) ? ((x < z) ? x : z) : ((y < z) ? y : z);
}

protected override void OnDispose(bool disposing)
{
    if (disposing)
    {
        if (bacAdjustment != null) bacAdjustment.Dispose();
        bacAdjustment = null;
    }

    base.OnDispose(disposing);
}

void PreRender(Surface dst, Surface src)
{
    bacProps = bacAdjustment.CreatePropertyCollection();
    PropertyBasedEffectConfigToken bacParameters = new PropertyBasedEffectConfigToken(bacProps);
    bacParameters.SetPropertyValue(BrightnessAndContrastAdjustment.PropertyNames.Brightness, Amount2);
    bacParameters.SetPropertyValue(BrightnessAndContrastAdjustment.PropertyNames.Contrast, Amount3);
    bacAdjustment.SetRenderInfo(bacParameters, new RenderArgs(dst), new RenderArgs(src));
}

unsafe void Render(Surface dst, Surface src, Rectangle rect)
{
    // Call the Brightness and Contrast Adjustment function
    bacAdjustment.Render(new Rectangle[1] {rect},0,1);

    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        ColorBgra* dstPtr = dst.GetPointAddressUnchecked(rect.Left, y);
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ColorBgra CurrentPixel = *dstPtr;
            byte K = CurrentPixel.R;

            if (!(CurrentPixel.R == CurrentPixel.G && CurrentPixel.G == CurrentPixel.B))
            {
                switch (Amount1)
                {
                    case 0:
                        K = (byte)((0.299f * CurrentPixel.R) + (0.587f * CurrentPixel.G) + (0.114f * CurrentPixel.B));
                        break;
                    case 1:
                        K = (byte)((CurrentPixel.R + CurrentPixel.G + CurrentPixel.B) / 3.0);
                        break;
                    case 2:
                        K = (byte)((Max3(CurrentPixel.R, CurrentPixel.G, CurrentPixel.B) + Min3(CurrentPixel.R, CurrentPixel.G, CurrentPixel.B)) / 2.0);
                        break;
                    default:
                        break;
                }
            }
            CurrentPixel = ColorBgra.FromBgra(K,K,K,CurrentPixel.A);

            *dstPtr = CurrentPixel;
            dstPtr++;
        }
    }
}

 

Note: User MJW also made a Black and White+ plugin. His has way more adjustments than mine. I'm not sure, but you might be able to use his to get the same results as mine... I just couldn't figure out how to do it.  If you like LOTS of things to tinker with, you might give his a try.

 

The above is for Paint.NET v4.1.4+

 

Paint.NET v3.5.11

 

I'm sure someone will come along shortly and compile this for you.

  • Like 3

Share this post


Link to post
Share on other sites
10 hours ago, BoltBait said:

Shade of Gray = 0.2126 * Red + 0.7152 * Green + 0.0722 * Blue

 

May I ask how you decided on the three numbers?  I mean, why those number?  Were they arbitrarily selected?

Share this post


Link to post
Share on other sites
6 hours ago, TrevorOutlaw said:

May I ask how you decided on the three numbers?

 

Got them from Wikipedia: https://en.wikipedia.org/wiki/Grayscale

 

Looking at the code, Paint.NET actually uses these numbers:

 

0.299 * Red + 0.587 * Green + 0.114 * Blue

 

I will update my code to use these numbers instead of the Wikipedia page's values.

 

 

 

NOTE: Moving this to the Dev Center until the bugs are worked out...

 

Edit: I have corrected the algorithm above.  Now, the algorithm is matching what Paint.NET used to do.  Newer Paint.NET versions use a GPU enhanced version of the Black and White algorithm, and even though the numbers are the same, the results are SLIGHTLY different.  But, the CodeLab script above is solid and I will republish tonight once I update the built-in help file.

 

 

  • Like 1

Share this post


Link to post
Share on other sites

Thank you, BoltBait.  I also appreciate the source code so I can look at it and study it.  I'm about to take C++ for my last Computer Science class (engineering management major) requirement, so...

 

 

  • Like 2

Share this post


Link to post
Share on other sites

OK, I've updated the help file and rebuilt the dll.

 

Moved back to the plugin forum.

  • Upvote 1

Share this post


Link to post
Share on other sites

I’m pretty sure it is in the Adjustments menu. It’s just that there isn’t a “//comment” for that. 

  • Like 1

Share this post


Link to post
Share on other sites
19 hours ago, BoltBait said:

I’m pretty sure it is in the Adjustments menu. It’s just that there isn’t a “//comment” for that. 

 

I tracked it down using the Plugin Browser. I'll check I'm using the most recent version before I squawk too loudly :)

 

  • Like 1

Share this post


Link to post
Share on other sites
21 hours ago, BoltBait said:

it is in the Adjustments menu. It’s just that there isn’t a “//comment” for that.

 

There will be... in the next build of CodeLab. ;) 

  • Like 1

Share this post


Link to post
Share on other sites

OK, you convinced me.  I've made a new build and replaced the one in the original post.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.