1 line
No EOL
7.8 KiB
JavaScript
1 line
No EOL
7.8 KiB
JavaScript
var PWImageResizer=function(config){this.setConfig(config)};PWImageResizer.prototype.resize=function(file,completionCallback){var img=document.createElement("img");this.currentFile=file;var reader=new FileReader;var This=this;var contentType=file.type.toString();reader.onload=function(e){img.src=e.target.result;img.onload=function(){if(!This.needsResize(img,contentType)){completionCallback(false);return}This.scaleImage(img,completionCallback)}};reader.readAsDataURL(file)};PWImageResizer.prototype.needsResize=function(img,contentType){var needsResize=false;var why="n/a";if(contentType!="image/jpeg"&&contentType!="image/png"&&contentType!="image/gif"){why="unsupported image content-type: "+contentType}else if(this.config.scaleRatio>0){needsResize=true;why="scaleRatio specified"}else if(this.config.maxWidth>0||this.config.maxHeight>0){if(this.config.maxWidth>0&&img.width>this.config.maxWidth)needsResize=true;if(this.config.maxHeight>0&&img.height>this.config.maxHeight)needsResize=true;why=needsResize?"dimensions exceed max allowed":"dimensions do not require resize"}if(!needsResize&&this.config.maxSize>0){if(this.config.maxSize<img.width*img.height/1e6)needsResize=true;why=(needsResize?"megapixels exceeds ":"megapixels below ")+this.config.maxSize}if(this.config.debug){this.consoleLog("needsResize="+(needsResize?"Yes":"No")+" ("+why+")")}return needsResize};PWImageResizer.prototype.drawImage=function(context,img,x,y,width,height,deg,flip,flop,center){context.save();if(typeof width==="undefined")width=img.width;if(typeof height==="undefined")height=img.height;if(typeof center==="undefined")center=false;if(center){x-=width/2;y-=height/2}context.translate(x+width/2,y+height/2);var rad=2*Math.PI-deg*Math.PI/180;context.rotate(rad);if(flip)flipScale=-1;else flipScale=1;if(flop)flopScale=-1;else flopScale=1;context.scale(flipScale,flopScale);context.drawImage(img,-width/2,-height/2,width,height);context.restore()};PWImageResizer.prototype.scaleImage=function(img,completionCallback){var canvas=document.createElement("canvas");canvas.width=img.width;canvas.height=img.height;var ctx=canvas.getContext("2d");ctx.save();var width=canvas.width;var styleWidth=canvas.style.width;var height=canvas.height;var styleHeight=canvas.style.height;ctx.drawImage(img,0,0);ctx.restore();var ratio=canvas.width/canvas.height;var mWidth=0;var resizeType="";if(this.config.maxWidth>0||this.config.maxHeight>0){mWidth=Math.min(this.config.maxWidth,ratio*this.config.maxHeight);resizeType="max width/height of "+this.config.maxWidth+"x"+this.config.maxHeight}if(this.config.maxSize>0&&this.config.maxSize<canvas.width*canvas.height/1e6){var mSize=Math.floor(Math.sqrt(this.config.maxSize*ratio)*1e3);mWidth=mWidth>0?Math.min(mWidth,mSize):mSize;if(mSize===mWidth)resizeType="max megapixels of "+this.config.maxSize}if(this.config.scaleRatio){var mScale=Math.floor(this.config.scaleRatio*canvas.width);mWidth=mWidth>0?Math.min(mWidth,mScale):mScale;if(mScale==mWidth)resizeType="scale ratio of "+this.config.scaleRatio}if(mWidth<=0){this.consoleLog("image size is too small to resize");completionCallback(false);return}if(this.config.debug){this.consoleLog("original image size: "+canvas.width+"x"+canvas.height+" px");this.consoleLog("scaled image size: "+mWidth+"x"+Math.floor(mWidth/ratio)+" px via "+resizeType)}while(canvas.width>=2*mWidth){canvas=this.getHalfScaleCanvas(canvas)}if(canvas.width>mWidth){canvas=this.scaleCanvasWithAlgorithm(canvas,mWidth)}var quality=this.config.quality;if(this.currentFile.type!="image/jpeg")quality=1;var imageData=canvas.toDataURL(this.currentFile.type,quality);if(typeof this.config.onScale==="function"){this.config.onScale(imageData)}if(this.currentFile.type==="image/jpeg"){try{var exifObj=piexif.load(img.src);var orientation=exifObj["0th"][piexif.ImageIFD.Orientation];if(orientation>4&&img.height>img.width){exifObj["0th"][piexif.ImageIFD.Orientation]=1}try{var exifStr=piexif.dump(exifObj);try{imageData=piexif.insert(exifStr,imageData)}catch(error){console.error(error)}}catch(error){console.error(error)}}catch(error){console.error(error)}}completionCallback(this.imageDataToBlob(imageData))};PWImageResizer.prototype.imageDataToBlob=function(imageData){var base64Marker=";base64,";if(imageData.indexOf(base64Marker)==-1){var parts=imageData.split(",");var contentType=parts[0].split(":")[1];var raw=parts[1];return new Blob([raw],{type:contentType})}var parts=imageData.split(base64Marker);var contentType=parts[0].split(":")[1];var raw=window.atob(parts[1]);var rawLength=raw.length;var uInt8Array=new Uint8Array(rawLength);for(var i=0;i<rawLength;++i){uInt8Array[i]=raw.charCodeAt(i)}return new Blob([uInt8Array],{type:contentType})};PWImageResizer.prototype.scaleCanvasWithAlgorithm=function(canvas,maxWidth){var scaledCanvas=document.createElement("canvas");var scale=maxWidth/canvas.width;scaledCanvas.width=canvas.width*scale;scaledCanvas.height=canvas.height*scale;var srcImgData=canvas.getContext("2d").getImageData(0,0,canvas.width,canvas.height);var destImgData=scaledCanvas.getContext("2d").createImageData(scaledCanvas.width,scaledCanvas.height);this.applyBilinearInterpolation(srcImgData,destImgData,scale);scaledCanvas.getContext("2d").putImageData(destImgData,0,0);return scaledCanvas};PWImageResizer.prototype.getHalfScaleCanvas=function(canvas){var halfCanvas=document.createElement("canvas");halfCanvas.width=canvas.width/2;halfCanvas.height=canvas.height/2;halfCanvas.getContext("2d").drawImage(canvas,0,0,halfCanvas.width,halfCanvas.height);return halfCanvas};PWImageResizer.prototype.applyBilinearInterpolation=function(srcCanvasData,destCanvasData,scale){function inner(f00,f10,f01,f11,x,y){var un_x=1-x;var un_y=1-y;return f00*un_x*un_y+f10*x*un_y+f01*un_x*y+f11*x*y}var i,j;var iyv,iy0,iy1,ixv,ix0,ix1;var idxD,idxS00,idxS10,idxS01,idxS11;var dx,dy;var r,g,b,a;for(i=0;i<destCanvasData.height;++i){iyv=i/scale;iy0=Math.floor(iyv);iy1=Math.ceil(iyv)>srcCanvasData.height-1?srcCanvasData.height-1:Math.ceil(iyv);for(j=0;j<destCanvasData.width;++j){ixv=j/scale;ix0=Math.floor(ixv);ix1=Math.ceil(ixv)>srcCanvasData.width-1?srcCanvasData.width-1:Math.ceil(ixv);idxD=(j+destCanvasData.width*i)*4;idxS00=(ix0+srcCanvasData.width*iy0)*4;idxS10=(ix1+srcCanvasData.width*iy0)*4;idxS01=(ix0+srcCanvasData.width*iy1)*4;idxS11=(ix1+srcCanvasData.width*iy1)*4;dx=ixv-ix0;dy=iyv-iy0;r=inner(srcCanvasData.data[idxS00],srcCanvasData.data[idxS10],srcCanvasData.data[idxS01],srcCanvasData.data[idxS11],dx,dy);destCanvasData.data[idxD]=r;g=inner(srcCanvasData.data[idxS00+1],srcCanvasData.data[idxS10+1],srcCanvasData.data[idxS01+1],srcCanvasData.data[idxS11+1],dx,dy);destCanvasData.data[idxD+1]=g;b=inner(srcCanvasData.data[idxS00+2],srcCanvasData.data[idxS10+2],srcCanvasData.data[idxS01+2],srcCanvasData.data[idxS11+2],dx,dy);destCanvasData.data[idxD+2]=b;a=inner(srcCanvasData.data[idxS00+3],srcCanvasData.data[idxS10+3],srcCanvasData.data[idxS01+3],srcCanvasData.data[idxS11+3],dx,dy);destCanvasData.data[idxD+3]=a}}};PWImageResizer.prototype.setConfig=function(customConfig){this.config=customConfig;this.config.debug=this.config.debug||false;if(typeof customConfig.quality=="undefined")customConfig.quality=1;if(customConfig.quality<.1)customConfig.quality=.1;if(customConfig.quality>1)customConfig.quality=1;this.config.quality=customConfig.quality;if(!this.config.maxWidth||this.config.maxWidth<0){this.config.maxWidth=0}if(!this.config.maxHeight||this.config.maxHeight<0){this.config.maxHeight=0}if(!this.config.maxSize||this.config.maxSize<0){this.config.maxSize=null}if(!this.config.scaleRatio||this.config.scaleRatio<=0||this.config.scaleRatio>=1){this.config.scaleRatio=null}if(this.config.maxWidth&&!this.config.maxHeight){this.config.maxHeight=this.config.maxWidth}else if(this.config.maxHeight&&!this.config.maxWidth){this.config.maxWidth=this.config.maxHeight}else if(!this.config.maxWidth&&!this.config.maxHeight){}};PWImageResizer.prototype.consoleLog=function(msg){if(this.config.debug)console.log("PWImageResizer: "+msg)}; |