在网上看到一个开源项目的代码,写的非常整洁,易懂,特此记录下来,网址忘了,还望见谅!!
#include <math.h>
#include <stdint.h>
#define ALIGN_2K(x) ((x + 2047) & ~ 2047)
struct Buffer {
void * data;
size_t size;
size_t width, height;
};
static int convertRGB888toRGB565(struct Buffer src, struct Buffer dst);
static int convertRGB888toYCbCr420SP(struct Buffer src, struct Buffer dst);
int main() {
struct Buffer src, dst;
FILE * in = fopen("input.yuv", "rb");
FILE * out = fopen("output.yuv", "wb");
int width = 800;
int height = 480;
uint8_t *srcData = malloc(width * height * 3);
uint8_t *dstData = malloc(width * height + ALIGN_2K(width * height));
fread(srcData, width * height * 3, 1, in);
src.data = srcData;
src.size = width * height * 3;
src.width = WIDTH;
src.height = HEIGHT;
dst.data = dstData;
dst.size = width * height + ALIGN_2K(width * height);
dst.width = WIDTH;
dst.height = HEIGHT;
convertRGB888toYCbCr420SP(src, dst);
fwrite(dstData, width * height + ALIGN_2K(width * height), 1, out);
free(srcData);
free(dstData);
fclose(in);
fclose(out);
return 0;
}
static int convertRGB888toRGB565(struct Buffer src, struct Buffer dst) {
uint8_t *srcData, *dstData;
srcData = (uint8_t *)src.data;
dstData = (uint8_t *)dst.data;
for (int c = 0, i = 0; c < src.width * src.height;) {
//scale down each component to 5 or 6 bits
uint8_t r, g, b;
r = srcData[c++];
g = srcData[c++];
b = srcData[c++];
r = (uint8_t)((srcData[c++]/255.0)*31); //R component
g = (uint8_t)((srcData[c++]/255.0)*63); //G component
b = (uint8_t)((srcData[c++]/255.0)*31); //B component
dstData[i++] = ((r & 0x1f) << 3) | ((g >> 3) & 0x7); //R (5 bits) + G (upper 3 bits)
dstData[i++] = ((g & 0x7) << 5) | (b & 0x1f); //G (lower 3 bits) + B (5 bits)
}
return 0;
}
static int convertRGB888toYCbCr420SP(struct Buffer src, struct Buffer dst) {
uint8_t *srcData, *dstData;
srcData = (uint8_t *)src.data;
dstData = (uint8_t *)dst.data;
//derive the luma
for (int c = 0, i = 0, j = 0; c < src.width * src.height * 3;) {
uint8_t r, g, b;
r = srcData[c++];
g = srcData[c++];
b = srcData[c++];
//stolen from wikipedia
uint8_t y, cb, cr;
y = (uint8_t)(16 + (65.481 * r + 128.553 * g + 24.966 * b)/256);
cb = (uint8_t)(128 + (-37.979 * r - 74.203 * g + 112 * b)/256);
cr = (uint8_t)(128 + (112 * r - 93.786 * g - 18.214 * b)/256);
dstData[i++] = y;
(dstData + ALIGN_2K(src.width * src.height))[j++] = cb;
(dstData + ALIGN_2K(src.width * src.height))[j++] = cr;
}
return 0;
}