以下是 JS图片上传对比度饱和度调整代码 的示例演示效果:
部分效果截图1:
部分效果截图2:
HTML代码(index.html):
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS图片上传对比度饱和度调整代码</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/zzsc-demo.css">
</head>
<body>
<div class="zzsc-container">
<div class="container">
<div class="row">
<div class="col-sm-12">
<h1>Chobi <small>The Image Processing Library</small></h1>
<hr>
<span class="btn btn-info" onclick="document.getElementById('image-chooser').click();">Upload Image</span>
<button class="btn btn-info" onclick="downloadImage()">Download Image</button>
<div class="alert alert-warning" id="error" style="display:none;">
<strong>Error!</strong> You didn't upload any image yet.
</div>
<hr>
<div class="btn-group" id="filters" style="display:none;">
<h3>Filters:</h3>
<button class="btn btn-success" onclick="loadImage(document.getElementById('image-chooser'))">Reset</button>
<button class="btn btn-success" onclick="filter(0)">Black and White</button>
<button class="btn btn-success" onclick="filter(10)">Black and White 2</button>
<button class="btn btn-success" onclick="filter(1)">Sepia</button>
<button class="btn btn-success" onclick="filter(2)">Negative</button>
<button class="btn btn-success" onclick="filter(3)">Vintage</button>
<button class="btn btn-success" onclick="filter(4)">Cross Process</button>
<button class="btn btn-success" onclick="filter(9)">Noise</button>
<button class="btn btn-success" onclick="filter(5)">Brightness +1</button>
<button class="btn btn-success" onclick="filter(6)">Brightness -1</button>
<button class="btn btn-success" onclick="filter(7)">Contrast +1</button>
<button class="btn btn-success" onclick="filter(8)">Contrast -1</button>
<button class="btn btn-success" onclick="filter(11)">Crayon</button>
<button class="btn btn-success" onclick="filter(12)">Cartoonify</button>
<button class="btn btn-success" onclick="filter(13)">Vignette</button>
<button class="btn btn-warning" onclick="myFilter()">Custom Filter</button>
</div>
</div>
<div class="col-sm-12">
<input type="file" id="image-chooser" style="display:none" onchange="loadImage(this)">
<canvas id="canvas" width="600" height="300" class="well"></canvas>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="src/Chobi.min.js"></script>
<script type="text/javascript">
//custom filter
function myFilter(){
var height = imgObj.imageData.height;
//orange
for(var i=0;i<imgObj.imageData.width;i++){
for(var j=0;j<Math.floor(height/3);j++){
var pixel = imgObj.getColorAt(i,j);
pixel.red = (255+pixel.red)/2;
pixel.green = (165+pixel.green)/2;
pixel.blue /= 2;
imgObj.setColorAt(i,j,pixel);
}
}
//white
for(var i=0;i<imgObj.imageData.width;i++){
for(var j=Math.floor(height/3);j<Math.floor(2*(height/3));j++){
var pixel = imgObj.getColorAt(i,j);
pixel.red = (255+pixel.red)/2;
pixel.green = (255+pixel.green)/2;
pixel.blue = (255+pixel.blue)/2;
imgObj.setColorAt(i,j,pixel);
}
}
//green
for(var i=0;i<imgObj.imageData.width;i++){
for(var j=Math.floor(2*(height/3));j<Math.floor(height);j++){
var pixel = imgObj.getColorAt(i,j);
pixel.red = (0+pixel.red)/2;
pixel.green = (255+pixel.green)/2;
pixel.blue = (0+pixel.blue)/2;
imgObj.setColorAt(i,j,pixel);
}
}
imgObj.loadImageToCanvas();
}
var imgObj = null; //global Chobi object
function loadImage(elem){
//you should probably check if file is image or not before passing it
imgObj = new Chobi(elem);
imgObj.ready(function(){
this.canvas = document.getElementById("canvas");
this.loadImageToCanvas();
//show filters to users
document.getElementById("filters").style.display = "block";
});
}
function downloadImage(){
if(imgObj == null){
document.getElementById("error").style.display="block";
setTimeout(function(){
document.getElementById("error").style.display="none";
}, 4000);
return;
}
imgObj.download('demo-image');
}
//0 -> Black and white
//10 -> Black and white2
//1 -> sepia
//2 -> negative
//3 -> vintage
//4 -> crossprocess
//5 -> Brightness increase
//6 -> Brightness decrease
//7 -> Contrast increase
//8 -> Contrast decrease
//9 -> Noise Effect
//11 -> Crayon effect
//12 -> Cartoonify
//13 -> Vignette
//filter chaining is also possible, like imgObj.brightness(-5).sepia().negative();
function filter(id){
if(imgObj == null){
alert("Choose an image first!");
return;
}
if(id==0){
imgObj.blackAndWhite();
}
else if(id==1){
imgObj.sepia();
}
else if(id==2){
imgObj.negative();
}
else if(id==3){
imgObj.vintage();
}
else if(id==4){
imgObj.crossProcess();
}
else if(id==5){
imgObj.brightness(1);
}
else if(id==6){
imgObj.brightness(-1);
}
else if(id==7){
imgObj.contrast(1);
}
else if(id==8){
imgObj.contrast(-1);
}
else if(id==9){
imgObj.noise();
}
else if(id==10){
imgObj.blackAndWhite2();
}
else if(id==11){
imgObj.crayon();
}
else if(id==12){
imgObj.cartoon();
}
else if(id==13){
imgObj.vignette();
}
imgObj.loadImageToCanvas();
}
</script>
</body>
</html>
JS代码(Chobi.min.js):
"use strict";
var Chobi=function(t){
if(t instanceof Image){
this.image=t,this.imageData=this.extractImageData(),console.log("Type matched. instanceof(Image). Saved as [Chobi object]");
try{
this.onload()}
catch(a){
console.log("ready callback not found")}
}
else if("string"==typeof t){
var e=this;
console.log("Not instanceof(Image). Trying as URL");
var o=new Image;
o.crossOrigin="Anonymous",o.src=t,o.onload=function(){
e.image=o,e.imageData=e.extractImageData(),console.log("Type matched. URL. Saved as [Chobi object]");
try{
e.onload()}
catch(t){
console.log("ready callback not found")}
}
}
else{
console.log("Not instanceof(Image). Trying as URL"),console.log("Not URL. Trying as input[file]");
var e=this;
try{
var i=t.files[0],r=new FileReader;
r.onload=function(){
var t=new Image;
t.onload=function(){
e.image=t,e.imageData=e.extractImageData(),console.log("Type matched. input[file]. Saved as [Chobi object]");
try{
e.onload()}
catch(a){
console.log("ready callback not found")}
}
,t.src=r.result}
,r.readAsDataURL(i)}
catch(a){
console.log("Not input[file]. Trying as <canvas>")}
try{
var o=new Image,h=t.toDataURL();
o.src=h,console.log(h),o.onload=function(){
e.image=o,e.imageData=e.extractImageData(),console.log("Type matched. <canvas>. Saved as [Chobi object]");
try{
e.onload()}
catch(t){
console.log("ready callback not found")}
}
}
catch(a){
console.log("Not <canvas>. Trying as <img>")}
try{
var o=new Image;
o.src=t.src,o.onload=function(){
e.image=o,e.imageData=e.extractImageData(),console.log("Type matched. <img>. Saved as [Chobi object]");
try{
e.onload()}
catch(t){
console.log("ready callback not found")}
}
}
catch(a){
console.log("Not <img>. No other type is supported")}
}
}
;
Chobi.prototype.ready=function(t){
this.onload=t}
,Chobi.prototype.onload=null,Chobi.prototype.extractImageData=function(){
var t=this.image,a=document.createElement("canvas"),e=a.getContext("2d");
return a.width=t.width,a.height=t.height,e.drawImage(t,0,0,t.width,t.height),this.imageData=e.getImageData(0,0,t.width,t.height),this.imageData}
,Chobi.prototype.getColorAt=function(t,a){
var e=4*a*this.imageData.width+4*t,o={
red:this.imageData.data[e],green:this.imageData.data[e+1],blue:this.imageData.data[e+2],alpha:this.imageData.data[e+3]}
;
return o}
,Chobi.prototype.setColorAt=function(t,a,e){
var o=4*a*this.imageData.width+4*t;
try{
return this.imageData.data[o]=e.red,this.imageData.data[o+1]=e.green,this.imageData.data[o+2]=e.blue,this.imageData.data[o+3]=e.alpha,!0}
catch(i){
return i}
}
,Chobi.prototype.blackAndWhite=function(){
for(var t=this.imageData,a=0;
a<t.width;
a++)for(var e=0;
e<t.height;
e++){
var o=4*e*t.width+4*a,i=t.data[o],r=t.data[o+1],h=t.data[o+2],n=(i+r+h)/3;
t.data[o]=n,t.data[o+1]=n,t.data[o+2]=n}
return this}
,Chobi.prototype.blackAndWhite2=function(){
for(var t=this.imageData,a=0;
a<t.width;
a++)for(var e=0;
e<t.height;
e++){
var o=4*e*t.width+4*a,i=t.data[o],r=t.data[o+1],h=t.data[o+2],n=.3*i+.59*r+.11*h;
t.data[o]=n,t.data[o+1]=n,t.data[o+2]=n}
return this}
,Chobi.prototype.sepia=function(){
for(var t=this.imageData,a=0;
a<t.width;
a++)for(var e=0;
e<t.height;
e++){
var o=4*e*t.width+4*a,i=t.data[o],r=t.data[o+1],h=t.data[o+2];
t.data[o]=.393*i+.769*r+.189*h,t.data[o+1]=.349*i+.686*r+.168*h,t.data[o+2]=.272*i+.534*r+.131*h}
return this}
,Chobi.prototype.negative=function(){
for(var t=this.imageData,a=0;
a<t.width;
a++)for(var e=0;
e<t.height;
e++){
var o=4*e*t.width+4*a,i=t.data[o],r=t.data[o+1],h=t.data[o+2];
t.data[o+3];
i=255-i,r=255-r,h=255-h,t.data[o]=i,t.data[o+1]=r,t.data[o+2]=h}
return this}
,Chobi.prototype.random=function(t,a){
return Math.floor(Math.random()*(a-t+1))+t}
,Chobi.prototype.noise=function(){
for(var t=this.imageData,a=0;
a<t.width;
a++)for(var e=0;
e<t.height;
e++){
var o=4*e*t.width+4*a,i=(4*a*t.width+4*e,this.random(100,200)),r=this.random(100,200),h=this.random(100,200),n=(t.data[o]+i)/2,d=(t.data[o+1]+r)/2,s=(t.data[o+2]+h)/2;
t.data[o]=n,t.data[o+1]=d,t.data[o+2]=s}
return this}
,Chobi.prototype.contrast=function(t){
var a=(255+t)/255;
a*=a;
for(var e=this.imageData,o=0;
o<e.width;
o++)for(var i=0;
i<e.height;
i++){
var r=4*i*e.width+4*o,h=e.data[r],n=e.data[r+1],d=e.data[r+2],s=h/255,g=n/255,c=d/255;
s=255*((s-.5)*a+.5),g=255*((g-.5)*a+.5),c=255*((c-.5)*a+.5),s>255&&(s=255),0>s&&(s=0),g>255&&(g=255),0>g&&(g=0),c>255&&(c=255),0>c&&(c=0),e.data[r]=s,e.data[r+1]=g,e.data[r+2]=c}
return this}
,Chobi.prototype.crossProcess=function(){
this.imageData;
return this.vintage(),this.brightness(10),this.contrast(50),this}
,Chobi.prototype.map=function(t,a,e,o,i){
return(i-o)*(t-a)/(e-a)+o}
,Chobi.prototype.brightness=function(t){
var a=this.imageData;
t=this.map(t,-100,100,-255,255),console.log(t);
for(var e=0;
e<a.width;
e++)for(var o=0;
o<a.height;
o++){
var i=4*o*a.width+4*e,r=a.data[i],h=a.data[i+1],n=a.data[i+2];
r+=t,h+=t,n+=t,r>255&&(r=255),0>r&&(r=0),h>255&&(h=255),0>h&&(h=0),n>255&&(n=255),0>n&&(n=0),a.data[i]=r,a.data[i+1]=h,a.data[i+2]=n}
return this}
,Chobi.prototype.vintage=function(){
for(var t=this.imageData,a=0;
a<t.width;
a++)for(var e=0;
e<t.height;
e++){
var o=4*e*t.width+4*a,i=t.data[o],r=t.data[o+1],h=t.data[o+2];
i=r,r=i,h=150,t.data[o]=i,t.data[o+1]=r,t.data[o+2]=h}
return this.contrast(50),this}
,Chobi.prototype.crayon=function(){
return this.noise().contrast(500),this}
,Chobi.prototype.cartoon=function(){
return this.contrast(400),this}
,Chobi.prototype.canvas=null,Chobi.prototype.loadImageToCanvas=function(t){
null==t&&null!=this.canvas&&(t=this.canvas);
try{
var a=this.imageData,e=t.getContext("2d");
return t.width=a.width,t.height=a.height,e.putImageData(a,0,0),!0}
catch(o){
return!1}
return this}
,Chobi.prototype.getImage=function(){
var t=document.createElement("canvas"),a=t.getContext("2d");
t.width=this.imageData.width,t.height=this.imageData.height,a.putImageData(this.imageData,0,0);
var e=document.createElement("img");
return e.src=t.toDataURL("image/png"),e}
,Chobi.prototype.crop=function(t,a,e,o){
if(""==t||""==a||""==e||""==o)return console.log("Invalid crop parameters"),this;
if(0>t||0>a||t>this.imageData.width||a>this.imageData.height||t+e>this.imageData.width||a+o>this.imageData.height)return console.log("Invalid crop parameters"),this;
var i=document.createElement("canvas");
this.loadImageToCanvas(i);
var r=i.getContext("2d"),h=r.getImageData(t,a,e,o);
return this.imageData=h,this}
,Chobi.prototype.vignette=function(t){
(""==t||null==t)&&(t=.1);
for(var a=this.imageData.width/2,e=this.imageData.height/2,o=Math.sqrt(e*e+a*a),i=Math.sqrt((this.imageData.width/2-r)*(this.imageData.width/2-r)-(this.imageData.height/2-h)*(this.imageData.height/2-h)),r=0;
r<this.imageData.width;
r++)for(var h=0;
h<this.imageData.height;
h++){
var n=this.getColorAt(r,h),i=Math.sqrt(Math.floor(Math.pow(r-e,2))+Math.floor(Math.pow(h-a,2)));
n.red=n.red*(1-(1-t)*(i/o)),n.green=n.green*(1-(1-t)*(i/o)),n.blue=n.blue*(1-(1-t)*(i/o)),this.setColorAt(r,h,n)}
return this}
,Chobi.prototype.download=function(t,a){
""==t&&(t="untitled"),""==a&&(a="png");
var e=this.imageData,o=document.createElement("canvas"),i=o.getContext("2d");
o.width=e.width,o.height=e.height,i.putImageData(e,0,0);
var r=o.toDataURL("image/"+a).replace("image/"+a,"image/octet-stream"),h=document.createElement("a");
return"string"==typeof h.download?(document.body.appendChild(h),h.download=t+"."+a,h.href=r,h.click(),document.body.removeChild(h)):location.replace(uri),!0}
;
CSS代码(normalize.css):
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}
audio,canvas,video{display:inline-block;}
audio:not([controls]){display:none;height:0;}
[hidden]{display:none;}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}
body{margin:0;}
a:focus{outline:thin dotted;}
a:active,a:hover{outline:0;}
h1{font-size:2em;margin:0.67em 0;}
abbr[title]{border-bottom:1px dotted;}
b,strong{font-weight:bold;}
dfn{font-style:italic;}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}
mark{background:#ff0;color:#000;}
code,kbd,pre,samp{font-family:monospace,serif;font-size:1em;}
pre{white-space:pre-wrap;}
q{quotes:"\201C" "\201D" "\2018" "\2019";}
small{font-size:80%;}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}
sup{top:-0.5em;}
sub{bottom:-0.25em;}
img{border:0;}
svg:not(:root){overflow:hidden;}
figure{margin:0;}
fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}
legend{border:0;padding:0;}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}
button,input{line-height:normal;}
button,select{text-transform:none;}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}
button[disabled],html input[disabled]{cursor:default;}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
textarea{overflow:auto;vertical-align:top;}
table{border-collapse:collapse;border-spacing:0;}
CSS代码(zzsc-demo.css):
body,html{font-size:100%;padding:0;margin:0;}
/* Reset */
*,*:after,*:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
.clearfix:before,.clearfix:after{content:" ";display:table;}
.clearfix:after{clear:both;}
body{background:#494A5F;color:#D5D6E2;font-weight:500;font-size:1.05em;font-family:"Microsoft YaHei","宋体","Segoe UI","Lucida Grande",Helvetica,Arial,sans-serif,FreeSans,Arimo;}
a{color:rgba(255,255,255,0.6);outline:none;text-decoration:none;-webkit-transition:0.2s;transition:0.2s;}
a:hover,a:focus{color:#74777b;text-decoration:none;}
.zzsc-container{margin:0 auto;}