-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.sml
85 lines (74 loc) · 2.77 KB
/
main.sml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
structure CLA = CommandLineArgs
val fps = CLA.parseInt "fps" 60
val width = CLA.parseInt "width" 640
val height = CLA.parseInt "height" 480
val frames = CLA.parseInt "frames" (10 * fps)
(* val frame = CLA.parseInt "frame" 100 *)
val _ = print ("width " ^ Int.toString width ^ "\n")
val _ = print ("height " ^ Int.toString height ^ "\n")
(* val _ = print ("frame " ^ Int.toString frame ^ "\n") *)
val _ = print ("fps " ^ Int.toString fps ^ "\n")
val _ = print ("frames " ^ Int.toString frames ^ "\n")
val duration = Real.fromInt frames / Real.fromInt fps
val _ = print ("(" ^ Real.fmt (StringCvt.FIX (SOME 2)) duration ^ " seconds)\n")
val _ = print ("generating frames...\n")
val (images, tm) = Util.getTime (fn _ =>
SeqBasis.tabulate 1 (0, frames) (fn frame =>
{ width = width
, height = height
, data =
ArraySlice.full
(TinyKaboom.frame (f32.fromInt frame / f32.fromInt fps) width height)
}))
val _ = print ("generated all frames in " ^ Time.fmt 4 tm ^ "s\n")
val perFrame = Time.fromReal (Time.toReal tm / Real.fromInt frames)
val _ = print ("average time per frame: " ^ Time.fmt 4 perFrame ^ "s\n")
val _ = print ("generating palette...\n")
(* val palette = GIF.Palette.summarize [Color.white, Color.black] 256
{ width = width
, height = height
, data = ArraySlice.full (TinyKaboom.frame 5.1667 640 480)
} *)
fun sampleColor i =
let
val k = Util.hash i
val frame = (k div (width*height)) mod frames
val idx = k mod (width*height)
in
Seq.nth (#data (Array.sub (images, frame))) idx
end
val palette = GIF.Palette.summarizeBySampling [Color.white, Color.black] 256
sampleColor
val blowUpFactor = CLA.parseInt "blowup" 1
val _ = print ("blowup " ^ Int.toString blowUpFactor ^ "\n")
fun blowUpImage (image as {width, height, data}) =
if blowUpFactor = 1 then image else
let
val width' = blowUpFactor * width
val height' = blowUpFactor * height
val output = ForkJoin.alloc (width' * height')
val _ =
ForkJoin.parfor 1 (0, height) (fn i =>
ForkJoin.parfor (1000 div blowUpFactor) (0, width) (fn j =>
let
val c = Seq.nth data (i*width + j)
in
Util.for (0, blowUpFactor) (fn di =>
Util.for (0, blowUpFactor) (fn dj =>
Array.update (output, (i*blowUpFactor+di)*width' + (j*blowUpFactor+dj), c)))
end))
in
{ width = width'
, height = height'
, data = ArraySlice.full output
}
end
val _ = print ("writing to boom.gif...\n")
val msBetween = Real.round ((1.0 / Real.fromInt fps) * 100.0)
val result =
GIF.writeMany "boom.gif" msBetween palette
{ width = blowUpFactor * width
, height = blowUpFactor * height
, numImages = frames
, getImage = fn i => #remap palette (blowUpImage (Array.sub (images, i)))
}