header={ "recipe_version": "1.6", "title": "Make image background transparent", "description": "Convert images to a transparent background by using a color from one corner", "tags": "ImageMagick,image,transparent", "chef": "BeatRig", "dependencies": "identify,convert", "instructions": "Drop image files here and run this recipe to select the background detection settings", "type": "default", "os": "windows,macOS", "palette": "Mint Cream", "spice": "BQ==:G+Hy36kJcnQQYYavb/JV2Il6eCYr6h4hRJHCF9rRbhX5BcazL6cuTgUMdz0xA50VWA5PmmV0Q7aWkiUtNFtbk991l+t0e8IBXMReMIT1GNjnZZDv7n2YRAo0xcSQbY0ixjG6LLH4wGKnspKAoA/v69iLn6N2IH0XzIZwTGdHSo4=", "flavour": "5gnchER9IDp3Qba1ew9cEMnTc+pUXHxXhJg7iMtxZrEmHReJsUclezzYzLSoirkfGsOmvQOGPrV976j4i9uN/04nmzQXjeMYmQOLk2tvuwGSv9ht0tMYtIP+yuWwL6cUA7Qh11eJAIrOO04B7horG/krlUQJ68cMVZu7jB2vvhA=", "time": 1694301146, "core_version": "0.5.7", "magnetron_version": "1.0.261", "functions": "main,onAbout", "uuid": "7ebe4cd6eee6474c8c1190d380f4c630" }; //---------------------------------------------------------------------------- // o7 based on https://github.com/hackerb9/mktrans/blob/master/mktrans function main() { CheckInstalled(); var antialias_items = ["Anti-alias","Anti-alias (fast)","No anti-alias"]; var corner_items = ["Top-Left","Top-Right","Bottom-Left","Bottom-Right"]; var corner = corner_items[0]; var fuzz = "20"; var antialias = antialias_items[0]; var tag = "-transparent"; var files = getFiles(); if (files.length <= 0) abort("drop a file to process first"); for (var i = 0; i < files.length; i++) { filename = files[i].path; pathInfo = getPathInfo(filename); setMainMessage("processing " + pathInfo.basename); setProgress((i+0.5) / files.length * 100.); var dialog_width = 500; var form = { "mainlabel" : { "type" : "label", "label" : "Add transparancy from a specific background corner color to\n" + pathInfo.basename, "bounds" : { "x" : 5, "w" : dialog_width, "h" : 60, "y" : 5, } }, "cornerlabel" : { "type" : "label", "label" : "The sample color corner", "bounds" : { "x" : 5, "w" : dialog_width/2, } }, "corner" : { "type" : "combobox", "default" : corner, "items" : corner_items, "label" : "Sample color corner", "bounds" : { "x" : dialog_width/2, "y" : -1, "w" : dialog_width/2, } }, "fuzzlabel" : { "type" : "label", "label" : "Color tolerance", "bounds" : { "x" : 5, "w" : dialog_width/2 } }, "fuzz" : { "type" : "slider", "value": 30, "range" : { "min" : 0, "max" : 100, "interval" : 1, "decimals": 0 }, "label" : "color % tolerance:", "bounds" : { "x" : dialog_width/2, "y" : -1, "w" : dialog_width/2 } }, "antialiaslabel" : { "type" : "label", "label" : "anti-alias type", "bounds" : { "x" : 5, "w" : dialog_width/2 } }, "antialias" : { "type" : "combobox", "default" : antialias, "items" : antialias_items, "label" : "anti-alias types:", "bounds" : { "x" : dialog_width/2, "y" : -1, "w" : dialog_width/2 } }, "tag" : { "type" : "textedit", "default" : tag, "label" : "add file name tag:", "bounds" : { "x" : dialog_width/2, "y" : -1, "w" : dialog_width/2 } }, "okay" : { "type" : "button", "label" : "okay", "returns" : 1 }, "cancel" : { "type" : "button", "label" : "cancel", "returns" : 0 } }; form_out = dialog(form); if (form_out.cancel) abort("Cancelled"); corner = form_out.corner; fuzz = form_out.fuzz; antialias = form_out.antialias; tag = form_out.tag; outfile = pathInfo.folder + pathInfo.sep + pathInfo.basename + form_out.tag + ".png"; var wah = cmd("identify", ["-format", "%w,%h", filename]); var dimensions = wah.split(","); echo("dimensions:" + dimensions[0] + "x" + dimensions[1]); var x = 0; var y = 0; if (form_out.corner == corner_items[1]) x = dimensions[0]; if (form_out.corner == corner_items[2]) y = dimensions[1]; if (form_out.corner == corner_items[3]) { x = dimensions[0]; y = dimensions[1]; } pixelcomma = x + "," + y; pixelplus = "+" + x + "+" + y; var pflag = false; // false for 1 pixel border // Get color of pixel var color = cmd("convert", [filename, "-format", "%[pixel:p{" + pixelcomma + "}]", "info:-"]); // check if starts with rgba and ends with ,0) if (color.substring(0, 4) == "rgba" && color.substring(color.length - 3, color.length) == ",0)") color = color.substring(0, color.length - 3) + ",1)"; // if so replace end with ,1) if (color == "none") abort (filename + " pixel at " + pixelcomma + " completely transparent. Cannot floodfill"); echo(color); var options=[filename]; if (pflag == false) // Add a 1 pixel border so we'll fill from the bottom and sides as well. { options.push("-bordercolor"); options.push(color); options.push("-border"); options.push("1"); } // In a new stack, make a copy of the image options.push("("); options.push("+clone"); // [copy] floodfill with transparency ("none") starting at top-left options.push("-fuzz"); options.push(form_out.fuzz + "%"); options.push("-fill"); options.push("none"); options.push("-floodfill"); options.push(pixelplus); options.push(color); // [copy] extract just the transparency (alpha channel) options.push("-alpha"); options.push("extract"); if (form_out.antialias != antialias_items[2]) { if (form_out.antialias == antialias_items[1]) { // [copy] blow up the alpha channel so we can do sub-pixel morphology options.push("-geometry"); options.push("200%"); // [copy] blur the alpha channel to make it antialiased options.push("-blur"); options.push("0x0.5"); // [copy] shrink the region that is opaque by half a pixel. options.push("-morphology"); options.push("erode"); options.push("square:1"); // [copy] scale the alpha channel back to normal size. options.push("-geometry"); options.push("50%"); } else // speedy antialias { // [copy] blur the alpha channel to make it antialiased options.push("-blur"); options.push("0x1"); // [copy] only antialias inside the figure (<50% opacity becomes 0%) options.push("-level"); options.push("50%,100%"); } } // [copy] end the stack. options.push(")"); // Compose the original image and the copy's alpha channel. options.push("-compose"); options.push("CopyOpacity"); options.push("-composite"); if (pflag == false) // Remove the 1 pixel border we added { options.push("-shave"); options.push("1"); } options.push(outfile); echo("convert " + objectToString(options)); echo(cmd("convert", options)); setProgress((i+1) / files.length * 100.); if (isCanceled()) abort("Canceled"); } setMainMessage("finished"); } function onAbout() { dialog(header.title, header.description, "i"); } //---------------------------------------------------------------------------- function CheckInstalled() { var cmds = header.dependencies.split(","); for (i = 0; i < cmds.length; i++) { var install_cmd = cmds[i];//"convert"; var cmd_path = getAllowedApps(install_cmd); if (cmd_path.length <= 0) abort("ImageMagick " + install_cmd + " not installed"); } }