package tiny_libs
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
From-scratch libraries for teaching: graphics, audio, compression, crypto, networking and more
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0
doc/src/tiny_libs.graphics_mpeg1/Motion.ml.html
Source file Motion.ml
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(* Claude Code * * Copyright (C) 2026 Yoann Padioleau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * (LGPL) as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. *) (* See Motion.mli *) type plane = { bytes : Bytes.t; stride : int; rows : int } type search = Full | Logarithmic (* a whole-pixel offset, the common case: a plain loop *) let sad_whole (cur : plane) (reference : plane) ~(x : int) ~(y : int) ((dx, dy) : int * int) : int = let s = ref 0 in for j = 0 to 15 do let c = ((y + j) * cur.stride) + x and r = ((y + j + dy) * reference.stride) + x + dx in for i = 0 to 15 do s := !s + abs (Char.code (Bytes.unsafe_get cur.bytes (c + i)) - Char.code (Bytes.unsafe_get reference.bytes (r + i))) done done; !s let sad (cur : plane) (reference : plane) ~(x : int) ~(y : int) ((vx, vy) : int * int) : int = if vx land 1 = 0 && vy land 1 = 0 then sad_whole cur reference ~x ~y (vx asr 1, vy asr 1) else let p = Mpeg1.prediction reference.bytes ~stride:reference.stride ~rows:reference.rows ~x ~y ~size:16 (vx, vy) in let s = ref 0 in Array.iteri (fun k v -> s := !s + abs (Char.code (Bytes.get cur.bytes (((y + (k / 16)) * cur.stride) + x + (k mod 16))) - v)) p; !s (* inside the reference: the square and, for a half pixel, the pixel * after it *) let inside (reference : plane) ~(x : int) ~(y : int) ((vx, vy) : int * int) : bool = let x0 = x + (vx asr 1) and y0 = y + (vy asr 1) in x0 >= 0 && y0 >= 0 && x0 + 16 + (vx land 1) <= reference.stride && y0 + 16 + (vy land 1) <= reference.rows let estimate (search : search) ~(range : int) (cur : plane) (reference : plane) ~(x : int) ~(y : int) : (int * int) * int * int = let tried = ref 0 in let best = ref ((0, 0), sad_whole cur reference ~x ~y (0, 0)) in incr tried; (* try v (half pixels), keep it if better *) let consider v = if inside reference ~x ~y v then ( incr tried; let s = sad cur reference ~x ~y v in if s < snd !best then best := (v, s)) in (match search with | Full -> for dy = -range to range do for dx = -range to range do if (dx, dy) <> (0, 0) then consider (2 * dx, 2 * dy) done done | Logarithmic -> (* the first step: the smallest power of two whose steps, halving, * reach the range -- 4 for 7 (4 + 2 + 1), 8 for 12 *) let step = ref 1 in while (2 * !step) - 1 < range do step := !step * 2 done; while !step >= 1 do let cx, cy = fst !best in List.iter (fun (i, j) -> if (i, j) <> (0, 0) then consider (cx + (2 * i * !step), cy + (2 * j * !step))) [ (-1, -1); (0, -1); (1, -1); (-1, 0); (1, 0); (-1, 1); (0, 1); (1, 1) ]; step := !step / 2 done); (* half a pixel around the best whole one *) let cx, cy = fst !best in List.iter (fun (i, j) -> if (i, j) <> (0, 0) then consider (cx + i, cy + j)) [ (-1, -1); (0, -1); (1, -1); (-1, 0); (1, 0); (-1, 1); (0, 1); (1, 1) ]; (fst !best, snd !best, !tried)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>