Commit 3b57e648 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

1. fixed borders in demosaicing 2. added RGB -> YCbCr*saturation (default=2) -> RGB

parent 2f6bd3df
......@@ -3,7 +3,6 @@
A template<br/>
Convert JP4/JP46 image files (\*.jp4/\*.jp46) into human perceivable format.<br/>
This includes reordering within JPEG blocks and demosaicing (bilinear interpolation).<br/>
The result looks a bit pale - saturation is not calculated.
Files in JPEG format are left untouched.
## Usage
Replace <i>test.jp4</i>
......
......@@ -11,6 +11,14 @@ var COLOR_MODE = 0;
var IS_JP4 = false;
var IS_JP46 = false;
//GRBG
var bayerMosaic = [
"Gr","R",
"B" ,"Gb"
];
var SATURATION=2.0;
$(function(){
initCanvas();
});
......@@ -61,6 +69,8 @@ function redraw(){
if (IS_JP4||IS_JP46){
pixelBlocksReorder(ctx);
demosaic_bilinear(ctx);
//convert to YCbCr to apply some saturation
saturation(ctx);
}
}
});
......@@ -121,17 +131,15 @@ function pixelBlocksReorder(ctx){
}
}
/* apply gammas here */
// ... or not
for (y=0;y<16;y++) {
offset=width*((yb<<4)+y)+(xb<<4);
for (x=0;x<16;x++) {
//red +0, green +1, blue +2, alpha +3
// thinking: GRBG
oPixels[4*(offset+x)+0] = ((x%2==1&&y%2==0) )?macroblock[y][x]:0;
oPixels[4*(offset+x)+1] = ((x%2==0&&y%2==0)||(x%2==1&&y%2==1))?macroblock[y][x]:0;
oPixels[4*(offset+x)+2] = ((x%2==0&&y%2==1) )?macroblock[y][x]:0;
bi = 2*(y%2)+x%2;
oPixels[4*(offset+x)+0] = ((bayerMosaic[bi]=="R" ) )?macroblock[y][x]:0;
oPixels[4*(offset+x)+1] = ((bayerMosaic[bi]=="Gr")||(bayerMosaic[bi]=="Gb"))?macroblock[y][x]:0;
oPixels[4*(offset+x)+2] = ((bayerMosaic[bi]=="B" ) )?macroblock[y][x]:0;
oPixels[4*(offset+x)+3] = 255;
}
}
......@@ -149,29 +157,79 @@ function demosaic_bilinear(ctx){
var outputImage = ctx.getImageData(0,0,width,height);
var oPixels = outputImage.data;
var x_l = 0, x_r = 0;
var y_t = 0, y_b = 0;
for(var y=0;y<height;y++){
for(var x=0;x<width;x++){
bi = 2*(y%2)+x%2;
x_l = (x==0)?1:(x-1);
x_r = (x==(width-1))?(width-2):(x+1);
y_t = (y==0)?1:(y-1);
y_b = (y==(height-1))?(height-2):(y+1);
//Gr
if (x%2==0&&y%2==0){
oPixels[4*(width*y+x)+0]=1/2*(oPixels[4*(width*(y+0)+(x-1))+0]+oPixels[4*(width*(y+0)+(x+1))+0]);
oPixels[4*(width*y+x)+2]=1/2*(oPixels[4*(width*(y-1)+(x+0))+2]+oPixels[4*(width*(y+1)+(x+0))+2]);
if (bayerMosaic[bi]=="Gr"){
oPixels[4*(width*y+x)+0]=1/2*(oPixels[4*(width*(y+0)+(x_l))+0]+oPixels[4*(width*(y+0)+(x_r))+0]);
oPixels[4*(width*y+x)+2]=1/2*(oPixels[4*(width*(y_b)+(x+0))+2]+oPixels[4*(width*(y_t)+(x+0))+2]);
}
//R
if (x%2==1&&y%2==0){
oPixels[4*(width*y+x)+1]=1/4*(oPixels[4*(width*(y-1)+(x+0))+1]+oPixels[4*(width*(y+0)+(x-1))+1]+oPixels[4*(width*(y+0)+(x+1))+1]+oPixels[4*(width*(y+1)+(x+0))+1]);
oPixels[4*(width*y+x)+2]=1/4*(oPixels[4*(width*(y-1)+(x-1))+2]+oPixels[4*(width*(y-1)+(x+1))+2]+oPixels[4*(width*(y+1)+(x-1))+2]+oPixels[4*(width*(y+1)+(x+1))+2]);
if (bayerMosaic[bi]=="R"){
oPixels[4*(width*y+x)+1]=1/4*(oPixels[4*(width*(y_t)+(x+0))+1]+oPixels[4*(width*(y+0)+(x_l))+1]+oPixels[4*(width*(y+0)+(x_r))+1]+oPixels[4*(width*(y_b)+(x+0))+1]);
oPixels[4*(width*y+x)+2]=1/4*(oPixels[4*(width*(y_t)+(x_l))+2]+oPixels[4*(width*(y_t)+(x_r))+2]+oPixels[4*(width*(y_b)+(x_l))+2]+oPixels[4*(width*(y_b)+(x_r))+2]);
}
//B
if (x%2==0&&y%2==1){
oPixels[4*(width*y+x)+0]=1/4*(oPixels[4*(width*(y-1)+(x-1))+0]+oPixels[4*(width*(y-1)+(x+1))+0]+oPixels[4*(width*(y+1)+(x-1))+0]+oPixels[4*(width*(y+1)+(x+1))+0]);
oPixels[4*(width*y+x)+1]=1/4*(oPixels[4*(width*(y-1)+(x+0))+1]+oPixels[4*(width*(y+0)+(x-1))+1]+oPixels[4*(width*(y+0)+(x+1))+1]+oPixels[4*(width*(y+1)+(x+0))+1]);
if (bayerMosaic[bi]=="B"){
oPixels[4*(width*y+x)+0]=1/4*(oPixels[4*(width*(y_t)+(x_l))+0]+oPixels[4*(width*(y_t)+(x_r))+0]+oPixels[4*(width*(y_b)+(x_l))+0]+oPixels[4*(width*(y_b)+(x_r))+0]);
oPixels[4*(width*y+x)+1]=1/4*(oPixels[4*(width*(y_t)+(x+0))+1]+oPixels[4*(width*(y+0)+(x_l))+1]+oPixels[4*(width*(y+0)+(x_r))+1]+oPixels[4*(width*(y_b)+(x+0))+1]);
}
//Gb
if (x%2==1&&y%2==1){
oPixels[4*(width*y+x)+0]=1/2*(oPixels[4*(width*(y-1)+(x+0))+0]+oPixels[4*(width*(y+1)+(x+0))+0]);
oPixels[4*(width*y+x)+2]=1/2*(oPixels[4*(width*(y+0)+(x-1))+2]+oPixels[4*(width*(y+0)+(x+1))+2]);
if (bayerMosaic[bi]=="Gb"){
oPixels[4*(width*y+x)+0]=1/2*(oPixels[4*(width*(y_t)+(x+0))+0]+oPixels[4*(width*(y_b)+(x+0))+0]);
oPixels[4*(width*y+x)+2]=1/2*(oPixels[4*(width*(y+0)+(x_l))+2]+oPixels[4*(width*(y+0)+(x_r))+2]);
}
}
}
ctx.putImageData(outputImage,0,0);
}
function saturation(ctx){
var width = ctx.canvas.width;
var height = ctx.canvas.height;
var inputImage = ctx.getImageData(0,0,width,height);
var iPixels = inputImage.data;
var r,g,b;
var Y,Cb,Cr;
for(var y=0;y<height;y++){
for(var x=0;x<width;x++){
//don't forget to multiply?
r = iPixels[4*(width*y+x)+0];
g = iPixels[4*(width*y+x)+1];
b = iPixels[4*(width*y+x)+2];
Y = 0.299*r+0.5870*g+ 0.144*b;
Cb = 128+SATURATION*(-0.1687*r-0.3313*g+ 0.500*b);
Cr = 128+SATURATION*( 0.5*r-0.4187*g-0.0813*b);
if (Cb<0) Cb=0; if (Cb>255) Cb=255;
if (Cr<0) Cr=0; if (Cr>255) Cr=255;
r = Y + 1.402*(Cr-128);
g = Y - 0.34414*(Cb-128)-0.71414*(Cr-128);
b = Y + 1.772*(Cb-128);
if (r<0) r=0; if (r>255) r=255;
if (g<0) g=0; if (g>255) g=255;
if (b<0) b=0; if (b>255) b=255;
iPixels[4*(width*y+x)+0]=r;
iPixels[4*(width*y+x)+1]=g;
iPixels[4*(width*y+x)+2]=b;
iPixels[4*(width*y+x)+3]=255;
}
}
ctx.putImageData(inputImage,0,0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment