跳转到内容

分形/计算机图形技术/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 容器格式。[


图形文件格式比较

[编辑 | 编辑源代码]

图像的大小和分辨率



按精度排列的图形文件格式[2]
格式 支持的位深 在动画和 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 的支持

光栅文件

[编辑 | 编辑源代码]
Ilya Voyager 的 PGM 图像文件和 C++ 程序

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
// 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);
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]


可移植浮点图 (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]
  • 未压缩
  • 文件不包含任何图像格式信息,因此要使用原始文件,应了解其结构和大小
  • 文件大小仅取决于图像尺寸和 像素数据格式


类型

  • 数据(非颜色数据,需要处理)
  • 静态图像(数据 = 颜色)
    • 非照片图像 = 由计算机创建的图像
    • 照片 = 来自数码相机的图像。[17] 它需要去马赛克
      • DNG
      • HEIC
      • RAW Canon 的 CR3
      • 尼康的 NEF
      • 索尼的 ARW
  • 视频,如 Y4M

文档

来源

用于 RAW 编辑的库:

使用 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图像格式

[编辑 | 编辑源代码]
  • 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

带有元数据的图像文件

[编辑 | 编辑源代码]

图像文件


OpenExr - 一种开放且非专有的扩展且高度动态范围 (HDR) 图像格式,保存 Alpha 和 Z 深度缓冲区信息。

描述

exr 文件格式

  • 标准: OpenExr
  • 扩展名:exr
  • 颜色始终以场景线性颜色空间存储,不会丢失任何数据。 这使得它们适合存储渲染,这些渲染可以稍后进行合成、颜色分级并转换为不同的输出格式。[20]
  • 文件还可以包含实际上不是颜色的数据。 例如,法线贴图或置换贴图仅包含向量和偏移量。 此类图像应标记为非颜色数据,以便不会对它们进行颜色空间转换。


程序

动态图像

[编辑 | 编辑源代码]

动画 gif

[编辑 | 编辑源代码]

使用 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) 在图像中的存储方式取决于图像格式


元数据

[编辑 | 编辑源代码]

使用 Image Magic 

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]

参数文件 


<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;
}

另请参见

[编辑 | 编辑源代码]

参考资料

[编辑 | 编辑源代码]
  1. Artem Dudko 和 Michael Yampolsky 的 Feigenbaum Julia 集的可计算性
  2. admvfx : Benjamin Seide 的文件格式和位深度
  3. a b "AV1 Image File Format (AVIF)". AOMediaCodec.GitHub.io. Archived from the original on 29 November 2018. Retrieved 25 November 2018.
  4. 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.
  5. "AOMediaCodec / av1-avif". GitHub. Retrieved 2022-02-05.
  6. 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.
  7. "Film Grain Synthesis for AV1 Video Codec" (PDF). Archived (PDF) from the original on 7 January 2021. Retrieved 14 December 2020.
  8. 位深度色彩精度在光栅图像中 (Denis Kozlov 著)
  9. 计算机语言基准测试游戏
  10. Nayuki 的可移植浮点映射格式 I/O Java
  11. imagemagick : 高动态范围
  12. HDR by Josef Pelikán & Alexander Wilkie
  13. [:w:Raw image format|维基百科中的原始图像格式]
  14. 维基百科:二进制文件
  15. 维基百科:图像文件格式 - 光栅格式
  16. 分形图像压缩的并行实现 By Ryan F. UYS
  17. rawpedia - RawTherapee、raw 拍摄和所有 raw 内容的百科全书
  18. itsfoss : Linux 上的 raw 图像工具
  19. photo.stackexchange 问题:TIFF 的质量真的比 PNG-24 高吗?
  20. blender 手册:色彩管理
  21. Gnu Parallel
  22. Fritz Mueller 的梅比乌斯变换动画 GIF
  23. ReCode 项目 - ClaudiusMaximus 的地形形式动画
  24. Mukund 的制作视频方法
  25. Yannick Gingras 的 Lisp 中的 mini-fract
  26. fileinfo : 扩展名 y4m
  27. pngmeta
  28. PNG 和 exif
  29. Image Magic - escape
  30. Stackoverflow : 如何向 PNG 添加额外的元数据?
  31. Stackoverflow : 如何将文本块插入 PNG 图像?
  32. 维基百科 : 块(信息)
  33. PNG(便携式网络图形)规范,版本 1.2 : 块
  34. https://github.com/gbenison/png-text-embed
  35. Mightymandel 文档
华夏公益教科书