hi folks!
maybe you can remember, months ago i wanted to know about YUV to RGB
conversion in the theora case.
finally i managed to go on with this issue, and here is a function i
made which needs a
theora_info and a yuv_buffer passed and will create an interleaved 24
bit RGB buffer.
just one big problem: i am coding since days, and the only remaining
problem which i cannot seem to solute is that in the last part, the
conversion from interleaved YUV to interleaved RGB seems to have
problems. theoretically (and when tried external with input and output
files it works perfectly) it should work.
but when dumping rgbbuf with fwrite(), the output is completely empty :(
maybe someone of you can help with this :)
greets,
---david
code:
#include <stdio.h>
#include "theora/theora.h"
/*
* theora2rgb 0.1
*
* Converts a yuv_buffer filled by theora_decode_YUVout to
* a 24bit RGB buffer, ordered R-G-B, interleaved.
* Currently, the color conversion is not very efficient.
* In addition, encoder specified color is ignored, resulting colors
* are a little red-weighted, and no resolution scaling is done.
*/
#define clip(a) (((a)&256) ? ((a)>>31)^(-1) : (a))
void theoraToRGB(theora_info ti, yuv_buffer yuv) {
// create yuvbuf in interleaved YUV format.
int i, j, crop_offset = 0;
char* yuvbuf = (char *)malloc(ti.width * ti.height * 3);
char* rgbbuf = (char *)malloc(ti.width * ti.height * 3);
crop_offset=ti.offset_x+yuv.y_stride*ti.offset_y;
int k=0;
i = 0;
while(i<ti.height) {
for(j=0;j<ti.width;j++) {
yuvbuf[k]=yuv.y[crop_offset+yuv.y_stride*i+j];
k += 3;
}
i++;
}
crop_offset=(ti.offset_x/2)+(yuv.uv_stride)*(ti.offset_y/2);
k=1;
i=0;
while(i<ti.height/2) {
for(j=0;j<ti.width/2;j++) {
yuvbuf[k++]=yuv.u[crop_offset+yuv.uv_stride*i+j];
yuvbuf[k++]=yuv.v[crop_offset+yuv.uv_stride*i+j];
k++;
yuvbuf[k++]=yuv.u[crop_offset+yuv.uv_stride*i+j];
yuvbuf[k++]=yuv.v[crop_offset+yuv.uv_stride*i+j];
k++;
}
for(j=0;j<ti.width/2;j++) {
yuvbuf[k++]=yuv.u[crop_offset+yuv.uv_stride*i+j];
yuvbuf[k++]=yuv.v[crop_offset+yuv.uv_stride*i+j];
k++;
yuvbuf[k++]=yuv.u[crop_offset+yuv.uv_stride*i+j];
yuvbuf[k++]=yuv.v[crop_offset+yuv.uv_stride*i+j];
k++;
}
i++;
}
// convert yuvbuf to rgbbuf, interleaved RGB.
int offset, y, u, v = 0;
while(offset < ti.width * ti.height * 3) {
y = yuvbuf[offset++] - 16;
u = yuvbuf[offset++] - 128;
v = yuvbuf[offset++] - 128;
offset -= 3;
rgbbuf[offset++] = clip((298 * y + 409 * v + 128) >> 8);
rgbbuf[offset++] = clip((298 * y + 100 * u - 208 * v + 128) >> 8);
rgbbuf[offset++] = clip((298 * y + 516 * u + 128) >> 8);
}
// just for testing: dump RGB data to RAW file
FILE * ofp = fopen("rgb.raw", "wb");
fwrite(rgbbuf, sizeof(char), ti.width * ti.height * 3, ofp);
/*
when using
fwrite(yuvbuf, sizeof(char), ti.width * ti.height * 3, ofp);
instead, you can see that the YUV buffer is perfectly correct.
*/
fclose(ofp);
free(yuvbuf);
free(rgbbuf);
}