2013年10月24日 星期四

GLImageProcessing image effects in opengl

將圖檔存入opengl texture memory
首先要先看懂texture environment的用法 http://www.khronos.org/opengles/sdk/1.1/docs/man/glTexEnv.xml 




brightness
//告訴目前貼圖環境為GL_COMBINE
//告訴目前貼圖環境為GL_COMBINE
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
if (t > 1.0f)
{
//對於GL_COMBINE_RGB參數為GL_ADD 也就是相加
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,      GL_ADD);
//顏色ARRAY
glColor4f(t-1, t-1, t-1, t-1);
}
else
{
//對於GL_COMBINE_RGB參數為GL_SUBTRACT 也就是相減
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,      GL_SUBTRACT);
//again顏色ARRAY
glColor4f(1-t, 1-t, 1-t, 1-t);
}
//對於RGB的第一個resource為材質
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB,         GL_TEXTURE);
//對於RGB的第二個resource為顏色array
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB,         GL_PRIMARY_COLOR);
//對於Alpha的方式為GL_REPLACE
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA,    GL_REPLACE);
//第一個resource為材質
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA,       GL_TEXTURE);

before drawarrays , order is not important .
基本上0.5 1.5左右就全黑全白了 以general color來說




constract


// One pass using two units:
// contrast < 1.0 interpolates towards grey
// contrast > 1.0 extrapolates away from grey
//
// Here, the general extrapolation 2*(Src*t + Dst*(0.5-t))
// can be simplified, because Dst is a constant (grey).
// That results in: 2*(Src*t + 0.25 - 0.5*t)
//
// Unit0 calculates Src*t
// Unit1 adds 0.25 - 0.5*t
// Since 0.5*t will be in [0..0.5], it can be biased up and the addition done in signed space.
此為extrapolate(外推)公式 取X_0 = 0 X_1 = 0.5 X_2 = t                        Y_0 = degen  Y_1 = src  便可算出Y_2

GLfloat h = t*0.5f;
告訴目前貼圖環境為GL_COMBINE
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
//GL_MODULATE  Arg0 × Arg1

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,      GL_MODULATE); 
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB,         GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB,         GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA,    GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA,       GL_TEXTURE);
//使用第二層紋理 是個灰階圖
GLubyte half[4] = { 0x80, 0x80, 0x80, 0x80 };

glActiveTexture(GL_TEXTURE1);
//這裡只對目前actived texture做enable
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
//GL_ADD_SIGNED Arg0 + Arg1 - 0.5
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,      GL_ADD_SIGNED);
//C f represents the primary color of the incoming fragment, and C p represent the color computed from the previous texture stage or C f if processing texture stage 0
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB,         GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB,         GL_PRIMARY_COLOR);
//Arg1使用GL_SRC_ALPHA = A f
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB,     GL_SRC_ALPHA);
//RGB x 2
glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE,        2);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA,    GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA,       GL_PREVIOUS);
glColor4f(h, h, h, 0.75 - 0.5 * h); // 2x extrapolation


簡單來說就是達成上面算好的公式 第一層用GL_MODULATE 第二層用GL_ADD_SIGNED去混合這些紋理 第二層比較tricky

saturation

這特效使用一個灰階的texture當作基底來合成

首先要產生灰階的texture







saturation


GLfloat lerp[4] = { 1.0, 1.0, 1.0, 0.5 };

GLfloat avrg[4] = { .667, .667, .667, 0.5 }; // average
GLfloat prcp[4] = { .646, .794, .557, 0.5 }; // perceptual NTSC
    //NTSC, named for the National Television System Committee,[1] is the analog television system that is used in most of North America, parts of South America (except Brazil, Argentina, Uruguay, and French Guiana), Myanmar, South Korea, Taiwan, Japan, the Philippines, and some Pacific island nations and territories (see map).
 GLfloat dot3[4] = { prcp[0]*t+avrg[0]*(1-t), prcp[1]*t+avrg[1]*(1-t), prcp[2]*t+avrg[2]*(1-t), 0.5 };
 
 // One pass using two units:
 // Unit 0 scales and biases into [0.5..1.0]
 // Unit 1 dot products with perceptual weights

lerp是第一張texture的constant , avrg為灰階平均像素資料 , prcp是電視顏色基準

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); //Arg0 x Arg2 + Arg1 x (1-Arg2) glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); //Constant means Color of GL_TEXTURE_ENV_COLOR glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR, lerp); // Note: we prefer to dot product with primary color, because // the constant color is stored in limited precision on MBX glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); //GL_DOT3_RGB or GL_DOT3_RGBA 4*((Arg0r - 0.5) * (Arg1r - 0.5) + (Arg0g - 0.5) * (Arg1g - 0.5) + (Arg0b - 0.5) * (Arg1b - 0.5)) glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB); //refers to the color computed from the previous texture stage (or the incoming fragment if processing texture stage 0), glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); glColor4f(dot3[0], dot3[1], dot3[2], dot3[3]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

第一張貼圖使用interpolate看似很威 實際上的constant是 1 1 1 0.5 也就是說除了alpha RGB還是使用bind的texture , 實際上alpha算出來也是1 , 而第二章用DOT3_RGB可以轉換成灰階 , alpha不變 也就能產出灰階圖片了 接著的外推 透過extrapolate算出後在使用 去作rgb scale

2013年10月17日 星期四

image effects

此篇未完

剛好找到一個直接對image作處理的project讀的一些心得

RGB處理

作色偏處理 

將RGB[0 , 255] 作 mapping 對應到 [ n, m ]  , n m      [0 , 255] . 即可達到色偏的效果 .

Gaussian Blur

將一個像素取周遭的像素來作平均 該矩陣由normal distribution 2 dimensional取得,邊緣失去的像素我assume是由中間去遞補, 事實上不會是一個很難的filter if you have the conception of all these stuffs .

Sepia Filter
Sepia toning is a specialized treatment to give a black-and-white photographic print a warmer tone and to enhance its archival qualities. Chemicals are used to convert the metallic silver in the print to a sulfidecompound, which is much more resistant to the effects of environmental pollutants such as atmospheric sulfur compounds. Silver sulfide is at least 50% more stable than silver.

基本上就是套用以下formula
outputRed = (inputRed * .393) + (inputGreen *.769) + (inputBlue * .189)
outputGreen = (inputRed * .349) + (inputGreen *.686) + (inputBlue * .168)
outputBlue = (inputRed * .272) + (inputGreen *.534) + (inputBlue * .131)