toxic-johann / toxic-johann.github.io

my blog
6 stars 0 forks source link

【2016-03-20】调整一下对比度 #23

Open toxic-johann opened 7 years ago

toxic-johann commented 7 years ago

如果还记得前几天我做的图片转换的玩意。就会发现一个问题。由于灰度的转化,丢失的数据量还是比较大。所以很多情况下,如果图片的对比度不够,很难得到我们想要的ascii码图。

所以这个问题还是挺好解决的,既然对比度不够,那我们就调节对比度。

将imageData取出,然后将其进行适当的调整即可。

对比度调整的原理还是比较简单的。算出灰度平均值,也就是RGB的平均值。然后将其与任意像素计算差距,按照你需要的系数进行相乘。

写成代码就是这样子。

this.adjustContrast = (imageData,coefficient)=>{
  if(!this._isUint8ClampedArray(imageData)){
    throw new Error("imageData need to be an Uint8ClampedArray");
  }
  coefficient = coefficient || 0;
  let average = this._getAverageOfRGB(imageData);
  imageData = imageData.map((each,index)=>{
    // 排除透明度
    if((index+1)%4 == 0){
      if(index == 0){
      }
      return each;
    }
    let delta = each-average;
    let ans = each+delta*coefficient;
    // 作防护性处理
    if(ans > 255){
      ans = 255;
    } else if(ans < 0 ){
      ans = 0;
    }

    return ans;
  });
  return imageData;
},

由于我这段代码主要服务的对象是canvas,也就是用canvas中的getImageData取出的数据。一般我就做一下判断。

因为Uint8ClamperdArray并不是数组封装,所以用Array.isArray无法将其检测。因此我用了构造函数判断这种方法。

this._isUint8ClampedArray = arr=>{
  arr = arr || 0;
  let cons = arr.constructor.toString();
  if(cons.match("Uint8ClampedArray")){
    return true;
  }
  return false;
}

然后我们可以轻易地计算出均值,再进行简单的计算就可以得到调整后的像素数据。

可以看到我在这里做出了防护性处理。其实这种处理不一定需要。

因为Uint8ClamperdArray数据中每一个元子大小就是0~255。超出他自己会进行相应的转化。所以原理上可以省略这一段话。

然后利用这个方法我们就可以轻易得到我们需要的数据。

另外imageData是一个只读对象,不能使用imageData.data = mydata这种方式进行赋值。

所以这种时候我们可以直接采用他所封装的set方式进行处理。

imageData.data.set(Photoshop.adjustContrast(imageData.data,contrast));

这种方式就可以达到我们的目的。下面还是上图吧。

原图:

辛炜哥哥

ascii转化后(粒子度为4):

灰色的辛炜哥哥

对比度系数为5调整后的ascii转化:

simple的辛炜哥哥

just for fun,exited!

要玩还是去老地方,不过没写手机支持。手机玩起来比较麻烦。