2013-10-06 4 views
1

다음과 같이 이미지를 밝게/어둡게하는 기능이 있습니다.HTML5 캔버스 이미지 향상

<script> 
brightness = function(delta) { 
    return function (pixels, args) { 
     var d = pixels.data; 
     for (var i = 0; i < d.length; i += 4) { 
      d[i] += delta;  // red 
      d[i + 1] += delta; // green 
      d[i + 2] += delta; // blue 
     } 
     return pixels; 
    }; 
}; 
</script> 

더 재미있는 것을 시도하고 싶습니다. 자동 보정 기능을 이미지에 적용 할 수 있습니까? 내 말은 사진의 특정 영역 만 밝게/어둡게하는 것입니다. 예를 들어 픽셀이 어둡다면 어떻게 감지해야합니까? 그러면 약간 밝게해야합니까? 감사.

+2

_ "픽셀이 어두운 지 여부를 감지하는 방법은 무엇입니까?"_define_ 먼저 "어두운"픽셀을 고려한 다음 해당 픽셀의 색상 값을 확인합니다 ...? – CBroe

+0

어두운 색 또는 0 ~ xx의 표준 범위가 있습니까? 밝은 색상의 경우 255까지? 모든 어둡고 밝은만을 수정해야합니까? 아니면 모든 픽셀을 특정 값으로 수정해야합니까? 아무도 이것에 대한 전문 지식이 있는지 궁금해. – Sky

답변

2

동적 이미지 수정이 필요합니다.
따라서 각 픽셀의 광도에 적용 할 변환 함수의 정규화 된 픽셀의 광도가 0.0에서 1.0까지 인 경우이를 결정해야합니다.

당신이 찾는 기능은 낮은 광도 (0에 가까운)를 강화해야하고, 높은 광도 (1에 가까운)를 위해 동일한 광도를 유지해야합니다.
enter image description here

그래서 당신은 감마> 당신은 입력 광도가 0.2 인 경우 것으로, 예를 들어 여기를 참조
1. 원하는 것 : 여기

은 (typicall) TRANSFERT 기능의 예 출력 광도는 원래 값의 두 배를 초과하는 0.45입니다. 012 입력 값 0.83에 대해
을 입력하면 0.95 값으로 20 % 증가합니다.

인식 된 색을 변경하지 않고 명도 만 변경하려면 hsl과 같은 다른 색 공간을 사용하는 것이 가장 간단한 해결책입니다.
시간 색조입니다 : 다음 '색상',
채도는 색 '힘'이다,
및 L은 H, S, L와
, 당신은 인간의 눈에 대한 meaningfull하는 방식으로 색상을 표현 ... 광도.

그래서 단계는 다음과 같습니다 것으로, 여기에 수정 된 버전은 다음과 같습니다

바이올린 결과 : http://jsfiddle.net/gamealchemist/yqvmC/embedded/result/
바이올린 자체 : http://jsfiddle.net/gamealchemist/yqvmC/

편집을

for each pixel 
    compute h,s,l of the pixel out of its r,g,b 
    apply one transform function on luminosity 
       a good one is : new l = Math.pow(l, 1/gamma); 
    compute new (r,g,b) out of (h, s, new l) 
    write those values. 

내가 설명하기 위해 바이올린을 만든 이미지를 입력으로 가져오고 은 이미지를 반환합니다.

매개 변수는 감마 값 (숫자)이거나 원하는 변형 함수 일 수 있습니다.
예를 들어 감마 압축 함수를 추가했습니다. 결과는 (아래로 스크롤)에서 볼 수 있습니다. 압축은 매우 가혹합니다 : 모든 광도 값 은 비율 * (max-min)을 중심으로하므로 이미지는 매우 판독 가능하지만 콘트라스트는 낮습니다.

// pow is the power of the function 
// min is min value returned 
// max is max value returned. 
function gamma(pow, min, max, x) { 
    return min + Math.pow(x, 1/pow) * (max - min); 
} 

// pow is the 'gamma' used for both part of the curves 
// min is the minimum value returned/max the max 
// center is the luminosity where we stop reducing and start expanding 
// ratio states where reduced luminosity should lay between min and max. 
function gammaCompress(pow, min, max, center, ratio, x) { 
    var xr = 0; 
    if (x < center) { 
     xr = x/center; 
     return min + Math.pow(xr, 1/pow) * (max - min) * ratio; 
    } else { 
     xr = (x - center)/(1 - center); 
     return min + (max - min) * ratio + Math.pow(xr, 1/pow) * (max - min) * (1 - ratio); 
    } 
} 

function getEnligthedImage(sourceImage, transform) { 
    // if a number, not a bound transform function, was provided, 
    // assume it's a gamma targetting [0;1] 
    if (typeof transform != 'function') { 
     transform = gamma.bind(null, transform, 0, 1); 
    } 
    var tgtCv = document.createElement('canvas'); 
    tgtCv.width = sourceImage.width; 
    tgtCv.height = sourceImage.height; 
    var context = tgtCv.getContext('2d'); 
    context.drawImage(img, 0, 0); 
    var imgData = context.getImageData(0, 0, canvasWidth, canvasHeight); 
    var pix = imgData.data; 
    var hslValue = {  h: 0,  s: 0,  l: 0 }; 
    var rgbValue = {  r: 0,  g: 0,  b: 0 }; 
    for (var i = 0; i < pix.length; i += 4) { 
     rgbToHsl(pix[i], pix[i + 1], pix[i + 2], hslValue); 
     hslValue.l = transform(hslValue.l); 
     hslToRgb(hslValue.h, hslValue.s, hslValue.l, rgbValue); 
     pix[i] = rgbValue.r; 
     pix[i + 1] = rgbValue.g; 
     pix[i + 2] = rgbValue.b; 
    } 
    context.putImageData(imgData, 0, 0); 
    var newImage = new Image(); 
    newImage.src = tgtCv.toDataURL("image/png"); 
    return newImage; 
} 

var result = getEnligthedImage(img, 1.6); 
var pr = document.createElement('div'); 
pr.innerHTML = 'example for a gamma 1.6' 
document.body.appendChild(pr); 
document.body.appendChild(result); 

var compressor = gammaCompress.bind(null, 1.4, 0.2, 1.0, 0.5, 0.5); 
var compressedResult = getEnligthedImage(img, compressor); 
pr = document.createElement('div'); 
pr.innerHTML = 'example using a gamma compressor. min is 0.2' 
document.body.appendChild(pr); 
document.body.appendChild(compressedResult); 

당신이 이미지와 다른 일을하려는 경우, 파일로 저장 서버로 보내거나 같은, 구글 :-) 검색은,이 링크가 도움이 될 수 있습니다 : 여기

코드입니다 :
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement

+0

이 경우 감마 조정을 통해 이미지가 조작됩니다. 맞습니까? 그것의 원래 rgb를 기반으로 이미지를 먼저 자동으로 조작하는 함수를 생성 할 수 있습니까? – Sky

+0

예/아니오 : 이미지는 변경 불가능한 객체입니다. 그러나 기존의 감마와 제공된 감마에서 새로운 수정 된 이미지를 만드는 함수를 만들 수 있습니다. 원한다면 그러한 함수로 코드를 업데이트 할 것이다. – GameAlchemist

+0

개별 이미지에 대해 조정할 감마 값을 결정하는 방법을 알고 싶습니다. 따라서 실제로 원하는 것은 감마 값이 이미 적용된 수정 된 이미지를 생성하는 것입니다. 방법에 의해 당신의 노력에 감사드립니다. – Sky

0

색상을 자동 조정하는 간단한 기능입니다.히스토그램을 기준으로 이미지를 밝게하거나 어둡게합니다.

변경되거나 변경되지 않은 영역에 쉽게 가입 할 수 없기 때문에 사진의 특정 영역 만 밝게/어둡게하는 것은 어렵습니다.

죄송합니다. 여기 이미지에 문제가 있습니다.

<img alt="" src="bright.png" /> 
<br /><br /> 
<canvas id="cc"></canvas> 

<script> 
var img = new Image(); 
img.src = 'bright.png'; 
img.onload = function(){ 
    var canvas = document.getElementById("cc"); 
    var ctx = canvas.getContext("2d"); 
    canvas.width=300; 
    canvas.height=200; 
    ctx.drawImage(img, 0, 0); 

    auto_adjust(ctx, 300, 200); 
    } 

function auto_adjust(context, W, H){ 
    //settings 
    var white = 240; //white color min 
    var black = 30;  //black color max 
    var target_white = 1; //how much % white colors should take 
    var target_black = 0.5; //how much % black colors should take 
    var modify = 1.1; //color modify strength 

    var img = context.getImageData(0, 0, W, H); 
    var imgData = img.data; 
    var n = 0; //pixels count without transparent 

    //make sure we have white 
    var n_valid = 0; 
    for(var i = 0; i < imgData.length; i += 4){ 
      if(imgData[i+3] == 0) continue; //transparent 
      if((imgData[i] + imgData[i+1] + imgData[i+2])/3 > white) n_valid++; 
      n++; 
     } 
    target = target_white; 
    var n_fix_white = 0; 
    var done = false; 
    for(var j=0; j < 30; j++){ 
     if(n_valid * 100/n >= target) done = true; 
     if(done == true) break; 
     n_fix_white++; 

     //adjust 
     for(var i = 0; i < imgData.length; i += 4){ 
      if(imgData[i+3] == 0) continue; //transparent 
      for(var c = 0; c < 3; c++){ 
       var x = i + c; 
       if(imgData[x] < 10) continue; 
       //increase white 
       imgData[x] *= modify; 
       imgData[x] = Math.round(imgData[x]); 
       if(imgData[x] > 255) imgData[x] = 255; 
       } 
      } 

     //recheck 
     n_valid = 0; 
     for(var i = 0; i < imgData.length; i += 4){ 
      if(imgData[i+3] == 0) continue; //transparent 
       if((imgData[i] + imgData[i+1] + imgData[i+2])/3 > white) n_valid++; 
      } 
     } 

    //make sure we have black 
    n_valid = 0; 
    for(var i = 0; i < imgData.length; i += 4){ 
     if(imgData[i+3] == 0) continue; //transparent 
      if((imgData[i] + imgData[i+1] + imgData[i+2])/3 < black) n_valid++;  
     } 
    target = target_black; 
    var n_fix_black = 0; 
    var done = false; 
    for(var j=0; j < 30; j++){ 
     if(n_valid * 100/n >= target) done = true; 
     if(done == true) break; 
     n_fix_black++; 

     //adjust 
     for(var i = 0; i < imgData.length; i += 4){ 
      if(imgData[i+3] == 0) continue; //transparent 
      for(var c = 0; c < 3; c++){ 
       var x = i + c; 
       if(imgData[x] > 240) continue; 
       //increase black 
       imgData[x] -= (255-imgData[x]) * modify - (255-imgData[x]); 
       imgData[x] = Math.round(imgData[x]); 
       } 
      } 

     //recheck 
     n_valid = 0; 
     for(var i = 0; i < imgData.length; i += 4){ 
      if(imgData[i+3] == 0) continue; //transparent 
       if((imgData[i] + imgData[i+1] + imgData[i+2])/3 < black) n_valid++; 
      } 
     } 

    //save 
    context.putImageData(img, 0, 0); 
    //log('Iterations: brighten='+n_fix_white+", darken="+n_fix_black); 
    } 
</script> 
+0

도움에 감사드립니다. 이미지를 시도해 보셨나요? 제 측면에서 테스트했을 때 아무런 조작이없는 것처럼 보였습니다. – Sky

+0

예, 어둡거나 밝은 이미지로 시도해보십시오. 이미지가 이미 확인 된 경우 최소한의 효과 만 얻을 수 있습니다. – ViliusL

+0

다음과 같이 물어볼 수 있습니까? '(imgData [i] + imgData [i + 1] + imgData [i + 2])/3> 흰색'평균을 구하면 더 많은 '흰색 '? – Sky