音视频入门文章目录

图片 & 像素点 & RGB

平时浏览的图片看不出像素点:

image-demo

图片放大时,可以看出图片是一个个像素点组成的:

image-demo-pixel

每个像素点的颜色可以用 RGB 表示:

image-demo-pixel-rgb

RGB 拼图

既然图片是像素点组成的,而像素点的颜色可以用 RGB 来表示,那我们可以用 RGB 来拼出自己的图片!

1. 设定目标

这是我们想要使用 RGB 像素点拼出来的图片:

image-demo-rainbow

彩虹的颜色:

颜色名RGB十六进制RGB24 二进制
255, 0, 00XFF000011111111 00000000 00000000
255, 165, 00XFFA50011111111 10100101 00000000
255, 255, 00XFFFF0011111111 11111111 00000000
绿0, 255, 00X00FF0000000000 11111111 00000000
0, 127, 2550X007FFF00000000 01111111 11111111
0, 0, 2550X0000FF00000000 00000000 11111111
139, 0, 2550X8B00FF10001011 00000000 11111111

2. 分析实现思路

用 RGB24 格式表示像素颜色值,每个像素用 24 比特位表示,占用三个字节。

分辨率 7X7 彩虹图片像素排列:
image-demo-rainbow-pixel-index

分辨率 7X7 彩虹图片像素 RGB 二进制:
image-demo-rainbow-pixel-binary

7X7 只是为了分析方便,我们动手时要拼出 700X700 像素点的图片

3. 动手实践

将像素点的 RGB24 二进制存入文件:

#include <stdio.h>

// 彩虹的七种颜色
u_int32_t rainbowColors[] = {
        0XFF0000, // 红
        0XFFA500, // 橙
        0XFFFF00, // 黄
        0X00FF00, // 绿
        0X007FFF, // 青
        0X0000FF, // 蓝
        0X8B00FF  // 紫
};

void writeRainbow(char *outputFile, int width, int height) {

    // 打开文件
    FILE *rgbFile = fopen(outputFile, "wb+");
    for (int i = 0; i < width; ++i) {
        // 当前颜色
        u_int32_t currentColor = 0X000000;
        if(i < 100) {
            // 前 100 行 红色
            currentColor = rainbowColors[0];
        } else if(i < 200) {
            // 100-200 行 橙色
            currentColor = rainbowColors[1];
        } else if(i < 300) {
            // 200-300 行 黄色
            currentColor = rainbowColors[2];
        } else if(i < 400) {
            // 300-400 行 绿色
            currentColor = rainbowColors[3];
        } else if(i < 500) {
            // 400-500 行 青色
            currentColor = rainbowColors[4];
        } else if(i < 600) {
            // 500-600 行 蓝色
            currentColor = rainbowColors[5];
        } else if(i < 700) {
            // 600-700 行 紫色
            currentColor = rainbowColors[6];
        }
        // 当前颜色 R 分量
        u_int8_t R = (currentColor & 0xFF0000) >> 16;
        // 当前颜色 G 分量
        u_int8_t G = (currentColor & 0x00FF00) >> 8;
        // 当前颜色 B 分量
        u_int8_t B = currentColor & 0x0000FF;
        for (int j = 0; j < height; ++j) {
            // 按顺序写入一个像素 RGB24 到文件中
            fputc(R, rgbFile);
            fputc(G, rgbFile);
            fputc(B, rgbFile);
        }
    }

    // 关闭文件
    fclose(rgbFile);
}

int main() {
    writeRainbow("/Users/staff/Desktop/rainbow-700x700.rgb24", 700, 700);
    return 0;
}

运行上面的代码,将会生成 rainbow-700x700.rgb24 文件

检查生成的文件

  • 700X700=490000 个像素点
  • 每个像素点颜色用 RGB24 编码表示,每个像素点用 24 比特位表示,占 3 个字节
  • 490000 X 3 = 1470000 字节(B)
$ cd Desktop
$ ls -al rainbow-700x700.rgb24
-rw-r--r--  1 staff  staff  1470000  9 12 18:17 rainbow-700x700.rgb24

感觉生成了正确的 rgb24 格式的图片。

确认 RGB24 文件正确性

要确认生成的 rgb24 格式的图片是正确的,最直接的方式就是使用图片查看软件打开。但是,普通的图片查看软件都不支持 rgb24 这种格式。这时就要用专业的多媒体框架 FFmpeg 了。

下载 ffplay 工具

FFmpeg 工具下载

根据自己的系统,下载 FFmpeg Static 工具包。

这里拿 macOS 为例:

$ ll
total 163968
-rw-r--r--@ 1 staff  staff    66M  9 12 20:43 ffmpeg-4.2-macos64-static.zip

# 解压压缩包
$ unzip ffmpeg-4.2-macos64-static.zip

$ cd ffmpeg-4.2-macos64-static
$ ll
total 88
-rw-r--r--@  1 staff  staff    35K  8  8 14:26 LICENSE.txt
-rw-r--r--@  1 staff  staff   4.0K  8  8 14:26 README.txt
drwxr-xr-x@  5 staff  staff   160B  8  8 14:26 bin
drwxr-xr-x@ 35 staff  staff   1.1K  8  8 14:26 doc
drwxr-xr-x@  8 staff  staff   256B  8  8 14:26 presets
$ cd bin
$ ll
total 394000
-rwxr-xr-x@ 1 staff  staff    64M  8  8 14:26 ffmpeg
-rwxr-xr-x@ 1 staff  staff    64M  8  8 14:26 ffplay
-rwxr-xr-x@ 1 staff  staff    64M  8  8 14:26 ffprobe

# 测试执行 ffplay 命令
$ ./ffplay
ffplay version 4.2 Copyright (c) 2003-2019 the FFmpeg developers
  built with Apple LLVM version 10.0.1 (clang-1001.0.46.4)
  configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-appkit --enable-avfoundation --enable-coreimage --enable-audiotoolbox
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
Simple media player
usage: ffplay [options] input_file

An input file must be specified
Use -h to get full help or, even better, run 'man ffplay'

使用 ffplay 打开 rgb24 图片

ffplay -f rawvideo -pixel_format rgb24 -s 700x700 rainbow-700x700.rgb24

# -pixel_format rgb24 指定像素格式 rgb24
# -s 700x700 指定图片分辨率 700x700

预览:

rgb24-preview

Congratulations!

成功用像素点拼出了一张图片!


代码:
rgb-pixel



binglingziyu
3 声望4 粉丝