TinyPTC是个操作非常简单的库,有各平台用的版本,linux平台版本又分为sdl版和gfx版,gfx版本比sdl版本速度快,尺寸不大,可操作的函数只有3个:
ptc_open, ptc_update, ptc_close
sdl版本增加了一个回调函数 ptc_cleanup_callback , 在TinyPTC即将结束前的回调。gfx版本增加了像素格式转换,用asm写的,nasm编译,ar\as处理,但没实际意义、只是放在了那里,编译mmx.s和yvs12.s与gcc的其它.o不能链接成 .a 库,修改Makefiles配置文件将AOBJECTS去掉即可。
FreeBASIC有它的.bi头文件,但没有它的.a库,所以需要自己编译(系统上要有gcc, make工具链)。对TinyPTC-SDL-0.3.2编译:到sourceforge下载后解压,在解压后的目录内执行:
make && sudo make install 即可,libtinyptc.a 是它生成的库文件,如果不 sudo make install 则将这个文件考贝到 /usr/lib/x86_64-linux-gnu下即可。
编译完成后生成一个测试程序 tinyptc_test,在终端上执行 ./tinyptc_test 显示不断变化的噪音信号,就好像老电视机收不信号满屏雪花一样。
打开Makefile文件,将链接时的 $(AOBJECTS) 去掉。然后:
make && sudo make install ,或是直接考贝到 /usr/lib/x86_64-linux-gnu 下。
FreeBasic示例程序一:正弦曲线,中间画一条直线。
ptc_open前定义一个宽w高h的像素数组,freebasic 整数是32位的,正好是rgba的像素数 4 个8bit, ptc_open后以这个w和h的一半计算出x点对应的y点,再折算成连续数组中的位置,然后 ptc_update这个数组,就显示到屏幕上了。如果是bmp位置,可以获取位置长宽后读取位置数据装入到数组中,然后ptc_update到屏幕上去。
- #include "tinyptc.bi"
-
- const SCR_WIDTH = 1024
- const SCR_HEIGHT = 768
-
- const SCR_SIZE = SCR_WIDTH*SCR_HEIGHT
-
- dim shared buffer( 0 to SCR_SIZE-1 ) as integer
-
- if( ptc_open( "Simple lines", SCR_WIDTH, SCR_HEIGHT ) = 0 ) then
- Print "Can not create ptc window!"
- end -1
- end if
-
- 'data buffer is integer, e.g. 32bit/4byte color in depth
- 'data arranged in ARGB order at each buffer cell &Haarrggbb
-
- Dim as integer x, y
- Dim as double rad = 0
- Dim as double PI = 3.1415926
- Do
- rad = 0
- for x = 0 to SCR_WIDTH/2 - 1
- ''Line diagonal
- 'y = x*(SCR_HEIGHT-1)/(SCR_WIDTH-1)
- 'buffer(y*SCR_WIDTH + x) = RGBA(255, 0, 255, 0)
-
- 'Sine wave
- y = SCR_HEIGHT/4 + (SCR_HEIGHT/5)*cos(rad)
- rad += 0.05
- if rad > 2*PI then
- rad = 0
- end if
- buffer(y*SCR_WIDTH + x) = RGBA(255, 255, 0, 0)
-
- 'axes
- y = SCR_HEIGHT/4
- buffer(y*SCR_WIDTH + x) = RGBA(255, 0, 0, 0)
- next x
-
- ptc_update @buffer(0)
- sleep 10
-
- loop until( inkey = chr( 27 ) )
-
- ptc_close
FreeBasic示例程序二:雪花噪音信号发生器
运算逻辑同示例一,只是算法不同,程序中有计算方法可细了解。
- ''
- '' ordinary TinyPTC test, based on the original
- ''
-
- #include "tinyptc.bi"
-
- 'const SCR_WIDTH = 320
- 'const SCR_HEIGHT = 200
-
- const SCR_WIDTH = 1850
- const SCR_HEIGHT =1000
-
- const SCR_SIZE = SCR_WIDTH*SCR_HEIGHT
-
- dim shared buffer( 0 to SCR_SIZE-1 ) as integer
-
- 'Integer is 8Bytes, e.g. 64bits per sizeof(integer)
- dim noise as integer, carry as integer, index as integer, seed as integer
-
- if( ptc_open( "freeBASIC v0.01 - tinyPTC test", SCR_WIDTH, SCR_HEIGHT ) = 0 ) then
- end -1
- end if
-
- seed = &h12345
-
- do
-
- for index = 0 to SCR_SIZE-1
- noise = (seed shr 3) xor seed
- carry = noise and 1
- noise = noise shr 1
- seed = seed shr 1
- seed = seed or (carry shl 30)
- noise = noise and &hFF
- buffer(index) = rgb( noise, noise, noise )
- next index
-
- ptc_update @buffer(0)
-
- loop until( inkey = chr( 27 ) )
-
-
- ptc_close
FreeBasic示例程序二:朱丽叶环
通过函数运算,将值放入数组,然后ptc_update到屏幕上。
- ' The Lord of the Julia Rings
- ' The Fellowship of the Julia Ring
- ' Free Basic
- ' Relsoft
- ' Rel.BetterWebber.com
- '
-
-
-
- #ifdef __FB_WIN32__
- #include once "windows.bi"
- #endif
-
- #include once "tinyptc.bi"
-
- '320*240
- 'const SCR_WIDTH = 640 * 1
- 'const SCR_HEIGHT = 480 * 1
-
- const SCR_WIDTH = 1850 * 1
- const SCR_HEIGHT = 1000 * 1
-
- const SCR_SIZE = SCR_WIDTH*SCR_HEIGHT
- const SCR_MIDX = SCR_WIDTH \ 2
- const SCR_MIDY = SCR_HEIGHT \ 2
-
-
- const PI = 3.141593
- const MAXITER = 20
- const MAXSIZE = 4
-
-
- dim shared Buffer(SCR_SIZE - 1) as integer
- dim Lx(SCR_WIDTH-1) as single
- dim Ly(SCR_HEIGHT-1) as single
- dim shared sqrt(SCR_SIZE - 1) as single
-
-
- if( ptc_open( "Julia (Relsoft)", SCR_WIDTH, SCR_HEIGHT ) = 0 ) then
- end -1
- end if
-
- dim px as integer, py as integer
- dim p as single, q as single
- dim xmin as single, xmax as single, ymin as single, ymax as single
- dim theta as single
- dim deltax as single, deltay as single
- dim x as single, y as single
- dim xsquare as single, ysquare as single
- dim ytemp as single
- dim temp1 as single, temp2 as single
- dim i as integer, pixel as integer
- dim p_buffer as integer ptr, p_bufferl as integer ptr
- dim t as uinteger, frame as uinteger
- dim ty as single
- dim r as integer, g as integer, b as integer
- dim red as integer, grn as integer, blu as integer
- dim tmp as integer, i_last as integer
-
- dim cmag as single
- dim cmagsq as single
- dim zmag as single
- dim drad as single
- dim drad_L as single
- dim drad_H as single
- dim ztot as single
- dim ztoti as integer
-
- xmin = -2.0
- xmax = 2.0
- ymin = -1.5
- ymax = 1.5
-
- deltax = (xmax - xmin) / (SCR_WIDTH - 1)
- deltay = (ymax - ymin) / (SCR_HEIGHT - 1)
-
- for i = 0 to SCR_WIDTH - 1
- lx(i) = xmin + i * deltax
- next i
-
- for i = 0 to SCR_HEIGHT - 1
- ly(i) = ymax - i * deltay
- next i
-
- for i = 0 to SCR_SIZE - 1
- sqrt(i) = sqr(i)
- next i
-
-
- #ifdef __FB_WIN32__
- dim hwnd as HWND
- hwnd = GetActiveWindow( )
- #endif
-
- dim stime as integer, Fps as single, Fps2 as single
-
- stime = timer
-
- do
- p_buffer = @buffer(0)
- p_bufferl = @buffer(SCR_SIZE-1)
-
- frame = (frame + 1) and &H7fffffff
- theta = frame * PI / 180
-
- p = cos(theta) * sin(theta * .7)
- q = sin(theta) + sin(theta)
- p = p * .6
- q = q * .6
-
-
-
- cmag = sqr(p *p + q* q)
- cmagsq = (p *p + q* q)
- drad = 0.04
- drad_L = (cmag - drad)
- drad_L = drad_L * drad_L
- drad_H = (cmag + drad)
- drad_H = drad_H * drad_H
-
-
- for py = 0 to (SCR_HEIGHT shr 1) - 1
- ty = ly(py)
- for px = 0 to SCR_WIDTH - 1
- x = Lx(px)
- y = ty
- xsquare = 0
- ysquare = 0
- ztot =0
- i = 0
- while (i < MAXITER) and (( xsquare + ysquare ) < MAXSIZE)
- xsquare = x * x
- ysquare = y * y
- ytemp = x * y * 2
- x = xsquare - ysquare + p
- y = ytemp + q
- zmag = (x * x + y * y)
- if (zmag < drad_H) then
- if (zmag > drad_L) and (i > 0) then
- ztot = ztot + ( 1 - (abs(zmag - cmagsq) / drad))
- i_last = i
- end if
- end if
- i = i + 1
- if zmag > 4.0 then
- exit while
- end if
- wend
-
- if ztot > 0 then
- i = cint(sqr(ztot) * 500)
- else
- i = 0
- end if
- if i < 256 then
- red = i
- else
- red = 255
- end if
-
- if i < 512 and i > 255 then
- grn = i - 256
- else
- if i >= 512 then
- grn = 255
- else
- grn = 0
- end if
- end if
-
- if i <= 768 and i > 511 then
- blu = i - 512
- else
- if i >= 768 then
- blu = 255
- else
- blu = 0
- end if
- end if
-
- tmp = cint((red+grn+blu) * 0.33)
- red = cint((red+grn+tmp) * 0.33)
- grn = cint((grn+blu+tmp) * 0.33)
- blu = cint((blu+red+tmp) * 0.33)
-
- select case (i_last and 3)
- case 1
- tmp = red
- red = grn
- grn = blu
- blu = tmp
- case 2
- tmp = red
- blu = grn
- red = blu
- grn = tmp
- end select
-
- pixel = rgb( red, grn, blu )
- *p_buffer = pixel
- *p_bufferl = pixel
- p_buffer = p_buffer + 1
- p_bufferl = p_bufferl - 1
- next px
- next py
-
- 'calc fps
- fps = fps + 1
- if stime + 1 < timer then
- fps2 = fps
- fps = 0
- stime = timer
- #ifdef __FB_WIN32__
- SetWindowText( hwnd, "FreeBasic Julia Rings FPS:" & Fps2 )
- #endif
- end if
- ptc_update @buffer(0)
- loop until inkey <> ""
-
-
- ptc_close
-
- end
-
-
-
-
由于它体积小,在嵌入式设备上有一定用处,在数据算法绘图上也能用,操作步骤简单,也决定了操控灵活性上有局限性。CSDN 上也能找到 TinyPTC 的应用和简介,所以就把它编译和试运行效果贴上来了。