Skip to main content
dolldivine
Inspiring
October 15, 2020
Open for Voting

Photoshop needs "Color to Alpha" button

  • October 15, 2020
  • 13 replies
  • 9772 views

I was just chatting with a group of other artists about the need to convert a color into transparency sometimes, and we've all needed such a function, then somebody said that in GIMP there's just a simple button for it, "Color to Alpha."  It does exactly what we need and very easily.  In Photshop this is possible but very cumbersome, having to use the channels to make a selection, then apply a mask.

 

Googling leads to 10 year old articles and people recommending plugins.  But yeah, I'd just like to suggest this as an official feature request.

 

You know how in Photoshop you can use Replace Color?  And you can pick a color, and vary the fuzziness of the selection, then change the color to something else?  It would be just like that I imagine, but instead of changing the color, you increase the opacity of those pixels.

13 replies

Jeff Arola
Community Expert
Community Expert
December 22, 2023

Alexander,

 

Here's an action that works on your particular image and other images that you want to remove the black or white background from.

http://www.ayatoweb.com/download/down04.html

google translated

https://www-ayatoweb-com.translate.goog/download/down04.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp&_x_tr_sch=http

 

The page is in Japanese, however, the action that still seems to work in photoshop 2024 is the

Photoshop Action File for MacOSX・Windows(Photoshop CS5・CS6)that includes an English version

and the action is called Un-Multiply

There is an updated version 2021, but some of the action steps are in Japanese

so the action doesn't work in English photoshop versions.

 

Anyhow, before running the action Un-Multiply on an image such as yours where you want to remove the white, first make sure the layer is a layer and not a Background layer, Invert the image, run the Un-Multiply action, then invert the image again.

 

Invert image

 

 

run Un-Multiply action

 

 

Invert image

 

 

Image on black background

 

 

 

final transparent png

 

Stephen Marsh
Community Expert
Community Expert
March 25, 2025

I've created a scripted version,  building upon Ayato Fujii's Action for Photoshop:

 

/*
Black or White to Transparency v1-0.jsx
Stephen Marsh
v1.0, 23rd March 2025
An approximation to the "Color to Alpha" function in Krita or GIMP.
https://docs.krita.org/en/reference_manual/filters/colors.html#color-to-alpha
https://docs.gimp.org/3.0/en/gimp-filter-color-to-alpha.html
Based on the original Japanese "UnMultiply" Action for black backgrounds by Ayato Fujii:
http://www.ayatoweb.com/download/down04.html
https://community.adobe.com/t5/photoshop-ecosystem-discussions/photoshop-needs-quot-color-to-alpha-quot-button/m-p/14315420#U15230303
*/

#target photoshop;

// Check if there's an open document
if (!app.documents.length) {
    alert("A document must be open to use this script!");
    throw new Error("A document must be open...");
}

// Check for RGB mode before proceeding
if (!(app.activeDocument.mode === DocumentMode.RGB)) {
    alert("The document must be in RGB mode!");
    throw new Error("RGB mode required...");
}

// Create the UI
var dlg = new Window("dialog", "Black or White to Transparency (v1.0)", undefined);
dlg.preferredSize.width = 275;

// Panel for radio buttons
var panel = dlg.add("panel", undefined, "Select:");
panel.orientation = "column";
panel.alignChildren = "left";
panel.preferredSize.width = 275;
var blackRadioButton = panel.add("radiobutton", undefined, "Black to Transparency");
whiteRadioButton = panel.add("radiobutton", undefined, "White to Transparency");
blackRadioButton.value = true; // Default selection
var applyLayerMaskCheckbox = panel.add("checkbox", undefined, "Apply Layer Mask");
applyLayerMaskCheckbox.value = false; // Default selection

// Cancel and OK buttons
var buttonGroup = dlg.add("group");
buttonGroup.orientation = "row";
buttonGroup.alignment = "right";
var cancelBtn = buttonGroup.add("button", undefined, "Cancel", { name: "cancel" });
var okBtn = buttonGroup.add("button", undefined, "OK", { name: "ok" });

// Event handler for OK button
okBtn.onClick = function () {
    if (app.activeDocument.activeLayer.isBackgroundLayer) {
        var userConfirm = confirm("Convert the Background layer to a standard layer. Yes or No?");
        // If the user confirms, convert the Background layer to a standard layer supporting transparency
        if (userConfirm) {
            app.activeDocument.suspendHistory("Undo script", "suspendFlattened()");
            function suspendFlattened() {
                app.activeDocument.activeLayer.isBackgroundLayer = false;
                app.activeDocument.activeLayer.name = "Background";
                // Proceed with the remaining operations
                if (blackRadioButton.value) {
                    blackBackground();
                } else {
                    whiteBackground();
                }
                if (applyLayerMaskCheckbox.value) {
                    applyLayerMask(true);
                }
            }
            dlg.close();
        } else {
            // If the user cancels, do nothing
            alert("Script cancelled!");
            dlg.close();
        }
    } else {
        // If the active layer is not a Background layer, proceed without confirmation
        app.activeDocument.suspendHistory("Undo script", "suspendLayer()");
        function suspendLayer() {
            if (blackRadioButton.value) {
                blackBackground();
            } else {
                whiteBackground();
            }
            if (applyLayerMaskCheckbox.value) {
                applyLayerMask(true);
            }
        }
        dlg.close();
    }
};

// Event handler for Cancel button
cancelBtn.onClick = function () {
    dlg.close();
};

// Render the dialog window
dlg.show();


///// Functions /////
function cTID(s) {
    return app.charIDToTypeID(s);
}
function sTID(s) {
    return app.stringIDToTypeID(s);
}

function blackBackground() {

    // Rename standard name Alpha channels to include a hyphen to avoid conflicts
    var theAlphas = app.activeDocument.channels;
    for (var i = 0; i < theAlphas.length; i++) {
        var channel = theAlphas[i];
        if (channel.name.match(/^Alpha \d+$/)) {
            var newName = channel.name.replace("Alpha ", "Alpha-");
            channel.name = newName;
        }
    }

    function selectChannel(channel, isName) {
        var desc = new ActionDescriptor();
        var ref = new ActionReference();
        if (isName) {
            ref.putName(cTID('Chnl'), channel);
        } else {
            ref.putEnumerated(cTID('Chnl'), cTID('Chnl'), channel);
        }
        desc.putReference(cTID('null'), ref);
        executeAction(cTID('slct'), desc, DialogModes.NO);
    }

    function makeChannel(targetChannel, calcMode, sourceChannel) {
        var desc1 = new ActionDescriptor();
        desc1.putClass(cTID('Nw  '), cTID('Chnl'));
        var desc2 = new ActionDescriptor();
        var ref1 = new ActionReference();
        ref1.putEnumerated(cTID('Chnl'), cTID('Ordn'), cTID('Trgt'));
        desc2.putReference(cTID('T   '), ref1);
        desc2.putEnumerated(cTID('Clcl'), cTID('Clcn'), calcMode);
        var ref2 = new ActionReference();
        ref2.putEnumerated(cTID('Chnl'), cTID('Chnl'), sourceChannel);
        desc2.putReference(cTID('Src2'), ref2);
        desc1.putObject(cTID('Usng'), cTID('Clcl'), desc2);
        executeAction(cTID('Mk  '), desc1, DialogModes.NO);
    }

    function setSelection(value, isName) {
        var desc = new ActionDescriptor();
        var ref1 = new ActionReference();
        ref1.putProperty(cTID('Chnl'), sTID('selection'));
        desc.putReference(cTID('null'), ref1);
        if (isName) {
            var ref2 = new ActionReference();
            ref2.putName(cTID('Chnl'), value);
            desc.putReference(cTID('T   '), ref2);
        } else {
            desc.putEnumerated(cTID('T   '), cTID('Ordn'), value);
        }
        executeAction(cTID('setd'), desc, DialogModes.NO);
    }

    function paste() {
        var desc = new ActionDescriptor();
        desc.putEnumerated(cTID('AntA'), cTID('Annt'), cTID('Anno'));
        executeAction(cTID('past'), desc, DialogModes.NO);
    }

    // Action conversion steps
    selectChannel(cTID('Rd  '), false);                     // Select Red channel
    makeChannel(null, cTID('Lghn'), cTID('Grn '));          // Alpha 1: Red lighten Green
    makeChannel(null, cTID('Lghn'), cTID('Bl  '));          // Alpha 2: Red lighten Blue
    makeChannel(null, sTID('blendDivide'), cTID('Rd  '));   // Alpha 3: Red divide Red
    selectChannel('Alpha 2', true);                         // Select Alpha 2
    makeChannel(null, sTID('blendDivide'), cTID('Grn '));   // Alpha 4: Alpha 2 divide Green
    selectChannel('Alpha 2', true);                         // Select Alpha 2
    makeChannel(null, sTID('blendDivide'), cTID('Bl  '));   // Alpha 5: Alpha 2 divide Blue

    selectChannel('Alpha 3', true);                         // Select Alpha 3
    setSelection(cTID('Al  '), false);                      // Set selection to all
    executeAction(cTID('copy'));                            // Copy
    selectChannel(cTID('Rd  '), false);                     // Select Red channel
    paste();                                                // Paste

    selectChannel('Alpha 4', true);                         // Select Alpha 4
    setSelection(cTID('Al  '), false);                      // Set selection to all
    executeAction(cTID('copy'));                            // Copy
    selectChannel(cTID('Grn '), false);                     // Select Green channel
    paste();                                                // Paste

    selectChannel('Alpha 5', true);                         // Select Alpha 5
    setSelection(cTID('Al  '), false);                      // Set selection to all
    executeAction(cTID('copy'));                            // Copy
    selectChannel(cTID('Bl  '), false);                     // Select Blue channel
    paste();                                                // Paste

    setSelection(cTID('None'), false);                      // Deselect
    setSelection('Alpha 2', true);                          // Load Alpha 2 as selection
    selectChannel(sTID('RGB'), false);                      // Select RGB channel
    executeAction(cTID('Invs'));                            // Inverse selection
    maskSelection("hideSelection");                         // Add a layer mask

    setSelection(cTID('None'), false);                      // Deselect
    selectChannel('Alpha 1', true);                         // Select Alpha 1
    selectChannel('Alpha 2', true);                         // Extend selection to Alpha 2
    selectChannel('Alpha 3', true);                         // Extend selection to Alpha 3
    selectChannel('Alpha 4', true);                         // Extend selection to Alpha 4
    selectChannel('Alpha 5', true);                         // Extend selection to Alpha 5

    // Delete all working Alpha channels
    var desc = new ActionDescriptor();
    var list = new ActionList();
    var alphaChannels = ['Alpha 5', 'Alpha 4', 'Alpha 3', 'Alpha 2', 'Alpha 1'];
    for (var i = 0; i < alphaChannels.length; i++) {
        var ref = new ActionReference();
        ref.putName(cTID('Chnl'), alphaChannels[i]);
        list.putReference(ref);
    }
    desc.putList(cTID('null'), list);
    executeAction(cTID('Dlt '), desc, DialogModes.NO);

    // Rename hyphenated Alpha channels back to standard names
    var theAlphas = app.activeDocument.channels;
    for (var i = 0; i < theAlphas.length; i++) {
        var channel = theAlphas[i];
        if (channel.name.match(/^Alpha-\d+$/)) {
            var newName = channel.name.replace("Alpha-", "Alpha ");
            channel.name = newName;
        }
    }
}

function whiteBackground() {
    // Invert the white to black
    app.activeDocument.activeLayer.invert();
    // Convert the black background to transparency
    blackBackground();
    // Invert the black back to white
    app.activeDocument.activeLayer.invert();
}

function maskSelection(maskParameter) {
    // Parameter = "revealSelection" or "hideSelection"
    var s2t = function (s) {
        return app.stringIDToTypeID(s);
    };
    var descriptor = new ActionDescriptor();
    var reference = new ActionReference();
    descriptor.putClass(s2t("new"), s2t("channel"));
    reference.putEnumerated(s2t("channel"), s2t("channel"), s2t("mask"));
    descriptor.putReference(s2t("at"), reference);
    descriptor.putEnumerated(s2t("using"), s2t("userMaskEnabled"), s2t(maskParameter));
    executeAction(s2t("make"), descriptor, DialogModes.NO);
}

function applyLayerMask(apply) {
    var s2t = function (s) {
        return app.stringIDToTypeID(s);
    };
    var descriptor = new ActionDescriptor();
    var reference = new ActionReference();
    reference.putEnumerated(s2t("channel"), s2t("channel"), s2t("mask"));
    descriptor.putReference(s2t("null"), reference);
    descriptor.putBoolean(s2t("apply"), apply);
    if (apply) {
        executeAction(s2t("delete"), descriptor, DialogModes.NO);
    }
}

 

  1. Copy the code text to the clipboard
  2. Open a new blank file in a plain-text editor (not in a word processor)
  3. Paste the code in
  4. Save as a plain text format file – .txt
  5. Rename the saved file extension from .txt to .jsx
  6. Install or browse to the .jsx file to run (see below)

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

D Fosse
Community Expert
Community Expert
October 15, 2020

This is a very sensible request on the face of it. The problem is that Select > Color Range already does it. The output is a selection, not a mask. But all you have to do is click the mask button.

 

Generally, "new" features that only combine existing ones get low priority. That's just my experience, not my opinion.

 

In short...well, maybe it might be worth it. Whether it actually happens depends on the marketing value.

dolldivine
Inspiring
October 15, 2020

Whoooa, what?  I didnt know this tool existed!  This is exactly what I needed!  This is SO much easier than fiddling with channels and layer masks.  Thank you!

Chuck Uebele
Community Expert
Community Expert
October 15, 2020

You can post your feature request here: https://feedback.photoshop.com/photoshop_family