RGB24,RGB565,RGB444图片质量比较
以下图片,第二幅是RGB24的原图。第一幅是对第二幅进行RGB444的有损变换图,第三幅是对第二幅进行RGB565的有损变换图。其中肉眼很难分辨RGB565和RGB24的差别。RGB444有明显噪点。

RGB444图片

RGB24原图

RGB565图片
转换都是用的ffmpeg的sws_scale算法。
主要是想比较每种图片的大小。

文件大小
其中 188_720_576.bmp是原图 1216K 188_720_576.bmp_444_1.bmp是转RGB444之后再转回RGB24保存的图片。所以大小也是1216K 188_720_576.bmp_555_1.bmp是转RGB565之后再转回RGB24保存的图片。所以大小也是1216K 188_720_576.bmp_444_1_2.raw是转RGB444之后的裸数据。大小是810K 188_720_576.bmp_555_1_2.raw是转RGB565之后的裸数据。大小也是810K 188_720_576.bmp_444_1_2.raw.zip是RGB444裸数据zip压缩后的文件。大小是185K 188_720_576.bmp_555_1_2.raw.zip是RGB565裸数据zip压缩后的文件。大小也是335K
得出结论因为RGB565和RGB444实际占用字节都是16bit,所以 裸数据文件大小一样。但是RGB444实际上只用了12bit,有4bit无用进行0填充,所以zip压缩率比较大。
然后又进行了一个尝试,就是把RGB444的4bit数据移除。两个RGB444有效数据(4byte)合并成3byte。得到的裸数据文件大小和压缩大小如下:

32bit RGB444数据移除8bit无效数据组成24bit
我们看到,在移除RGB444的无用数据后,裸数据大小由原来的810K减少到608K.(810*3/4=607.5),但是实际zip压缩文件只是从185K变成183K,可以忽略不计。
例子代码如下:
// RGBStudy.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <Windows.h>
#include <iostream>
#include <string>
#include <wingdi.h>
#pragma warning(disable:4996)
#ifdef __cplusplus
extern "C" {
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/imgutils.h>
#include <libavutil/parseutils.h>
#include <libavutil/file.h>
#include <libswscale/swscale.h>
#ifdef __cplusplus
}
#endif
int go(char *argv);
int main()
{
go((char*)"d:\\188_720_576.bmp");
std::cout << "Hello World!\n";
}
int go(char *argv){
BITMAPFILEHEADER bmpFHeader;
BITMAPINFOHEADER bmpIHeader;
uint8_t *src_data[4], *dst_data[4];
int src_linesize[4], dst_linesize[4];
int src_w = 640, src_h = 480, dst_w, dst_h;
enum AVPixelFormat src_pix_fmt = AV_PIX_FMT_RGB24, dst_pix_fmt = AV_PIX_FMT_RGB565;
const char *dst_filename = NULL;
std::string file,file0;
FILE *dst_file;
int dst_bufsize;
struct SwsContext *sws_ctx, *sws_ctx1;
int i, ret;
dst_filename = argv;
file = dst_filename;
file = file + "_555_1.bmp";
file0 = dst_filename;
file0 = file0 + "_555_1_2.raw";
dst_w = src_w;
dst_h = src_h;
dst_file = fopen(dst_filename, "rb");
if (dst_file) {
fseek(dst_file, 0L, SEEK_END);
int len = ftell(dst_file);
if (len > 0) {
char* buf0 = new char[len];
char* buf = buf0;
fseek(dst_file, 0L, SEEK_SET);
fread(buf, 1, len, dst_file);
fclose(dst_file);
memcpy(&bmpFHeader, buf, sizeof(BITMAPFILEHEADER));
int nHeadLen = bmpFHeader.bfOffBits - sizeof(BITMAPFILEHEADER);
memcpy(&bmpIHeader, buf + sizeof(BITMAPFILEHEADER), nHeadLen);
src_w = dst_w = bmpIHeader.biWidth;
src_h = dst_h = bmpIHeader.biHeight;
buf += bmpFHeader.bfOffBits;
len = len - bmpFHeader.bfOffBits;
sws_ctx = sws_getContext(src_w, src_h, src_pix_fmt,
dst_w