摘要:可移植像素图格式,灰度图格式,位图格式的介绍简介可移植像素图格式,可移植灰度图格式和可移植位图格式是便于跨平台的图像格式。每个文件的开头两个字节码作为文件描述符,指出具体格式和编码形式。
可移植像素图格式 PPM,灰度图格式 PGM,位图格式 PBM 的介绍 简介
可移植像素图格式(PPM),可移植灰度图格式(PGM)和可移植位图格式(PBM)是便于跨平台的图像格式。有时候也被统称为 PNM 格式
文件格式描述这三种格式其实是一样的描述方法,只不过 PBM 是单色,PGM 是灰度图,PPM 使用 RGB 颜色。
每个文件的开头两个字节(ASCII 码)作为文件描述符,指出具体格式和编码形式。
Type | Magic number | Extension | Colors | |
---|---|---|---|---|
ASCII | Binary | |||
Portable BitMap | P1 | P4 | .pbm | 0–1 (white & black) |
Portable GrayMap | P2 | P5 | .pgm | 0–255 (gray scale) |
Portable PixMap | P3 | P6 | .ppm | 0–255 (RGB) |
Portable Arbitrary Map | P7 | .pam | 0–255 (RGB_ALPHA) |
注意每行结束有换行符
P1 # This is an example bitmap of the letter "J" 6 10 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
上面的图像是一个J
PGMP2 # Shows the word "FEEP" (example from Netpbm man page on PGM) 24 7 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0 0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0 0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0 0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0 0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
上面的图像是
P3 3 2 255 # The part above is the header # "P3" means this is a RGB color image in ASCII # "3 2" is the width and height of the image in pixels # "255" is the maximum value for each color # The part below is image data: RGB triplets 255 0 0 0 255 0 0 0 255 255 255 0 255 255 255 0 0 0
把上面六个像素放大后显示如下
P7 WIDTH 4 HEIGHT 2 DEPTH 4 MAXVAL 255 TUPLTYPE RGB_ALPHA ENDHDR 0000FFFF 00FF00FF FF0000FF FFFFFFFF 0000FF7F 00FF007F FF00007F FFFFFF7F
上面数据放大显示如下:
下面是简单的ppm包
package ppm import ( "fmt" "io" "os" ) // WriteTo outputs 8-bit P6 PPM format to an io.Writer. func (b *Bitmap) WritePpmTo(w io.Writer) (err error) { // magic number if _, err = fmt.Fprintln(w, "P6"); err != nil { return } // comments for _, c := range b.Comments { if _, err = fmt.Fprintln(w, c); err != nil { return } } // x, y, depth _, err = fmt.Fprintf(w, "%d %d 255 ", b.cols, b.rows) if err != nil { return } // raster data in a single write b3 := make([]byte, 3*len(b.px)) n1 := 0 for _, px := range b.px { b3[n1] = px.R b3[n1+1] = px.G b3[n1+2] = px.B n1 += 3 } if _, err = w.Write(b3); err != nil { return } return } // WriteFile writes to the specified filename. func (b *Bitmap) WritePpmFile(fn string) (err error) { var f *os.File if f, err = os.Create(fn); err != nil { return } if err = b.WritePpmTo(f); err != nil { return } return f.Close() }
下面是生成ppm的程序
package main // Files required to build supporting package raster are found in: // * This task (immediately above) // * Bitmap task import ( "raster" "fmt" ) func main() { b := raster.NewBitmap(400, 300) b.FillRgb(0x240008) // a dark red err := b.WritePpmFile("write.ppm") if err != nil { fmt.Println(err) } }用C生成PPM文件
#includeint main() { const char *filename = "n.pgm"; int x, y; /* size of the image */ const int x_max = 100; /* width */ const int y_max = 100; /* height */ /* 2D array for colors (shades of gray) */ unsigned char data[y_max][x_max]; /* color component is coded from 0 to 255 ; it is 8 bit color file */ const int MaxColorComponentValue = 255; FILE * fp; /* comment should start with # */ const char *comment = "# this is my new binary pgm file"; /* fill the data array */ for (y = 0; y < y_max; ++y) { for (x = 0; x < x_max; ++x) { data[y][x] = (x + y) & 255; } } /* write the whole data array to ppm file in one step */ /* create new file, give it a name and open it in binary mode */ fp = fopen(filename, "wb"); /* write header to the file */ fprintf(fp, "P5 %s %d %d %d ", comment, x_max, y_max, MaxColorComponentValue); /* write image data bytes to the file */ fwrite(data, sizeof(data), 1, fp); fclose(fp); printf("OK - file %s saved ", filename); return 0; }
或者
imglib.h
#ifndef _IMGLIB_0 #define _IMGLIB_0 #include#include #include #include #include #include typedef unsigned char color_component; typedef color_component pixel[3]; typedef struct { unsigned int width; unsigned int height; pixel * buf; } image_t; typedef image_t * image; image alloc_img(unsigned int width, unsigned int height); void free_img(image); void fill_img(image img, color_component r, color_component g, color_component b ); void put_pixel_unsafe( image img, unsigned int x, unsigned int y, color_component r, color_component g, color_component b ); void put_pixel_clip( image img, unsigned int x, unsigned int y, color_component r, color_component g, color_component b ); #define GET_PIXEL(IMG, X, Y) (IMG->buf[ ((Y) * IMG->width + (X)) ]) #endif
imglib.c
image alloc_img(unsigned int width, unsigned int height) { image img; img = malloc(sizeof(image_t)); img->buf = malloc(width * height * sizeof(pixel)); img->width = width; img->height = height; return img; } void free_img(image img) { free(img->buf); free(img); } void fill_img( image img, color_component r, color_component g, color_component b ) { unsigned int i, n; n = img->width * img->height; for (i=0; i < n; ++i) { img->buf[i][0] = r; img->buf[i][1] = g; img->buf[i][2] = b; } } void put_pixel_unsafe( image img, unsigned int x, unsigned int y, color_component r, color_component g, color_component b ) { unsigned int ofs; ofs = (y * img->width) + x; img->buf[ofs][0] = r; img->buf[ofs][1] = g; img->buf[ofs][2] = b; } void put_pixel_clip( image img, unsigned int x, unsigned int y, color_component r, color_component g, color_component b ) { if (x < img->width && y < img->height) put_pixel_unsafe(img, x, y, r, g, b); }
output_ppm
#include "imglib.h" void output_ppm(FILE *fd, image img) { unsigned int n; (void) fprintf(fd, "P6 %d %d 255 ", img->width, img->height); n = img->width * img->height; (void) fwrite(img->buf, sizeof(pixel), n, fd); (void) fflush(fd); }生成raw rgb格式
其实raw rgb和ppm数据是一样的,我们生成出300帧的ppm数据,然后送给ffplayer(ffmpeg)来播放
下面是我的go代码:
// // Created by : Harris Zhu // Filename : genrgb.go // Author : Harris Zhu // Created On : 2018-09-14 02:13:11 // Last Modified : 2018-09-14 02:13:11 // Update Count : 1 // Tags : // Description : // Conclusion : // //======================================================================= package main import ( "bufio" "os" "strconv" "time" "github.com/urfave/cli" ) func main() { app := cli.NewApp() app.Name = "genrgb" app.Version = "1.0.0" app.Compiled = time.Now() app.Authors = []cli.Author{ cli.Author{ Name: "Harris Zhu", Email: "zhuzhzh@163.com", }, } app.Usage = "svpaser" name := "rgb.data" w := 600 h := 480 f := 20 app.Action = func(c *cli.Context) error { name = c.Args().Get(0) w, _ = strconv.Atoi(c.Args().Get(1)) h, _ = strconv.Atoi(c.Args().Get(2)) f, _ = strconv.Atoi(c.Args().Get(3)) genrgb(name, w, h, f) return nil } app.Run(os.Args) } func genrgb(filepath string, w int, h int, f int) { fout, err := os.Create(filepath) defer fout.Close() if err != nil { panic(err) } bufout := bufio.NewWriter(fout) // bufout.WriteString("P6 # this is my ppm file ") // bufout.WriteString(strconv.Itoa(w)) // bufout.WriteString(" ") // bufout.WriteString(strconv.Itoa(h)) // bufout.WriteString(" ") // bufout.WriteString(strconv.Itoa(255)) // bufout.WriteString(" ") r := []byte{255, 0, 0} g := []byte{0, 255, 0} b := []byte{0, 0, 255} dcnt := 0 //k: frame //i: height column //j: width line for k := 0; k < f; k++ { for i := 0; i < h; i++ { //fmt.Println("hline: ", i) for j := 0; j < w; j++ { if k%3 == 0 { bufout.Write(r) dcnt++ } else if k%3 == 1 { bufout.Write(g) dcnt++ } else if k%3 == 2 { bufout.Write(b) dcnt++ } //fmt.Println("vline: ", j) } } bufout.Flush() //fmt.Printf("total pixels = %d ", dcnt) } }
下面是makefile:
FILE = genrgb GENFILE = rgb.data b build: go build -gcflags "-N -l" $(FILE).go g gen: ./$(FILE) $(GENFILE) 60 40 300 p play: cat $(GENFILE) | ffplay -i pipe:0 -f rawvideo -pix_fmt rgb24 -video_size 60x40
依次执行make b; make g; make p可以看到下面的播放视频
它交替显示红绿蓝
总结RGB比较直观的图像显示方法,但相对YUV来说比较占空间,每个像素占用3个byte, 像1080P的图像就要占用$1920*1080*3=6,220,800byte$, 但它用于作为图像和显示入门是非常好的。能够让你很快就常会编程显示图像。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/11071.html
摘要:因为分别代表不同颜色信号,所以直接使用与信号表示色度的。彩色图像记录的格式,常见的有等。主要的抽样格式有和。的表示法称为表示法表示完全取样。表示的水平取样,垂直采样。格式则有一通道。 YUV和RGB详解 前言 YUV,是一种颜色编码方法。常使用在各个视频处理组件中。 YUV在对照片或视频编码时,考虑到人类的感知能力,允许降低色度的带宽。 YUV是编码true-color时使用的颜色空...
摘要:了解华为海思的方案海思的前身是华为的半导体部门,主要产品线包括智能手机处理器麒麟系列,视频采集和编解码处理器系列,无线通信方向芯片等。 目录 一、视频行业1、视频...
阅读 3330·2021-11-22 09:34
阅读 2809·2021-10-09 09:43
阅读 1336·2021-09-24 09:47
阅读 2170·2019-08-30 12:53
阅读 954·2019-08-29 14:00
阅读 3322·2019-08-29 13:17
阅读 2236·2019-08-28 18:00
阅读 1252·2019-08-26 12:00