SVG-2-PIXELART icon indicating copy to clipboard operation
SVG-2-PIXELART copied to clipboard

Flash 2 Pixelart - Experiments with Adobe Animate

Open jetrotal opened this issue 2 years ago • 0 comments

Flash 2 Pixelart

Flash 2 Pixelart is a tool for converting animation in Adobe Flash to pixel art. It allows you to adjust the pixel size, alpha threshold, outline size,

c

Prerequisites

To use Flash 2 Pixelart, you will need the following:

  • Adobe Animate
  • A web browser that supports HTML5 Canvas and the ability to download multiple files (such as Google Chrome or Mozilla Firefox)

Instructions

  1. Create a new HTML5 Canvas document in Adobe Animate:

image

  1. Press F9 to open the Actions Menu, and Select Global / Script:

image

  1. Paste the code bellow into the script window:
// Made by Mauro Junior [ CC-BY ] - https://www.behance.net/gallery/65727549/Portifolio-2018-Mauro-Junior
// You can edit the canvas2pixel to control what changes from start 
// and hide/show the in-browser controller
//
// Thanks :]
var anim;
var canvas2pixel = {
    defaultVal: {
        alphaThreshold: 10,
        pixelSize: 5,
        outlineSize: 0,
        outlineColor: '#000',
        expandEdges: true,
    },
    showController: true
}

var flaName;
var renderedFrames = {};
var currFrame;

function ID(obj) {
return document.getElementById(obj)	
	}

function createControllers() {
    window.ctrlStyle = document.createElement('style');
    ctrlStyle.innerHTML = `
	#ctrlDiv{ display: ${canvas2pixel.showController ? "table-caption" : "none"}; width: 150px; position: absolute; right: 0; top: 0; padding: 15px; background-color: #fff5;}
	#ctrlDiv * {display: inline-block; min-width: 30px; text-align: center; }
	#ctrlDiv [type=color] {width: 100%; margin: 5px 0;}
	canvas { filter: url(#strokeFilter); }
	`;
    document.getElementsByTagName('head')[0].appendChild(ctrlStyle);

    window.ctrlSvg = document.createElement('div');
    ctrlSvg.style.cssText= "width:0; height:0; overflow:hidden;"

    window.ctrlDiv = document.createElement('div');
    ctrlDiv.id = 'ctrlDiv';
    ctrlDiv.style.display = canvas2pixel.showController ? "block" : "none";
	ctrlDiv.style.position = "fixed";

    ctrlDiv.innerHTML += `
	Pixel Size: <label id="pixelSizeDisplay"></label><input type="range" step=".1" min="1" max="30" value="${canvas2pixel.defaultVal.pixelSize}" id="pixelSize" oninput="changePixelSize(this.value)">
	Alpha Threshold: <label id="alphaThresholdDisplay"></label> <input type="range" step="1" min="1" max="100" value="${canvas2pixel.defaultVal.alphaThreshold}" id="alphaThreshold" oninput="changeAlphaThreshold(this.value)">
	Outline Size: <label id="outlineSizeDisplay"></label> <input type="range" step=".1" min="0" max="30" value="${canvas2pixel.defaultVal.outlineSize}" id="outlineSize" oninput="changeAlphaThreshold(ID('alphaThreshold').value)">
	Outline color: <input type="color" value="${canvas2pixel.defaultVal.outlineColor}" id="outlineColor" oninput="changeAlphaThreshold(ID('alphaThreshold').value)">
	Expand Edges: <input type="checkbox" ${canvas2pixel.defaultVal.expandEdges == true ? 'checked': ''} id="expandEdges" oninput="changeAlphaThreshold(ID('alphaThreshold').value)">

	<br><br>Frame: <a id="currFrame"></a>/<a id="durFrame"></a>
	<br>Resolution:<a id="dispW"></a>x<a id="dispH"></a>
	
	<br><br><input id="downloadBT" type="button" value="Rendering" onclick="initDownload()" disabled></input>
	
`

}

function changePixelSize(pixelNewSize = canvas2pixel.defaultVal.pixelSize) {
	renderedFrames = {};
    ID("pixelSizeDisplay").innerHTML = pixelNewSize;

    stage.canvas.style.imageRendering = "pixelated";
    stage.canvas.width = initialSize[0] / pixelNewSize;
    stage.canvas.height = initialSize[1] / pixelNewSize;
    stage.children[0].scaleX = 1 / pixelNewSize;
    stage.children[0].scaleY = 1 / pixelNewSize;

    changeAlphaThreshold(Number(ID("alphaThresholdDisplay").innerHTML));
}

function changeAlphaThreshold(feedArrayXtimes = canvas2pixel.defaultVal.alphaThreshold) {
	renderedFrames = {};
    var alphaTableVals = [0];
    ID("alphaThresholdDisplay").innerHTML = feedArrayXtimes;


    var pixelSize = Number(ID("pixelSizeDisplay").innerHTML)

    for (var i = 0; i < feedArrayXtimes; i++) alphaTableVals.push(1 * ID('expandEdges').checked);
    alphaTableVals.push(1);
    createSVG(alphaTableVals, pixelSize);

    ctx = stage.canvas.getContext("2d");
    ctx.filter = "url(#pixelateFilter)"; //+"url(#strokeFilter)";
}

function createSVG(alphaTable = "0 1", strokeSize = 0) {
    var outlineSize = ID('outlineSize').value;
    var outlineColor = ID('outlineColor').value;
    ID("outlineSizeDisplay").innerHTML = outlineSize;

    ctrlSvg.innerHTML = ` 
<svg>
	
  <filter id="pixelateFilter" color-interpolation-filters="sRGB">
    <feComponentTransfer>
      <feFuncA tableValues="${alphaTable}" type="discrete"/>
    </feComponentTransfer>
  </filter>

<filter id="strokeFilter" color-interpolation-filters="sRGB">
	<feMorphology operator="dilate" radius="${strokeSize*outlineSize}" in="SourceAlpha" result="morphology"/>
	<feFlood flood-color="${outlineColor}" flood-opacity="1" result="flood"/>
	<feComposite in="flood" in2="morphology" operator="in" result="composite"/>
	<feMerge result="merge">
    		<feMergeNode in="composite" result="mergeNode"/>
		<feMergeNode in="SourceGraphic" result="mergeNode1"/>
  	</feMerge>
</filter>	
	
</svg>
`

};


window.addEventListener('load', function() {
	
    createControllers();
    document.body.appendChild(ctrlDiv);
    ctrlSvg = document.body.appendChild(ctrlSvg);

    var interval = setInterval(function() {

        if (typeof stage == 'undefined') return;


        console.log('Element is ready');
		
		var lib = AdobeAn.getComposition(AdobeAn.bootcompsLoaded[0]).getLibrary();
		flaName = Object.getOwnPropertyNames(lib)[Object.getOwnPropertyNames(lib).length-3];
		lib = '';
		
		anim = stage.getChildAt(0);
        clearInterval(interval);		
		
		ID("durFrame").innerHTML = stage.getChildAt(0).totalFrames;
		

		createjs.Ticker.on("tick", tick);
		function tick() {
			currFrame = stage.getChildAt(0).currentFrame
			
			//stage.getChildAt(0).jonas.text = currFrame; 				
			
			ID("currFrame").innerHTML = currFrame;
			ID("dispW").innerHTML = stage.canvas.width;
			ID("dispH").innerHTML = stage.canvas.height;

			if( stage.getChildAt(0).totalFrames == Object.keys(renderedFrames).length ) return ID("downloadBT").disabled = false, ID("downloadBT").value = "Download Frames";
			
			ID("downloadBT").disabled = true, ID("downloadBT").value = "Rendering Frames"			
			renderedFrames[currFrame] = makeCanvas();
			
			}
			
		
		document.body.style.backgroundColor = "#5EC941";
        initialSize = [stage.canvas.width, stage.canvas.height];
        changePixelSize();
        changeAlphaThreshold();

    }, 10);


});


function padLeadingZeros(num, size) {
    var s = num+"";
    while (s.length < size) s = "0" + s;
    return s;
}


this.makeCanvas = function() {

    var dt = canvas.toDataURL('image/png');
    this.href = dt.replace(/^data:image\/[^;]/, 'data:application/octet-stream');
	return {"data": dt, "filename": flaName + "_" + padLeadingZeros(currFrame,4)};
};


function initDownload(){
	Object.keys(renderedFrames).forEach(key => {
		  setTimeout(() => {
		obj = renderedFrames[key];  
		
		console.log(obj.filename)
		downloadImage(obj.data,obj.filename);
 }, key*300);
});
	}

function downloadImage(url, name){
      fetch(url)
        .then(resp => resp.blob())
        .then(blob => {
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.style.display = 'none';
            a.href = url;
            // the filename you want
            a.download = name;
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(url);
        })
        .catch(() => alert('An error sorry'));
};
  1. Hit CTRL + Enter to preview it!

Known Issues and Quirks

  • Semi transparent pixels may not work. You can try adjusting the blending modes between graphics/Movieclip as a workaround.
  • The outline generated by the code cannot be exported as an image.
  • You may need to break the assets into different layers to see the transparency crop working properly.
  • You will need to allow your browser to download multiple files in order to download all the exported images.
  • Better results may be achieved by changing the background color to transparent.

Tips and Tricks

  • Experiment with different canvas2pixel settings to achieve the desired appearance of your pixel art.
  • You may want to double your animation size, since it gets downscaled being pixelated.
  • For best results, try breaking your assets into different layers.
  • Use Graphics/Movieclip Blend Mode instead of changes in opacity
  • If you are having trouble with transparent pixels, try changing the background color to transparent.

Need Help?

If you have any questions or need help using Flash 2 Pixelart, feel free to reach out for assistance. You can also consider posting your code to a code sharing platform like GitHub, where other developers may be able to review and contribute to it.

image image

jetrotal avatar Jul 18 '22 23:07 jetrotal