分形/计算机图形技术/2D/gfile
"Any computer-generated picture is a finite collection of pixels." ( A Dudko, M Yampolsky)[1]
a matrix of color entries (a.k.a. image)
图形文件
可以
- 直接创建图形文件
- 打开现有的图形文件
- 添加/读取/删除图形文件的文本信息
图形文件类型
- 图像
- 静态图像
- SDR 文件格式:PNG8、JPG、
- HDR 文件格式:FITS、JPEG XR、JPEG XT、Logluv TIFF、exr (OpenEXR)、RGBE 图像格式、TIFF、PNG64、AV1
- 动态图像
- 视频(ogg 文件) - 需要特殊的程序(查看器)才能运行
- 动画(没有查看器的动画 GIF 文件)
- 静态图像
- 非图像文件
数字图像表示
- 光栅
- 矢量
图像的动态范围
- LDR
- 标准 LDR
- 从 HDR 映射的 LDR 色调
- 伪 HDR 或曝光混合或曝光融合 = 从多个曝光中合并的图像,而无需创建中间 HDR 图像,也无需使用色调映射
- HDR
- 数据 = 未处理的 HDR = 浮点帧缓冲区(在 OpenGl GL_RGB16F、GL_RGBA16F、GL_RGB32F 或 GL_RGBA32F 中)
- AV1 图像文件格式 (AVIF) 是一种开放的、免版税的图像文件格式规范,用于存储使用 AV1 压缩的图像或图像序列,采用 HEIF 容器格式。[
- 维基百科中的图形文件格式比较
- Commons 中的文件类型
- 美国国家医学图书馆的图形格式指南
- 美国国家医学图书馆的文件格式
- 分形论坛允许的文件类型:kfr、jpg、jpeg、gif、png、ufr、upr、uxf、ucl、ufm、map、par、m3a、m3f、m3i、m3p、m3c、frag、m3v、zip、ifp、lua、txt
格式 | 支持的位深 | 在动画和 VFX 中的使用 |
---|---|---|
JPEG | 8 位 sRGB | 预览渲染。使用 100% 的质量。文件尺寸小,在播放器中加载速度快。也可以用作 3D 中的背景或动作匹配的底片。永远不要用作中间格式 TARGA (tga) |
TARGA (tga) | 8 位 sRGB | 非常古老,但仍然用作电视广告后期制作中的中间格式 |
TIFF | 8 位和 16 位 sRGB。32 位线性浮点。 | 如果需要中间 16 位整数,则为标准格式 |
PNG | 8 位和 16 位 sRGB。8 位调色板。 | 标准 Web 格式。支持无损压缩,因此非常有用 |
Cineon (dpx, cin) | 8、10、12、16 sRGB 和对数 | 用作交付、中间和输出格式。电影转电视和数字中间调色的标准格式 |
Photoshop (psd) | 8 位和 16 位 sRGB。32 位线性浮点 | Photoshop 工作的默认格式。可以用作中间格式,将图层交付到下一阶段 |
Radiance (hdr) | 32 位线性浮点 | 存储用于基于图像的照明的 HDR 图像的标准格式 |
OpenEXR (exr) | 16 位线性浮点。32 位线性浮点 | VFX 渲染和中间格式的标准 |
pfm | 四字节 IEEE 754 单精度浮点扩展 | PFM 受 Photoshop[16]、GIMP 和 ImageMagick 的支持。它受事实上的参考实现 netpbm 的支持 |
AV1 图像文件格式 (AVIF) 是一种开放的、免版税的图像文件格式规范,用于存储使用 AV1 压缩的图像或图像序列,采用 HEIF 容器格式。[3] 它与 HEIC 竞争,HEIC 使用相同的基于 ISOBMFF 的容器格式,但使用 HEVC 进行压缩。AVIF 规范的 1.0.0 版于 2019 年 2 月定稿。
在 Netflix 于 2020 年进行的一系列测试中,AVIF 表现出比 JPEG 更好的压缩效率,以及更好的细节保留、更少的块状伪影,以及在自然图像、文本和图形的合成图像中更少的颜色溢出。[4]
AVIF 特性
- 多个颜色空间,包括
- HDR(使用 PQ(传递函数)[5]Template:Failed verification 或混合对数伽马 (HLG) 传递函数,以及 BT.2020 色彩原色,作为 BT.2100 的一部分)[3]
- 标准动态范围 (SDR),使用 sRGB / BT.709 / BT.601 或宽色域
- 通过编码无关代码点 (CICP)(ITU-T H.273 和 ISO/IEC 23091-2)或 ICC 配置文件[6] 传输颜色空间信号
- 无损压缩和有损压缩
- 8 位、10 位和 12 位色深[6]
- 单色(alpha/深度)或多组件
- 4:2:0、4:2:2、4:4:4 色度采样和 RGB
- 胶片颗粒[7]
- 图像序列/动画
- AVIF 是由开放媒体联盟开发的一种文件格式。它是一个开放的标准,在主要网页浏览器中已经得到了相当广泛的支持,用于标准图像。AVIF 比 JPG 具有众多优势
- PNG 支持 1、2、4、8 和 16 位灰度以及 8 和 16 位每样本(即 24 和 48 位)真彩色。
- PFM 文件 - 用于 HDR 图像的浮点图像格式
- EXR(OpenEXR):16 位 OpenEXR 文件可以被认为是通用情况下色彩精度/文件大小折衷的良好选择[8] OpenEXR 支持使用以下颜色深度:16 位浮点(半精度)、32 位浮点和 32 位无符号整数
- TIFF
- RGBE 图像格式或 Radiance HDR 是 Gregory Ward Larson 为 Radiance 渲染系统发明的一种图像格式。它将像素存储为 RGB(红、绿、蓝)值的每个字节,并使用一个字节的共享指数。因此,它每个像素存储四个字节。
- Gertbuschmann 的描述
- 独立 JPEG 组
- JPEGclub.org 开发新的 JPEG 功能并维护独立 JPEG 组 (IJG) 的软件。
- jpeg-faq
- compression-faq
- 参考
- IJG 软件的三大工具
- cjpeg (压缩 JPEG):压缩命名图像文件,如果未命名文件则压缩标准输入,并在标准输出上生成 JPEG/JFIF 文件。当前支持的输入文件格式为:PPM(PBMPLUS 彩色格式)、PGM(PBMPLUS 灰度格式)、BMP、Targa 和 RLE(Utah Raster Toolkit 格式)。(仅当 URT 库可用时才支持 RLE。)另请参阅 新 cjpeg 功能
- djpeg(解压缩 JPEG)
- jpegtran(转码 JPEG - 无损)
Command 'cjpeg' not found, but can be installed with: sudo apt install libjpeg-progs # version 1:9d-1, or sudo apt install libjpeg-turbo-progs # version 2.1.2-0ubuntu1
如何使用它
./a.out | cjpeg > temp.jpg && open temp.jpg
- Richard Zanibbi 于 1998 年 5 月编写的 cprogram_to_read_PGM/PGM.c
- John Burkardt 编写的 PGMB_IO 二进制可移植灰度图 (PGM) 文件读写实用程序
- John Burkardt 提供的二进制 pgm 文件示例
// create 1D array
iSize = iWidth*iHeight; // size = number of points in array
/* create dynamic 1D arrays for colors ( shades of gray ) */
data = malloc( iSize * sizeof(unsigned char) );
if (data == NULL )
{
fprintf(stderr," Could not allocate memory\n");
return 1;
}
// *******************************************************************************************
// ********************************** save A array to pgm file ****************************
// *********************************************************************************************
int
SaveArray2PGMFile (unsigned char A[], int a, int b, int c, char *comment)
{
FILE *fp;
const unsigned int MaxColorComponentValue = 255; /* color component is coded from 0 to 255 ; it is 8 bit color file */
char name[100]; /* name of file */
snprintf (name, sizeof name, "%d_%d_%d", a, b, c ); /* */
char *filename = strcat (name, ".pgm");
char long_comment[200];
sprintf (long_comment, "fc(z)=z*(1+z)*(1+z)*(C-(2C+1)*z+(3+4*C)*z*z/4) %s", comment);
// save image array to the pgm file
fp = fopen (filename, "wb"); // create new file,give it a name and open it in binary mode
fprintf (fp, "P5\n # %s\n %u %u\n %u\n", long_comment, iWidth, iHeight, MaxColorComponentValue); // write header to the file
size_t rSize = fwrite (A, sizeof(A[0]), iSize, fp); // write whole array with image data bytes to the file in one step
fclose (fp);
// info
if ( rSize == iSize)
{
printf ("File %s saved ", filename);
if (long_comment == NULL || strlen (long_comment) == 0)
printf ("\n");
else { printf (". Comment = %s \n", long_comment); }
}
else {printf("wrote %zu elements out of %llu requested\n", rSize, iSize);}
return 0;
}
// free memory
free(data);
- 以下是用于创建 pbm 文件的各种程序[9]
- Mukund 编写的 C 语言中的 PPM 文件
- JOSEPH THOMAS 编写的 C 语言中的 ppm 文件
- Ilya Voyager 编写的 PGM 文件和 C++ 程序
- Lori L Scarlatos 使用 glut 加载和绘制 ppm/pgm 文件
- John Meacham 编写的 C 语言下黑手:泄漏的编辑
- 来自墨尔本大学的 Haskell 中的 ppm 文件
- Ryan Lothian 编写的 Haskell 中的 PPM
- Daniel Díaz 编写的使用 PPM 的 Haskell 中的图像处理
P3 #the P3 means colors are in ascii, then 3 columns and 2 rows, then 255 for max color, then RGB triplets 3 2 255 255 0 0 0 255 0 0 0 255 255 255 0 255 255 255 0 0 0
图像(展开):w:Image:tiny6pixel.png
上面的图像使用 imagemagick 命令没有插值地展开。
convert -sample %6400 tiny6pixel.ppm tiny6pixel.png
相同图像的 P6 格式将以一个字节(因此每个像素三个字节)的顺序存储每个像素的每个颜色分量,顺序为红色、绿色然后蓝色。文件将更小,但颜色信息对人类来说将不可读。
P6 #any comment string 3 2 255 !@#$%^&*()_+|{}:"<
PPM 格式未压缩,因此与压缩格式相比需要更多空间和带宽。例如,上面的 192x128 PNG 图像的文件大小为 187 字节。转换为 192x128 PPM 图像后,文件大小为 73848 字节。PPM 格式通常是用于图像处理的中间格式,然后转换为更有效的格式,例如 PNG (可移植网络图形) 格式。PPM 格式可以转换为 PNG,不会丢失信息。
PPM 格式当然很容易从头开始编写。以下 Python 代码生成了上面的示例图像。它可以通过读取或构建数值数据数组,并编写将数据转换为颜色三元组的转换来适应生成有用的图像。
#!/usr/bin/python
triplets=[ [255, 0, 0], [0, 255, 0], [0, 0, 255], [255, 255, 0], [255, 255, 255], [0, 0, 0] ]
width=3; height=2
comment='any comment string'
ftype='P6' #use 'P3' for ascii, 'P6' for binary
ppmfile=open('testimage.ppm','wb')
ppmfile.write("%s\n" % (ftype))
ppmfile.write("#%s\n" % comment )
ppmfile.write("%d %d\n" % (width, height))
ppmfile.write("255\n")
if ftype=='P3':
for red,green,blue in triplets:
ppmfile.write("%d %d %d\n" % (red,green,blue))
elif ftype=='P6': #print 1 byte per color
for red,green,blue in triplets:
ppmfile.write("%c%c%c" % (red,green,blue))
ppmfile.close()
类似的 C 代码
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define xor(a, b) (((!a && b)) || (a && !b))
int main (int argc, char * argv[]){
/* Declare the variables */
FILE* ppmFile;
int columns, rows, numberOfPixelsInPicture;
/* Check the input arguments */
if(argc != 4){
printf("Usage: %s cols rows fname.ppm\n\n", *argv);
return 1;
}
/* Open the file and write the first 4 lines to it */
ppmFile = fopen(argv[3], "w");
columns = atoi(argv[1]);
rows = atoi(argv[2]);
numberOfPixelsInPicture = rows * columns;
fprintf(ppmFile, "P3\n%d\n%d\n255\n", columns, rows);
int m, n;
for(m=0;m<rows;m++) {
for(n=0;n<columns;n++) {
/* Set the pixels in the bottom left of the picture a green-yellow color */
if(m>n) {
fprintf(ppmFile, "%d 255 %d\n", (256*m)/rows, (256*n)/columns);
} else if(xor((m/10)%2,(n/10)%2)) {
/* Create a checkerboard pattern in the upper-right of the picture */
/* Create the blue-red pixels in the checkerboard pattern */
fprintf(ppmFile, "%d 0 %d\n", (255*m*n)/numberOfPixelsInPicture, 255 -(255*m*n)/numberOfPixelsInPicture);
} else {
/* Create the black pixels in the checkerboard pattern */
fprintf(ppmFile, "0 0 0\n");
}
}
/* Print a blank line between rows */
fprintf(ppmFile, "\n");
}
fclose(ppmFile);
return 0;
}
汇编代码
; create a ppmb file by ker2x
; http://www.fractalforums.com/programming/an-absolute-beginner-to-x64-asm-on-linux/
: yasm -f elf64 ppmb.asm
; gcc -o ppmb ppmb.o
; ./ppmb | hexdump
segment .data
header: db 'P6 4 4 255', 0x0a
headerlen: equ $-header
image: db 255,0,0, 0,255,0, 0,0,255, 255,255,255
imagelen: equ $-image
segment .text
global main
main:
mov eax, 4
mov ebx, 1
mov ecx, header
mov edx, headerlen
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, image
mov edx, imagelen
int 0x80
mov eax, 4
int 0x80
mov eax, 4
int 0x80
mov eax, 4
int 0x80
; Call sys_exit(0)
mov eax, 1
xor ebx, ebx
int 0x80
C 代码
一种颜色的静态数组 : 在 C 中用于创建 pgm 文本文件的代码
#include <stdio.h>
int main(){
int iX,iY;
const int iXmax = 300;
const int iYmax = 300;
/* color is coded from 0 to 255 */
/* it is 8 bit color RGB file */
const int MaxColorComponentValue=255;
FILE * fp;
char *filename="m.pgm";
char *comment="# this is my new text pgm file "; /* comment should start with # */
static unsigned char color;
/*create new file,give it a name and open it in text mode */
fp= fopen(filename,"w"); /* text mode */
/*write ASCII header to the file*/
fprintf(fp,"P2\n%s\n%d %d\n%d\n",comment,iXmax,iYmax,MaxColorComponentValue);
/*write image data bytes to the file*/
for(iY=0;iY<iYmax;++iY){
for(iX=0;iX<iXmax;++iX){
color=150; /* compute pixel color (8 bit = 1 byte) */
fprintf(fp," %d ", color); /*write color to the file*/
}
fprintf(fp," \n ");
}
fclose(fp);
printf("OK\n");
getchar();
return 0;
}
编译它
gcc m.c
运行它
./a.out
记住
- fwrite 用于二进制文件
- fprintf 用于二进制文件和文本文件
因此,如果您想使用 fwrite,那么您将获得二进制文件(即使您以文本模式打开它)。
C 代码 : 用于整个图像的静态二维数组
#include <stdio.h>
int main(){
int iX,iY;
const int iXmax = 100;
const int iYmax = 100;
unsigned char data[iYmax][iXmax]; /* 2D array for colors ( shades of gray ) */
const int MaxColorComponentValue=255; /* color component is coded from 0 to 255 ; it is 8 bit color file */
FILE * fp;
char *filename="n.pgm";
char *comment="# this is my new binary pgm file";/* comment should start with # */
/* fill the data array */
for(iY=0;iY<iYmax;++iY){
for(iX=0;iX<iXmax;++iX){
data[iY][iX]=255;
}
}
}
/* write the whole data array to ppm file in one step */
fp= fopen(filename,"wb"); /*create new file,give it a name and open it in binary mode */
fprintf(fp,"P5\n %s\n %d %d\n %d\n",comment,iXmax,iYmax,MaxColorComponentValue); /*write header to the file*/
fwrite(data,sizeof data,1,fp); /*write image data bytes to the file*/
fclose(fp);
printf("OK - file %s saved\n", filename);
return 0;
}
C 代码 : 虚拟二维数组和动态一维数组
这里的图像是虚拟二维数组,但在程序中我们使用一维数组。
索引之间的关系
i = ix + iy*iWidth; // index of 1D array ix = i % iWidth; iy = (i- ix) / iWidth;
这是整个程序,我们只检查数组索引的范围,而没有使用显式数组
#include <stdio.h>
/* --------- global variables ----------------- */
// 2D array
// Indexes of array starts from 0 not 1
unsigned int ix, iy;
unsigned int ixMin = 0;
unsigned int ixMax = 3; //
unsigned int iWidth ; // = (ixMax -ixMin + 1) = 4
unsigned int iyMin = 0;
unsigned int iyMax = 3; //
unsigned int iHeight ; //= (iyMax -iyMin + 1) = 4
// The size of array has to be a positive constant integer
unsigned int i2Dsize ; // = iWidth*iHeight = 16
// 1D array
unsigned int i; // index of 1D array
unsigned int iMin = 0;
// Indexes of array starts from 0 not 1 so the highest elements of an array is = array_name[size-1].
unsigned int iMax ; // = i2Dsize-1; // = 15
// The size of array has to be a positive constant integer
unsigned int i1Dsize ; // = i2Dsize = (iMax -iMin + 1) = 16 ; 1D array with the same size as 2D array
/* ---------- functions ----------------*/
/* gives position of 2D point (iX,iY) in 1D array ; uses also global variable iWidth */
unsigned int f(unsigned int ix, unsigned int iy)
{ return ix + iy*iWidth; }
/* ---------------------- main ------------------*/
int main()
{
iWidth = (ixMax -ixMin + 1); //
iHeight = (iyMax -iyMin + 1); //
i2Dsize = iWidth*iHeight; // number of points in array
iMax = i2Dsize-1; // Indexes of array starts from 0 not 1 so the highest elements of an array is = array_name[size-1].
i1Dsize = i2Dsize; // 1D array with the same size as 2D array
// first method using 1D index i
for (i=iMin; i<i1Dsize; ++i) printf(" %d \n", i ); // from 0 to 15
// second method using 1D index i
for (i=iMin; i<=iMax ; ++i) printf(" %d \n", i ); // from 0 to 15
// check second method using 1D index i
for (i=iMin; i<=iMax ; ++i) // i from 0 to 15
{ ix = i % iWidth;
iy = ( i- ix) / iWidth; // inversion of f function
printf(" ix = %d ; iy = %d ; i = %d \n",ix , iy , i );}
// using 2D indexes : iy and ix
for(iy=iyMin;iy<=iyMax;++iy)
for(ix=ixMin;ix<=ixMax;++ix) printf(" ix = %d ; iy = %d ; i = %d \n", ix, iy, f(ix,iy) );
return 0;
}
用于二进制 B@W PBM 文件的 Lua 代码
-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall
local width = tonumber(arg and arg[1]) or 100
local height, wscale = width, 2/width
local m, limit2 = 50, 4.0
local write, char = io.write, string.char
write("P4\n", width, " ", height, "\n")
for y=0,height-1 do
local Ci = 2*y / height - 1
for xb=0,width-1,8 do
local bits = 0
local xbb = xb+7
for x=xb,xbb < width and xbb or width-1 do
bits = bits + bits
local Zr, Zi, Zrq, Ziq = 0.0, 0.0, 0.0, 0.0
local Cr = x * wscale - 1.5
for i=1,m do
local Zri = Zr*Zi
Zr = Zrq - Ziq + Cr
Zi = Zri + Zri + Ci
Zrq = Zr*Zr
Ziq = Zi*Zi
if Zrq + Ziq > limit2 then
bits = bits + 1
break
end
end
end
if xbb >= width then
for x=width,xbb do bits = bits + bits + 1 end
end
write(char(255-bits))
end
end
Python 代码
#!/usr/bin/python
# -*- coding: utf8 -*-
# code by User:Geek3
# https://commons.wikimedia.org/wiki/User:Geek3/ImageScripting
# use the PNM format (http://en.wikipedia.org/wiki/Netpbm_format)
# no need for external libraries
import colorsys
from math import *
width, height = 800, 600
# create header
image = open('pnm-example.ppm', 'w')
image.write('P3\n') # color image
image.write('{0} {1}\n'.format(width, height))
image.write('255\n')
def color(ix, iy):
'''return color for specific position'''
# create a rainbow ring
rx = (ix + 0.5 - width / 2.) / 100.
ry = (iy + 0.5 - height / 2.) / 100.
angle = pi + atan2(rx, ry)
amplitude = (rx**2 + ry**2) * exp(1 - (rx**2 + ry**2))
return colorsys.hsv_to_rgb(angle / (2*pi), amplitude, 1)
for iy in range(height):
for ix in range(width):
c = color(ix, iy)
image.write('{0} {1} {2}'.format(*[int(max(0, min(256*i, 255))) for i in c]))
if (ix < width - 1):
image.write(' ')
else:
image.write('\n')
image.close()
PFM(可移植浮点图)是 HDR 图像的非官方浮点 Netpbm 图像格式[10]
- Antoine Toisoul Le Cann 编写的 C++ 中的 PFM_ReadWrite 和 OpenCV 3 的版本
- wpfhtl 编写的读取和写入 pfm 文件,以及在 C++ 和 opencv 中查看它
- Paul Debevec 编写的 PFM 可移植浮点图图像格式
- 来自 netpbm 的 pfm 格式描述
- C++ 中的 pfm 和 OpenCV
- c++
- imageMagic 检查您是否具有 hdri 功能 : "identify -version" 并查找 hdri[11]
- 显示
- 创建
- gimp(2.8 不行,但 2.10 可以打开)
- darktable
- c
可移植浮点图 (PFM) 格式[12]
- 类似于 PPM / PGM / PBM
- 二进制文件
- 无压缩
- 这些文件中没有注释
结构
- 文本标题 = 3 行文本。三行文本中的每一行都以一个 1 字节的 Unix 风格的回车符结尾:十六进制中的 0x0a,而不是 Windows/DOS CR/LF 组合。
- 文件以 type = ASCII 字符 "PF" 或 "Pf" 开头。PF 表示它是彩色 PFM(3 通道 RGB 彩色图像)。Pf 表示它是灰度 PFM(单色单通道图像)。
- 下一行是分辨率 : 2 个整数 = "[xres] [yres]" 表示图像的 x 和 y 分辨率
- 最后一行包含单个浮点值:byte_order。
- 数据 : 每个像素三个浮点数(每个像素的一系列三个 4 字节 IEEE 754 单精度浮点数,以从左到右、从下到上的顺序指定)。
.pfm 文件的文本标题采用以下格式
[type] [xres] [yres] [byte_order]
使用 xxd 检查文件
xxd memorial.pfm|head
输出
00000000: 5046 0a35 3132 2037 3638 0a2d 312e 3030 PF.512 768.-1.00 00000010: 3030 3030 0a00 8020 3c00 001e 3b00 0038 0000... <...;..8
原始文件格式:[13]
- 二进制文件[14],这意味着您不能在文本编辑器中打开它,而只能在专用程序或十六进制编辑器中打开它
- 光栅文件[15]:"由像素(数据)值的顺序列表组成,按行描述,从顶行开始,从左到右工作。" [16]
- 未压缩
- 文件不包含任何图像格式信息,因此要使用原始文件,应了解其结构和大小
- 文件大小仅取决于图像尺寸和 像素数据格式
类型
- 数据(非颜色数据,需要处理)
- 静态图像(数据 = 颜色)
- 视频,如 Y4M
文档
来源
用于 RAW 编辑的库:
- libraw
- libvips
- ImageMagic rgb raw
- rawtherapee
使用 raw 格式的示例 Fractal 程序:
- K I Martin 编写的 SuperFractalThing(Java,跨平台)
- Kalles Fraktaler 由 Karl Runmo 编写,使用 kfb 地图文件
- kf-extras 用于处理 Kalles Fraktaler 2 输出的程序
- 曼德尔机器 by Botond Kósa
- mandelbulber(m3p文件仅包含参数,而.m3i文件还包含原始图像)
用于原始文件的图片编辑器[18]
- RGBE图像格式或Radiance HDR 是Gregory Ward Larson为Radiance渲染系统发明的图像格式。 它将像素存储为 RGB(红、绿、蓝)值的每个字节,以及一个共享的字节指数。 因此,它每像素存储四个字节。
- TIFF - 最高品质的栅格图像格式
- TIFF文件中的通道也可以使用任何 IEEE 754 浮点格式,包括 128 位格式,用于 RGB、YCbCr 和 CIE Lab* 格式的每个像素 384 位(48 字节)和 CMYK 格式的每个像素 512 位(64 字节)。 同样适用于任何 Alpha 通道[19]
- 支持无损压缩,在压缩过程中不会丢失任何图像数据。 也可以使用未压缩的 TIFF 图像。
- 支持 Alpha 通道(透明度)
- 它支持 YCbCr、RGB、CMYK 和 CIELab 色彩空间
- 并非所有网络服务或程序都支持它
- 打开速度较慢,文件较大
- libtiff - c 库和实用程序
Dot 文件 是描述 dot 语言中的图表的文本文件。 例如文件
digraph "BinaryAddingMachine" { a [shape=circle] b [shape=circle] a -> a [label="1/1",color=red]; a -> a [label="2/2",color=blue]; b -> a [label="1/2",color=red]; b -> b [label="2/1",color=blue]; }
可以使用命令行程序 dot 将此文件转换为其他格式。 例如,转换为 svg
dot -Tsvg b.dot -o b.svg
图像文件
- 带有嵌入元数据的 png 图像
- 带有嵌入元数据的 ppm 图像
- gif - 带有嵌入元数据的 FractInt 输出 http://www.nahee.com/spanky/www/fractint/fractint.html
- EXR 格式,OpenEXR,扩展名 .exr
OpenExr - 一种开放且非专有的扩展且高度动态范围 (HDR) 图像格式,保存 Alpha 和 Z 深度缓冲区信息。
描述
exr 文件格式
- 标准: OpenExr
- 扩展名:exr
- 颜色始终以场景线性颜色空间存储,不会丢失任何数据。 这使得它们适合存储渲染,这些渲染可以稍后进行合成、颜色分级并转换为不同的输出格式。[20]
- 文件还可以包含实际上不是颜色的数据。 例如,法线贴图或置换贴图仅包含向量和偏移量。 此类图像应标记为非颜色数据,以便不会对它们进行颜色空间转换。
程序
- exrtact - 用于操作 EXR 图像的各种工具
- HDR + WCG 图像查看器 by Simon Tao
- Commons 中使用的视频格式
- GNU Parallel[21]
- 转换视频
- ffmpeg2theora 参数列表
- 二次 Julia 集的视频
- 二次 Mandelbrot 集的视频
- FFMPEG 文件格式
使用 BASH 和 Image Magic 将 pgm(或其他)静态文件转换为动画 gif:[22]
#!/bin/bash
# script file for BASH
# which bash
# save this file as g
# chmod +x g
# ./g
# for all pgm files in this directory
for file in *.pgm ; do
# b is name of file without extension
b=$(basename $file .pgm)
# convert from pgm to gif and add text ( level ) using ImageMagic
convert $file -pointsize 100 -annotate +10+100 $b ${b}.gif
echo $file
done
# convert gif files to animated gif
convert -delay 100 -loop 0 %d.gif[0-24] a24.gif
echo OK
# end
或者由 ClaudiusMaximus 提供的另一个版本[23]
for i in ??.svg
do
rsvg $i ${i%svg}png
convert ${i%svg}png ${i%svg}gif
done
gifsicle --delay 4 --loop --optimize ??.gif > out.gif
不要忘记: 12.5MP 限制 = 500 x 500 x 50 帧 = 600 x 600 x 34 帧 = 1000 x 1000 x 12 帧
从 pgm 到视频使用 Image Magic convert 的步骤
- pgm 文件到 gif 文件
- gif 文件到视频
convert -delay 100 -loop 0 %d.gif[0-25] a25.mpg
#!/bin/bash
# script file for BASH
# which bash
# save this file as g
# chmod +x g
# ./g
i=0
# for all pgm files in this directory
for file in *.pgm ; do
# b is name of file without extension
b=$(basename $file .pgm)
# change file name to integers and count files
((i= i+1))
# convert from pgm to gif and add text ( Cx from name of file ) using ImageMagic
convert $file -pointsize 50 -annotate +10+100 $b ${i}.gif
echo $file
done
echo convert all gif files to one ogv file
ffmpeg2theora %d.gif --framerate 12 --videoquality 9 -o output129.ogv
echo b${i} OK
# end
可以从图像制作视频。 例如
使用 ffmpeg 创建 WebM 视频文件[24][25]
ffmpeg -i x%08d.png -r 24 tifa.webm
或 ffmpeg2theora
ffmpeg2theora %d.gif --framerate 5 --videoquality 9 -f webm --artist "your name" -o otput.webm
如果您使用包含参数(此处为 Cx)的 名称 文件,那么对文件进行排序并制作视频会很容易
char name [10]; /* name of file */
i = sprintf(name,"%2.7f",Cx); /* result (is saved in i) but is not used */
char *filename =strcat(name,".pgm"); /* new name thru concatenate of strings */
- YUV4Mpeg 格式的视频文件
- 压缩成其他格式之前的原始视频[26]
- 元数据
- exif
- 注释
- 块
- ICC
- 单独文件
- 参数文件
- 单独文本文件
颜色配置文件 (ICC) 在图像中的存储方式取决于图像格式
- 例如,在 PNG 中,它包含在 PNG iCCP 块中
- 在 JPEG 中,它存储在特定的“标记”中
- 对于其他图像格式,请参见 http://www.color.org/profile_embedding.xalter
- pngmeta[27]
使用 Image Magic
- 评论
- 转义[29]
Image Magic 可以使用 mogrify 将评论添加到 png 图像中:[30]
mogrify -comment "My test comment" p.png
或使用 convert :[31]
convert in.png \
-set 'Copyright' 'CC-BY-SA 4.0' \
-set 'Title' 'A wonderful day' \
-set comment 'Photo taken while running' \
out.png
从 png 中读取评论
identify -verbose p.png | grep -i "comment:"
comment: My test comment
或
identify -format "%c" X.ppm
块是信息片段,用于许多多媒体格式,例如 PNG、IFF、MP3 和 AVI。每个块都包含一个标头,它指示一些参数(例如块类型、注释、大小等)。中间有一个可变区域,包含由程序从标头中的参数解码的数据。 [32]
文本块是标准辅助 PNG 块之一。它的名称是 tEXt。 [33]
PNG 文本块的标准关键字
Title Short (one line) title or caption for image Author Name of image's creator Description Description of image (possibly long) Copyright Copyright notice Creation Time Time of original image creation Software Software used to create the image Disclaimer Legal disclaimer Warning Warning of nature of content Source Device used to create the image Comment Miscellaneous comment; conversion from GIF comment
ImageMagick 目前已知的辅助块有 bKGD、cHRM、gAMA、iCCP、oFFs、pHYs、sRGB、tEXt、tRNS、vpAg 和 zTXt。
使用 **Image Magic 的 convert** 的示例
convert in.png -define png:include-chunk=tEXt file.txt out.png
可以使用 **pnmtopng** 实用程序
pnmtopng -text file.txt 1000.pgm > 1000.png
其中文本文件 file.txt 为
Title Short (one line) title or caption for image Author Name of image's creator Description Description of image (possibly long) Copyright Copyright notice Creation Time Time of original image creation Software Software used to create the image Disclaimer Legal disclaimer Warning Warning of nature of content Source Device used to create the image Comment Miscellaneous comment; conversion from GIF comment
png-text-embaded[34]
保存 pgm 文件和一些图像描述的文本文件
// save "A" array to pgm file and info txt file
int SaveArray2PGMFile( unsigned char A[], double k, char* text)
{
FILE * fp;
const unsigned int MaxColorComponentValue=255; /* color component is coded from 0 to 255 ; it is 8 bit color file */
char name [100]; /* name of file , error Naruszenie ochrony pamięci */
snprintf(name, sizeof name, "%f", k); /* */
char *filename =strncat(name,".pgm", 4);
char *comment="# ";/* comment should start with # */
/* save image to the pgm file */
fp= fopen(filename,"wb"); /*create new file,give it a name and open it in binary mode */
fprintf(fp,"P5\n %s\n %u %u\n %u\n",comment,iWidth,iHeight,MaxColorComponentValue); /*write header to the file*/
fwrite(A,iLength,1,fp); /*write A array to the file in one step */
printf("File %s saved. \n", filename);
fclose(fp);
// save info text filename
filename =strcat(name,".txt");
fp= fopen(filename,"wb");
fprintf(fp,"This image shows rectangle part of dynamic plane of discrete complex dynamical system z(n+1) = fc(zn) \n");
fprintf(fp," where fc(z)= z^2 + c \n");
fprintf(fp,"with numerical approximation of parabolic Julia set \n\n");
fprintf(fp,"parameter c is a root point between iPeriodParent = %d and iPeriodOfChild = %d hyperbolic components of Mandelbrot set \n", iPeriodParent , iPeriodChild);
fprintf(fp,"on the end of the internal ray of parent component of Mandelbrot set with angle = 1/%d in turns \n", iPeriodChild);
fprintf(fp," c = ( %f ; %f ) \n", Cx, Cy);
fprintf(fp," \n");
fprintf(fp,"critical point z = Zcr= ( %f ; %f ) \n", creal(Zcr), cimag(Zcr));
fprintf(fp,"parabolic alfa fixed point z = ZA = ( %f ; %f ) \n", creal(ZA), cimag(ZA));
fprintf(fp," radius around parabolic fixed point AR = %.16f ; Pixel width = %.16f \n", AR, PixelWidth);
fprintf(fp," iMaxN = %d ; ARn = %.16f \n",iMaxN, ARn); // info
fprintf(fp," EscapeRadius ER = %f ; \n", EscapeRadius);
fprintf(fp," Fatou coordinate U(Zcr) = Ux0 = %f ; \n", Ux0);
fprintf(fp," Maxima number of iterations : iMax = %d \n\n", iMax);
fprintf(fp," Image shows rectangular part of dynamic plane with %s\n", text);
fprintf(fp," from ZxMin = %f to ZxMax = %f\n", ZxMin, ZxMax);
fprintf(fp," from ZyMin = %f to ZyMax = %f\n\n", ZyMin, ZyMax);
fprintf(fp," iWidth = %d and iHeight = %d\n", iWidth, iHeight);
fprintf(fp," distortion = %f ; It should be 1.0 \n", ((ZxMax-ZxMin)/(ZyMax -ZyMin)/(iWidth/iHeight)));
if (t==0) fprintf(fp," No lost pixels : t = %d ; Parameters iMax and AR are good \n",t);
else fprintf(fp," Error : there are lost pixels : t > 0 ; you should increase iMax or make bigger AR \n\n");
fprintf(fp," computations made with double type numbers \n\n");
fprintf(fp,"use (k+AR) for file names where k is a number of file ; range(k) =[0,k] so there are (k+1) png files nad (k+1) text files \n\n");
fprintf(fp,"made with c console program \n");
//
printf("File %s saved. \n", filename);
fclose(fp);
return 0;
}
A parameter file is a small text file which contains all the settings required to produce a particular image ( Gnofract4D)
参数可以从参数文件和图像文件读取 :[35]
参数文件
- fct 扩展名由 Gnofract 4D 使用
- .fzs 扩展名由 Fractal Zoomer (二进制文件)使用
- F3 或 f3.toml 由 fractaler-3 程序 使用
- kfr 扩展名由 Kalles Fraktaler 2 http://www.chillheimer.de/kallesfraktaler/ 使用
- mdz 扩展名由 Mandelbrot Deep Zoom 使用
- mm 扩展名由 mightymandel 使用
- mmit 扩展名由 Mandel Machine 使用
- mp 扩展名由 mandelbrot-perturbator 使用
- m3p 扩展名由 Mandelbulb3D 使用
- par 扩展名由 Fractint 使用
- sft 扩展名由 SuperFractalThing 使用
- upr 扩展名由 UltraFractal 使用
- XML 扩展名由 David Eck Java 程序 用于保存 Mandelbrot 设置
<mandelbrot_settings_2>
<image_size width="800" height="600"/>
<limits>
<xmin>-1.368156475175454059721</xmin>
<xmax>-1.368156475171886859735</xmax>
<ymin>0.001591278471916748399</ymin>
<ymax>0.001591278474592148387</ymax>
</limits>
<palette colorType="RGB">
<divisionPoint position="0" color="0.7909;0.9961;0.763"/>
<divisionPoint position="0.1667" color="0.8974;0.8953;0.6565"/>
<divisionPoint position="0.3333" color="0.9465;0.3161;0.1267"/>
<divisionPoint position="0.5" color="0.5184;0.1109;0.0917"/>
<divisionPoint position="0.6667" color="0.0198;0.4563;0.6839"/>
<divisionPoint position="0.8333" color="0.5385;0.8259;0.8177"/>
<divisionPoint position="1" color="0.7909;0.9961;0.763"/>
</palette>
<palette_mapping length="250" offset="96"/>
<max_iterations value="50000"/>
</mandelbrot_settings_2>
另请参见
/*
from gui main.c
https://gitorious.org/maximus/book/source/47ce485c4266b3d5fc62f685f001ce7606ce426f:
by
http://mathr.co.uk/blog/
loads txt file with parameters
http://qualapps.blogspot.com/2009/01/unicode-bom-handling-in-c-run-time.html
http://www.joelonsoftware.com/articles/Unicode.html
http://programmers.stackexchange.com/questions/102205/should-utf-16-be-considered-harmful
http://utf8everywhere.org/
http://www.codeguru.com/cpp/misc/misc/multi-lingualsupport/article.php/c10451/The-Basics-of-UTF8.htm
http://stackoverflow.com/questions/2113270/how-to-read-unicode-utf-8-binary-file-line-by-line
http://www.cl.cam.ac.uk/~mgk25/unicode.html
gcc l.c -lmpfr -lgmp -Wall
*/
#include <stdio.h>
#include <stdlib.h> // malloc
#include <string.h> // strncmp
#include <ctype.h> // isascii
#include <mpfr.h>
struct view {
mpfr_t cx, cy, radius, pixel_spacing;
};
static struct view *view_new() {
struct view *v = malloc(sizeof(struct view));
mpfr_init2(v->cx, 53);
mpfr_init2(v->cy, 53);
mpfr_init2(v->radius, 53);
mpfr_init2(v->pixel_spacing, 53);
return v;
}
static void view_delete(struct view *v) {
mpfr_clear(v->cx);
mpfr_clear(v->cy);
mpfr_clear(v->radius);
mpfr_clear(v->pixel_spacing);
free(v);
}
//http://stackoverflow.com/questions/5457608/how-to-remove-a-character-from-a-string-in-c?rq=1
// Fabio Cabral
void removeChar(char *str, char garbage) {
char *src, *dst;
for (src = dst = str; *src != '\0'; src++) {
*dst = *src;
if (*dst != garbage) dst++;
}
*dst = '\0';
}
//wikipedia : Serialization
// read data from file
static int deserialize(const char *filename) {
// open file in a text mode
FILE *in = fopen(filename, "r");
if (in) {
printf( "file %s opened\n", filename);
char *line = 0;
size_t linelen = 0;
ssize_t readlen = 0; // bytes_read = length of the line
// read line
while (-1 != (readlen = getline(&line, &linelen, in)))
{
//
if (readlen && line[readlen-1] == '\n') {
line[readlen - 1] = 0; }
// remove BOM
while (! isascii(line[0]))
{printf(" removed non-printing char = %c ( non -ASCII char ) = %3d (signed 8 bit) = %u (unsigned 8 bit) = 0x%.2X (hexadecimal) \n", line[0], line[0], (unsigned char) line[0], (unsigned char) line[0]);
removeChar(line,line[0]);
}
// size
if (0 == strncmp(line, "size ", 5))
{
printf( "size line found :");
int w = 0, h = 0;
sscanf(line + 5, "%d %d\n", &w, &h);
printf( "size of image in pixels : width = %d ; height = %d \n", w,h);
// resize_image(w, h); // FIXME TODO make this work...
}
// view
else if (0 == strncmp(line, "view ", 5))
{
printf( "view line found : \n");
int p = 53;
char *xs = malloc(readlen);
char *ys = malloc(readlen);
char *rs = malloc(readlen);
sscanf(line + 5, "%d %s %s %s", &p, xs, ys, rs);
struct view *v = view_new();
mpfr_set_prec(v->cx, p);
mpfr_set_prec(v->cy, p);
mpfr_set_str(v->cx, xs, 0, GMP_RNDN);
mpfr_set_str(v->cy, ys, 0, GMP_RNDN);
mpfr_set_str(v->radius, rs, 0, GMP_RNDN);
//
printf ("precision p = %d\n", p);
printf ("center = ");
mpfr_out_str (stdout, 10, p, v->cx, MPFR_RNDD);
printf (" ; ");
mpfr_out_str (stdout, 10, p, v->cy, MPFR_RNDD);
putchar ('\n');
printf ("radius = ");
mpfr_out_str (stdout, 10, p, v->radius, MPFR_RNDD);
putchar ('\n');
free(xs);
free(ys);
free(rs);
view_delete(v);
}
else if (0 == strncmp(line, "ray_out ", 8))
{
printf( "ray_out line found :\n");
int p = 53;
char *xs = malloc(readlen);
char *ys = malloc(readlen);
sscanf(line + 8, "%d %s %s", &p, xs, ys);
mpfr_t cx, cy;
mpfr_init2(cx, p);
mpfr_init2(cy, p);
mpfr_set_str(cx, xs, 0, GMP_RNDN);
mpfr_set_str(cy, ys, 0, GMP_RNDN);
free(xs);
free(ys);
mpfr_clear(cx);
mpfr_clear(cy);
}
else if (0 == strncmp(line, "ray_in ", 7)) {
printf( "ray_in line found : \n");
int depth = 1000;
char *as = malloc(readlen);
sscanf(line + 7, "%d %s", &depth, as);
free(as);
}
else if (0 == strncmp(line, "text ", 20)) {
printf( "text line found : \n");
//int p = 53;
char *xs= malloc(readlen);
char *ys = malloc(readlen);
char *ss = malloc(readlen);
sscanf(line + 20, "%s %s %s \n", xs, ys, ss);
free(xs);
free(ys);
free(ss);
}
else if (0 == strncmp(line, "//", 2 )) {
printf( "line of comment found : %s\n", line );
}
else printf( "not-known line found ! Maybe line with BOM ? \n");
} // while
free(line);
fclose(in);
printf( "file %s closed\n", filename);
return 0;}
// if (in)
else {
printf( "file %s not opened = error !\n", filename);
return 1;}
}
int main (int argc, const char* argv[])
{
if (argc != 2) {
fprintf(stderr, "program opens text file \n");
fprintf(stderr, "program input : text file with parameters \n");
fprintf(stderr, "usage: %s filename\n", argv[0]);
return 1;
}
deserialize(argv[1]);
return 0;
}
这个程序
- 打开二进制 ppm (P6) 或 pgm (P5) 文件
- 它不打开这些文件的 ASCII 版本。
它可用于通过检查鼠标移动时控制台中的输出来检查图像。将您的代码添加到 Motion 函数并更新 Zxmin 和 Zymin(世界坐标)。
它不适用于最新版本的 OpenGl。
/*
* image.c
*
* read in a PPM or PGM binary image and display it, full size
Based on code by :
Dr. Lori L. Scarlatos
Stony Brook University
http://ms.cc.sunysb.edu/~lscarlatos/
"I do not have a license for image.c;
it was created as an example for my students.
Please feel free to use it.
Best regards,
Lori"
* ----------------------------
* it does not opens asci versions of these files
* examples files :
* http://people.sc.fsu.edu/~jburkardt/data/data.html
http://web.eecs.umich.edu/~sugih/courses/eecs487/glut-howto/sample.c
// gcc v.c -lm -lGLU -lglut -Wall // ? windows
gcc v.c -lm -lglut -lGL -lGLU -Wall // ubuntu
./a.out 5.pgm
*/
/*
locate glut.h
/usr/include/GL/freeglut.h
/usr/include/GL/glut.h
#ifdef FREEGLUT
#include <GL/freeglut.h>
#else
#include <GL/glut.h>
#endif
*/
//#include <Windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
//#include <GL/glut.h> // oryginal glut
#include <GL/freeglut.h> // freeglut
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h> /* fabs*/
//#include <malloc.h>
/* Global variables */
#define MAXLINE 80 /* maximum length of a line of text */
/*
3.2 Conventions
In developing the freeglut library, we have taken careful steps to ensure consistency in function operation across the board,
in such a manner as to maintain compatibility with GLUT's behavior whenever possible. In this section some of the important conventions of FreeGLUT,
and their compatibility with GLUT, are made explicit.
3.2.1 Window placement and size
There is considerable confusion about the "right thing to do" concerning window size and position. GLUT itself is not consistent between Windows and UNIX/X11;
since platform independence is a virtue for freeglut, we decided to break with GLUT's behaviour.
Under UNIX/X11, it is apparently not possible to get the window border sizes in order to subtract them off the window's initial position until some time after the window has been created.
Therefore we decided on the following behavior, both under Windows and under UNIX/X11:
When you create a window with position (x,y) and size (w,h), the upper left hand corner of the outside of the window (the non-client area) is at (x,y) and the size of the drawable (client) area is (w,h).
The coordinates taken by glutInitPosition and glutPositionWindow, as well as the coordinates provided by FreeGLUT when it calls the glutPositionFunc callback, specify the top-left of the non-client area of the window.
When you query the size and position of the window using glutGet, FreeGLUT will return the size of the drawable area
--the (w,h) that you specified when you created the window
--and the coordinates of the upper left hand corner of the drawable (client) area
--which is NOT the (x,y) position of the window you specified when you created it.
*/
GLint ImageWidth, ImageHeight; /* size of the Image in pixels */
GLint WindowWidth, WindowHeight; /* size of the window in pixels */
GLint MaxScreenWidth, MaxScreenHeight; /* size of the screen in pixels */
GLubyte *Picture; /* Array of colors (GLubyte) */
int size;
// mouse position as a global variables
//static float mx=0.0f,my=0.0f ;
int iX, iY; //
int centerX = 200, centerY = 200;
GLint iYmax,iXmax; // mouse coordinate inside image
unsigned char pixel[3];
// change it manually !!!!!
const double ZyMin=-1.0;
const double ZxMin=-2.0;
const double PixelHeight=0.0020010005002501 ;
const double PixelWidth=0.0020010005002501 ;
int filetype;
enum {P2, P3, P5, P6}; /* possible file types */
/* gives position of point (iX,iY) in 1D array ; uses also global variables */
unsigned int f(unsigned int _iX, unsigned int _iY)
{return (_iX + (iYmax-_iY-1)*iXmax );}
/*
* Read from a PPM or PGM (binary) file
* Output is a array of GLubyte
*/
void readPPM (char *filename, GLubyte **pic) {
FILE *fp;
char line[MAXLINE];
int i, rowsize;
// int size; // moved to global var
int j ;
GLubyte *ptr;
/* Read in file type */
fp = fopen(filename, "r"); /* in Unix rb = r */
if (fp==NULL) {perror(" perror : " ); printf("Error from fopen : I can't open %s file' ! ", filename); exit(1); }
else printf("File %s has been opened !\n", filename);
/* Each file starts with aa two-byte magic number (in ASCII) that explains :
* - the type of file it is (PBM, PGM, and PPM)
* - its encoding (ASCII or binary).
* The magic number is a capital P followed by a single digit number.
*/
fgets (line, MAXLINE, fp); /* 1st line : Magic Number */
switch (line[1])
{
case '2':
filetype = P2;
printf("This is PGM text file (P2), but now I do not have procedure for opening it \n");
break;
case '3' :
filetype = P3;
printf("This is PPM text file (P3), but now I do not have procedure for opening it !\n");
break;
case '5':
filetype = P5;
printf("This is PGM binary file (P5) and I can open it !\n");
break;
case '6' :
filetype = P6;
printf("This is PPM binary file (P6) and I can open it !\n");
break;
default :
printf("Error from readPPM : need binary PPM or binary PGM file as input!\n");
exit(1);
}
/* if this is a comment, read next line. Maybe in binary files there is no comment ?*/
/* there maybe more then one line of comment */
fgets (line, MAXLINE, fp);
while (line[0]=='#')
{ printf(" comment = %s \n", line); /* 2nd or more line starting with # = comment, print it */
fgets (line, MAXLINE, fp); // read next line
}
/* Read in width and height, & allocate space */
/* these 2 numbers should be in one line with space between them */
/* 3nd line: width and height */
sscanf(line, "%d %d", &ImageWidth, &ImageHeight);
printf ("iWidth = %d\n", ImageWidth);
printf ("iHeight = %d\n", ImageHeight);
iXmax=ImageWidth-1;
iYmax=ImageHeight-1;
if (filetype == P5) {
size = ImageHeight * ImageWidth; /* greymap: 1 byte per pixel */
rowsize = ImageWidth;
}
else /* filetype == P6 */ {
size = ImageHeight * ImageWidth * 3; /* pixmap: 3 bytes per pixel */
rowsize = ImageWidth * 3;
}
*pic = (GLubyte *)malloc (size); /* create dynamic array */
/* Read in maximum value (ignore) */
fgets (line, MAXLINE, fp); /* next line */
/* */
if (filetype==P5 || filetype==P6){
/* Read in the pixel array row-by-row: 1st row = top scanline */
ptr = *pic + (ImageHeight-1) * rowsize;
for (i = ImageHeight; i > 0; i--) {
/* For binary File I/O you use fread and fwrite */
j = fread((void *)ptr, 1, rowsize, fp);
ptr -= rowsize;
}
if (j) printf("File %s has been read !\n", filename);
else printf(" j Error from readPPM procedure : I can't read %d file !.\n", j);
}
else printf("Error from readPPM procedure : I can't read %s file !. It should be P5 or P6 file !\n", filename);
fclose(fp);
printf("File %s has been closed !\n", filename);
}
/* Draw the picture on the screen */
void Draw(void) {
/* black background of GLUT window */
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to black
glClear(GL_COLOR_BUFFER_BIT); //Clear the colour buffer (more buffers later on)
glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations
glFlush(); // Flush the OpenGL buffers to the window
// left lower corner of displayed image
glRasterPos2i(-1,-1); // By default, OpenGL assumes a system running from -1 to 1,
switch (filetype){
case P5 : /* greymap: use as illumination values */
glDrawPixels(ImageWidth, ImageHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, Picture);
printf("P5 Image has been drawn !\n");
break;
case P6 :
glDrawPixels(ImageWidth, ImageHeight, GL_RGB, GL_UNSIGNED_BYTE, Picture);
printf("P6 Image has been drawn !\n");
break;
default :
printf("Error from Draw procedure : There is no image to draw !\n");
}
}
// Detecting Mouse Clicks
// x and y specify the location (in window-relative coordinates) of the mouse when
// the event occurred
void MouseClicks (int button, int state, int x, int y)
{
switch (button)
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN)
// do something
case GLUT_RIGHT_BUTTON: ;
// etc., etc.
}
// mouse motion
//The x and y callback parameters
// indicate the mouse location
// in window relative coordinates
//
// x, y –> coordinates of the mouse relative to upper left corner of window
// setting the mouse position to be relative to the mouse
// position inside the window
//
void PassiveMouseMotion(int x, int y) {
//double Zx,Zy;
//double Ux;
//int index;
//GLubyte Gray;
// put your code here ????
iX = x;
/* invert y axis */
iY = WindowHeight - y -1 ; //+ (glutGet(GLUT_WINDOW_HEIGHT) - ImageHeight); ///glutGet(GLUT_WINDOW_HEIGHT) - y; // ????
/* output : prints to console */
if ((filetype==P5 || filetype==P6) && -1<iX && iX< ImageWidth && iY<ImageHeight) // && iY<ImageHeight
{
glReadPixels(iX, iY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
// pixel coordinates of the mouse relative to upper left corner of window
printf(" pixel iX=%3d / %d ; iY=%3d color = %d \n", iX, MaxScreenWidth, iY, pixel[1] );
}
}
static void Key(unsigned char key, int x, int y)
{
switch (key) {
case 27 : {glutLeaveFullScreen(); break;}/* esc */
case 'f': {glutFullScreen(); break; }
case 'q': {printf("Key preseed and exit \n"); exit(1) ;}
case 'Q': {printf("Key preseed and exit \n"); exit(1) ;}
case 't': {glutFullScreenToggle(); break; } // GLUT does not include the glutLeaveFullScreen and glutFullScreenToggle functions from freeglut
default: return ;
}
}
/*
Resize the picture ; OpenGL calls this function whenever the window is resized
Called when window is resized, also when window is first created, before the first call to display().
*/
void Reshape(GLint w, GLint h) {
/* save new screen dimensions */
WindowWidth = w;
WindowHeight = h;
/* the viewport is the rectangular region of the window where the image is drawn */
// Viewport : A rectangular region in the screen for display (in screen coordinate system)
glViewport(0, 0, ImageWidth-1, ImageHeight-1); // glViewport( 0.f, 0.f, SCREEN_WIDTH, SCREEN_HEIGHT );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Define a world window : A rectangular region in the world that is to be displayed (in world coordinate system)
// By default, OpenGL assumes a system running from -1 to 1,
gluOrtho2D(-1, 1, -1, 1); // An orthographic projection is basically a 3D projection that does not have perspective
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/*
Initialization: create window
glutInitWindowSize(600, 600);
*/
void MyInit(int argc, char *argv[]) {
char filename[MAXLINE];
/* Read in the file (allocates space for Picture) */
if (argc < 2)
{
printf ("Enter the name of a binary PPM or PGM file: ");
scanf("%s", filename);
readPPM ((char *)filename, &Picture);
}
else { readPPM (argv[1], &Picture); }
glutInit(&argc, argv);
MaxScreenWidth = glutGet(GLUT_SCREEN_WIDTH);
MaxScreenHeight = glutGet(GLUT_SCREEN_HEIGHT);
glutInitWindowPosition(-1, 1); // upper left corner
glutInitWindowSize(MaxScreenWidth, MaxScreenHeight ); // full screen of my monitor
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
if (glutCreateWindow("OpenGl binary pgm/ppm Image viewer ") == GL_FALSE)
{printf("Error from MyInit , glutCreateWindow\n"); exit(1);}
}
/* ------------------ Main program ---------------------------------------*/
int main(int argc, char **argv)
{
MyInit(argc, argv);
glutPassiveMotionFunc(PassiveMouseMotion); // mouse move with no key pressed
glutReshapeFunc(Reshape); // move or resize of screen window
glutDisplayFunc(Draw); //
glutKeyboardFunc(Key);
//
glutMainLoop();
return 0;
}
- ↑ Artem Dudko 和 Michael Yampolsky 的 Feigenbaum Julia 集的可计算性
- ↑ admvfx : Benjamin Seide 的文件格式和位深度
- ↑ a b "AV1 Image File Format (AVIF)". AOMediaCodec.GitHub.io. Archived from the original on 29 November 2018. Retrieved 25 November 2018.
- ↑ Mavlankar, Aditya; De Cock, Jan; Concolato, Cyril; Swanson, Kyle; Moorthy, Anush; Aaron, Anne (2020-02-13). "AVIF for Next-Generation Image Coding". The Netflix Tech Blog. Archived from the original on 2020-02-15. Retrieved 2021-11-19.
- ↑ "AOMediaCodec / av1-avif". GitHub. Retrieved 2022-02-05.
- ↑ a b Concolato, Cyril (2019年10月14日). "AV1 Image File Format (AVIF)" (PDF). AOMedia. Archived (PDF) from the original on 5 November 2019. Retrieved 6 November 2019.
- ↑ "Film Grain Synthesis for AV1 Video Codec" (PDF). Archived (PDF) from the original on 7 January 2021. Retrieved 14 December 2020.
- ↑ 位深度色彩精度在光栅图像中 (Denis Kozlov 著)
- ↑ 计算机语言基准测试游戏
- ↑ Nayuki 的可移植浮点映射格式 I/O Java
- ↑ imagemagick : 高动态范围
- ↑ HDR by Josef Pelikán & Alexander Wilkie
- ↑ [:w:Raw image format|维基百科中的原始图像格式]
- ↑ 维基百科:二进制文件
- ↑ 维基百科:图像文件格式 - 光栅格式
- ↑ 分形图像压缩的并行实现 By Ryan F. UYS
- ↑ rawpedia - RawTherapee、raw 拍摄和所有 raw 内容的百科全书
- ↑ itsfoss : Linux 上的 raw 图像工具
- ↑ photo.stackexchange 问题:TIFF 的质量真的比 PNG-24 高吗?
- ↑ blender 手册:色彩管理
- ↑ Gnu Parallel
- ↑ Fritz Mueller 的梅比乌斯变换动画 GIF
- ↑ ReCode 项目 - ClaudiusMaximus 的地形形式动画
- ↑ Mukund 的制作视频方法
- ↑ Yannick Gingras 的 Lisp 中的 mini-fract
- ↑ fileinfo : 扩展名 y4m
- ↑ pngmeta
- ↑ PNG 和 exif
- ↑ Image Magic - escape
- ↑ Stackoverflow : 如何向 PNG 添加额外的元数据?
- ↑ Stackoverflow : 如何将文本块插入 PNG 图像?
- ↑ 维基百科 : 块(信息)
- ↑ PNG(便携式网络图形)规范,版本 1.2 : 块
- ↑ https://github.com/gbenison/png-text-embed
- ↑ Mightymandel 文档