From 6925b7d6d97c73668eabb8ec3fd3638e8ca71bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Fri, 2 May 2014 23:01:34 +0200 Subject: [PATCH] Canvas export: Background color, Blend modes (no Layer yet) --- trunk/src/com/jpexs/decompiler/flash/SWF.java | 18 +- .../exporters/shape/CanvasShapeExporter.java | 17 +- .../src/com/jpexs/helpers/resource/filters.js | 159 ++++++++++++++++++ 3 files changed, 188 insertions(+), 6 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index 4921a94a7..49408b6af 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -1509,8 +1509,20 @@ public final class SWF implements TreeItem, Timelined { fos.write(Utf8Helper.getBytes("frames.push(" + i + ");\r\n")); } fos.write(Utf8Helper.getBytes("\r\n")); + RGB backgroundColor = new RGB(255,255,255); + for(Tag t:fswf.tags){ + if(t instanceof SetBackgroundColorTag){ + SetBackgroundColorTag sb=(SetBackgroundColorTag)t; + backgroundColor = sb.backgroundColor; + } + } + + fos.write(Utf8Helper.getBytes("var backgroundColor = \""+backgroundColor.toHexRGB()+"\";\r\n")); + fos.write(Utf8Helper.getBytes("function nextFrame(ctx,ctrans){\r\n")); - fos.write(Utf8Helper.getBytes("\tctx.clearRect(0,0," + width + "," + height + ");\r\n")); + //fos.write(Utf8Helper.getBytes("\tctx.clearRect(0,0," + width + "," + height + ");\r\n")); + fos.write(Utf8Helper.getBytes("\tctx.fillStyle = backgroundColor;\r\n")); + fos.write(Utf8Helper.getBytes("\tctx.fillRect(0,0," + width + "," + height + ");\r\n")); fos.write(Utf8Helper.getBytes("\tframe = (frame+1)%frames.length;\r\n")); fos.write(Utf8Helper.getBytes("\t" + currentName + "(ctx,ctrans,frames[frame],0);\r\n")); fos.write(Utf8Helper.getBytes("}\r\n\r\n")); @@ -2297,12 +2309,12 @@ public final class SWF implements TreeItem, Timelined { ctrans.getRedMulti()+","+ctrans.getGreenMulti()+","+ctrans.getBlueMulti()+","+ctrans.getAlphaMulti() +"))"; } - sb.append("\t\t\t").append("place(\"").append(getTypePrefix(character)).append(layer.characterId).append("\",canvas,ctx,[").append(placeMatrix.scaleX).append(",") + sb.append("\t\t\tplace(\"").append(getTypePrefix(character)).append(layer.characterId).append("\",canvas,ctx,[").append(placeMatrix.scaleX).append(",") .append(placeMatrix.rotateSkew0).append(",") .append(placeMatrix.rotateSkew1).append(",") .append(placeMatrix.scaleY).append(",") .append(placeMatrix.translateX).append(",") - .append(placeMatrix.translateY).append("],").append(ctrans_str).append(",").append(f).append(",").append(layer.ratio < 0 ? 0 : layer.ratio).append(");\r\n"); + .append(placeMatrix.translateY).append("],").append(ctrans_str).append(",").append(""+(layer.blendMode<1?1:layer.blendMode)).append(",").append(f).append(",").append(layer.ratio < 0 ? 0 : layer.ratio).append(");\r\n"); if(layer.filters!=null){ for(FILTER filter:layer.filters){ diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java b/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java index 6cbba3f9d..77c3a1fc6 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java @@ -164,10 +164,21 @@ public class CanvasShapeExporter extends ShapeExporterBase { + "this.isEmpty = function(){return this.r_add==0 && this.g_add==0 && this.b_add==0 && this.a_add==0 && this.r_mult==255 && this.g_mult==255 && this.b_mult==255 && this.a_mult==255};" + "};\r\n" + "\r\n" - + "var place = function(obj,canvas,ctx,matrix,ctrans,frame,ratio){\r\n" - + "\tctx.save();\r\n" - + "\tctx.transform(matrix[0],matrix[1],matrix[2],matrix[3],matrix[4],matrix[5]);\r\n" + + "var place = function(obj,canvas,ctx,matrix,ctrans,blendMode,frame,ratio){\r\n" + + "\tctx.save();\r\n" + + "\tctx.transform(matrix[0],matrix[1],matrix[2],matrix[3],matrix[4],matrix[5]);\r\n" + + "\tif(blendMode>1){\r\n" + + "\t\tvar oldctx = ctx;\r\n" + + "\t\tvar ncanvas = Filters.createCanvas(canvas.width,canvas.height);\r\n" + + "\t\tctx = ncanvas.getContext(\"2d\");\r\n" + + "\t\tenhanceContext(ctx);\r\n" + + "\t\tctx.applyTransforms(oldctx._matrices);" + + "\t}\r\n" + "\teval(obj+\"(ctx,ctrans,frame,ratio);\");\r\n" + + "\tif(blendMode>1){\r\n" //TODO:Layer mode! + + "\t\tBlendModes.blendCanvas(ncanvas,canvas,canvas,blendMode);\r\n" + + "\t\tctx = oldctx;\r\n" + + "\t}\r\n" + "\tctx.restore();\r\n" + "}\r\n" + "var tocolor = function(c){var r= \"rgba(\"+c[0]+\",\"+c[1]+\",\"+c[2]+\",\"+c[3]+\")\"; return r;};\r\n" diff --git a/trunk/src/com/jpexs/helpers/resource/filters.js b/trunk/src/com/jpexs/helpers/resource/filters.js index bcc9e5b0c..2c26947c9 100644 --- a/trunk/src/com/jpexs/helpers/resource/filters.js +++ b/trunk/src/com/jpexs/helpers/resource/filters.js @@ -601,3 +601,162 @@ Filters.colorMatrix = function(canvas,ctx,m){ Filters.glow = function(canvas,src,blurX,blurY,strength,color, inner,knockout,iterations) { return Filters.dropShadow(canvas,src, blurX, blurY, 45, 0, color, inner, iterations, strength, knockout); }; + + +var BlendModes = {}; + +BlendModes._cut = function(v) {if(v<0) v = 0; if(v>255) v = 255; return v;}; + +BlendModes.normal = function(src,dst,result,pos){ + var am = (255-src[pos + 3])/255; + result[pos] = this._cut(src[pos]*src[pos + 3]/255 + dst[pos]*dst[pos+3]/255*am); + result[pos + 1] = this._cut(src[pos+1]*src[pos + 3]/255 + dst[pos+1]*dst[pos+3]/255*am); + result[pos + 2] = this._cut(src[pos+2]*src[pos + 3]/255 + dst[pos+2]*dst[pos+3]/255*am); + result[pos + 3] = this._cut(src[pos + 3] + dst[pos+3]*am); +}; + +BlendModes.layer = function(src,dst,result,pos){ + BlendModes.normal(src,dst,result,pos); +}; + +BlendModes.multiply = function(src,dst,result,pos){ + result[pos+0] = (src[pos+0] * dst[pos+0]) >> 8; + result[pos+1] = (src[pos+1] * dst[pos+1]) >> 8; + result[pos+2] = (src[pos+2] * dst[pos+2]) >> 8; + result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255); +}; + +BlendModes.screen = function(src,dst,result,pos){ + result[pos+0] = 255 - ((255 - src[pos+0]) * (255 - dst[pos+0]) >> 8); + result[pos+1] = 255 - ((255 - src[pos+1]) * (255 - dst[pos+1]) >> 8); + result[pos+2] = 255 - ((255 - src[pos+2]) * (255 - dst[pos+2]) >> 8); + result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255); +}; + +BlendModes.lighten = function(src,dst,result,pos){ + result[pos+0] = Math.max(src[pos+0], dst[pos+0]); + result[pos+1] = Math.max(src[pos+1], dst[pos+1]); + result[pos+2] = Math.max(src[pos+2], dst[pos+2]); + result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255); +}; + +BlendModes.darken = function(src,dst,result,pos){ + result[pos+0] = Math.min(src[pos+0], dst[pos+0]); + result[pos+1] = Math.min(src[pos+1], dst[pos+1]); + result[pos+2] = Math.min(src[pos+2], dst[pos+2]); + result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255); +}; + +BlendModes.difference = function(src,dst,result,pos){ + result[pos+0] = Math.abs(dst[pos+0] - src[pos+0]); + result[pos+1] = Math.abs(dst[pos+1] - src[pos+1]); + result[pos+2] = Math.abs(dst[pos+2] - src[pos+2]); + result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255); +}; + +BlendModes.add = function(src,dst,result,pos){ + result[pos+0] = Math.min(255, src[pos+0] + dst[pos+0]); + result[pos+1] = Math.min(255, src[pos+1] + dst[pos+1]); + result[pos+2] = Math.min(255, src[pos+2] + dst[pos+2]); + result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3]); +}; + +BlendModes.subtract = function(src,dst,result,pos){ + result[pos+0] = Math.max(0, src[pos+0] + dst[pos+0] - 256); + result[pos+1] = Math.max(0, src[pos+1] + dst[pos+1] - 256); + result[pos+2] = Math.max(0, src[pos+2] + dst[pos+2] - 256); + result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255); +}; + +BlendModes.invert = function(src,dst,result,pos){ + result[pos+0] = 255 - dst[pos+0]; + result[pos+1] = 255 - dst[pos+1]; + result[pos+2] = 255 - dst[pos+2]; + result[pos+3] = src[pos+3]; +}; + +BlendModes.alpha = function(src,dst,result,pos){ + result[pos+0] = src[pos+0]; + result[pos+1] = src[pos+1]; + result[pos+2] = src[pos+2]; + result[pos+3] = dst[pos+3]; //? +}; + +BlendModes.erase = function(src,dst,result,pos){ + result[pos+0] = src[pos+0]; + result[pos+1] = src[pos+1]; + result[pos+2] = src[pos+2]; + result[pos+3] = 255 - dst[pos+3]; //? +}; + +BlendModes.overlay = function(src,dst,result,pos){ + result[pos+0] = dst[pos+0] < 128 ? dst[pos+0] * src[pos+0] >> 7 + : 255 - ((255 - dst[pos+0]) * (255 - src[pos+0]) >> 7); + result[pos+1] = dst[pos+1] < 128 ? dst[pos+1] * src[pos+1] >> 7 + : 255 - ((255 - dst[pos+1]) * (255 - src[pos+1]) >> 7); + result[pos+2] = dst[pos+2] < 128 ? dst[pos+2] * src[pos+2] >> 7 + : 255 - ((255 - dst[pos+2]) * (255 - src[pos+2]) >> 7); + result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255); +}; + +BlendModes.hardlight = function(src,dst,result,pos){ + result[pos+0] = src[pos+0] < 128 ? dst[pos+0] * src[pos+0] >> 7 + : 255 - ((255 - src[pos+0]) * (255 - dst[pos+0]) >> 7); + result[pos+1] = src[pos+1] < 128 ? dst[pos+1] * src[pos+1] >> 7 + : 255 - ((255 - src[pos+1]) * (255 - dst[pos+1]) >> 7); + result[pos+2] = src[pos+2] < 128 ? dst[pos+2] * src[pos+2] >> 7 + : 255 - ((255 - src[pos+2]) * (255 - dst[pos+2]) >> 7); + result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255); +}; + +BlendModes._list = [ + BlendModes.normal, + BlendModes.normal, + BlendModes.layer, + BlendModes.multiply, + BlendModes.screen, + BlendModes.lighten, + BlendModes.darken, + BlendModes.difference, + BlendModes.add, + BlendModes.subtract, + BlendModes.invert, + BlendModes.alpha, + BlendModes.erase, + BlendModes.overlay, + BlendModes.hardlight + ]; + +BlendModes.blendData = function(srcPixel,dstPixel,retData,modeIndex){ + var result = []; + var retPixel = []; + var alpha = 1.0; + for(var i=0;i