diff --git a/src/utils_gif.ml b/src/utils_gif.ml index 8052994..7192356 100644 --- a/src/utils_gif.ml +++ b/src/utils_gif.ml @@ -15,39 +15,21 @@ let color_table_of_palette (p : Palette.t) : ColorTable.t = let b = rgb land 0xFF in (r, g, b)) -let pad_palette_to_power_of_two (colors : ColorTable.t) : ColorTable.t = - let len = Array.length colors in - let next_pow2 n = - let rec loop x = if x >= n then x else loop (x * 2) in - loop 1 - in - let target_len = min 256 (next_pow2 len) in - Array.init target_len (fun i -> if i < len then colors.(i) else (0, 0, 0)) - let capture_frame (screen : Screen.t) (fb : Framebuffer.t) = let width, height = Screen.dimensions screen in let scale = Screen.scale screen in let palette = Screen.palette screen in + let palette_size = Palette.size palette in let scaled_width = width * scale in let scaled_height = height * scale in let size = scaled_width * scaled_height in - let colors = - palette |> color_table_of_palette |> pad_palette_to_power_of_two - in - - let color_depth = - let len = Array.length colors in - let rec bits_needed n b = - if n <= 1 then b else bits_needed (n / 2) (b + 1) - in - min 8 (max 2 (bits_needed (len - 1) 1)) - in + let colors = palette |> color_table_of_palette in let pixels = - List.init size (fun idx -> + Array.init size (fun idx -> let x = idx mod scaled_width in let y = idx / scaled_width in let src_x = x / scale in @@ -59,14 +41,15 @@ let capture_frame (screen : Screen.t) (fb : Framebuffer.t) = failwith (Printf.sprintf "Invalid pixel coordinate (%d,%d)" src_x src_y) in - if v < 0 || v > Palette.size palette then + if v < 0 || v > palette_size then failwith (Printf.sprintf "Framebuffer value %d out of byte range at (%d,%d)" v src_x src_y); - (Z.of_int v, color_depth)) + v) in - let flattened = Lzw.flatten_codes 8 pixels in - let compressed = Lzw.encode flattened color_depth in + (* Claudius attempts to run at 60 fps, and GIF delay time is specified as multiples + of 1/100th of a second, so the closest we can do is 2 (50 FPS). *) + let delay_time = Some 2 in - Image.v (scaled_width, scaled_height) colors compressed color_depth true + Image.of_pixels ~delay_time (scaled_width, scaled_height) colors pixels diff --git a/src/utils_gif.mli b/src/utils_gif.mli index c6357de..25bf439 100644 --- a/src/utils_gif.mli +++ b/src/utils_gif.mli @@ -8,10 +8,6 @@ val timestamp : string -> string val color_table_of_palette : Palette.t -> ColorTable.t (** [color_table_of_palette palette] converts a palette to a GIF color table. *) -val pad_palette_to_power_of_two : ColorTable.t -> ColorTable.t -(** [pad_palette_to_power_of_two table] extends a color table to the next power - of two, padding with black as needed, up to maximum 256 colors. *) - val capture_frame : Screen.t -> Framebuffer.t -> Image.t (** [capture_frame screen framebuffer] captures the current framebuffer contents as a compressed GIF image. Raises [Failure] if framebuffer contains invalid