ARRI LogC3 (EI 800) HDR compression. Maps linear [0, inf) -> [0, 1] via the camera log curve, then scales to [-1, 1] for VAE input.
| 23 | |
| 24 | |
| 25 | class LogC3: |
| 26 | """ARRI LogC3 (EI 800) HDR compression. |
| 27 | |
| 28 | Maps linear [0, inf) -> [0, 1] via the camera log curve, then scales to |
| 29 | [-1, 1] for VAE input. |
| 30 | """ |
| 31 | |
| 32 | A = 5.555556 |
| 33 | B = 0.052272 |
| 34 | C = 0.247190 |
| 35 | D = 0.385537 |
| 36 | E = 5.367655 |
| 37 | F = 0.092809 |
| 38 | CUT = 0.010591 |
| 39 | |
| 40 | def compress(self, hdr: Tensor) -> Tensor: |
| 41 | x = torch.clamp(hdr, min=0.0) |
| 42 | log_part = self.C * torch.log10(self.A * x + self.B) + self.D |
| 43 | lin_part = self.E * x + self.F |
| 44 | logc = torch.where(x >= self.CUT, log_part, lin_part) |
| 45 | logc = torch.clamp(logc, 0.0, 1.0) |
| 46 | return logc * 2.0 - 1.0 |
| 47 | |
| 48 | def decompress(self, z: Tensor) -> Tensor: |
| 49 | logc = torch.clamp((z + 1.0) / 2.0, 0.0, 1.0) |
| 50 | cut_log = self.E * self.CUT + self.F |
| 51 | lin_from_log = (torch.pow(10.0, (logc - self.D) / self.C) - self.B) / self.A |
| 52 | lin_from_lin = (logc - self.F) / self.E |
| 53 | return torch.where(logc >= cut_log, lin_from_log, lin_from_lin) |
| 54 | |
| 55 | |
| 56 | # --------------------------------------------------------------------------- |