openGL 显卡YUV转RGB(转)

/*
 * Very simple example of how to perform YUV->RGB (YCrCb->RGB)
 * conversion with an OpenGL fragmen shader. The data (not included)
 * is presumed to be three files with Y, U and V samples for a 720x576
 * pixels large image.
 *
 * Note! The example uses NVidia extensions for rectangular textures
 * to make it simpler to read (non-normalised coordinates).
 * Rewriting it without the extensions is quite simple, but left as an
 * exercise to the reader. (The trick is that the shader must know the
 * image dimensions instead)
 *
 * The program also does not check to see if the shader extensions are
 * available - this is after all just a simple example.
 *
 * This code is released under a BSD style license. Do what you want, but
 * do not blame me.
 *
 * Peter Bengtsson, Dec 2004.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include <SDL/SDL.h>

int Quit=0;

static int B_WIDTH=640;
static int B_HEIGHT=480;

int main(int cnt,char *arg[])
{
SDL_Surface *Win=NULL;
GLubyte *Ytex,*Utex,*Vtex;
SDL_Event evt;
int i;
GLhandleARB FSHandle,PHandle;
char *s;
FILE *fp;

char *FProgram=
  "uniform sampler2DRect Ytex;/n"
  "uniform sampler2DRect Utex,Vtex;/n"
  "void main(void) {/n"
  "  float nx,ny,r,g,b,y,u,v;/n"
  "  vec4 txl,ux,vx;"
  "  nx=gl_TexCoord[0].x;/n"
  "  ny=576.0-gl_TexCoord[0].y;/n"
  "  y=texture2DRect(Ytex,vec2(nx,ny)).r;/n"
  "  u=texture2DRect(Utex,vec2(nx/2.0,ny/2.0)).r;/n"
  "  v=texture2DRect(Vtex,vec2(nx/2.0,ny/2.0)).r;/n"

  "  y=1.1643*(y-0.0625);/n"
  "  u=u-0.5;/n"
  "  v=v-0.5;/n"

  "  r=y+1.5958*v;/n"
  "  g=y-0.39173*u-0.81290*v;/n"
  "  b=y+2.017*u;/n"

  "  gl_FragColor=vec4(r,g,b,1.0);/n"
  "}/n";


if(!SDL_Init(SDL_INIT_VIDEO)) {

  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);

  Win=SDL_SetVideoMode(B_WIDTH,B_HEIGHT,32,SDL_HWSURFACE|SDL_ANYFORMAT|SDL_OPENGL);

  if(Win) {
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0,B_WIDTH,0,B_HEIGHT,-1,1);
    glViewport(0,0,B_WIDTH,B_HEIGHT);
    glClearColor(0,0,0,0);
    glColor3f(1.0,0.84,0.0);
    glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);

    /* Set up program objects. */
    PHandle=glCreateProgramObjectARB();
    FSHandle=glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

    /* Compile the shader. */
    glShaderSourceARB(FSHandle,1,&FProgram,NULL);
    glCompileShaderARB(FSHandle);

    /* Print the compilation log. */
    glGetObjectParameterivARB(FSHandle,GL_OBJECT_COMPILE_STATUS_ARB,&i);
    s=malloc(32768);
    glGetInfoLogARB(FSHandle,32768,NULL,s);
    printf("Compile Log: %s/n", s);
    free(s);

    /* Create a complete program object. */
    glAttachObjectARB(PHandle,FSHandle);
    glLinkProgramARB(PHandle);

    /* And print the link log. */
    s=malloc(32768);
    glGetInfoLogARB(PHandle,32768,NULL,s);
    printf("Link Log: %s/n", s);
    free(s);

    /* Finally, use the program. */
    glUseProgramObjectARB(PHandle);

    /* Load the textures. */
    Ytex=malloc(414720);
    Utex=malloc(103680);
    Vtex=malloc(103680);

    fp=fopen("Image.Y","rb");
    fread(Ytex,414720,1,fp);
    fclose(fp);
    fp=fopen("Image.U","rb");
    fread(Utex,103680,1,fp);
    fclose(fp);
    fp=fopen("Image.V","rb");
    fread(Vtex,103680,1,fp);
    fclose(fp);

    /* This might not be required, but should not hurt. */
    glEnable(GL_TEXTURE_2D);

    /* Select texture unit 1 as the active unit and bind the U texture. */
    glActiveTexture(GL_TEXTURE1);
    i=glGetUniformLocationARB(PHandle,"Utex");
    glUniform1iARB(i,1);  /* Bind Utex to texture unit 1 */
    glBindTexture(GL_TEXTURE_RECTANGLE_NV,1);

    glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
    glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_LUMINANCE,376,288,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,Utex);

    /* Select texture unit 2 as the active unit and bind the V texture. */
    glActiveTexture(GL_TEXTURE2);
    i=glGetUniformLocationARB(PHandle,"Vtex");
    glBindTexture(GL_TEXTURE_RECTANGLE_NV,2);
    glUniform1iARB(i,2);  /* Bind Vtext to texture unit 2 */

    glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
    glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_LUMINANCE,376,288,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,Vtex);

    /* Select texture unit 0 as the active unit and bind the Y texture. */
    glActiveTexture(GL_TEXTURE0);
    i=glGetUniformLocationARB(PHandle,"Ytex");
    glUniform1iARB(i,0);  /* Bind Ytex to texture unit 0 */
    glBindTexture(GL_TEXTURE_RECTANGLE_NV,3);

    glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
    glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_LUMINANCE,752,576,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,Ytex);

    /* Simple loop, just draws the image and waits for quit. */
    while(!Quit) {
      if(SDL_PollEvent(&evt)) {
        switch(evt.type) {
        case  SDL_KEYDOWN:
        case  SDL_QUIT:
          Quit=1;
        break;
        }
      }
    
      glClear(GL_COLOR_BUFFER_BIT);

      /* Draw image (again and again). */

      glBegin(GL_QUADS);
        glTexCoord2i(0,0);
        glVertex2i(0,0);
        glTexCoord2i(720,0);
        glVertex2i(B_WIDTH,0);
        glTexCoord2i(720,576);
        glVertex2i(B_WIDTH,B_HEIGHT);
        glTexCoord2i(0,576);
        glVertex2i(0,B_HEIGHT);
      glEnd();

      /* Flip buffers. */

      glFlush();
      SDL_GL_SwapBuffers();

      sleep(1);
    } /* while(!Quit) */

    /* Clean up before exit. */

    glUseProgramObjectARB(0);
    glDeleteObjectARB(sprog);

    free(Ytex);
    free(Utex);
    free(Vtex);

  } else {
    fprintf(stderr,"Unable to create primary surface. /"%s/"./n",SDL_GetError());
  }
  SDL_Quit();
} else {
  fprintf(stderr,"Initialisation failed. /"%s/"./n",SDL_GetError());
}

return(0);
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值