graphics - 从 Ocaml Graphics 中的文件加载图像

标签 graphics ocaml

我正在阅读the documentation for the Graphics module ,并且没有任何有关从文件加载图像的信息,仅从颜色数组加载图像。我该怎么做呢?例如,假设我有 file.png,并且我想在坐标 (x, y) 处以 z 度旋转来绘制它.

最佳答案

camlimages库可以加载 png 文件(如果它们不是以 RGBA 或 CMYK 格式表示)。一个简单的例子:

open Images

let () = Graphics.open_graph "";;

let img = Png.load "png.png" [];;
let g = Graphic_image.of_image img;;

Graphics.draw_image g 0 0;;

Unix.sleep 10;;

运行:

opam install graphics camlimages
ocamlfind ocamlc -o test -package graphics -package unix \
    -package camlimages.png -package camlimages.graphics \
    -linkpkg test.ml
wget https://bytebucket.org/camlspotter/camlimages/raw/1611545463f493462aeafab65839c1112162559a/test/images/png.png
./test

(基于example in the library source code。)

但是,我不认为 camimages 可以旋转 png。您可以推出自己的旋转函数(改编自 Mortimer's code on Dr. Dobb's ):

let rotate src dst angle =
  let sh, sw = Array.(float (length src), float (length src.(0))) in
  let dh, dw = Array.(length dst, length dst.(0)) in
  let dx, dy = float dw /. 2., float dh /. 2. in
  let scale = min (float dh /. sh) (float dw /. sw) in
  let duCol = sin(-.angle) *. (1. /. scale) in
  let dvCol = cos(-.angle) *. (1. /. scale) in
  let rec col dst x u v =
    if x < dw then (
      dst.(x) <- if (0. <= u && u < sw) && (0. <= v && v < sh)
                 then src.(truncate v).(truncate u)
                 else Graphics.white;
      col dst (x + 1) (u +. dvCol) (v -. duCol))
  in
  let rec row y rowu rowv =
    if y < dh then (col dst.(y) 0 rowu rowv;
                    row (y + 1) (rowu +. duCol) (rowv +. dvCol))
  in
  row 0 ((sw /. 2.) -. (dx *. dvCol +. dy *. duCol))
        ((sh /. 2.) -. (dx *. (-.duCol) +. dy *. dvCol))

并从上面的示例代码中调用它

let dg = Graphics.dump_image g
let dgr =Array.(make_matrix (length dg) (length dg.(0)) Graphics.white);;
rotate dg dgr (4. *. atan 1. /. 2);;
let g = Graphics.make_image dgr;;

或者,您可以使用 OCamlSDLSdlgfx.rotozoomSurface 函数。 .

一个简单的例子:

let png = Sdlloader.load_image "png.png"

let png_rot = Sdlgfx.rotozoomSurface png 45.0 1.0 true;;

Sdl.init [`VIDEO];;
let screen = Sdlvideo.set_video_mode ~w:250 ~h:166 [];;

Sdlvideo.(blit_surface ~dst_rect:{ r_x = 0; r_y = 0; r_w = 250; r_h = 166}
                       ~src:png_rot ~dst:screen ());;

Sdlvideo.flip screen;
Sdltimer.delay 10000;
Sdl.quit ();;

在系统上安装适当的 SDL 软件包后(并不总是那么容易......),运行:

opam install ocamlsdl
ocamlfind ocamlc -o test -package sdl -package sdl.sdlimage \
    -package sdl.sdlgfx -linkpkg test.ml
./test

关于graphics - 从 Ocaml Graphics 中的文件加载图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50108152/

相关文章:

c# - 如何在 .NET 中将缇转换为像素?

c++ - 可以支持动画 GIF 的快速图形库

int - OCaml 的最大整数值

haskell - 为什么 MLF 中有弹性和刚性边界?

java - 使用 Java 图形沿弧形路径移动形状

Java游戏使用线程在屏幕上移动物体,速度变慢

c# - 如何获取和设置图像的属性项

ocaml - 在 OCaml 中漂亮地打印一个 Hashtbl 以使用 ppx-deriving

ocaml - 将camlp4和camlp5结合在ocamlopt的-pp字符串中?

haskell - Haskell 和 OCaml 中的仿函数有何相似之处?