From 3880d57d7308af71633c2890d81fb766ce849cf2 Mon Sep 17 00:00:00 2001 From: DonislawDev Date: Fri, 13 Nov 2026 19:30:12 +0100 Subject: [PATCH 1/3] An AVIF or a JPEG XL cut short loses the share of its picture asked for An AVIF or a JPEG XL a damage cuts splits its padding around the picture, so the cut keeps the share of the picture it keeps of the whole file. Before, all of the padding stood in free boxes behind the picture, and a cut of any share took only padding and left the picture whole. An AVIF puts free boxes between the coder's meta box and its media data. The item locations give the picture's place in bytes from the start of the file, so every one moves by as much, and an offset of four bytes that the move takes past 4 GiB is widened to eight - only then, so a smaller file keeps the coder's meta box but for the numbers. A JPEG XL puts skip boxes between its file type box and its codestream, which knows nothing of where it sits: ffmpeg takes a JPEG XL with a free box near its start for a movie and refuses it, and a skip box, the same to the format, for nothing. The front is rounded to whole boxes by format.SplitFront, which PNG's front padding became with the size of its piece as a parameter. Files nothing cuts keep their bytes, and PNG's do cut or not. The structural checker allows padding right in front of the picture as well as behind it, and requires every item location of an AVIF to land inside its media data. Both formats leave the share ratchet. A new guard writes consecutive sizes and cuts a byte apart where the front starts, where it rounds to a box and where the padding behind runs out, decodes one file of each layout, and plans an AVIF of 5 GiB whose item location needs eight bytes. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 8 + internal/format/avif/avif.go | 14 +- internal/format/avif/cut.go | 342 ++++++++++++++++++++++++ internal/format/cut.go | 32 +++ internal/format/isobmff/isobmff.go | 11 +- internal/format/jxl/cut.go | 64 +++++ internal/format/jxl/jxl.go | 33 +-- internal/format/png/cut.go | 32 +-- internal/guard/boxcut_test.go | 340 +++++++++++++++++++++++ internal/guard/cutshare_test.go | 4 +- internal/guard/mutation/entries.py | 6 +- internal/guard/mutationcoverage_test.go | 5 + internal/oracle/strict.py | 79 ++++-- 13 files changed, 893 insertions(+), 77 deletions(-) create mode 100644 internal/format/avif/cut.go create mode 100644 internal/format/jxl/cut.go create mode 100644 internal/guard/boxcut_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ddf84fc..037644f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -116,6 +116,14 @@ because it turns other people's test suites red. manifest says so: a few percent of a small PDF, falling in the index, and one keeping 10 billion bytes or more, which the index cannot reach. Files nothing cuts are unchanged. +- **`truncate` cuts the picture of an AVIF or a JPEG XL by the percentage you + set.** A cut used to take only padding, leaving the whole picture. Now + `--damage truncate:missing=50` removes half of the coded picture, as an + interrupted download does. Chrome, Firefox, Windows, libavif and Pillow + refuse the cut AVIF. Half of a JPEG XL still shows the whole picture at + lower detail in Chrome and in libjxl with partial files allowed, because the + format sends a coarse picture first. A cut of 90% shows nothing. Files + nothing cuts are unchanged. - **tfg is on npm, for tests in Node.** `npm install --save-dev testing-files-generator` gives Playwright, Vitest diff --git a/internal/format/avif/avif.go b/internal/format/avif/avif.go index 814131b1..9a29d09b 100644 --- a/internal/format/avif/avif.go +++ b/internal/format/avif/avif.go @@ -35,7 +35,8 @@ // sixty four bit box length that files above four gigabytes need. There is no // dead zone above the minimum. Pillow reads every one of them and refuses a // truncated or corrupted file, which is what makes it a witness. ffprobe reads -// the broken ones too, so it is not. +// the broken ones too, so it is not. A file a damage will cut has part of its +// free boxes in front of the media data instead (cut.go). package avif import ( @@ -166,6 +167,9 @@ type memo struct { // which is what makes every size above the minimum reachable a byte at a // time. total int64 + // cutAt is where a damage will cut the file, zero when nothing does + // (format.Request.CutAt). + cutAt int64 } func (generator) Plan(r format.Request) (format.Plan, error) { @@ -187,7 +191,7 @@ func (generator) Plan(r format.Request) (format.Plan, error) { if err := checkFits(r.Bytes, m); err != nil { return format.Plan{}, err } - m.total = r.Bytes + m.total, m.cutAt = r.Bytes, r.CutAt p := format.Plan{ Bytes: r.Bytes, @@ -491,6 +495,12 @@ func (generator) Write(ctx context.Context, w io.Writer, p format.Plan) error { m.width, m.height, len(coded), m.total)) } + if m.cutAt > 0 { + if done, err := writeForACut(ctx, w, m, coded); done || err != nil { + return err + } + } + // The map: the coder's boxes, its media data the content, and the free // boxes after them that make up the size. markBoxes(w, coded) diff --git a/internal/format/avif/cut.go b/internal/format/avif/cut.go new file mode 100644 index 00000000..aef62c22 --- /dev/null +++ b/internal/format/avif/cut.go @@ -0,0 +1,342 @@ +package avif + +import ( + "context" + "encoding/binary" + "fmt" + "io" + "math" + + "github.com/donislawdev/TestingFilesGenerator/internal/core" + "github.com/donislawdev/TestingFilesGenerator/internal/format" + "github.com/donislawdev/TestingFilesGenerator/internal/format/isobmff" +) + +// writeForACut writes a file a damage will cut after its first m.cutAt bytes, +// with the padding split around the picture so that the cut keeps the share of +// the picture it keeps of the whole file (format.Request.CutAt): the coder's +// boxes up to the media data, free boxes, the media data, and free boxes +// behind it. +// +// With all of the padding behind the picture, as an uncut file has it, a large +// file cut at any share kept the whole picture and lost only padding. A free +// box may stand anywhere among the top level boxes, and readers skip it +// (docs/TRUNCATE-2026-11-11.md section 13). The one thing a box in front of the +// media data changes is where the picture starts, and the item locations in +// the meta box say that in bytes from the start of the file, so they move by +// as much. Their offsets are four bytes long as the coder writes them. One +// that the move would take past 4 GiB is widened to eight bytes, which the +// item location box allows, and the meta box grows by four bytes for each +// offset - only then, so every file that does not need it keeps the coder's +// meta box but for the numbers. +// +// A file whose share wants nothing in front, or too little for a free box, is +// written as one nothing cuts. +func writeForACut(ctx context.Context, w io.Writer, m memo, coded []byte) (bool, error) { + head, mdat, err := splitAtTheMediaData(coded) + if err != nil { + return false, err + } + pad := m.total - int64(len(coded)) + front := format.SplitFront(pad, int64(len(head)), int64(len(mdat)), m.cutAt, m.total, boxHeader) + if front == 0 { + return false, nil + } + locs, err := readItemLocations(head) + if err != nil { + return false, err + } + wide := locs.furthest+front > math.MaxUint32 + if wide { + grown := locs.growth() + front = format.SplitFront(pad-grown, int64(len(head))+grown, int64(len(mdat)), m.cutAt, m.total, boxHeader) + if front == 0 { + return false, nil + } + } + moved, err := locs.moved(head, front, wide) + if err != nil { + return false, err + } + back := m.total - int64(len(moved)) - front - int64(len(mdat)) + if back < 0 || back > 0 && back < boxHeader { + return false, core.Defect(fmt.Errorf("avif: a split of %d B in front of the picture leaves %d B behind it", front, back)) + } + + markBoxes(w, moved) + at := int64(len(moved)) + format.Mark(w, format.RolePadding, at, front) + format.Mark(w, format.RoleContent, at+front, int64(len(mdat))) + if back > 0 { + format.Mark(w, format.RolePadding, at+front+int64(len(mdat)), back) + } + + // Both sides draw their filler from the file's seed. Nobody reads padding, + // and the side behind the picture lies past any cut. + if _, err := w.Write(moved); err != nil { + return true, err + } + if err := isobmff.WritePadding(ctx, w, m.seed, front); err != nil { + return true, err + } + if _, err := w.Write(mdat); err != nil { + return true, err + } + return true, isobmff.WritePadding(ctx, w, m.seed, back) +} + +// splitAtTheMediaData parts the coder's file into the boxes in front of its +// media data and the media data box, which has to be the last one: that is +// where a box in front of the picture goes, and nothing behind it would move. +func splitAtTheMediaData(coded []byte) (head, mdat []byte, err error) { + for pos := 0; pos+boxHeader <= len(coded); { + size := int(binary.BigEndian.Uint32(coded[pos:])) + if size < boxHeader || pos+size > len(coded) { + break + } + mdat := string(coded[pos+4:pos+boxHeader]) == "mdat" + if mdat && pos+size == len(coded) { + return coded[:pos], coded[pos:], nil + } + if mdat { + break + } + pos += size + } + return nil, nil, core.Defect(fmt.Errorf("avif: the coder's file does not end with one media data box behind its other boxes")) +} + +// itemLocations is the item location box in a meta box, read far enough to +// move the places it gives. +type itemLocations struct { + // metaAt and ilocAt are where the meta box and the item location box start + // in the head, ilocLen how long the item location box is. + metaAt, ilocAt, ilocLen int + version byte + // offsetSize, lengthSize, baseSize and indexSize are the four field sizes + // in bytes, as the box gives them. + offsetSize, lengthSize, baseSize, indexSize int + // moving is how many fields hold a place in the file - the base offset of + // each item when the box has one, each extent's offset otherwise. + moving int + // furthest is the largest place any of them gives. + furthest int64 +} + +// countSize is how long the item count and each item's number are: two bytes, +// and four from version 2 on. +func (l itemLocations) countSize() int { + if l.version == 2 { + return 4 + } + return 2 +} + +// growth is how much the item location box, and so the meta box, grows when +// the fields that hold a place are widened from four bytes to eight. +func (l itemLocations) growth() int64 { return int64(4 * l.moving) } + +// readItemLocations finds the item location box in the meta box of head and +// reads the places it gives. Only places in this file (construction method 0) +// are what the coder writes, and only those are read. +func readItemLocations(head []byte) (itemLocations, error) { + l, why := locateItemLocations(head) + if why == "" { + why = l.readPlaces(head[l.ilocAt+boxHeader : l.ilocAt+l.ilocLen]) + } + if why != "" { + return itemLocations{}, core.Defect(fmt.Errorf("avif: the coder's item locations %s", why)) + } + return l, nil +} + +// locateItemLocations finds the meta box among the top level boxes of head and +// the item location box in it, or says why it cannot. +func locateItemLocations(head []byte) (itemLocations, string) { + l := itemLocations{metaAt: -1} + for pos := 0; pos+boxHeader <= len(head); { + size := int(binary.BigEndian.Uint32(head[pos:])) + if size < boxHeader || pos+size > len(head) { + return l, "stand in a box this cannot walk past" + } + why := "" + if string(head[pos+4:pos+boxHeader]) == "meta" { + l.metaAt = pos + why = l.findIn(head, pos, size) + } + if why != "" { + return l, why + } + pos += size + } + if l.metaAt < 0 || l.ilocLen == 0 { + return l, "are missing" + } + return l, "" +} + +// findIn finds the item location box among the boxes of the meta box that +// starts at pos. meta is a full box: its version and flags come before its +// boxes. +func (l *itemLocations) findIn(head []byte, pos, size int) string { + for at := pos + boxHeader + 4; at+boxHeader <= pos+size; { + n := int(binary.BigEndian.Uint32(head[at:])) + if n < boxHeader || at+n > pos+size { + return "stand in a meta box this cannot walk" + } + if string(head[at+4:at+boxHeader]) == "iloc" { + l.ilocAt, l.ilocLen = at, n + } + at += n + } + return "" +} + +// readPlaces reads the field sizes of the item location box's content b and +// every place in this file it gives, or says why it cannot. +func (l *itemLocations) readPlaces(b []byte) string { + if len(b) < 8 { + return "are cut short" + } + l.version = b[0] + if l.version > 2 { + return fmt.Sprintf("are in version %d", l.version) + } + l.offsetSize, l.lengthSize, l.baseSize = int(b[4]>>4), int(b[4]&15), int(b[5]>>4) + if l.version >= 1 { + l.indexSize = int(b[5] & 15) + } + moveBase := l.baseSize > 0 + if !moveBase && l.offsetSize == 0 { + return "give no offset to move" + } + r := reader{b: b, at: 6} + for range r.uint(l.countSize()) { + r.uint(l.countSize()) + if l.version >= 1 && r.uint(2)&15 != 0 { + return "point outside the file" + } + r.uint(2) + l.place(moveBase, r.uint(l.baseSize)) + for range r.uint(2) { + r.uint(l.indexSize) + off := r.uint(l.offsetSize) + r.uint(l.lengthSize) + l.place(!moveBase, off) + } + } + if r.short || r.at != len(b) { + return "do not read to their end" + } + return "" +} + +// place counts a field that holds a place in the file, when moves says it is +// one of the fields a move changes. +func (l *itemLocations) place(moves bool, at int64) { + if moves { + l.moving++ + l.furthest = max(l.furthest, at) + } +} + +// moved is head with every place the item locations give moved by front, and +// by what the widening adds to the meta box when wide. Widening turns the four +// byte fields that hold a place into eight byte ones. +func (l itemLocations) moved(head []byte, front int64, wide bool) ([]byte, error) { + by := front + from, to := l.offsetSize, l.offsetSize + if l.baseSize > 0 { + from, to = l.baseSize, l.baseSize + } + if wide { + if from != 4 { + return nil, core.Defect(fmt.Errorf("avif: the coder's item locations hold places in %d bytes, which this does not widen", from)) + } + to = 8 + by += l.growth() + } + + b := head[l.ilocAt+boxHeader : l.ilocAt+l.ilocLen] + out := append([]byte(nil), b[:6]...) + if l.baseSize > 0 { + out[5] = byte(to)<<4 | b[5]&15 + } else { + out[4] = byte(to)<<4 | b[4]&15 + } + r := reader{b: b, at: 6} + count := r.copy(&out, l.countSize()) + for range count { + r.copy(&out, l.countSize()) + if l.version == 1 || l.version == 2 { + r.copy(&out, 2) + } + r.copy(&out, 2) + r.move(&out, l.baseSize, l.baseSize > 0, by, to) + for range r.copy(&out, 2) { + r.copy(&out, l.indexSize) + r.move(&out, l.offsetSize, l.baseSize == 0, by, to) + r.copy(&out, l.lengthSize) + } + } + if to < 8 && by > 0 && l.furthest+by > math.MaxUint32 { + return nil, core.Defect(fmt.Errorf("avif: a place moved by %d B no longer fits four bytes", by)) + } + + grown := len(out) + boxHeader - l.ilocLen + moved := make([]byte, 0, len(head)+grown) + moved = append(moved, head[:l.ilocAt]...) + moved = binary.BigEndian.AppendUint32(moved, uint32(boxHeader+len(out))) + moved = append(moved, "iloc"...) + moved = append(moved, out...) + moved = append(moved, head[l.ilocAt+l.ilocLen:]...) + meta := binary.BigEndian.Uint32(head[l.metaAt:]) + binary.BigEndian.PutUint32(moved[l.metaAt:], meta+uint32(grown)) + return moved, nil +} + +// reader reads big endian fields of a box's content and remembers whether it +// ran out. +type reader struct { + b []byte + at int + short bool +} + +func (r *reader) uint(n int) int64 { + if r.at+n > len(r.b) { + r.short, r.at = true, len(r.b) + return 0 + } + var v int64 + for _, c := range r.b[r.at : r.at+n] { + v = v<<8 | int64(c) + } + r.at += n + return v +} + +// copy reads a field of n bytes, appends it to out as it was and returns it. +func (r *reader) copy(out *[]byte, n int) int64 { + start := r.at + v := r.uint(n) + *out = append(*out, r.b[start:r.at]...) + return v +} + +// move reads a field of n bytes and appends it to out - as it was, or, when +// moves, moved by by and written in to bytes. +func (r *reader) move(out *[]byte, n int, moves bool, by int64, to int) { + if !moves { + r.copy(out, n) + return + } + *out = appendUint(*out, r.uint(n)+by, to) +} + +func appendUint(out []byte, v int64, n int) []byte { + for i := n - 1; i >= 0; i-- { + out = append(out, byte(v>>(8*i))) + } + return out +} diff --git a/internal/format/cut.go b/internal/format/cut.go index 5cba050c..e4d54770 100644 --- a/internal/format/cut.go +++ b/internal/format/cut.go @@ -25,6 +25,38 @@ func PaddingInFront(before, content, cutAt, whole int64) int64 { return cutAt - before - int64(kept) } +// SplitFront is how much of a file's padding goes in front of its content for +// a cut after its first cutAt bytes, where the padding comes in pieces that +// cost least bytes before they carry anything - a PNG chunk, an ISO base media +// free box - so each side is nothing or at least that. before is what stands +// in front of the padding and pad all of it, both sides. +// +// The share is PaddingInFront. Where the pieces cannot land on it, the front +// grows, which moves the content later and cuts more of it - the "at least" +// missing promises - and a side too short for a piece goes to the front. The +// one way the cut keeps more is padding too short for the front the share +// wants: all of it goes in front then, and the cut keeps more than the share +// (docs/TRUNCATE-2026-11-11.md section 7.4). The manifest's cut reports what +// was kept either way. +func SplitFront(pad, before, content, cutAt, whole, least int64) int64 { + if pad == 0 || cutAt <= 0 || cutAt >= whole { + return 0 + } + front := PaddingInFront(before, content, cutAt, whole) + switch { + case front <= 0: + return 0 + case front < least: + front = least + } + if pad-front < least { + // Behind the content there is room for nothing or for less than a + // piece, so the whole padding goes in front. + return pad + } + return front +} + // AfterTheHead passes a stream on and, once its first Head bytes have gone on, // calls Insert before the rest: padding a format puts between the headers an // encoder writes first and the content that follows them. Insert gets the head diff --git a/internal/format/isobmff/isobmff.go b/internal/format/isobmff/isobmff.go index 9b60f7aa..ad8ee4a2 100644 --- a/internal/format/isobmff/isobmff.go +++ b/internal/format/isobmff/isobmff.go @@ -40,12 +40,21 @@ func WriteBoxHeader(w io.Writer, kind string, payload int64) error { // can say. The step below keeps the leftover from landing between one and // seven bytes, which no box could then carry. func WritePadding(ctx context.Context, w io.Writer, seed uint64, total int64) error { + return WriteFreeSpace(ctx, w, "free", seed, total) +} + +// WriteFreeSpace is WritePadding in boxes of kind, free or skip - the two +// names ISO 14496-12 section 8.1.2 gives a box whose content means nothing. +// They are the same to the format, and not to every reader: ffmpeg takes a +// JPEG XL container with a free box near its start for a movie, and one with +// a skip box for a picture (docs/TRUNCATE-2026-11-11.md section 13). +func WriteFreeSpace(ctx context.Context, w io.Writer, kind string, seed uint64, total int64) error { rng := core.NewRand(seed) buf := make([]byte, 32*1024) for total > 0 { payload := nextPayload(total) - if err := WriteBoxHeader(w, "free", payload); err != nil { + if err := WriteBoxHeader(w, kind, payload); err != nil { return err } if err := writeFiller(ctx, w, buf, rng, payload); err != nil { diff --git a/internal/format/jxl/cut.go b/internal/format/jxl/cut.go new file mode 100644 index 00000000..3e1f9360 --- /dev/null +++ b/internal/format/jxl/cut.go @@ -0,0 +1,64 @@ +package jxl + +import ( + "context" + "io" + + "github.com/donislawdev/TestingFilesGenerator/internal/format" + "github.com/donislawdev/TestingFilesGenerator/internal/format/isobmff" +) + +// splitForACut is how much of the padding pad goes in front of the codestream +// box of a file a damage will cut after its first cutAt bytes, so that the cut +// keeps the share of the codestream it keeps of the whole file +// (format.Request.CutAt). The rest stays behind it. +// +// With all of the padding behind the codestream, as an uncut file has it, a +// large file cut at any share kept the whole picture and lost only padding. A +// free box may stand anywhere among the top level boxes, readers skip it, and +// the codestream knows nothing of where it sits in the file, so nothing else +// moves (docs/TRUNCATE-2026-11-11.md section 13). Zero is a file written as +// one nothing cuts. +func splitForACut(pad, codestream, cutAt, whole int64) int64 { + return format.SplitFront(pad, int64(len(signature)+len(fileType)), codestream, cutAt, whole, boxHeader) +} + +// writeAround writes the container around the codestream with front bytes of +// free boxes in front of the codestream box and back bytes behind it, and +// marks its map: the signature and file type boxes, the padding in front, the +// codestream box, the padding behind. A side with no padding has no box and no +// region. +func writeAround(ctx context.Context, w io.Writer, m memo, coded []byte, front, back int64) error { + head := int64(len(signature) + len(fileType)) + box := boxHeader + int64(len(coded)) + format.Mark(w, format.RoleStructure, 0, head) + if front > 0 { + format.Mark(w, format.RolePadding, head, front) + } + format.Mark(w, format.RoleContent, head+front, box) + if back > 0 { + format.Mark(w, format.RolePadding, head+front+box, back) + } + + if _, err := w.Write(signature[:]); err != nil { + return err + } + if _, err := w.Write(fileType[:]); err != nil { + return err + } + // Both sides draw their filler from the file's seed. Nobody reads padding, + // and the side behind the codestream lies past any cut. The side in front + // is skip boxes: ffmpeg takes a free box ahead of the codestream for the + // start of a movie and refuses the file, and a skip box, which the format + // makes the same, for nothing. + if err := isobmff.WriteFreeSpace(ctx, w, "skip", m.seed, front); err != nil { + return err + } + if err := isobmff.WriteBoxHeader(w, "jxlc", int64(len(coded))); err != nil { + return err + } + if _, err := w.Write(coded); err != nil { + return err + } + return isobmff.WritePadding(ctx, w, m.seed, back) +} diff --git a/internal/format/jxl/jxl.go b/internal/format/jxl/jxl.go index 6d7ca328..50ef18f4 100644 --- a/internal/format/jxl/jxl.go +++ b/internal/format/jxl/jxl.go @@ -50,6 +50,8 @@ // something two readers tolerate, and this project's fourth untouchable rule // says fidelity does not drop for the implementer's convenience. The free box // says "nothing here" in the format's own words, and it is what AVIF writes. +// A file a damage will cut has part of its padding in front of the codestream +// instead, in skip boxes (cut.go). package jxl import ( @@ -206,6 +208,9 @@ type memo struct { // which is what makes every size above the minimum reachable a byte at a // time. total int64 + // cutAt is where a damage will cut the file, zero when nothing does + // (format.Request.CutAt). + cutAt int64 } func (generator) Plan(r format.Request) (format.Plan, error) { @@ -227,7 +232,7 @@ func (generator) Plan(r format.Request) (format.Plan, error) { if err := checkFits(r.Bytes, m); err != nil { return format.Plan{}, err } - m.total = r.Bytes + m.total, m.cutAt = r.Bytes, r.CutAt p := format.Plan{ Bytes: r.Bytes, @@ -513,25 +518,11 @@ func (generator) Write(ctx context.Context, w io.Writer, p format.Plan) error { m.width, m.height, len(coded), containerOverhead, m.total)) } - // The map, all of it known once the picture is coded: the signature and - // file type boxes, the box of the code stream, and the free boxes that - // make up the size. - head := int64(len(signature) + len(fileType)) - format.Mark(w, format.RoleStructure, 0, head) - format.Mark(w, format.RoleContent, head, boxHeader+int64(len(coded))) - format.Mark(w, format.RolePadding, head+boxHeader+int64(len(coded)), pad) - - if _, err := w.Write(signature[:]); err != nil { - return err - } - if _, err := w.Write(fileType[:]); err != nil { - return err - } - if err := isobmff.WriteBoxHeader(w, "jxlc", int64(len(coded))); err != nil { - return err - } - if _, err := w.Write(coded); err != nil { - return err + // The map is all known once the picture is coded, and a file nothing cuts + // has all of its padding behind the codestream. + front := int64(0) + if m.cutAt > 0 { + front = splitForACut(pad, boxHeader+int64(len(coded)), m.cutAt, m.total) } - return isobmff.WritePadding(ctx, w, m.seed, pad) + return writeAround(ctx, w, m, coded, front, pad-front) } diff --git a/internal/format/png/cut.go b/internal/format/png/cut.go index b68a6ecd..639ecbb4 100644 --- a/internal/format/png/cut.go +++ b/internal/format/png/cut.go @@ -38,7 +38,7 @@ func writeForACut(ctx context.Context, w io.Writer, m memo, whole int64) error { if pad < chunkOverhead || pad-chunkOverhead > maxChunkData { return core.Defect(fmt.Errorf("png: the picture encodes to %d B, which leaves %d B of padding for a %d B file", m.body, pad, whole)) } - front := frontPadding(pad, m.body-headSize, m.cutAt, whole) + front := format.SplitFront(pad, headSize, m.body-headSize, m.cutAt, whole, chunkOverhead) markAroundThePicture(w, m.body, front, pad-front) // Both padding chunks draw from the file's seed. Nobody reads padding, and @@ -69,36 +69,6 @@ func writeForACut(ctx context.Context, w io.Writer, m memo, whole int64) error { return err } -// frontPadding is how much of the padding, chunk headers included, goes in -// front of the picture, so that a cut after the first cutAt bytes of a whole -// file keeps content*cutAt/whole bytes of the picture's content. -// -// A chunk costs twelve bytes before any padding, so each side is nothing or at -// least that. Where the chunks cannot land exactly, the front grows, which -// moves the picture later and cuts more of it - the "at least" missing -// promises. The one way it can keep more is a tail too short for the content -// the cut should take: there all of the padding is in front, and the cut keeps -// up to a chunk's worth more than the share (docs/TRUNCATE-2026-11-11.md -// section 7.4). The manifest's cut reports what was kept either way. -func frontPadding(pad, content, cutAt, whole int64) int64 { - if pad == 0 || cutAt <= 0 || cutAt >= whole { - return 0 - } - front := format.PaddingInFront(headSize, content, cutAt, whole) - switch { - case front <= 0: - return 0 - case front < chunkOverhead: - front = chunkOverhead - } - if back := pad - front; back < chunkOverhead { - // Behind the picture there is room for nothing or for less than a - // chunk, so the whole padding goes in front. - return pad - } - return front -} - // markAroundThePicture marks the map of a file whose padding is split around // its picture: the header, the padding in front, the picture, the padding // behind and the closing chunk. A side with no padding has no chunk and no diff --git a/internal/guard/boxcut_test.go b/internal/guard/boxcut_test.go new file mode 100644 index 00000000..dddd48ff --- /dev/null +++ b/internal/guard/boxcut_test.go @@ -0,0 +1,340 @@ +package guard + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "image" + "io" + "testing" + + gavif "github.com/gen2brain/gav1d/avif" + gjxl "github.com/gen2brain/jxl" + + "github.com/donislawdev/TestingFilesGenerator/internal/format" + _ "github.com/donislawdev/TestingFilesGenerator/internal/format/all" +) + +// An AVIF or a JPEG XL laid out for a cut comes to every size asked for, its +// picture is where its boxes say, and the cut keeps the share of it. +// +// Both put free boxes in front of the picture for a cut, and a free box costs +// eight bytes before it carries anything, so each side is nothing or at least +// that: where the share wants less than a box in front, a box goes there, and +// where the padding left behind would be shorter than a box, it goes in front +// too (format.SplitFront). In an AVIF the box in front moves the media data, +// and the item locations in the meta box give its place in bytes from the +// start of the file, so they move with it. No other guard asks for the sizes +// and the cuts where those happen. So this writes consecutive sizes cut at +// their last byte and at the half, and cuts of one size a byte at a time from +// just in front of the picture, holds each to its size, to the share and, for +// an AVIF, to an item location that lands on the media data, and asserts it +// met each layout: nothing in front where the share wants nothing, a box where +// it wants less, the share to the byte, and all of the padding in front where +// what would stay behind is shorter than a box. One file of each layout is +// decoded and must give the pixels of the file nothing cuts. +// +// An AVIF of 5 GiB cut at 90% is planned and only its head is written: its +// media data starts past where four bytes reach, so the item location is +// widened to eight. +// +// Canary: an item location a byte off is refused. +func TestAnAVIFOrAJPEGXLLaidOutForACutComesToEverySizeAndReads(t *testing.T) { + for _, id := range []string{"avif", "jxl"} { + desc, err := format.Get(id) + if err != nil { + t.Fatal(err) + } + met := map[string]bool{} + decoded := map[string]bool{} + check := func(size, cutAt int64) { + data, regions := writeBoxes(t, desc, size, cutAt) + layout, err := boxLayoutOf(id, data, regions, size, cutAt) + if err != nil { + t.Errorf("%s %d B cut at %d: %v", id, size, cutAt, err) + return + } + met[layout] = true + if !decoded[layout] { + decoded[layout] = true + whole, _ := writeBoxes(t, desc, size, 0) + if err := samePicture(id, data, whole); err != nil { + t.Errorf("%s %d B cut at %d, %s: %v", id, size, cutAt, layout, err) + } + } + } + smallest := desc.SmallestAccepted(format.Request{Label: true}) + for size := smallest; size < smallest+64; size++ { + check(size, size/2) + } + // Cuts a byte apart where the share starts to want padding in front - + // it wants cutAt times the part of the file that is not the picture, + // less the head - and near the end, where what the share leaves behind + // runs out: j bytes from the end it leaves the padding's part of j. + const size = 4_000 + _, regions := writeBoxes(t, desc, size, 0) + pic := pictureRegion(regions) + rest, pad := size-pic.Length, size-pic.At-pic.Length + start := (pic.At - 3) * size / rest + for cutAt := start; cutAt < start+12*size/rest; cutAt++ { + check(size, cutAt) + } + for j := int64(1); j <= 10*size/pad; j++ { + check(size, size-j) + } + for _, layout := range []string{"nothing in front, the share wants none", "a box in front, the share wants less", + "the share", "all in front, what would stay behind is shorter than a box"} { + if !met[layout] { + t.Errorf("%s: no size met the layout %q - met %v", id, layout, met) + } + } + } + + avifTooLargeForFourBytes(t) + + // Canary: an item location a byte off. + desc, _ := format.Get("avif") + data, _ := writeBoxes(t, desc, 64<<10, 32<<10) + broken := bytes.Clone(data) + at, _, err := avifItemPlace(broken) + if err != nil { + t.Fatal(err) + } + binary.BigEndian.PutUint32(broken[at:], binary.BigEndian.Uint32(broken[at:])+1) + if err := avifPlaceLands(broken); err == nil { + t.Errorf("canary: an item location a byte off passed") + } +} + +// writeBoxes writes a file of size bytes laid out for a cut after cutAt, +// whole, and the regions it marked. +func writeBoxes(t *testing.T, desc format.Descriptor, size, cutAt int64) ([]byte, []format.Region) { + t.Helper() + p, err := desc.Generator.Plan(format.Request{Bytes: size, Label: true, Seed: 7, CutAt: cutAt}) + if err != nil { + t.Fatalf("%s %d B: planning: %v", desc.ID, size, err) + } + var out bytes.Buffer + rec := &format.MapRecorder{W: &out} + if err := desc.Generator.Write(t.Context(), rec, p); err != nil { + t.Fatalf("%s %d B: writing: %v", desc.ID, size, err) + } + return out.Bytes(), rec.Map(size, true) +} + +// pictureRegion is the region a file marked as its content. +func pictureRegion(regions []format.Region) format.Region { + for _, r := range regions { + if r.Role == format.RoleContent { + return r + } + } + return format.Region{} +} + +// boxLayoutOf holds a file laid out for a cut to its size, its picture's place +// and the share the cut keeps of the picture, and names the layout it took. +func boxLayoutOf(id string, data []byte, regions []format.Region, size, cutAt int64) (string, error) { + if int64(len(data)) != size { + return "", fmt.Errorf("came to %d B", len(data)) + } + if id == "avif" { + if err := avifPlaceLands(data); err != nil { + return "", err + } + } else if err := jxlNoFreeAhead(data); err != nil { + return "", err + } + content := -1 + for i, r := range regions { + if r.Role == format.RoleContent { + content = i + } + } + if content < 0 { + return "", errors.New("no content marked") + } + pic := regions[content] + front, back := int64(0), int64(0) + if content > 0 && regions[content-1].Role == format.RolePadding { + front = regions[content-1].Length + } + for _, r := range regions[content+1:] { + if r.Role != format.RolePadding { + return "", fmt.Errorf("a %s region behind the picture", r.Role) + } + back += r.Length + } + if pic.At+pic.Length+back != size { + return "", fmt.Errorf("the picture ends at %d and %d B of padding follow it in a %d B file", pic.At+pic.Length, back, size) + } + if (front > 0 && front < 8) || (back > 0 && back < 8) { + return "", fmt.Errorf("a side shorter than a box: %d in front, %d behind", front, back) + } + head := pic.At - front + want := format.PaddingInFront(head, pic.Length, cutAt, size) + kept, share := cutAt-head-front, pic.Length*cutAt/size + switch { + case front == 0 && want <= 0: + return "nothing in front, the share wants none", nil + case front == 0: + return "", fmt.Errorf("nothing in front and %d B behind, where the share wants %d B in front", back, want) + case front == want && kept == share: + return "the share", nil + case front == 8 && want > 0 && want < 8: + return "a box in front, the share wants less", nil + case back == 0 && front > want && front-want < 8: + return "all in front, what would stay behind is shorter than a box", nil + } + return "", fmt.Errorf("%d B in front where the share wants %d, keeping %d B of the picture where the share is %d", front, want, kept, share) +} + +// samePicture decodes a file laid out for a cut and the file nothing cuts with +// the coder's own decoder, and requires the same pixels. +func samePicture(id string, laid, whole []byte) error { + decode := gjxl.Decode + if id == "avif" { + decode = func(r io.Reader, _ ...gjxl.Options) (image.Image, error) { return gavif.Decode(r) } + } + a, err := decode(bytes.NewReader(laid)) + if err != nil { + return fmt.Errorf("the decoder refused it: %v", err) + } + b, err := decode(bytes.NewReader(whole)) + if err != nil { + return fmt.Errorf("the decoder refused the file nothing cuts: %v", err) + } + if a.Bounds() != b.Bounds() { + return fmt.Errorf("a %v picture where nothing cut gives %v", a.Bounds(), b.Bounds()) + } + for y := a.Bounds().Min.Y; y < a.Bounds().Max.Y; y++ { + for x := a.Bounds().Min.X; x < a.Bounds().Max.X; x++ { + if a.At(x, y) != b.At(x, y) { + return fmt.Errorf("the pixel at %d,%d differs from the file nothing cuts", x, y) + } + } + } + return nil +} + +// avifItemPlace finds the one item location of an AVIF as tfg's coder writes +// it - version 0, no base offset, one item with one extent - and gives where +// its offset field is in the file and the place the field holds. +func avifItemPlace(data []byte) (field int, place int64, err error) { + for pos := 0; pos+8 <= len(data); { + size := int(binary.BigEndian.Uint32(data[pos:])) + if size < 8 || pos+size > len(data) { + break + } + if string(data[pos+4:pos+8]) == "meta" { + for at := pos + 12; at+8 <= pos+size; { + n := int(binary.BigEndian.Uint32(data[at:])) + if n < 8 { + break + } + if string(data[at+4:at+8]) == "iloc" { + b := data[at+8 : at+n] + offSize := int(b[4] >> 4) + if b[0] != 0 || b[5]>>4 != 0 || binary.BigEndian.Uint16(b[6:]) != 1 || binary.BigEndian.Uint16(b[12:]) != 1 { + return 0, 0, fmt.Errorf("an item location box this does not read: % x", b[:min(len(b), 16)]) + } + field = at + 8 + 14 + for _, c := range data[field : field+offSize] { + place = place<<8 | int64(c) + } + return field, place, nil + } + at += n + } + } + pos += size + } + return 0, 0, errors.New("no item location box") +} + +// avifPlaceLands requires the item location of an AVIF to give the first byte +// after the header of its media data box. +func avifPlaceLands(data []byte) error { + _, place, err := avifItemPlace(data) + if err != nil { + return err + } + for pos := int64(0); pos+8 <= int64(len(data)); { + size := int64(binary.BigEndian.Uint32(data[pos:])) + if size < 8 { + break + } + if string(data[pos+4:pos+8]) == "mdat" { + if place != pos+8 { + return fmt.Errorf("the item location gives %d where the media data starts at %d", place, pos+8) + } + return nil + } + pos += size + } + return errors.New("no media data box") +} + +// jxlNoFreeAhead requires no free box in front of a JPEG XL's codestream box. +// ffmpeg 9.0.1 takes a JPEG XL container with a free box in its first two +// kilobytes for a movie and refuses it, and one with a skip box there for a +// picture (docs/TRUNCATE-2026-11-11.md section 13). +func jxlNoFreeAhead(data []byte) error { + for pos := 0; pos+8 <= len(data); { + size := int(binary.BigEndian.Uint32(data[pos:])) + switch kind := string(data[pos+4 : pos+8]); { + case kind == "jxlc": + return nil + case kind == "free": + return fmt.Errorf("a free box at %d, in front of the codestream", pos) + case size < 8: + return fmt.Errorf("a box of %d B at %d", size, pos) + } + pos += size + } + return errors.New("no codestream box") +} + +// avifTooLargeForFourBytes plans an AVIF of 5 GiB cut at 90% and holds the +// head it writes to an item location of eight bytes that gives where the map +// says the media data starts. It writes nothing past the head. +func avifTooLargeForFourBytes(t *testing.T) { + t.Helper() + const size = 5 << 30 + desc, _ := format.Get("avif") + p, err := desc.Generator.Plan(format.Request{Bytes: size, Label: true, Seed: 7, CutAt: size / 10 * 9}) + if err != nil { + t.Fatalf("planning %d B: %v", int64(size), err) + } + head := &headOnly{keep: 1024} + rec := &format.MapRecorder{W: head} + if err := desc.Generator.Write(t.Context(), rec, p); err == nil { + t.Fatalf("writing %d B went through a writer that stops after its head", int64(size)) + } + pic := pictureRegion(rec.Map(size, true)) + field, place, err := avifItemPlace(head.got) + if err != nil { + t.Fatalf("%d B: %v", int64(size), err) + } + if width := head.got[field-14+4] >> 4; width != 8 || place != pic.At+8 || pic.At <= 1<<32 { + t.Errorf("%d B cut at 90%%: an item location of %d bytes gives %d, where the media data starts at %d", + int64(size), width, place, pic.At+8) + } +} + +// headOnly keeps the first keep bytes written to it and refuses the rest. +type headOnly struct { + keep int + got []byte +} + +func (h *headOnly) Write(p []byte) (int, error) { + if len(h.got)+len(p) > h.keep { + n := h.keep - len(h.got) + h.got = append(h.got, p[:n]...) + return n, errors.New("only the head is kept") + } + h.got = append(h.got, p...) + return len(p), nil +} diff --git a/internal/guard/cutshare_test.go b/internal/guard/cutshare_test.go index dadb21aa..6a9d600f 100644 --- a/internal/guard/cutshare_test.go +++ b/internal/guard/cutshare_test.go @@ -32,8 +32,6 @@ type notYet struct { // that leaves is held to every size and share, and so is a new format unless // it is added here with its reason. var notYetCutAtTheShare = map[string]notYet{ - "avif": {paddingBehind, 64 << 10, 50}, - "jxl": {paddingBehind, 64 << 10, 50}, "mp4": {paddingBehind, 64 << 10, 50}, "webm": {paddingBehind, 64 << 10, 50}, // Both take the share at 64 KiB and above. At 4 KiB what stands behind the @@ -50,7 +48,7 @@ var notYetCutAtTheShare = map[string]notYet{ // guard for it, and it stays red until the format splits its padding for // format.Request.CutAt. A format that leaves the ratchet leaves this list too, // so it cannot go back. -var listedBeforeTheRule = []string{"avif", "jxl", "mp4", "webm", "webp", "tiff"} +var listedBeforeTheRule = []string{"mp4", "webm", "webp", "tiff"} // listedAfterTheRule is a problem for every format notYetAt names that // listedBeforeTheRule does not. diff --git a/internal/guard/mutation/entries.py b/internal/guard/mutation/entries.py index 1ee94990..85a5174b 100644 --- a/internal/guard/mutation/entries.py +++ b/internal/guard/mutation/entries.py @@ -7545,7 +7545,7 @@ ), ( "the JPEG XL codestream goes into a partial codestream box without the index one needs, so no reader finds a picture", - "internal/format/jxl/jxl.go", + "internal/format/jxl/cut.go", " if err := isobmff.WriteBoxHeader(w, \"jxlc\", int64(len(coded))); err != nil {", " if err := isobmff.WriteBoxHeader(w, \"jxlp\", int64(len(coded))); err != nil {", "TestEveryFormatSurvivesItsReferenceTool", @@ -14001,8 +14001,8 @@ ( "an MP4 carries its padding in a box that is not free", "internal/format/isobmff/isobmff.go", - " if err := WriteBoxHeader(w, \"free\", payload); err != nil {", - " if err := WriteBoxHeader(w, \"skip\", payload); err != nil {", + " return WriteFreeSpace(ctx, w, \"free\", seed, total)", + " return WriteFreeSpace(ctx, w, \"skip\", seed, total)", "TestAFilmHoldsTheFramesTheManifestDeclares", ), ( diff --git a/internal/guard/mutationcoverage_test.go b/internal/guard/mutationcoverage_test.go index f75f8d12..fde2b99e 100644 --- a/internal/guard/mutationcoverage_test.go +++ b/internal/guard/mutationcoverage_test.go @@ -159,6 +159,11 @@ var provenByProbe = map[string]string{ "fixed codes, must inflate to its bytes and read as those runs - its reach check, every frame of the marker met - and red on " + "2026-11-13 for a frame a byte short (the plan refuses at 65541 B) and for an empty block's BTYPE bit one place off " + "(compress/flate refuses at 65537 B), where the first passed the share and the map guards.", + "TestAnAVIFOrAJPEGXLLaidOutForACutComesToEverySizeAndReads": "its own canary - an item location a byte off must be " + + "refused - its reach check, every layout of the split met, and red on 2026-11-13 with the item locations not moved " + + "(50 cuts), with the widening's four bytes left out of the move (5 GiB: 4831825054 where the media data starts at " + + "4831825058), with a side of padding allowed below a box (4000 B came to 4007 B) and with a free box rather than a " + + "skip box in front of a JPEG XL's codestream (81 cuts).", "TestAPDFLaidOutForACutComesToEverySizeAndItsOffsetsLand": "its own canaries - a table that sends one object a byte off " + "must be refused, and the layout of a document nothing cuts must fail a cut at its half - its reach check, every " + "layout of the split met, red on 2026-11-13 with nothing in front of a document under 400 B of padding (398 sizes, " + diff --git a/internal/oracle/strict.py b/internal/oracle/strict.py index 4826ad63..ea7956a0 100644 --- a/internal/oracle/strict.py +++ b/internal/oracle/strict.py @@ -2065,20 +2065,66 @@ def check_avif(data): if needed not in inner: fail(f"the meta box has no {needed} box, so it does not say {AVIF_MEANING[needed]}") - # Padding belongs after the picture and nowhere else. + # Padding stands after the picture data, and a file laid out for a cut puts + # part of it right in front of the picture data too + # (docs/TRUNCATE-2026-11-11.md section 13) - nowhere else. free_bytes = 0 - seen_mdat = False - for name, start, stop in top: - if name == b"mdat": - seen_mdat = True - elif name == b"free": + mdat_at = names.index("mdat") + for i, (name, start, stop) in enumerate(top): + if name == b"free": free_bytes += stop - start + 8 - if not seen_mdat: - fail("a free box sits before the picture data, and this generator puts padding after it") + if i < mdat_at and any(n != b"free" for n, _, _ in top[i + 1:mdat_at]): + fail("a free box sits in front of the picture data with other boxes between them, and this generator " + "puts padding right in front of the picture data or after it") + + # The item locations give the picture's place in bytes from the start of + # the file, so padding in front of it moves them. Each has to land inside + # the media data. + iloc = next((s, e) for n, s, e in iso_boxes(data, meta_start + 4, meta_end) if n == b"iloc") + media = [(s, e) for n, s, e in top if n == b"mdat"] + for at, length in iloc_extents(data, *iloc): + if not any(s <= at and at + length <= e for s, e in media): + fail(f"an item location gives {length} B at {at}, which is not inside the media data at {media}") ok(f"boxes {names}, brands {[b.decode('latin1') for b in brands]}, {free_bytes} B of free") +def iloc_extents(data, start, stop): + """The places in this file an item location box's payload between start and + stop gives, as (offset, length) - ISO 14496-12 section 8.11.3, versions 0 + to 2. Places in other files or in idat are left out.""" + b = data[start:stop] + if len(b) < 8 or b[0] > 2: + fail("the item location box is too short or in a version this does not read") + version = b[0] + off_size, len_size, base_size = b[4] >> 4, b[4] & 15, b[5] >> 4 + index_size = b[5] & 15 if version in (1, 2) else 0 + at = 6 + + def field(n): + nonlocal at + if at + n > len(b): + fail("the item location box ends inside a field") + v = int.from_bytes(b[at:at + n], "big") + at += n + return v + + places = [] + for _ in range(field(4 if version == 2 else 2)): + field(4 if version == 2 else 2) + method = field(2) & 15 if version in (1, 2) else 0 + field(2) + base = field(base_size) + for _ in range(field(2)): + field(index_size) + offset, length = field(off_size), field(len_size) + if method == 0: + places.append((base + offset, length)) + if at != len(b): + fail("the item location box carries bytes its fields do not account for") + return places + + JXL_SIGNATURE = b"\x00\x00\x00\x0cJXL \x0d\x0a\x87\x0a" @@ -2126,16 +2172,17 @@ def check_jxl(data): if data[code_start:code_start + 2] != b"\xff\x0a": fail("the jxlc box does not start with the codestream signature FF 0A") - # Padding belongs after the picture and nowhere else. + # Padding stands after the codestream, and a file laid out for a cut puts + # part of it right in front of the codestream too, in skip boxes + # (docs/TRUNCATE-2026-11-11.md section 13) - nowhere else. free_bytes = 0 - seen_code = False - for name, start, stop in top: - if name == b"jxlc": - seen_code = True - elif name == b"free": + code_at = names.index("jxlc") + for i, (name, start, stop) in enumerate(top): + if name in (b"free", b"skip"): free_bytes += stop - start + 8 - if not seen_code: - fail("a free box sits before the picture data, and this generator puts padding after it") + if i < code_at and any(n not in (b"free", b"skip") for n, _, _ in top[i + 1:code_at]): + fail("a free box sits in front of the codestream with other boxes between them, and this generator " + "puts padding right in front of the codestream or after it") tail = len(data) - top[-1][2] if tail: From 761530c12666427f8a8e0ebced57120f63121ef4 Mon Sep 17 00:00:00 2001 From: DonislawDev Date: Fri, 13 Nov 2026 19:49:01 +0100 Subject: [PATCH 2/3] A JPEG XL opens in ffmpeg: padding in skip boxes in front of the picture Breaking: no JPEG XL is byte for byte what 0.5.0 wrote. A JPEG XL carried its padding in a free box behind its codestream. ffmpeg 7.1.5 with libjxl never finishes a JPEG XL with any box behind its codestream - free, skip or private, eight bytes or a thousand - so it read no file this tool wrote. ffmpeg 9.0.1 tells a JPEG XL by its first two kilobytes and takes one with a free box there for a movie, so it refused every one below about 3.8 KB. All of the padding now stands in skip boxes between the file type box and the codestream box, and nothing follows the codestream. A skip box is the other name ISO 14496-12 section 8.1.2 gives a box of free space, and ffmpeg does not take it for a movie. Pillow, ImageMagick, the Windows Imaging Component, Chrome, djxl and both ffmpeg read the same pixels from 2 KB to 10 MB. A file a damage cuts keeps the rest of its padding behind the codestream, past the cut, so no file on disk has a box behind it. Sizes are unchanged and the box costs the same eight bytes. The two sentences about the smallest JPEG XL say a box of free space. The structural checker refuses a free box in a JPEG XL. The four golden JPEG XL values are remeasured, and a new guard requires the codestream to be the last box of a file nothing cuts. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 7 ++ internal/format/jxl/cut.go | 28 +++---- internal/format/jxl/jxl.go | 55 ++++++++------ internal/format/jxl/measure.go | 2 +- internal/guard/boxcut_test.go | 73 ++++++++++++++++++- internal/guard/mutationcoverage_test.go | 3 + internal/guard/testdata/generator-golden.json | 26 +++++-- internal/gui/text/locale/said/en.json | 8 +- internal/gui/text/locale/said/pl.json | 4 +- internal/oracle/strict.py | 17 +++-- 10 files changed, 163 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 037644f4..337dadf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,13 @@ because it turns other people's test suites red. padding, which busybox reads, and the padding file inside the archive takes the rest, as it did for larger archives. Those archives are not byte for byte what 0.5.0 wrote. Every other tar.gz is unchanged. +- **A JPEG XL now opens in ffmpeg.** ffmpeg 7.1 never finished one, and + ffmpeg 9 took one below about 3.8 KB for a video and refused it, because of + the padding box behind the picture. The padding now stands in front of the + picture, in a box of the kind ffmpeg passes over, and nothing follows the + picture. Pillow, ImageMagick, Windows, Chrome and libjxl show the same + picture as before. Sizes are unchanged, but no JPEG XL is byte for byte what + 0.5.0 wrote. ### Added diff --git a/internal/format/jxl/cut.go b/internal/format/jxl/cut.go index 3e1f9360..555eaef2 100644 --- a/internal/format/jxl/cut.go +++ b/internal/format/jxl/cut.go @@ -11,23 +11,27 @@ import ( // splitForACut is how much of the padding pad goes in front of the codestream // box of a file a damage will cut after its first cutAt bytes, so that the cut // keeps the share of the codestream it keeps of the whole file -// (format.Request.CutAt). The rest stays behind it. +// (format.Request.CutAt). The rest goes behind it, past the cut. // -// With all of the padding behind the codestream, as an uncut file has it, a -// large file cut at any share kept the whole picture and lost only padding. A -// free box may stand anywhere among the top level boxes, readers skip it, and -// the codestream knows nothing of where it sits in the file, so nothing else -// moves (docs/TRUNCATE-2026-11-11.md section 13). Zero is a file written as -// one nothing cuts. +// With all of the padding in front of the codestream, as an uncut file has it, +// a cut of any share would take the codestream before any padding. The +// codestream knows nothing of where it sits in the file, so nothing else +// moves (docs/TRUNCATE-2026-11-11.md section 13). Zero puts all of the padding +// behind the codestream, where the share wants nothing in front. func splitForACut(pad, codestream, cutAt, whole int64) int64 { return format.SplitFront(pad, int64(len(signature)+len(fileType)), codestream, cutAt, whole, boxHeader) } // writeAround writes the container around the codestream with front bytes of -// free boxes in front of the codestream box and back bytes behind it, and +// skip boxes in front of the codestream box and back bytes behind it, and // marks its map: the signature and file type boxes, the padding in front, the // codestream box, the padding behind. A side with no padding has no box and no // region. +// +// Skip rather than free on both sides, for ffmpeg: see the package comment. A +// file nothing cuts has nothing behind its codestream, and the side behind it +// in a file a damage cuts lies past the cut, so no file on disk carries a box +// behind its codestream. func writeAround(ctx context.Context, w io.Writer, m memo, coded []byte, front, back int64) error { head := int64(len(signature) + len(fileType)) box := boxHeader + int64(len(coded)) @@ -46,11 +50,7 @@ func writeAround(ctx context.Context, w io.Writer, m memo, coded []byte, front, if _, err := w.Write(fileType[:]); err != nil { return err } - // Both sides draw their filler from the file's seed. Nobody reads padding, - // and the side behind the codestream lies past any cut. The side in front - // is skip boxes: ffmpeg takes a free box ahead of the codestream for the - // start of a movie and refuses the file, and a skip box, which the format - // makes the same, for nothing. + // Both sides draw their filler from the file's seed. Nobody reads padding. if err := isobmff.WriteFreeSpace(ctx, w, "skip", m.seed, front); err != nil { return err } @@ -60,5 +60,5 @@ func writeAround(ctx context.Context, w io.Writer, m memo, coded []byte, front, if _, err := w.Write(coded); err != nil { return err } - return isobmff.WritePadding(ctx, w, m.seed, back) + return isobmff.WriteFreeSpace(ctx, w, "skip", m.seed, back) } diff --git a/internal/format/jxl/jxl.go b/internal/format/jxl/jxl.go index 50ef18f4..3aec92cd 100644 --- a/internal/format/jxl/jxl.go +++ b/internal/format/jxl/jxl.go @@ -36,22 +36,33 @@ // of the file asked for - still applies here unchanged, and this format passes // it. Owner's decision, 2026-08-31. // -// The padding channel is a free box, which is the box the container defines -// for space that means nothing. Measured on 2026-08-31 at 0, 1, 7, 64, 100, -// 101, 4096, 100 000 and 1 048 576 bytes, and again with two boxes, four -// boxes, a private box type, a skip box and the sixty four bit box length. -// libjxl through pillow-jxl-plugin reads every one of them, and refuses a -// truncated file and a corrupted one, which is what makes it a witness. The -// pure Go decoder in the encoder's own module agrees on all of it. +// The padding channel is skip boxes between the file type box and the +// codestream box, with nothing behind the codestream. A skip box is one of +// the two names the container gives a box for space that means nothing, and +// free is the other. Measured on 2026-08-31 at 0, 1, 7, 64, 100, 101, 4096, +// 100 000 and 1 048 576 bytes, and again with two boxes, four boxes, a +// private box type, a skip box and the sixty four bit box length: libjxl +// through pillow-jxl-plugin reads every one of them, and refuses a truncated +// file and a corrupted one, which is what makes it a witness. The pure Go +// decoder in the encoder's own module agrees on all of it. +// +// The place and the name are ffmpeg's, measured on 2026-11-13 +// (docs/TRUNCATE-2026-11-11.md section 13.4, O341). ffmpeg 7.1.5 with libjxl +// never finishes a JPEG XL with any box behind its codestream - free, skip or +// private, eight bytes or a thousand - and reads one with nothing behind it in +// a fifth of a second. ffmpeg 9.0.1 tells a JPEG XL by its first two +// kilobytes and takes one with a free box there for a movie, and one with a +// skip box there for a picture. With skip boxes in front, Pillow, ImageMagick, +// the Windows Imaging Component, Chrome, djxl and both ffmpeg read the same +// pixels at every size from 2 KB to 10 MB. // // Trailing bytes after a bare codestream were measured too, and they work - // both readers take them, down to a single byte, with no dead zone at all. // They are not used. They are not a structure the format defines, only // something two readers tolerate, and this project's fourth untouchable rule -// says fidelity does not drop for the implementer's convenience. The free box -// says "nothing here" in the format's own words, and it is what AVIF writes. -// A file a damage will cut has part of its padding in front of the codestream -// instead, in skip boxes (cut.go). +// says fidelity does not drop for the implementer's convenience. A file a +// damage will cut keeps part of its padding behind the codestream instead, +// where the cut never reaches (cut.go). package jxl import ( @@ -76,7 +87,7 @@ const ( // containerOverhead is everything the container costs around the // codestream: the signature box, the file type box, and the header of the - // box the codestream sits in. The free box header is counted separately, + // box the codestream sits in. The skip box header is counted separately, // because it is what makes every size above the minimum reachable. containerOverhead = len(signature) + len(fileType) + boxHeader @@ -99,7 +110,7 @@ const ( // for every seed there is. Measured across all of them by // tools/probes/jxlladder on 2026-08-31. // - // The container and the free box header are included, because this + // The container and the skip box header are included, because this // generator always writes both even when the box carries nothing. That is // what removes the unreachable band above the floor that PNG and GIF have. // @@ -151,8 +162,8 @@ func init() { // half that matters: both refuse a truncated file and a corrupted // payload, so both can say no. exiftool reads JPEG XL too and // accepts the truncated file, so it witnesses nothing. - Name: "a free box after the picture", - Where: format.PlacementEnd, + Name: "skip boxes in front of the picture", + Where: format.PlacementStart, Capacity: 0, }, Label: format.LabelVisible, @@ -204,7 +215,7 @@ type memo struct { // from the ladder without coding it and the work happens while writing. coded []byte // total is the size the file has to come to, so writing can work out how - // much free box follows the picture. There is always at least one, empty, + // much skip box goes in front of the picture. There is always at least one, empty, // which is what makes every size above the minimum reachable a byte at a // time. total int64 @@ -289,7 +300,7 @@ const holdsPerPixel = 34 func checkFits(want int64, m memo) error { floor := int64(minimumBytes) reason := core.Says("jxl.MinimumReason", - "the smallest picture this format draws codes to %d B at worst, the container around it costs %d B, and the file always carries a free box, which costs %d B even when it holds nothing", + "the smallest picture this format draws codes to %d B at worst, the container around it costs %d B, and the file always carries a box of free space, which costs %d B even when it holds nothing", core.A("Coded", minimumBytes-containerOverhead-boxHeader), core.A("Container", containerOverhead), core.A("Box", boxHeader)) // A picture named by hand can be larger than the smallest one, and then its @@ -299,7 +310,7 @@ func checkFits(want int64, m memo) error { if own := int64(len(m.coded) + containerOverhead + boxHeader); own > floor { floor = own reason = core.Says("jxl.MinimumReasonOwn", - "a %dx%d picture at quality %d codes to %d B, the container around it costs %d B, and the file always carries a free box, which costs %d B even when it holds nothing", + "a %dx%d picture at quality %d codes to %d B, the container around it costs %d B, and the file always carries a box of free space, which costs %d B even when it holds nothing", core.A("Width", m.width), core.A("Height", m.height), core.A("Quality", m.quality), core.A("Coded", len(m.coded)), core.A("Container", containerOverhead), core.A("Box", boxHeader)) } @@ -330,7 +341,7 @@ func checkFits(want int64, m memo) error { // width and height are settings, and 40 megapixels is the ceiling. // // Ceiling is the LARGEST file that rung has ever been seen to produce, the -// container and the free box header included, and it is what lets planning +// container and the skip box header included, and it is what lets planning // choose a picture without coding one. Measured by tools/probes/jxlladder on // 2026-08-31 across all 256 seeds, four orders of magnitude of requested size - // the label carries the byte count, so its length moves with it - and with the @@ -514,13 +525,13 @@ func (generator) Write(ctx context.Context, w io.Writer, p format.Plan) error { if pad < boxHeader { // The ladder's ceiling for this picture was too low. Said out loud // rather than written short, because a short file is a wrong file. - return core.Defect(fmt.Errorf("jxl: a %dx%d picture coded to %d B, the container costs %d B and the file was to be %d B, which leaves no room for the free box every one of these carries", + return core.Defect(fmt.Errorf("jxl: a %dx%d picture coded to %d B, the container costs %d B and the file was to be %d B, which leaves no room for the skip box every one of these carries", m.width, m.height, len(coded), containerOverhead, m.total)) } // The map is all known once the picture is coded, and a file nothing cuts - // has all of its padding behind the codestream. - front := int64(0) + // has all of its padding in front of the codestream and nothing behind it. + front := pad if m.cutAt > 0 { front = splitForACut(pad, boxHeader+int64(len(coded)), m.cutAt, m.total) } diff --git a/internal/format/jxl/measure.go b/internal/format/jxl/measure.go index 581553a7..d4763274 100644 --- a/internal/format/jxl/measure.go +++ b/internal/format/jxl/measure.go @@ -13,7 +13,7 @@ package jxl // FileSizeFor reports how many bytes this generator produces for one picture: -// the coded picture, the container around it, and the empty free box every +// the coded picture, the container around it, and the empty skip box every // file carries. It is the number a rung's ceiling has to be at least as large // as. // diff --git a/internal/guard/boxcut_test.go b/internal/guard/boxcut_test.go index dddd48ff..b7acadc0 100644 --- a/internal/guard/boxcut_test.go +++ b/internal/guard/boxcut_test.go @@ -74,9 +74,9 @@ func TestAnAVIFOrAJPEGXLLaidOutForACutComesToEverySizeAndReads(t *testing.T) { // runs out: j bytes from the end it leaves the padding's part of j. const size = 4_000 _, regions := writeBoxes(t, desc, size, 0) - pic := pictureRegion(regions) - rest, pad := size-pic.Length, size-pic.At-pic.Length - start := (pic.At - 3) * size / rest + head, pic, pad := boxParts(regions) + rest := size - pic.Length + start := (head - 3) * size / rest for cutAt := start; cutAt < start+12*size/rest; cutAt++ { check(size, cutAt) } @@ -133,6 +133,73 @@ func pictureRegion(regions []format.Region) format.Region { return format.Region{} } +// boxParts reads a file's map as what stands in front of all of its padding, +// its picture and all of its padding, wherever the padding stands. +func boxParts(regions []format.Region) (head int64, pic format.Region, pad int64) { + for _, r := range regions { + switch r.Role { + case format.RoleStructure: + head += r.Length + case format.RolePadding: + pad += r.Length + case format.RoleContent: + pic = r + } + } + return head, pic, pad +} + +// A JPEG XL nothing cuts has nothing behind its codestream and no free box +// anywhere. ffmpeg 7.1.5 with libjxl never finishes a JPEG XL with any box +// behind its codestream, and ffmpeg 9.0.1 takes one with a free box in its +// first two kilobytes for a movie (O341, docs/TRUNCATE-2026-11-11.md section +// 13.4). So this writes the smallest sizes, where the padding is one box that +// carries nothing or a few bytes, and larger ones, and requires the codestream +// box to be the last box and no box to be a free one. +// +// Canary: the same file with an empty box behind its codestream is refused. +func TestAJPEGXLKeepsNothingBehindItsCodestream(t *testing.T) { + desc, err := format.Get("jxl") + if err != nil { + t.Fatal(err) + } + smallest := desc.SmallestAccepted(format.Request{Label: true}) + for _, size := range []int64{smallest, smallest + 1, smallest + 7, smallest + 8, smallest + 9, 2 << 10, 64 << 10, 1 << 20} { + data, _ := writeBoxes(t, desc, size, 0) + if err := jxlNothingBehind(data); err != nil { + t.Errorf("%d B: %v", size, err) + } + } + + data, _ := writeBoxes(t, desc, 2<<10, 0) + broken := append(bytes.Clone(data), 0, 0, 0, 8, 's', 'k', 'i', 'p') + if err := jxlNothingBehind(broken); err == nil { + t.Errorf("canary: a JPEG XL with an empty box behind its codestream passed") + } +} + +// jxlNothingBehind requires a JPEG XL's codestream box to be its last box, and +// none of its boxes to be a free one. +func jxlNothingBehind(data []byte) error { + last := "" + for pos := 0; pos+8 <= len(data); { + size := int(binary.BigEndian.Uint32(data[pos:])) + kind := string(data[pos+4 : pos+8]) + if size < 8 || pos+size > len(data) { + return fmt.Errorf("a %q box of %d B at %d", kind, size, pos) + } + if kind == "free" { + return fmt.Errorf("a free box at %d", pos) + } + last = kind + pos += size + } + if last != "jxlc" { + return fmt.Errorf("the last box is %q, where the codestream should end the file", last) + } + return nil +} + // boxLayoutOf holds a file laid out for a cut to its size, its picture's place // and the share the cut keeps of the picture, and names the layout it took. func boxLayoutOf(id string, data []byte, regions []format.Region, size, cutAt int64) (string, error) { diff --git a/internal/guard/mutationcoverage_test.go b/internal/guard/mutationcoverage_test.go index fde2b99e..8baf5595 100644 --- a/internal/guard/mutationcoverage_test.go +++ b/internal/guard/mutationcoverage_test.go @@ -159,6 +159,9 @@ var provenByProbe = map[string]string{ "fixed codes, must inflate to its bytes and read as those runs - its reach check, every frame of the marker met - and red on " + "2026-11-13 for a frame a byte short (the plan refuses at 65541 B) and for an empty block's BTYPE bit one place off " + "(compress/flate refuses at 65537 B), where the first passed the share and the map guards.", + "TestAJPEGXLKeepsNothingBehindItsCodestream": "its own canary - the same file with an empty box behind its " + + "codestream must be refused - and red on 2026-11-13 with the padding of a file nothing cuts put back behind the " + + "codestream (all 8 sizes).", "TestAnAVIFOrAJPEGXLLaidOutForACutComesToEverySizeAndReads": "its own canary - an item location a byte off must be " + "refused - its reach check, every layout of the split met, and red on 2026-11-13 with the item locations not moved " + "(50 cuts), with the widening's four bytes left out of the move (5 GiB: 4831825054 where the media data starts at " + diff --git a/internal/guard/testdata/generator-golden.json b/internal/guard/testdata/generator-golden.json index 1ec1b63f..e5ed1054 100644 --- a/internal/guard/testdata/generator-golden.json +++ b/internal/guard/testdata/generator-golden.json @@ -146,18 +146,18 @@ }, "jxl_64kib": { "bytes": 65536, - "sha256": "1f7946aacc7f6a90c3b2cc9713dca2a9113d1b76d7ec61691b52935d74b26437", - "measured_on": "2026-08-31" + "sha256": "eef78830e117ca9bfca4a06e09f84f3da2fffe2f7237b4a96dca7eb77bf93f99", + "measured_on": "2026-11-13" }, "jxl_odd_size": { "bytes": 65537, - "sha256": "768e0af192480e02607d4fa6f0f343f1cb0dd8ab49d373c92245f3aa68caa017", - "measured_on": "2026-08-31" + "sha256": "5f55ef75b2e4a56d24d03b493e82561beb34260e136dca626e7f3d4cca76716c", + "measured_on": "2026-11-13" }, "jxl_quality": { "bytes": 65536, - "sha256": "c5c522aed0d2051a20f8eb52bfecd49bb13f41cf86b30170eaf3c05998323a9a", - "measured_on": "2026-08-31" + "sha256": "405418822737987df23e31d0e5927fa9472438eb5a9a10915031c1d8631b9e27", + "measured_on": "2026-11-13" }, "log_8kib": { "bytes": 8192, @@ -653,8 +653,8 @@ }, "jxl_label_cut": { "bytes": 16384, - "sha256": "47e864c31b44ecc262d3b2f9cc9cca6f404daba0bb0dbc0f252cb8d470aa3311", - "measured_on": "2026-10-27" + "sha256": "04c4b0ffa9b8f631f800f60f0436ae8b2a206266ded04bccab340b6cba75e3dc", + "measured_on": "2026-11-13" }, "mp4_label_cut": { "bytes": 65536, @@ -773,6 +773,16 @@ } }, "remeasured": [ + { + "on": "2026-11-13", + "why": "A JPEG XL carries its padding in skip boxes in front of its codestream now, where it carried a free box behind it, and nothing stands behind the codestream. ffmpeg 7.1.5 with libjxl never finishes a JPEG XL with any box behind its codestream - free, skip or private, eight bytes or a thousand - so it could not read a single file this tool wrote, and ffmpeg 9.0.1 tells a JPEG XL by its first two kilobytes and took one with a free box there for a movie, so it refused every one below about 3.8 KB (O341). With skip boxes in front, Pillow, ImageMagick, the Windows Imaging Component, Chrome, djxl and both ffmpeg read the same pixels at every size from 2 KB to 10 MB (docs/TRUNCATE-2026-11-11.md section 13.4). Sizes are unchanged, and the box costs the same eight bytes. This is a breaking change by the owner's decision of 2026-11-13. Guarded from now on by TestAJPEGXLKeepsNothingBehindItsCodestream.", + "files": [ + "jxl_64kib", + "jxl_odd_size", + "jxl_quality", + "jxl_label_cut" + ] + }, { "on": "2026-10-15", "why": "A page with no label to fill its title carries Page there now, where it carried an empty title - the smallest document and every page under --clean, in every size. The Nu HTML Checker calls an empty title an error, so every such page was invalid HTML since 2026-08-01 (O277). Page rather than the tool's name, because --clean is there to keep the tool's description out of the file. The smallest html page goes from 118 B to 122 B. The catalogue of every element names its forms article tfg-forms, and its two links to it, because DOMPurify takes out an id that shadows document.forms and the links then led nowhere (O282) - the reason the links list is tfg-links. Its hidden field is named tfg-hidden, because a name hidden shadows document.hidden and DOMPurify took that out too, leaving the field out of a submitted form. The page of a newsletter says its language, , as the html format's pages always did, written in the frame so quoted-printable gives its = as =3D. Inside it, the line in Polish and Japanese marks each half with its own lang in a span, on two lines where the Japanese half comes, so the page saying English does not make a screen reader read them as English (review of #190). A message laid out simple is unchanged. This is a breaking change by the owner's decision of 2026-10-15, docs/HTML-6-2026-10-15.md. The two placeholder pages had no golden case and have one from today. Guarded from now on by the structural checker, which refuses a document without a title with text in it and a newsletter page without its language.", diff --git a/internal/gui/text/locale/said/en.json b/internal/gui/text/locale/said/en.json index e9d67579..d475d061 100644 --- a/internal/gui/text/locale/said/en.json +++ b/internal/gui/text/locale/said/en.json @@ -2322,13 +2322,13 @@ }, "jxl.MinimumReason": { "description": "Said by internal/format/jxl - a refusal under the box it is about or at the foot of the form, or a note after a run. Carries {{.Coded}}, {{.Container}}, {{.Box}}, written the way the program writes them - keep each spelled exactly that way.", - "hash": "sha256-8031f7cf3cc6", - "other": "the smallest picture this format draws codes to {{.Coded}} B at worst, the container around it costs {{.Container}} B, and the file always carries a free box, which costs {{.Box}} B even when it holds nothing" + "hash": "sha256-96322e155f28", + "other": "the smallest picture this format draws codes to {{.Coded}} B at worst, the container around it costs {{.Container}} B, and the file always carries a box of free space, which costs {{.Box}} B even when it holds nothing" }, "jxl.MinimumReasonOwn": { "description": "Said by internal/format/jxl - a refusal under the box it is about or at the foot of the form, or a note after a run. Carries {{.Width}}, {{.Height}}, {{.Quality}}, {{.Coded}}, {{.Container}}, {{.Box}}, written the way the program writes them - keep each spelled exactly that way.", - "hash": "sha256-08ce5283cdaa", - "other": "a {{.Width}}x{{.Height}} picture at quality {{.Quality}} codes to {{.Coded}} B, the container around it costs {{.Container}} B, and the file always carries a free box, which costs {{.Box}} B even when it holds nothing" + "hash": "sha256-ab4120801908", + "other": "a {{.Width}}x{{.Height}} picture at quality {{.Quality}} codes to {{.Coded}} B, the container around it costs {{.Container}} B, and the file always carries a box of free space, which costs {{.Box}} B even when it holds nothing" }, "log.ClientAddress": { "description": "Said by internal/format/logfile - a refusal under the box it is about or at the foot of the form, or a note after a run.", diff --git a/internal/gui/text/locale/said/pl.json b/internal/gui/text/locale/said/pl.json index 0affa011..677035eb 100644 --- a/internal/gui/text/locale/said/pl.json +++ b/internal/gui/text/locale/said/pl.json @@ -462,8 +462,8 @@ "html.UseOneOfThePictureFormats": { "hash": "sha256-a6669f6abe6b", "other": "Użyj jednego z: {{.Formats}}." }, "imagelabel.ThePictureIsPxTallAnd": { "hash": "sha256-238ba2886f79", "other": "Obrazek ma {{.Height}} px wysokości, a etykieta potrzebuje {{.Needs}} px, więc jej tekst jest ucięty i ten plik nie niesie czytelnej etykiety. Wciąż wskazują go jego nazwa i manifest." }, "json.HasToBeStyle": { "hash": "sha256-c1343585d922", "other": "musi to być {{.Indented}}, {{.Minified}} albo {{.RecordPerLine}}" }, - "jxl.MinimumReason": { "hash": "sha256-8031f7cf3cc6", "other": "najmniejszy obrazek, jaki rysuje ten format, koduje się w najgorszym razie do {{.Coded}} B, kontener wokół niego kosztuje {{.Container}} B, a plik zawsze niesie wolny blok, który kosztuje {{.Box}} B nawet pusty" }, - "jxl.MinimumReasonOwn": { "hash": "sha256-08ce5283cdaa", "other": "obrazek {{.Width}}x{{.Height}} w jakości {{.Quality}} koduje się do {{.Coded}} B, kontener wokół niego kosztuje {{.Container}} B, a plik zawsze niesie wolny blok, który kosztuje {{.Box}} B nawet pusty" }, + "jxl.MinimumReason": { "hash": "sha256-96322e155f28", "other": "najmniejszy obrazek, jaki rysuje ten format, koduje się w najgorszym razie do {{.Coded}} B, kontener wokół niego kosztuje {{.Container}} B, a plik zawsze niesie blok wolnego miejsca, który kosztuje {{.Box}} B nawet pusty" }, + "jxl.MinimumReasonOwn": { "hash": "sha256-ab4120801908", "other": "obrazek {{.Width}}x{{.Height}} w jakości {{.Quality}} koduje się do {{.Coded}} B, kontener wokół niego kosztuje {{.Container}} B, a plik zawsze niesie blok wolnego miejsca, który kosztuje {{.Box}} B nawet pusty" }, "log.ClientAddress": { "hash": "sha256-df4616586839", "other": "adres klienta" }, "log.ConflictDrop": { "hash": "sha256-9d99490328fe", "other": "{{.Why}}. Usuń jedno z dwóch albo zmień drugie" }, "log.RequestMethod": { "hash": "sha256-eaa67a9c3b30", "other": "metoda żądania" }, diff --git a/internal/oracle/strict.py b/internal/oracle/strict.py index ea7956a0..2493ae34 100644 --- a/internal/oracle/strict.py +++ b/internal/oracle/strict.py @@ -2172,16 +2172,21 @@ def check_jxl(data): if data[code_start:code_start + 2] != b"\xff\x0a": fail("the jxlc box does not start with the codestream signature FF 0A") - # Padding stands after the codestream, and a file laid out for a cut puts - # part of it right in front of the codestream too, in skip boxes - # (docs/TRUNCATE-2026-11-11.md section 13) - nowhere else. + # Padding stands in skip boxes right in front of the codestream, and a file + # laid out for a cut puts part of it behind the codestream, past the cut + # (docs/TRUNCATE-2026-11-11.md section 13) - nowhere else. Never a free + # box: ffmpeg takes a JPEG XL with one in its first two kilobytes for a + # movie (O341). free_bytes = 0 code_at = names.index("jxlc") for i, (name, start, stop) in enumerate(top): - if name in (b"free", b"skip"): + if name == b"free": + fail("the file carries a free box, and this generator pads a JPEG XL with skip boxes, which ffmpeg " + "does not take for a movie") + if name == b"skip": free_bytes += stop - start + 8 - if i < code_at and any(n not in (b"free", b"skip") for n, _, _ in top[i + 1:code_at]): - fail("a free box sits in front of the codestream with other boxes between them, and this generator " + if i < code_at and any(n != b"skip" for n, _, _ in top[i + 1:code_at]): + fail("a skip box sits in front of the codestream with other boxes between them, and this generator " "puts padding right in front of the codestream or after it") tail = len(data) - top[-1][2] From bdd07978cca40b9f0c54cf075ab03ad3233f2013 Mon Sep 17 00:00:00 2001 From: DonislawDev Date: Fri, 13 Nov 2026 20:13:21 +0100 Subject: [PATCH 3/3] One name for the box that pads an AVIF, a JPEG XL or an MP4 The changelog entry on cutting an AVIF or a JPEG XL said that files nothing cuts are unchanged, which the breaking entry on JPEG XL contradicts. It now says so of AVIF only. The sentences on why an AVIF, a JPEG XL or an MP4 cannot be smaller named the box that pads the file in three ways: a free box, a box of free space, and in Polish also by the box's type. Free space is what the tool calls room on a disk. All five sentences now say a padding box, as the PNG sentence says the padding chunk, in English and in Polish. The screen of a refused size is redrawn, still three lines. The guard that sweeps a cut AVIF or JPEG XL wraps the decoder's error, and fails on an end region, which neither format writes and which its count of what stands in front of the padding would miss. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 4 ++-- internal/format/avif/avif.go | 4 ++-- internal/format/jxl/jxl.go | 4 ++-- internal/format/mp4/mp4.go | 2 +- internal/guard/boxcut_test.go | 15 ++++++++----- .../testdata/screens/generate-refused.png | Bin 124634 -> 125608 bytes .../testdata/screens/generate-refused.xml | 4 ++-- internal/gui/text/locale/said/en.json | 20 +++++++++--------- internal/gui/text/locale/said/pl.json | 10 ++++----- 9 files changed, 34 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 337dadf6..04f1d2b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -129,8 +129,8 @@ because it turns other people's test suites red. interrupted download does. Chrome, Firefox, Windows, libavif and Pillow refuse the cut AVIF. Half of a JPEG XL still shows the whole picture at lower detail in Chrome and in libjxl with partial files allowed, because the - format sends a coarse picture first. A cut of 90% shows nothing. Files - nothing cuts are unchanged. + format sends a coarse picture first. A cut of 90% shows nothing. An AVIF + nothing cuts is unchanged. Every JPEG XL changes (see Breaking). - **tfg is on npm, for tests in Node.** `npm install --save-dev testing-files-generator` gives Playwright, Vitest diff --git a/internal/format/avif/avif.go b/internal/format/avif/avif.go index 9a29d09b..6945018f 100644 --- a/internal/format/avif/avif.go +++ b/internal/format/avif/avif.go @@ -248,7 +248,7 @@ const holdsPerPixel = 8 func checkFits(want int64, m memo) error { floor := int64(minimumBytes) reason := core.Says("avif.MinimumReason", - "the smallest picture this format draws codes to %d B at worst, and the file always carries a free box, which costs %d B even when it holds nothing", + "the smallest picture this format draws codes to %d B at worst, and the file always carries a padding box, which costs %d B even when it holds nothing", core.A("Coded", minimumBytes-boxHeader), core.A("Box", boxHeader)) // A picture named by hand can be larger than the smallest one, and then its @@ -258,7 +258,7 @@ func checkFits(want int64, m memo) error { if own := int64(len(m.coded)) + boxHeader; own > floor { floor = own reason = core.Says("avif.MinimumReasonOwn", - "a %dx%d picture at quality %d codes to %d B, and the file always carries a free box, which costs %d B even when it holds nothing", + "a %dx%d picture at quality %d codes to %d B, and the file always carries a padding box, which costs %d B even when it holds nothing", core.A("Width", m.width), core.A("Height", m.height), core.A("Quality", m.quality), core.A("Coded", len(m.coded)), core.A("Box", boxHeader)) } } diff --git a/internal/format/jxl/jxl.go b/internal/format/jxl/jxl.go index 3aec92cd..63329091 100644 --- a/internal/format/jxl/jxl.go +++ b/internal/format/jxl/jxl.go @@ -300,7 +300,7 @@ const holdsPerPixel = 34 func checkFits(want int64, m memo) error { floor := int64(minimumBytes) reason := core.Says("jxl.MinimumReason", - "the smallest picture this format draws codes to %d B at worst, the container around it costs %d B, and the file always carries a box of free space, which costs %d B even when it holds nothing", + "the smallest picture this format draws codes to %d B at worst, the container around it costs %d B, and the file always carries a padding box, which costs %d B even when it holds nothing", core.A("Coded", minimumBytes-containerOverhead-boxHeader), core.A("Container", containerOverhead), core.A("Box", boxHeader)) // A picture named by hand can be larger than the smallest one, and then its @@ -310,7 +310,7 @@ func checkFits(want int64, m memo) error { if own := int64(len(m.coded) + containerOverhead + boxHeader); own > floor { floor = own reason = core.Says("jxl.MinimumReasonOwn", - "a %dx%d picture at quality %d codes to %d B, the container around it costs %d B, and the file always carries a box of free space, which costs %d B even when it holds nothing", + "a %dx%d picture at quality %d codes to %d B, the container around it costs %d B, and the file always carries a padding box, which costs %d B even when it holds nothing", core.A("Width", m.width), core.A("Height", m.height), core.A("Quality", m.quality), core.A("Coded", len(m.coded)), core.A("Container", containerOverhead), core.A("Box", boxHeader)) } diff --git a/internal/format/mp4/mp4.go b/internal/format/mp4/mp4.go index 3aa217fd..48bb3fe0 100644 --- a/internal/format/mp4/mp4.go +++ b/internal/format/mp4/mp4.go @@ -116,7 +116,7 @@ func belowMinimum(requested, need int64, c video.Choice, s video.Settings) error Requested: requested, Minimum: need, Reason: core.Says("mp4.MinimumReasonPictures", - "a film of %s at %d frames a second with a key frame every %s and a new %dx%d picture every %s takes %d B, and the file always carries a free box, which costs %d B even when it holds nothing", + "a film of %s at %d frames a second with a key frame every %s and a new %dx%d picture every %s takes %d B, and the file always carries a padding box, which costs %d B even when it holds nothing", core.A("Duration", core.FormatDuration(s.DurationMs)), core.A("FPS", s.FPS), core.A("Interval", core.FormatDuration(s.KeyEvery*1000/int64(s.FPS))), core.A("Width", c.Width), core.A("Height", c.Height), core.A("Change", core.FormatDuration(s.ChangeMs())), diff --git a/internal/guard/boxcut_test.go b/internal/guard/boxcut_test.go index b7acadc0..3f29debe 100644 --- a/internal/guard/boxcut_test.go +++ b/internal/guard/boxcut_test.go @@ -74,7 +74,7 @@ func TestAnAVIFOrAJPEGXLLaidOutForACutComesToEverySizeAndReads(t *testing.T) { // runs out: j bytes from the end it leaves the padding's part of j. const size = 4_000 _, regions := writeBoxes(t, desc, size, 0) - head, pic, pad := boxParts(regions) + head, pic, pad := boxParts(t, regions) rest := size - pic.Length start := (head - 3) * size / rest for cutAt := start; cutAt < start+12*size/rest; cutAt++ { @@ -134,10 +134,15 @@ func pictureRegion(regions []format.Region) format.Region { } // boxParts reads a file's map as what stands in front of all of its padding, -// its picture and all of its padding, wherever the padding stands. -func boxParts(regions []format.Region) (head int64, pic format.Region, pad int64) { +// its picture and all of its padding, wherever the padding stands. Neither +// format closes with an end region, and one would stand behind the padding, +// where head does not count it, so meeting one fails. +func boxParts(t *testing.T, regions []format.Region) (head int64, pic format.Region, pad int64) { + t.Helper() for _, r := range regions { switch r.Role { + case format.RoleEnd: + t.Fatalf("an end region at %d, which neither format writes", r.At) case format.RoleStructure: head += r.Length case format.RolePadding: @@ -266,11 +271,11 @@ func samePicture(id string, laid, whole []byte) error { } a, err := decode(bytes.NewReader(laid)) if err != nil { - return fmt.Errorf("the decoder refused it: %v", err) + return fmt.Errorf("the decoder refused it: %w", err) } b, err := decode(bytes.NewReader(whole)) if err != nil { - return fmt.Errorf("the decoder refused the file nothing cuts: %v", err) + return fmt.Errorf("the decoder refused the file nothing cuts: %w", err) } if a.Bounds() != b.Bounds() { return fmt.Errorf("a %v picture where nothing cut gives %v", a.Bounds(), b.Bounds()) diff --git a/internal/guard/testdata/screens/generate-refused.png b/internal/guard/testdata/screens/generate-refused.png index d9462bd7d0cbb1b048e869800bd73a716f3be376..e369d7f44b4a937a0884f1d7299a2be63352ea8a 100644 GIT binary patch delta 64650 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 CI@yl^ delta 63691 zcmZU)Wl$VZ+paqh+}$m>ySoSX1b4UK!D(EQ;2tcvLvZ)t4#7P*1b09EzWdvIpE{>% zYO3MKOwa1I9=Y%9DVc*`9*6&>(*wLsu6qPFsaqa19F3<~D!QI^q&6=s9&#`g&|!Sh zJ;KsafM(7OEfm}AVa;V>W{IN-gGq?{JV;Z6E%e!?$x^?+c87KN$a0;JNPZ~cg#Udz z?5DTkyP&gG!tt>Vw^Q3Y5+z=d`MFV!R6m-nO=t8yDP#>a4|mhYF1D;&B_rTVJ>55m zRE<%#Cml@^`q-E=zn0z44E;D_s=16Sn@@TR2We6a7A>;JDzq&b$6FSU4?A#=<~Pn5 ziSka|kDNAM2r&Ote>J1Q@%@%HBqZU43REg4PRlePB(%aV1^(^1*#0?*a=}2DK@2T+ z<;n;zXg@SfBzSS#of)i~aj^p6@grm#P|GK5r0vBstcfxdbjh*hvrjwKh*5m=+Ngf? z+X`Q#XO`Ler6G_zofHbQBr9Ds_rQKYKMB)Q=~82Gq{IeCY^_|M%} zn>m1y4;x*A9l_O>J6+cP$8P=?Z&!nCl2p2VzU^UMJUqd&8UBJ&fu)tV*Gm}#BG?ro zul8am&wyL_FY;fVf;-QEql+SSF`XJ133KP37srziLTwlrekW$*vn{&lMKtdbE_L1P zjefqN&`pL|2(E1xj~daBtr3yGlTuqbKS_TiP zaecKCWHzO zv{10+nm0;iMM1!WgC|>RmaXKIOCG5W=p+x}b<>6rq$P>Dz4lgRj%6(!V!(LBMxU{k z*OO)98uK)DYGiiN3YwiXZRoC$xHNY#jZW_WAti2*HQyi7X%Od@D%O=NT{yeH_*b<$ zW}e{$4>6I<_bzS(J~t}gF7#6o+UnHEC97;OlLqYkc_22_AAyHy`tTuTqhU9sHC$jU z@2%P3P3!Ys&`mk2EESC8ll}_nCGdmdeIlxM+zYa@6An`QzqCqMy&G3WIpNnzxZbZAerjQ& zGq?T(haxrS_daFPT&q&_&-#P>;f&ScdB>nCFu#a(cvu6hF;@1RZ_O2L=~moe6ODt9 zF`H$mMTiCy;C|vJSw&6}*+m@}s^cV+Q)GDjORT@`z+E-nsq40z{`_wZc8Qv#%82>F z`Ifmg(ZE`+@KGV0OZZC_0Q+OSmy^W$8%7#_rxW9{*sk*Q zcJ+#+ycJrAmS0_>iM9oJB&WA^k;^KcEW(q^JnfEOKP7!jBXw`c>ro}jAdy)lBTH3T zX){9%q`-g#tgHvo^rg+C1#dKZkT@Je)WUSH{GDgFWn3R7xORoF;EL579;51ZCwHwkk~2-D;}X|| z^`kQInb=OoChn~dIfYRUqX#rQ{GH~q*iG!9S>Hx>7#ssAh%p*|T3MTLy-zMlHLt0YeUcS)@bd1HSA3ePgeQE z+@*7`m6r)p(x)w=0qV}1cNuC%j0vjAz}=ND*GHR5oXFRt9~SzvY)Ehm{nADaf=6N% zPJX__y_Y8$m=ONCl?5RVj+2$cBX4G=7ss|dz-i%6M?3plaLZeo!i$n_m_L0R@*67T z9dxjj&6h3hcWi8ELE=fHmRCnFITVyAzUsq$d)@EtiNyoovnKQAX^eL2TO$*u0++U|*#xT1$h|{RC zU}LdIaj&)tC?2J>vS!`J!5FM@?zPhSuoS7BD^B4hm0^4m6+W2g+{}@DwD5~;3K6DI z#nTWr>T4gES}_Y{n%!wJB$~N_9}^Ztn&sB~!gMu5)Rbss39936Ivuv$(Gp^x@iQV+ z-0vI7 z^Zs7w<-3T!k0)V-prRzHHt6lEhO1DNT>I>I<9=VE_wd=*BR zx?*jtv#7zG%~2y?{jj(pzk(omk$WUm?^um4P=~$h@O2RSPMBZy5o|55{K9x2rfxk*`uLwEGdeRpniFuWDW)SE? zq#4Amx)nmvc8mXJ09>!oBpb0MFzl_Y$gsLjI|YqAKGc1*ciyt5WSe?ZWr)J{>k+;Z zY3`jf*s`l~=Fx6m_UoH7aPEP{|L@zY@8;#sGp(?|)J@xeZpRh;&>c$rmj7H%J4F~M z#Qe|w4i@e-Cy}HkY-_mw-+%4{o`pNzpFf|9-4U@q(nKi~_OPpz&rK|Erxv>#pLy}F zyf@rtleQII_0>$AX>UoD4&fr{)Wx8n4?R3JNdEhV&5wX&**eOtx9`VKY@UDZM*HeY z7vE05lau3glo}$ImHl_zGC{77aqc@J08N0xo7_v8sB6Iq8>?wke_N^r01XItCX60j z1zV2-I6Y>pNT`i-;+gSj)CqK9?ow2zlO}9<(9;s-f@w4MYO51;g@tf3;uZm^ht-= zzb$9a?=cH!vbCEr5uiS!RQA{~S?nklyVz>&6HYW{kfBhTDin7`JrA)y@?ao9w#byi zK3Pj*I58$$uq;23!^F#R5=Ap6Ukbh$M8W^BSHNx*{JeA+5aGkFdJ%9@&mMsCxRIJd za&~w^NZ!=AM&vbn_%xq_2h;$f58S|eulQl`Pu8c$z&K+eW8CbYih`>SJgOPqRidwZskFvri|xCxgxB^?#VdmtKX<-LVoI`U~flZsiSxG-%PaPL8GXChYGK5Q3=* zM8}D}YVwxZ(bEGwwC?lMkvkpF{Mw2>R|P=2x!ryxZ;<>D>UbUPht(493}z#l9kXjl zC#D8SP81+t34=L;P0eP-!?d@vy#TetDdgkyroO(X|jarU>6o{xRDU<|a=vE; zVd75r#}H(Vz3Lt2^R23{C|$<~QP~%W!Z0U>od=VL3~c-#kNX%=0_NRO>-4)c41RIZ znGX)v&4;|n+?RA-Tou_9)pa(B(q8&?b?Xj4pqi>X$1R(bkm5{E%TsIP04;#AV{=UP zChb9Q;O60#O_Z!K%v#2eYX$ip$0zg`YyWI?RykW@vW^B1fxnB{zNu`l+UBDPQ|U~r z`6F}j*nWgR@@Rjrz2wi(6vmr=5Uj4&U`0oM$!+tLw>fWXxM})rPB>!GspV0cz?M1h zLv=4@mdTg(WrZ&SOg3=w=X1bOGO<~Hr^9DMBBEytmA&Is*0YJxT6!&+haROSz@YQd z*=qSa(nlWS`YQtgyD8Wnc>IEY3}c3`H$D2tX)hgSwmL(74Wa2*>hF? zw-EMUN?kHdpS9fED#02mYZ$1_#-U%U5HTz?z|qUXSg|~$?O_sG18dPpnjpZ|)M)U0 zaiQ`gV>@q9i^v#`r4LwmN-on2GMJ!_KUMnv&4go6>nP;Ja3TCdg%z2Xy`KYCYW|LX-lixyB<@&PYgKDoQ;@^uAB#^eq0s*q$^&VZhliI6labM)ughf5L-> zZ4bEM#KWnf5-9{UzO-jpcPw(NUECL6ae{>v*6{RBSB6=BM+vY47}$!#`Usy^d+UY&z-Gr`s$1!8lW z#+&1782Hf<-H9Fk#oq7c_j1Gow^&>_7(_`bdz?FCfv*c^Q&n696W6GjTd4f)d>zwX zwM}OZ8{N?4r+}e6V%!po+BkmJ-y6;I=E{qjC#7nYH`cc`wO~EPh`W#%9CyiYh z{g!Sq8alb+q(Pslt)cT9T~b^Xx=sD?4_%*a`@WKW24cRYFeYmW=TcM4RW1Pjl_$&B z=j<4eY^EWBKkH!(1f#u@8tnpX+H*g5`!IHvB(E{{x^uA+Vl7z^%sIWW6W<(cY7wU{ z9I8=k)XAtd78dWdSsZmNCPvQH2%vHG{B5Pvpg2fBpSh;ICbkPa1VNn{Rc&OYo=loB zqaw%L0+(Km6(hQr3U?Rl82DlDa<@g=-TYJ3`=qAA7falYojQiK)+fa{G0zvYWz&sk7|JqEr$ii&PQVusSvc=^JWiKX- zI^lI8W-eUf;YwqbpuLP6Ub?%sh9v!L2jJ=o*gw744p)Dio0xqn<4YIqT&`z%&l}%Y z#pxC(jppmGM4c#oL_+*j*5WurG={g`zl??7M;%`lmNzkd0Y0k^4^#@sv!m(ylLsnb z21^9|m7o<#Y3RN^=8ECrb^Iy?EziD6LHJtMlB^-J5%u5TCa!*nSejg$8<7UQ$fE(*XO88Q7_(STMIFjP7 zi01ga?3jb;gX@c5%7@TA5-L_J7n>SOjRXfjgi(@w}vTDEGudzV2x%>OFC(r=d~fr$0&L#T0Gbm>F}iK z=R=XdTUzq}C3E$y=##sJ?VooiS*f9UU~<|PAjws_4KU2FRB-spXYJ@tohVnIBY^DJ z%&@*XFkfA`TMSt5+e_?q^=w2|jnGi>Th4wiC1y}-B%ec}PwMO~~ zOLKVZS5trdroa-jw>u=uXcpsP$lRS4;k^y;r@|Xm=-*an2pgRzR!;WoLC+F#(?X-! zcGllEPvCb5GXnA=B9u+w;(vh^kFndz?eBY+=skeduB z&e7}oq`yC2<@k8w-!=S13ZSy*ACmbC-EDTJ_Vp zOnF|fr=@k;N?<0$m|Sp;Sr4;Ir=vGk;;klvuR^P{$xpqptD5EXd7_~CD-@J*kyj19 z*vh2mGHF`jEx^pefQZU?yw4{ePClyerm2tzNcrYlcv*iM5ZU{3g*-ftc>dH`*QQ7D zX#e?>x>|RM!kP$g3`9Ic=PQE)8$NEq)1%+QoFNmAn0B0F8#ytLLcuz>US?{sZhi=u z7>?m0AQ39Fh%kY@6mNuU`1X0d#;hYwwoG2&9jS_8o`3cRstMaX{*Sq@sTh z*_6*s3e|BvsE&=+BgDiz7=S=1dS~6dbxL$TW6F{b>#&z;A)ottn+7RoueABq z=x}&cMBw+jKP{A5;*i*JeZ91BRE`7;N$}jOx{OO_U(RO!vZD|B$BMf9s6ZZxGH5gk zjl}4+xg!e$6FrtTqB~jM-}VNI(?sCIus#Ed4nifTi) zDbzQmM~53%v@oB%2>76>{4cVn`vD+Oeme_=oWvnU`>47FpUWeE0zC6j&;9fMndyrwhtOGallZ-gdC6&pApCud%}Es zSSs7K%iq%RWW$YkGrK`zMa_y>*E;I@#Ac0wD0X|Tffx!ut5Jat)eh8@oNv!q&UZ1} z#K+XjeJJ7?M?>dii0?~}^>xLTu>m;hCfZ7}nagNG!uv6qFrgj`z}1XpL13A!xYKIuGkTgsOsH7R=(y9S_gj z>^3cQ{XN`=x4-*Py^>;&`iL#kfdjoY%ERfbHsPHBO4(rr|cseRj9`M3T{;#Sa@Mmqr(HQ-n_U?Fmf{9_cq2) zFDQOBVq+lDQX)P1H*tRDFO1ya-9vFdJyPf$6j1E*#EK*hb}UOczJR<1jK>dF%Xs8` zWuL@cicoynBwI3J^hGrY!pX!8!&^Chyn;S|4;BX^I^bn`f-sr)j+|nL#_R$8g+;F< zy3v*nC&}Brzj;z8hS)^Pt<{r?$@rs>(=JZLWTdktA3h#2b~co7EHOzS-QuafDf_;4_U zouYo}!lRQ<%jX9LpODjwr-@Kh25TCdrrs`p^3P7vMUNW3oOq^{Hk-Tu>%&z4060~gzJDXsv?mjBBdb}& z=advlo1eZ80HfZ&mwF)jyGls|R|OLL_3tH4s^FhTP>JdIn+x>u6TII*4=gMQ$}Xgb z*YuqI*>#s@3{PcX8wvWIXijGk3}njj0uV8d3UFC#C#dGpeeLv5tesQe!hoFcd*ju~ zAAc_*U`y$XnxN?6XG4Mo%Xm%~U$b_Da{H7#vvIJ<0{Z|Rz@^*G{~cI5=#r87H0M8o zg6ICzef6h&);4nAM^U4eq~NZY8mGn@mAebpGkm{|u*W|Ahz|!a!3x!HRdv4BDzdo7 zizX>mr;5sg>*Kz4aJz+I7!WgRao2Ph6G}a9qWz6zQA;O#mNJ}y+aGlYuABa5wdm@T7d*_&ism-BvRKNJ6wNl!ecAIMo9AzTU&U#{7JB~ zF-M*3T*7@UPcM=XpK^NayK$kpJ-d(YWR}3k;SK0r(&Q3s6Ew+$`>He8cZmdtVMXGO zSYOr!92|W*R5$W3sN28V%OR0K(;*_NW#Ql*imm~=8n$&7P{@b;=(D$PPG`*O_Ed8* z&to%%_esic_pkqu`#$};IUUUIY)WNrr{g(nL8iB-?Kua{CakvD(QHwt&hUO_Y42JJ zjOPP8?ABIgW&dU~#77RQA*ys+avpB8+%7ub$4(>tRtDC`9IM;Nce$W^*Sp^5fLv~u z@(;i?VDwP*8+)Ns;geTet4?6!uf4cc0=kHlL?&+>5ZRKoi)a*I}jO@*76Uw z+tz#3sOzJ>v9m|P2{y)j_iHG+o*hWJdU;NW`)OJ@a%;F!V(t#HgGoO2noT)drUM31i5wA(T6fAB&m zhJ3ZF8e_kYj9*QKNV1}!EN(2Diue*Ghr)Pk3>~AB_2U>O8v(`&Gw6F~n2vSU6Pv79!6jv(#1+?*+am3ZYGR|ORRbnkEr zQ~<8wm-)j669uwu%*-fEVqYUDNKoK8)|NjE=tV>rGcoW_&n{4;7!Z@W7|FE`4uqtC zF2pqLMDf8&MGdBa3ZJWEcOkx6TKkBVTFHCRMEzTr>Nmoc)ilde23P6)IvJ^@vZBm2 zMWQawR~D0Q*^hqThMg6P+ZchA-*rpYUhjqt8ei}RuKa_wzp>0e&c{y!O<(+enaO8) z4dMOeA^wOcy{E%T51QIXaTaP-L+5q$0-#!>=L;olpU^517OddT9SE-S?u*|_+td0; zH53G6Xs6MnQldYJc=*r&?dd2^%c^00?iMxhR^|;Z5HXrJb61@KgY@k5 zrNq6IIEZ5QFeMBKBRe~k!Jr<>>dA|HArQOC`C~(+LzafIVUIe;P8sR0aLCO62`Mzz zy4Y7^NSJ?%>ZM^^JfRw%Em&#c;hZEi55KsqX6UFi;85#qL$ubHnzF)W&e1s_@LWzr#9AnCuBNVGt=y;-2OS$h5EZOQ&|-`%Hp;8pRw_r2fIO8kuE<3?~&!qiU> z_?U@!)EU`fgD)pP7ilYu2{yZQl8Co@dh?v0XleKPyTJT1x@T{ywD*`+@)|Y#Anhz* zE?xRthYu=TJ2awGC&_c8MpL29175nL(vt)qv4(Oy&OIAp(E7Fx+NEmNY2Rpj!U;-dFK+cdLw9H{V+ zK=pjSh%;O|x<&Ux5A?_a@94Uo4GPK?r3~6m%yo3Y)C+=vw zMzUM5|8S^!M?8%X3br)4n-?B`-^UwF^K*Y+a;^Bq+~kIV3BPSRlp_H&@j^Zbwiefy z^zZgyTPspYa=rLB4GhxPx02FL3jD?uPR%jI!SPb3#u~wy^E0hYUYJzAy_4?k!8o6- zK8`L*+_Q{@*_Pv9+^WhXCr@VoH_sa_p~~&{k@CCd$_bjrkvj|lG$yxVyspi>n)CVU zw;G;o3!QvEY8Qd@SJ6SB&9@(Ew+?m*3Iz@Xp*&j_rBxy6ThZ7qbxZ+bS%?%Wf&~u- ztKYrNNtZFX>(}JCg(7dYj0{MKGRZeR^(_csBvrFJrszG~PsQ|&8n~IM`MN%IS;r;zh>6KLr~!0RneKzBi01=lk8H`c zq`28q*4fm%i)iQ`DLY z>%XOoa#T4Z+`OF+E;l!gIW-BTC50ni>~2(-*f6>;fSQ{$3z zm%>5(d{7Xm2*54vJ!4ijWV`4l$OLRrqt~tjS}te)PHnb}zu_afnPB)FJ%@$o3iJtJ zVE970jZuD(jPn*2Ie3ma$FRxi_Zm=LOlO1-O`Co>TpeRaw@MX|0kzO}dM(EFJkv(h z*v9mxb4(LCd-m~rSF7J3Op;fuT9KxQMHGBe>sws~Y-QM=pcP}guqR4hHi>?d6AddH zfdocKJaN=oOYlV_zmx17qg;$G=Rq$l9;@78Mn~?Em?{VjsvujY?+i zu5O^aS@tS*43@8WN3KYVH`}ef?QUqGVU$u5eaVs{^gRN+#O=nPBqOJ`z8tBv1E;q+ zdJjQsf0NTN4_W>S-K+L}tHYtJ4>8r>5mpGWJA~MtPW{(w5J+4^Pn0~hIo!v?etc|LAPWEhJ>sVzDva8 zp~^m)6XpDId^Sj(_~}IKJK^@3vV3OMjsdx3OK&7awPF1bKmiG)i2O(fkvLcTa0leZ ze1=8=^jaOH9FoTUEzoc&DkBk|`tIo1wG_z9IoAEjJ&y&28R56eiCoL*6+|wYPYMU z>G$I|#>NO3O`{>S+G{4A9+MvLHUMoE3RQEh*zz(xP~%vobz8f-n&V1Z*;!MHs3s>hp)b zMQmYms`)EYGcWEvG|obQLWVpuZ@mpb44)OaYA_FNO2 z|2gTc6e`U9(rDmibhWXw`^>Z%ss{#M)r&_***oHwwTy6aS~fJqdKO-NuP;Q)wb_`eV8Ya~lY zhWi~VUqb$ekJO;cM@IVK;`4fmLM1PO%I)o3BpfN+(6g&BE0PQv8~j{3W~fCn&RS%_ zaSV?I+U4)dFo*Ba%kkN*Z+dMZc8qbu_F-oFTEEsDm1KNy-WG;n47YI+l3?`XlV1P5A4A>$U3>Xy;M!B99LerER#i1mVHO@n_|Cb zAMd|&dxje^#61*UpYI9;TV+ZV3#7~kMBdZqsvrsWq{D#Im}q&c+}~N!1y~noJez;uLe_0i zc%9h30906K^2)!+TA)Zy5A;Z|46sOGf)PUGyg>A8e{97R_;-SA*6Q>vwqF8#KAyW4 z0j+i|HwCuMLNxL6loAkUZ8PBvSrKzyH!{29WfFYSNm9YW~mp#B?ac>T20L&iJVm5_L`h@1f`gc`#4ZG zbgt!uh8Emj`iJz;mNMOMpdnM97Ou4gww1%ILpWz*oco8;!avu+Td7S`URfWV-&2Vl?fk0M{kc7Z73zMPf@>hnXt;E^XmzUPbeir+Y}OHwKw7N` z7W$1{=$PT&Rt-maYW43~NATwPiGlQ~6Bt9G8O?WVQw*fTm;9ZUSu7{NQR4?pu5)J* zru=j-S~{VyzWX{$AfW}9@ULpN=(b-B?;TcO=%_k@U~sPqw+i!6R*mR9)`Ud=wyNVw zGbbg^3jht8i_t5(OZ!DjR+x_nvQ(+EJ-jb(BqX+Hw}sPR@OKKl+&;;M0?S`Y-a*ue zFmEq=pIfk((3O=*4-Z<|c%mQ@vM>V6OILETWn%BfsWG>Q1#2utQp&e=_?*lQ+>_`8 zOK1GskwaLf-EA5JFQVG8w$rJxQe|JHT%SD#AN!IObB5#xB`{Ee4Tu~y>`Sl8c?kRn z+}pjC&^_JPl5t|k<;CDmfQ{o%m3$u-NRCfg5K%`s^n3b5((M1?41o`sY*NqUL zvG_laqovLA@nJP5Maw+J#}vcQ(lo%MxjYSIc@geFr!BqhK^f)gP)SpK1I zH<`<57xZb*cq<0_erZ&17=8-Et>vHZ+n%unk$fl&80a3S6+uvZgHU*Bn`OdBU1tlR zUW4(tzb6PhX&V(SpiSz-Pj&K?js&RvL4rSo={3!@By6K60qbf%sT<0p{shoK_3nh= zvYB8AgY>?sf1*^*5_{FWuuIXuhu};x+I}gFKh%T)jqM{X9Ws>uN6)bC_CYFlkNu;n z7R6%8i4woJh-hZ+#xCeU+hOZlfpv2CI!L*0OTkEU1>rCE_MCs>bO`lTaP4@Z-kU z0eSvrmiH3@QWFmMKRcsj0SZ4i-_mJ|VDWP`U+o6xbHV*FY2(KF&USVH%vNOp`IiZY zW0WwJyMx0kU!*JE!TxTHMGnqKP_4A^>GG-BSzB%e0sK3hV5G|1m(~GmWHq-yjcVY; z>;$C7vxgMu{yL9i9g49os0z8Q*NyUi8{;$^6jD?yduu+)B?l&7N$j8EG`u%1X77q= zUU>N00N2aPA57#GI%cCl^69a1=+;uBnfbM?rlPII;z093wchf2muqrL;=@Vn3d$Z7 zXqu~2;XqL|cQvd{M&B-#;rb-XQ>Owe^XcR!!^?MeAICxDuDH>WK(lnC#UK@bQ|wNs z%j0ll6#0q`aM*CzlRR3p#B02oo+|=JR6GlcnU_2_o%M_H)1P}3k~%g`@0Fb1)ZK)2 zlEtql%g3v6@hK@NW^F_rZ63bOQD*nUiSGQn?ow2odZUO`%5S5`>M&oolMCH) z7b9=^z@a8sEHq_r><35%N&^Bgapx@|R3Z-z3zD=)1iWv7Y zHnxwo^zBsFsDF9dcKef!&y=K^-F6PjK{3}_Brt|#BtEabGRHl-7kVBi+e?I?^d1~x z8Zzu2!*@O~ZUv=sbtC#K0C#TybI4-SxWtZ-%;n(jrr`@4#vM-!p5(SrX80y$OqdX|+|KZ$5TW@@p&bea0?a?)`F z1e`SrFQ;estBKjphv)XRzadYowa7bh+M*8NGqRffyNjx`^!@5OxzRFg!l``dUahrY zHca=rwtR8>H*5}A{W4jTc$@yR-sXA(D0~H29X7sGbZ<>m5w^^)@OUg12SK|3OO*G2 zufd(rqQlDByLox~qNPB%U^DV~AGNA0(yCE-6vbuPc2!Gm5C=XhG5=s!D(O=JmO%bV_ zuT;`7qWc9Y!I?cnGMO>?O7-y&1%c;>#vh;jkU9iu474meZYVeHZSd4GbINlTy30k2 z2b%IG3zuoEwBOcE&o`%`h~ScEvt){Ko^zNu?#JemCh z0qI7@(u{1@%%R2Xf*im|R?S6J(+vAB07r0* zBJXicBC<0TT7_b*H!%)#UN9G-bJ~i|TA_7Q$PH{ee$3dDHz1O6;vSE`h(+kj#;MgR zbzNMA4xxyU{djcUsFV6I>rjUP0}+gOHsm;Nl@2u}c8j#|_5)h1EHCh%im!d9D&F%C zEnU4wLfe;kA5A}pCL9qyI2$D$C0WDDYxmLOcO%tc#fK>b@s>~alS_MK_PohRkfHNy zM-&)@;P+~d>=Wa}))pTyAmZ~ntNPH;Fd){yPuI#S45l_1feH#f2?~g_EqC(kKoJR9 za2oYYfvg+$HV}X_(hCyUt8HZSHm>+_7gwFc4!n<=l>mz*+_z44BV(j8#JMayd;&W=4;;VCK@| zsct^im-*lH_L7gZ9<9qM3gKNOVfU z(aX}|;Hj&&8IX6?K21VypRFKM1@pwvVo0i2@GK&HkuBaPjo4LXA!4 z|7lRYx(G~$5(i-%3^?1sKvArQ2)vQBK_EDAus8;6Ic%x2{g*gzWt+0pk6Z+9H}`Yz z;DbT7I#XB05R)unudjj3<$q)F2KPYl|N5d&(xL0AKP+DCiPrUN=+`FUD;<=Jmr~2_ zop%!~&Wt~qu%IFOR5nk6POX-30I;#F;Uq}v%+D_581)VGjqP9Tt%T!#w2N>|JT9o3 zU?6(Z4wza_yuH=%b02{C+DYzBM^v)Tn6JbKrva)8f4lUZBy{WFtRJspt>Yf&K_F7^f07h}HwZ%@Sf^`40YyQ9ZKDd>}Dt0U$9;}|8+CPST3J#Gt ze+XW6dwHiLKZ0VMLjr6x*&km*zx0X-i#j^=j9`K_m+od?vaLHgpN@j+-aYWNmX4v= zyJe)8rajL_&y{LS-E$sdJ6z*XEfMydqphFGG$T&YOv@;|vVo7@Gd{EB58{nhX&*Re zz%jjqmP}aDRnz37*#WEg)r4vKky&$lzY6#$cX|GjY(r?PgeYS3*^t$>wt)dLTbst@ z3{Z%km-)~dAL&Sy|5Vjr3J|_1QuU(J&Z4i`bf^$P0U%{qUmPKw`&^QHxb^){M=Ei6 zQp%$x$Y0<^gxjEmzbq_g6!cAJSNLkG!7mtJ)qzA6>5o#u22_yR<%!2Ur8e7NyiWz2 z-~K>w1z=*d&+dPpOk;i!@+B=(1H~J@0qKV}4lpXcb0p=$1H$VtBPp1udXYljxnOw7 za9=z67WY_OQYXG8B;TqizmyPFB7#jO7&2aM$v&WSUer`vgI1I591%2(i^MIhp7;@NZ} z@4}{|2;9@SEy+kgIW6SLP_IS)X1U;~$!2bt_WCb3Yu%9mo3U*k>Kdj-+a-qTUk<`M zRcP|d;UAo0qwe+lY4qnJ;b#)Ov9YZ`t3!!uH~(NV7{{&JL(+B&D{uLKjf|YJ8#qcA zu3`|M*v8<0wf1E}Le(RU3P*tgAip>%lVrv3R$yA%iXXf(Rsy?N#`KACU4qyg2+6!V zDN-F`{t$g)^rfTyjxa-!@)Z|}S>t%Uo;qvVD|`X}Z1-kj#_SmVHPrg5?kz6US)Cn( zd#m}W&(qr-zK!5)K3RN*OAZv9TOr@syM4W+;lCowuu+|-D;(v9>x(i1j0*7WLFw&A zA;t?dmwrm>&QG!-BKl1jbdo{>!+N0J+UlFZip&e0E#>54a>i2nYJ9Lp#Jn9ut0^BYeXb*pirx7)Ok8u#~8SG{^vLbzPNlo545Dv+HO4Nm#;nT&`q zEt4sK4Kz943=Np$Mgi5^TbbIloJu1V9w!SV=ltrZn8j=yV8Pu1NL zQ=X)2eG0oDm{R$j#5ogXt^sbLmmt_-5CuYh*ZXmL%ZXX?-NS%ZnFSi(EO|6tsD!h= z*=kCtPWywU)#C%LTeJCIu#FR|Q8P974ztrwb;h;yESF*db^slwN9KLcB>tXUa+%LX z+|54oA_n%2pXp~1Qhb1VHI%ZrtB-L>JFQ+lGaL62S#Q;Tb-TB{2pjG^CO91|>07PH$hy3LR0N z6QxwT!QEjO;D6?Y|8xC+FKh00u47acijoKe)r{aa}Ie#7I7{u4B4K7$@L97G)aJqz|u zS4Gp|MMc9!AlM{k-%c9`kLv=)^)&Wu$zMi6D>?LK5K`OaEs0I?!eUfdKsb z;MDP^Yjf3&2&R-~%&2*;qOH-Q`Kxy&e6~uJAXP7l06~EKlT-CCE_#*2_lekldicOs z1uB?+6>SSXSZX9B2Yo-+8sFIW9tbr{v0EIDCB#9D<5Uv&7BCQV=oFbJv$aIura?%~va7(CEPi+FO3Hw|$2`O24S(*#Us@|g;FYJnYn^kR#P z!z2hF)qH^}gXvA);@bB+ZpaobQQM@54DFkaf*}{oQY?08*dqXC1+We{CZzAL>mZ7t zZd`0+%$@Rqd0F7%uyxClD@x);pY#}xRk<+ih3h^ekuNr%zV|CA4` z&F5D^Z4)l|0U0G&2zNMpt%;HE$xfrCW=2E)YLTNsg0&;4?fU9puDu9m2$gQ14)+(G zoucxgAu#DJas5ol$TR*OY>4n-t`9P~AY5W80!=Z*{UrKD6e_sk%NDaRl=Hf=mHqGa?oqlsSHi_^P1Upf&!HUq zKj(6^q~E4p9RlEhP@+SF^PCvJKgh){fvyRMC%}(y; zXlFn{?ll!8zZcUX#+DOHhfE>-Kcu~NKoworJ}iQOh=73Pp%D=2?v@Ve2BkX=oug9H zC0)|e(%sT=2ZEVTcRPD}fP)^RWLbxbaVyg`~tdsWVV?9BzO8L=&uL&0&BYQv2fj1JpM{N6Px36$beGoFNP-=CP&=UBFQ#AW3kL<_s!GPb9E)}7 zYN&iMIUq+K3-g)0n*M6_0rg1~;)Azxd+y@UuKGPQUrwWQ$ zb4)%Bak{BR-O=Wv03kogavqJzc=urU6 zf|b9Yu~qo#r&mYs|NqxE`Cya>4@Oet6HtP#{$WN2Y5**J)e8sX3Lx_B?7JhmR=shFlgXa$Auv#0o zpeNfhf%F)K(+xc2M|DOMdgWH7TAZ52$*;gLjG~PYb*HYvg;_05FujM{P9N()dq>BY z_i|=0q|Dh|BEmo-Ld?sa92j5r5r|HdF))CzPM3+;*(A4wr}q3yP;fMe9!2VML-uw( zsy%fYJ`!506ahZx(A%XD=+iu#=Ft;dT`7T-y=hB65}Sh)H{%<4jVW@h41=ckqPK00 zATRq$+Q6yOrYY(Cx9+zbA0J!{Rdc0Kb+2{AYYJb$Hv~CiTk87{jaMQINSCh>i zVD%owOsK?aZE1sl4bA@v&P3FE)B63nC%m@nFKoZbXjA&C}?eq>*bD@@i5fk)bF z+p{DU0vB1bjYZ8m`fzvGZvDQ;3)!nnZZ2h^qOm{q39uN@F$5|c!*%SV=tsZ1`JyLx za@r=2SYTASde<4r%=Pvz2&amrxgQq{N0-0NYgFL=9n$@G^mT*!Z#0OvrvBHIgn!soR1>9uqOeua{>!R1D+=Lq9=M{Jy#i_(^}J zi|c*57gql9W2eU(=}y_xu*Tp|EH-miD>5`0(+$3z?FW|?J55Sxq+A5g()v!ivpPyg z9gDw2vHt;XqU2xNzA!A6(<7RA%kfU#ZUa$??QtM^feI&lnfI{^2SVG^v;ja&koPBD zatD*WN{LTpcMRS`WKlHIGKXYRdF4PlZ&7ncMKk+ zQdavyr13ErG*zfwSj-{=G`*-Bl%tEWg(F=&k?kp#MZKnFZ;+09nidHrVXRvNKPnZ0%3z2i^+#+qtiUpmjiuHa2J-Ot;Vy` zn)`liCMwy}@NIi|59lfZXJKZ&I=asT_ILDuBJ%(1s{evbAj?+&8IPZg37TZSILlTe zPfuL_1}=cVqWJYLCOZE;h54$>4&Rr%owF*ZdO+GT(q^>N(tJ|7+WMIC=Yzi$q0-rW zQP3H9m}N=tS=HB7iFFW?vsmp`65bc!7c03hFYl?)najb+WoZRVEHV#6EB;(mAi*5X z)uY}Aox z^)iG9W%z^B&%fSCd4bI@0hW$6EZQZ60x%`{3vvkRrd@zIYH*j4&{Ca7QKeRK74pAJ z^mqB51VQ3W8REkV3S@LdqP%3tSuCqd-x46h+((6s$x(U{pzk4ny`@S$;+4#Hwqvkwme6ua`gs z=)q$ZHsB)&EY}))OwrkCr$c24SQZe4n;98V5}=RHo`*|j%gD)vOHdjd@RTq*XvHfi z8Ip$fQBhIpFlNNWU}FUJ^!Pa6`=Jd~R9C}-#4@v`?!~OnX(9Q2{a4RmaARX`f%IoO z5tz*e=4?sW+{8;X5?Ib=l`_h>wR7T;A(1C1>kI?k!p|rN`Y-B~Vkn&f+W&P21x|WL zt*Wojxv|Au_X@K)E37qbH6{xuCu^Av_j9WoBXmkiztXAVuJ6uZh)J7m^!r?&VPF^t zx*uW*ntU*3OFBESPX+t-R<5QE*Ic^bsgI9g(@}Sd^L<+2yTtx}G_l^9N|KPQk>e&- zA|O0c*Z@0xm_+z)%HpJjFG9SmzHu{z3m9Fj*M!|l>OAJ6qgOG@aSr-t&(-I~(Q~jaWJmcKG?0gMLA3IdRCy=hiMz zIZepN%-OlPc+j$TuCOru^03o5F77!@P;>8GiDn7sr?XJCagWmNos8(n7|wh;d=t!( zk&gFz+&D7MW>!szhv(vQ^FD|F!{5E~UvHbhsQ56@>8NM9rOKs?(NiELDap^r=hN~S z`s&dmj~6ex_|kqJg*m&XUwdXJDCUltDLM#lXO*)tuCfSFzzpZoL zBJ1qjA6CStFo8n1tEUY51_$NkwW@2~&QA1f?Cj(f-+@OjEM!zwag2kl9x1#}N<>8C z&!FGn+!=VPQS|&j1i|0K`!UqO+tJNnkuL+bd9D;657;^Lgb)!Wo0*x_*c23(E|Q`J z(9(D-np?`qI6A?}nih$jiKNof(n#(lJ}ubo>|A$jhT`x4E zp81-w{30eM9yD{b*$pJOfWzS$rGqy={j%Zuf#a7Grv9B2LD_T!=yCgh?jT-@i;p?XTD98jb}$UMqM*SLJ<)`Kx?wFzM_K-RGE?n5Ol6lHhwR zQLM4?@#nAWp{DQm|1E+4?(3;i*t}>yQYwx)EqW>@DRt)a$(B&gk1lu=#tSqR^YMN}jiu{JTLjWK^c*O<;eavHrC>zNZ}^rtMkpw4!ofU24r)}l-?@c?4(co}MJNw-*9 zB}Ju-*|DtoiglojDWRzD;@$~b0Zxln)=Cxm$is~Xc43i`RQ^AH{Ls)KrSP8@ymQ)& zZc{y(EP3TpuV+*~z3iZ-wrgW+YpVM{6Yal5nz=k>e(Stlf@F4ZXy~g~b6?)jsTHPd z4(qcJg%c90z6`0DBVlf?8sW|krtzl+Uc9(eLf0S)*T}V^_2=N!AME#};rP)=<4^cF zI5^k<9Fzx4u}n)vg8Nd6-|P-AZ(CIY#FkwfhG$v|4~#p=<4&pySH-ii%T4M%mno)0M6PafS}Skq4r$ zzo1gEmgd%9s#jmAQk@|TESfZs{31`$;$f3s9VD(_JwYHREm~G z43vr$T}DrCFg`2}@10$2%Cg$yqz-axQ-IliZTe^yKk7(a=-!xJ$F@}GTqEUz` z(cej<%2%m&bN)(#(I_HP8IC}&1vv99ppe-BDZ)UhJdK>9;@Mu~Lb>I**;!Njk-LCy zt=+(YZm;Y0Wk<)yp_JN_lamUiEhXQ(dxa!QO}bK2p_|h-A%A~=mZfh4>kZCZP;+xy zFUb)IzsC9;l3s%cJP)izbv5mf8T%Xoi(e~W9@x298bfNUtIKpwb$st${n6!s|I|6z zxuT5AwHWb2rKytzy*6r>Ca<`Vr4^+=fpv4;b{8-(Fyso5_?*pH+6?@<>XhdyD!$Pvnf%_}Z8QB%h=StX%J&|1 z`sZHTB$;&dY;0LAEsn7CTcdLKq2w5_6Xq!l7}ciiz}R6X3_4X`YBdd&kCa-6ocTy9 zznY!z`wU8BD2$8G8(Hkn<8KTmWxt_2+q+H`+*mlJpa%R&F?c)u^P0)gpFT(SdicM! zF}+^!cBrfOBrs?I<6ku_4g#Iz1C*xp_h6l}(p!KIKW znXIX;eHGWgwzkH-cyT*XG{wfw{#&Zrw-kVS+S2Y5oS@ESXTFyq06mj|HYj%lA>^E# zwBuuW#aiVIe0<4S7w}E51KvvC+YIzT-%Wr25roF}mNu4m@n7VVD7jOH#`Dct{ix4J zGGt=YwVE4pz*_73=+WT@`j05)S2kY9k8c@C28D!b`rh9rSx=Q-<3B0U)$CtADl9B~ zitM9?J8t{5QkfH|w5(R6_qjct@}8|?sXRrc$ndGzyt%weFdQD}OL|w!@9F7j21|b# zEiH6=Vt9IrZ&I-~I2aa>x8BxB@Df+^$&)8$L&=21#PD$?L1=v{7WCFL6nNG2_PNc} z?((2#BE9S*w2(3BS-wCWEBt==A95edmUo{ELBgsL$!d z^2d)isi}mL*;_qiDKqiymUecF)z(VymRD|W5*|~4lIHpx*vB8nS~xrqWN}tk2S^h7 zOt!Wx!8KoT!m@gHdRnW-5%;#B%>GkEL^`)UQ}(koMYo@AqGsQ>Ml$=evR=&0z>oKRz0KKty3ORoaXfdfJIu zi;rLCebj}IN}*8{&YOT06Hk)?fWJ`LS}9BvewH11r=h0C(nmZtHRZN3IK$k+^SuTo zya(rkhn)Jv-YTG49%Gk!I4hw7(^&^CDnRkYT_}k?(F1q9vSe0|H^2PXZ`v?NbhX zheVehc%D65W=fbdVJq+HMQvn_k&uw!fnXF(^pldGPm(bu5QG1BK1-6XMNv?E0*;uQ zoR+;34}{j~cXAAPPmn%-AoDogjsX?*+C}=OJeUe}xMLi)Y)SjeuZYwG0s@G`k*lw0 zydM0v$$WPnKY0SU@$A;xxhy#1Qt=Y>wM!2p680TUwVAT`vHkkEXy|G(W|bF6WbBJz0zk7K8EqNFj7+T^VtDxwV{vxm#u^n3|R_^zzFSP zdnbnb`kesEDsMI^ER)Wv!(VF1tWu-MERy0+y~2`yqPcq;AUN@)T2J9RIzB!+dhFWR zxei_IZ0Y{G^wyEbzh`y4>Pz-&o<`Az0}mC?*WW$tAxCF)*8(%Qf203RDZQ| zuRA8bFy4)pCl|sCicE!3yDiW^?u_*jlSEN_Ml5%oqgEX)dEE&a* zTlW>3*iBrRn=V*uN68Tg5n@?_NC79g7*$$fEU^|T<hkJD&A=@rFO}D~ z`9E0}tBZQY*r(_nI= z^S7`(a&wmOYyV=I?BrD0*qE`lnzPXn;6O2Dh)R)zw*u!(Pt!(0Y0&%q`(SY*{Nxm= z$G8M;Mk)p`FS&JfQ=qquqZXS#e>PuTT_q)HdU-WM6|CsM8bEIY{yqugMGx-_DN7rh zn2cbY)l)7ySs=|+8>+0_u?*b!0^=SW3Im();}pY?p4G%dBzJD-%>;^*fZ?jGcKc_gQ#a4N7XsG>T$Coas)M07P|jSf#tV4lHl+&R~K#v2Ic zYC^k=l$7krv3gC|3JU`}?==h=H^u0ius~p;kgOKaWsH*z5W91`qdQnTRKz$~Q#)2v zq(7y`u2*I7z2zR*b2SG^rr#@_`FyrA2ZDQ61K-)$*z|Ti-`d|NB9_Zjd0FqEca!XC zlP0(qY`+0zo)U`hUq>raG+cULSXfzE78wDB(n?B_#>r;n=cQ-dzo?km?dX`3SP`|i zzh41X_%GG=(kHv*6&0Bn8J|9Vp{N)Z7Z-PSc6M}hWWx5cwJgSg;<*88Ckr~9cJqms zIqAfYq`RZ@cJ%DY^?^STu0GL0DH^UuEa z!qCtycS@bC`4}Pl1Wz<23&~{ky(A9aYY|ygKu#=1PD^Zqnj4=1?bDUBNrT7X#uLu45Kh!-{U~-L|rg+^IpMC*N!}MilBnTTr(1W#qE@60UC;e|(K6MHA^z`U5^TyF*2m6cJ zqj#EA=q4p4Ei8ah73Jf3_428|c-}oc_%(_P=}D3|Gcn0YNl7s%gAENazI;gmkUhfV7hZ+6{4aEv~DpJ80o2B&>HHqs|9)j`4gYoPj;?ZsRfPa5!zq z$M#Xj$yQcWd}?gFxL{05BFxNu=iL&kbu+L&P(KjQ2tPiyva$lXLIwpk)cX$?=I1FX zDIpL@VNnrqu`CrXsnBAcu?UN6BEdb(x7=_gy8pZg@ECZ;rV`5I(8%YE6Fz_bdhNaX zRB7A^vr*@_{{G|l??pgkOQoQ9c~j3UATV%+Cp{%a4nvF6dU7`^>Jd7!DpSJ!g|Vbm zQ05ZCD~;khpX-`RxSFA%aJZz?*>2LTj&=X&(vmO>%gFF>OJ3f_e0?QRxW{8X2?>9V zA{Pe&VCO)%th99h;t06By80wR>HkJ!GGN7M=XF(WZDdFYHY$=;H4XpuN3nMSIOdxL zq4>t(Fw zAEau|Cm{)j28t~eh4nMu1h|!_ugu_w4sMQ)6o%T*@$hO)2R1@NLSAW>4kmMgDs9?r z)N}>%7(W+ReCM)3i+2(*WJXIv!%DC*IVcy;u-N3`t z+ClhfX?s8|iDJ2=D-=JpYo(z9M8)p**VZI(BYh6r4TLh7@j_FQ)f(Ms(E@}vCc+@Y z>4FEA)jCg7v)vYDD$2_#gi(1+oJk%gL3-CjXi(UAqxwF`0~jVy@>uqVNvUmZUo6M- zDEuKLB-J{5Ek4(M)skC`jEoX^S&fbSG#e8jVk%47_XGo@u%u+DuTK;;ASejL+VvY< zU0hu${kONbKcxs{b!`4@hkdGmqM!uLRBr0kMg8vdW8*NH++0)&NROe{kWPAZaW zZ<>y+Py(P>t6j%J&B!>!<~N*i|5Dh{$TI0ChsW_+S?e7Uh4aB;bENRy_u*lK{Bh9M zKK@aly0x{1N)app0zx06qN2jW(2t*%(0?t071zNVGQKs{=Qh=^w`j->3j}vZlG$@~ zgk;~nifC#MKnlY0=m<(EeI}Z%Z0NDh9E3qa&jfJMelOL3C8H>`wz^6cCtD&FrL3*( zcyrG@tCE_X&m-~hMP?M7kS_N{^+uvCgB z8r=>IT77+Vb#)C4(%;a5_HS`n8Gdlb+$_iS+1}2O0h1xAzJ|v32G@ecE}!Fyf1e3G zz{GTRd<&k)g@Tqi_g2SYl_Y?EYk2NuDNFEYrc! z@#yH;u{(~x7)9FMC)ycyv%xxFeOW9F#~qnr@^H!VIUczJ8}Ex{!DpPD)f)hom5q%F z+t5q=*gof-Nk+{nU<({9DJ&m0cXp)m$9p@k)1yJGF}!=W`DxD_BaehJ8{xwbA~cQF z&RZ%2=wn+a4?nPbxMonhoT6sF;yh1r5Ilmfe!3tlpMgN%vVg$K!1))_!%yb=YTE?# z6P|lte;`o2>;GI(Q^Ozx9D^WR?}7F!Fe7DPs@J(y@2d!4$JrAvGyu!W;tf%_V0(Le zL`1~H4>M-X2DX;v@pr`N8>Ugsdv^|y{Lw+O!Eq-uuf}(M*hRWp4DpqfGmK~f9VQ*% ztwBQrle_40+b<#og$4d!jmVIw3?E>gd>9N09vWI&SR$)9QvxkDHBi^kAe%cyO!PT7 zH&=pHTzGWrWO7pDc!HehiqO@5k273SPF8jWTA!P1Dr@Q|@7f8o$Mg7sl{NY+o)N!i zZaNVVL0xF}+T342sMV8aE+YrL8D7TqM?_$_xkWZL4XjOPo3bU%&(F`z9p&ZGKzHlM zPj|*XRB&U4C~_Mz0Hl#qy1vYDvR*s3$Y`PO25Fm4#^k`s8=8P9?K0<~?_eQ^-Rby}62N#zA4 zmKhx`6ngOt94=;+yqaYj;;Y3J#O9nFiPl%_?Cd)`I~hLEm2?wfZ{`il%myw7;)IF(Ev^Hn~Hk-9L(_w}^i^dcZ;Yz8i7G{Q(iC$SQ(` zz=Lp zO!^IL8yk2;L{*UzDKWjpww!h7<75T&+?-RZEJi7z8}9^H_F4G(y(S9d zz;yEz)L_0qk}L0hJuvSn(&vl}a~1+hN<1eXAGsJ6Ri$*Hg@lTqNAB<5E%QX+<4Tjt zYl{f5{n(z&%F1%tnG7f9CZ$;0*>M7^_xYu2-z7!P_*QCaDhqlgQ2q{m%6Ddl7ryZb z3ms-uzUb}5KdS$R8r$b&RLX`cMVeKa&e(Ix;7=Qn$0GhidV|6{Fs<+L)2CEAS)dTs z(9{GKjiC4tKtV@mHiCq|p@EN|uYt*6aBJwRiHV8LQp;_MeT&ES9?8UnoACASTRmXD zfz#UPC2oJU^^~eg%gvBISqrH8_+GuV21PHjA3~2~u*AxNFjnq~eOmyQtejkBW#wEe z&^l@XVK)PnR#$rsbBTvNN1zyykScROotT)J(Pm3R@BFq{ffn1hw!Th+ho_kNMlnN? zN>)@ve7iTADuwIz^l%y0*w`2bbf^FLQ8hc8yaZwWrlO+4WgkIX_-$-#%)tBTHPp;P zU0vPhsB3w8dKzp*<$}*(r($m9Aimhl=t@s#rlzHJb9PptGgeIFdyy~@bm#IjO4$h& z>G$h9-6JlS!Y@l$zc62r+Eb?4!7pGbWK!}pPN2>}A6K|EOM%{L1K8T0dJ2}ig8DU6 zLeT2fV)POj1Kz-*uZ?kbMSgw|ggB4@J2Ymv~Am;Xst*4?1VEEgxIx<)+C zLKZKi6r3MZhT0u(c4q+LJ6pa_SfO1NmByUhwI}eoDA8P%dcAbXY?^o;3{C$JpsVic z_Huf*Vs|fN4gMYwm+Yee2Qb#XE~{&?xVd?dY%Zjm_rae<2?0uu{21Af7x4X3TN~A9 z5@Y-T<0PBpKgL0LHmCnObZ35@sRZ4^JT9C}$G4;LoBG!i*$ z`t4hd=s#^J5_PLq-YP{#_@CF2H!^4){J$)~|I5k$_qoIDk9hCj9o!hD@WEK_(pOiF zQ)YQ0a5f`tiNqm2A84p32&rFwx8`t>qaFF8+H4{9dP30%`;`u@%eH#%!nslMkCc#w zssQES(B~9Lx?8;#M9>|@-i0t=a z^+DAR3E0^cXkt}W9bYSJVdMskd2Y*s*kdok8mJQRzK4ilkZ-<=Qq|r9T{@upUTC|U-Jqsz}%>oAH@7GE(l1)j|e;ujOm`e z3}F-U700TIi&Kmjx6G{4XsP6@Un2EhPmVQ@Oe z&y(YCbWo8%je^1cEs2ibPSlKz40VkAXaxSAoI%wRabe+NJ-aQJuGT}aI68e}5C2{F z-`Dp*S|dOw9^2A(eI&X>5iw4U{n)R)4g2?nW#jS4|ECClN;FJG9<<7%u0Hb|$tTDi zNC(*m*LQiS|5?prR{3tKy2P<7e4YfY0I2B8fG)i_M&d zlms!CfN|~I3@)lC#CG;%_X)G}{(ODxCxLXG#^#t$63XC%4vbXeMJ2OG*P(F<2}Rpu zd%*x>{K`-Yw{D3>Je{=qL`4N#f^}t|iBbJWbY#B?tLI2h#83=agC zq3X@&iwB?@a-ZYA9-Ec>-0tpfU}GcR-FwW0O+m36gk%M|6Bcy*R(UdDn)-VY zJ*(h!oSmI*=zUZ>Pm(iX)!5Jw5-MkAmdA)UAY8efooZz@-{|IMQ9Y}guh?b8Jrne= zF8M!guJL@0Cv8}__ReW{Is>YCayHl6XToNK^^w%Dt1CVUNJ^4RxD(|~<8jne#^tIL zsF>;3(eZT$eK9gkIOD*y7X_rbT?p8&GdbCP+9#&TUCbM%Bhmf)o+ z-f!iT<&STHlR&fAc^{MqJ9u)6n}d^6zsbEEoaB8T{`3A}kegSF4udn^vMXTEniO`> zFHBfuiV1I%r_S9?m(h~A$8f5*J}4unf~M`&~XY{twKwYo}Mi#xVfdJ!w2U| z3JT9g2M4Q`gcE}x5vxs$v-|t|&U^|IqZZCKyPmeT`qbD8xiJ|&u25f6;&;YWyC`=4 z;pvc*wJ)?Ng1o=_M3pc+p&Ft}iYymp4q9MWAcLF)b+SFPU1*p9mbGR>;Ku{kOP)L7 z9}oZ~*z=6C)de>o#lDNz`yyd)&lXfAf9>5~jbu*o^PPR;|8iQI!kvBO?){DeC)gjn zKME4AjSEIE%~l`nO_yhbO`#nxB`HR#v=_>JN1c!ddO7MACZsiGUjD;RW3UO;+m=j)VlT|$E>LG8Q#9;01?vi&U7 zxYGgpbFHoKA0ksDA$EM>_W84eQ%_h1bJeT06vBO~?WXX0gwKOM+Vxp z8)j(Z0;Ff+N1e5m6_<dN1A)dua9bVR*Xru8=;_g>Bodg{V#i}4eURo%8DbEnqRIpf@zfr7YczBi9RyV-&|eH;hT!9Id52ayw#0%dGcMh1|<4SHbgZm;JuLCaMUmZu^^33?BBS^lV@E(c#u%{!PqB=(zJ!i&Z2 zuxR^X5U}{4Wf@(Rm*3oU=a4cFu!fkQBr~pr|HXy4S)Y` zc;sGO{=jo*vZTw1HDMqa$V%)pSvi`{mcm?+Dwn6B3RwZUD?%BOT`N>nFVB^|?_TkJ z{-A;^OGsz>XBg;-@QIeEA?Z1~ zY%1I?i!?Nt{Pk-=+GO=?k6(ZkmZy;7x;L99yHJ2~F`Tw+J0~PhjU7Yn;tW1Npij*z zqD{3xO>=74fHKxgvr#sxom)ln%Ab>{7 zT>@t+clWw83F-WCadGa(Mof@u1?UufwqLk9JzDLVK;gW5jPy_{!kb1$rCh5CYWmI5 z<*9KPYxmBa5yRyEUD%?e?fgXxEWc^;FsFnukB%`m7B=rUrAmi;d_7T6uzA{OaK+r4>a*x&hq~dDZUJj539V+YNV6%mRjikd;@sArd>b5qRAMWfZkF zfdi(-(BrKvr@z{`xP#jKGQFhlmVR+l8~V$WcFh$4XCgwSj1AVsg!;dNyHZ zWemnrI^zgY{>(7oJt3?UZlO-UE}JV~wODOY?*6_Dk%9E>(SuMFErGTb1UyU*ZGkU4 z4TbdkwEpo?rrPaq4>Jr-XmuoZfC#*Qc+C|7oZi0mJoO1sd@msS;}zY}$aAH*V1B|I z)fuw*C(niB17xm-bFXh>$d`H^)IZ{QtPdG}cQv{GP;$eRKuNr*NWF-B1TTKxWzOYo0 zTT;oMx$|0|8|eeH#?le9Mv-ALy{sJh `aJi$x1ae}PZRT^|UCu<|I;z}5Ty#LxM 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 diff --git a/internal/guard/testdata/screens/generate-refused.xml b/internal/guard/testdata/screens/generate-refused.xml index 87685aab..7d86e773 100644 --- a/internal/guard/testdata/screens/generate-refused.xml +++ b/internal/guard/testdata/screens/generate-refused.xml @@ -160,8 +160,8 @@ AVIF cannot be smaller than 311 B - the smallest picture this format draws codes to 303 B at worst, and the file always - carries a free box, which costs 8 B even when it holds nothing. Requested: 1 B. Ask for 311 B or more, or set a smaller - width and height, or a lower quality + carries a padding box, which costs 8 B even when it holds nothing. Requested: 1 B. Ask for 311 B or more, or set a + smaller width and height, or a lower quality diff --git a/internal/gui/text/locale/said/en.json b/internal/gui/text/locale/said/en.json index d475d061..3bcafcb9 100644 --- a/internal/gui/text/locale/said/en.json +++ b/internal/gui/text/locale/said/en.json @@ -341,13 +341,13 @@ }, "avif.MinimumReason": { "description": "Said by internal/format/avif - a refusal under the box it is about or at the foot of the form, or a note after a run. Carries {{.Coded}}, {{.Box}}, written the way the program writes them - keep each spelled exactly that way.", - "hash": "sha256-97b2a4a72e3a", - "other": "the smallest picture this format draws codes to {{.Coded}} B at worst, and the file always carries a free box, which costs {{.Box}} B even when it holds nothing" + "hash": "sha256-0ce5a98f055a", + "other": "the smallest picture this format draws codes to {{.Coded}} B at worst, and the file always carries a padding box, which costs {{.Box}} B even when it holds nothing" }, "avif.MinimumReasonOwn": { "description": "Said by internal/format/avif - a refusal under the box it is about or at the foot of the form, or a note after a run. Carries {{.Width}}, {{.Height}}, {{.Quality}}, {{.Coded}}, {{.Box}}, written the way the program writes them - keep each spelled exactly that way.", - "hash": "sha256-ff69f6fa9b64", - "other": "a {{.Width}}x{{.Height}} picture at quality {{.Quality}} codes to {{.Coded}} B, and the file always carries a free box, which costs {{.Box}} B even when it holds nothing" + "hash": "sha256-bed39f5c0c28", + "other": "a {{.Width}}x{{.Height}} picture at quality {{.Quality}} codes to {{.Coded}} B, and the file always carries a padding box, which costs {{.Box}} B even when it holds nothing" }, "checksum.AChecksumDigitsLongIsNot": { "description": "Said by internal/tool/checksum - a refusal under the box it is about or at the foot of the form, or a note after a run. Carries {{.Digits}}, written the way the program writes them - keep each spelled exactly that way.", @@ -2322,13 +2322,13 @@ }, "jxl.MinimumReason": { "description": "Said by internal/format/jxl - a refusal under the box it is about or at the foot of the form, or a note after a run. Carries {{.Coded}}, {{.Container}}, {{.Box}}, written the way the program writes them - keep each spelled exactly that way.", - "hash": "sha256-96322e155f28", - "other": "the smallest picture this format draws codes to {{.Coded}} B at worst, the container around it costs {{.Container}} B, and the file always carries a box of free space, which costs {{.Box}} B even when it holds nothing" + "hash": "sha256-0c3cd13e8d89", + "other": "the smallest picture this format draws codes to {{.Coded}} B at worst, the container around it costs {{.Container}} B, and the file always carries a padding box, which costs {{.Box}} B even when it holds nothing" }, "jxl.MinimumReasonOwn": { "description": "Said by internal/format/jxl - a refusal under the box it is about or at the foot of the form, or a note after a run. Carries {{.Width}}, {{.Height}}, {{.Quality}}, {{.Coded}}, {{.Container}}, {{.Box}}, written the way the program writes them - keep each spelled exactly that way.", - "hash": "sha256-ab4120801908", - "other": "a {{.Width}}x{{.Height}} picture at quality {{.Quality}} codes to {{.Coded}} B, the container around it costs {{.Container}} B, and the file always carries a box of free space, which costs {{.Box}} B even when it holds nothing" + "hash": "sha256-1d657fb59674", + "other": "a {{.Width}}x{{.Height}} picture at quality {{.Quality}} codes to {{.Coded}} B, the container around it costs {{.Container}} B, and the file always carries a padding box, which costs {{.Box}} B even when it holds nothing" }, "log.ClientAddress": { "description": "Said by internal/format/logfile - a refusal under the box it is about or at the foot of the form, or a note after a run.", @@ -2468,8 +2468,8 @@ }, "mp4.MinimumReasonPictures": { "description": "Said by internal/format/mp4 - a refusal under the box it is about or at the foot of the form, or a note after a run. Carries {{.Duration}}, {{.FPS}}, {{.Interval}}, {{.Width}}, {{.Height}}, {{.Change}}, {{.Bytes}}, {{.Free}}, written the way the program writes them - keep each spelled exactly that way.", - "hash": "sha256-2d553380ec9d", - "other": "a film of {{.Duration}} at {{.FPS}} frames a second with a key frame every {{.Interval}} and a new {{.Width}}x{{.Height}} picture every {{.Change}} takes {{.Bytes}} B, and the file always carries a free box, which costs {{.Free}} B even when it holds nothing" + "hash": "sha256-0c2a2c450da2", + "other": "a film of {{.Duration}} at {{.FPS}} frames a second with a key frame every {{.Interval}} and a new {{.Width}}x{{.Height}} picture every {{.Change}} takes {{.Bytes}} B, and the file always carries a padding box, which costs {{.Free}} B even when it holds nothing" }, "otlp.AFileHoldsWholeRecords": { "description": "Said by internal/format/otlp - a refusal under the box it is about or at the foot of the form, or a note after a run.", diff --git a/internal/gui/text/locale/said/pl.json b/internal/gui/text/locale/said/pl.json index 677035eb..3cc05771 100644 --- a/internal/gui/text/locale/said/pl.json +++ b/internal/gui/text/locale/said/pl.json @@ -67,8 +67,8 @@ "archivescan.TwoNames": { "hash": "sha256-8816d7bc260e", "other": "{{.Listed}} w spisie, {{.Local}} przy wpisie" }, "archivescan.Type": { "hash": "sha256-ea85c62d6ca3", "other": "to wpis typu {{.Type}}, którego większość programów nie rozpakowuje" }, "archivescan.WaitAndRunAgain": { "hash": "sha256-161d36039e9c", "other": "poczekaj, aż to, co go zapisuje, skończy, i uruchom to jeszcze raz" }, - "avif.MinimumReason": { "hash": "sha256-97b2a4a72e3a", "other": "najmniejszy obrazek, jaki rysuje ten format, koduje się w najgorszym razie do {{.Coded}} B, a plik zawsze niesie wolny blok, który kosztuje {{.Box}} B nawet pusty" }, - "avif.MinimumReasonOwn": { "hash": "sha256-ff69f6fa9b64", "other": "obrazek {{.Width}}x{{.Height}} w jakości {{.Quality}} koduje się do {{.Coded}} B, a plik zawsze niesie wolny blok, który kosztuje {{.Box}} B nawet pusty" }, + "avif.MinimumReason": { "hash": "sha256-0ce5a98f055a", "other": "najmniejszy obrazek, jaki rysuje ten format, koduje się w najgorszym razie do {{.Coded}} B, a plik zawsze niesie blok dopełnienia, który kosztuje {{.Box}} B nawet pusty" }, + "avif.MinimumReasonOwn": { "hash": "sha256-bed39f5c0c28", "other": "obrazek {{.Width}}x{{.Height}} w jakości {{.Quality}} koduje się do {{.Coded}} B, a plik zawsze niesie blok dopełnienia, który kosztuje {{.Box}} B nawet pusty" }, "checksum.AChecksumDigitsLongIsNot": { "hash": "sha256-0dcdc03bd2f7", "other": "suma kontrolna o długości {{.Digits}} cyfr nie jest taką, jaką to narzędzie wylicza" }, "checksum.AChecksumFileIsNeverWritten": { "hash": "sha256-49681362425b", "other": "pliku sum kontrolnych nigdy się nie nadpisuje, bo może być jedynym zapisem tego, co było w folderze" }, "checksum.AChecksumFilePromisesEveryFile": { "hash": "sha256-354be45714f3", "other": "plik sum kontrolnych obiecuje każdy plik w folderze, a taki z luką nie powiedziałby, gdzie ta luka jest" }, @@ -462,8 +462,8 @@ "html.UseOneOfThePictureFormats": { "hash": "sha256-a6669f6abe6b", "other": "Użyj jednego z: {{.Formats}}." }, "imagelabel.ThePictureIsPxTallAnd": { "hash": "sha256-238ba2886f79", "other": "Obrazek ma {{.Height}} px wysokości, a etykieta potrzebuje {{.Needs}} px, więc jej tekst jest ucięty i ten plik nie niesie czytelnej etykiety. Wciąż wskazują go jego nazwa i manifest." }, "json.HasToBeStyle": { "hash": "sha256-c1343585d922", "other": "musi to być {{.Indented}}, {{.Minified}} albo {{.RecordPerLine}}" }, - "jxl.MinimumReason": { "hash": "sha256-96322e155f28", "other": "najmniejszy obrazek, jaki rysuje ten format, koduje się w najgorszym razie do {{.Coded}} B, kontener wokół niego kosztuje {{.Container}} B, a plik zawsze niesie blok wolnego miejsca, który kosztuje {{.Box}} B nawet pusty" }, - "jxl.MinimumReasonOwn": { "hash": "sha256-ab4120801908", "other": "obrazek {{.Width}}x{{.Height}} w jakości {{.Quality}} koduje się do {{.Coded}} B, kontener wokół niego kosztuje {{.Container}} B, a plik zawsze niesie blok wolnego miejsca, który kosztuje {{.Box}} B nawet pusty" }, + "jxl.MinimumReason": { "hash": "sha256-0c3cd13e8d89", "other": "najmniejszy obrazek, jaki rysuje ten format, koduje się w najgorszym razie do {{.Coded}} B, kontener wokół niego kosztuje {{.Container}} B, a plik zawsze niesie blok dopełnienia, który kosztuje {{.Box}} B nawet pusty" }, + "jxl.MinimumReasonOwn": { "hash": "sha256-1d657fb59674", "other": "obrazek {{.Width}}x{{.Height}} w jakości {{.Quality}} koduje się do {{.Coded}} B, kontener wokół niego kosztuje {{.Container}} B, a plik zawsze niesie blok dopełnienia, który kosztuje {{.Box}} B nawet pusty" }, "log.ClientAddress": { "hash": "sha256-df4616586839", "other": "adres klienta" }, "log.ConflictDrop": { "hash": "sha256-9d99490328fe", "other": "{{.Why}}. Usuń jedno z dwóch albo zmień drugie" }, "log.RequestMethod": { "hash": "sha256-eaa67a9c3b30", "other": "metoda żądania" }, @@ -491,7 +491,7 @@ "manifest.TwiceBecause": { "hash": "sha256-1ae6ad202098", "other": "{{.Detail}}. To narzędzie zapisuje każdy klucz raz, więc manifest zapisało albo zmieniło coś innego, a to, którą z dwóch wartości ma na myśli, to zgadywanie. Użyj manifestu, który faktycznie zapisał przebieg" }, "manifest.Unreadable": { "hash": "sha256-bb90fafec850", "other": "{{.Path}} nie daje się odczytać jako manifest: {{.Detail}}" }, "manifest.ValueTooLarge": { "hash": "sha256-65f9e8304926", "other": "{{.Path}} zawiera pojedynczą wartość dłuższą niż {{.Limit}} B, zaczynającą się mniej więcej {{.At}} B od początku, a to narzędzie czyta z manifestu naraz najwyżej tyle. Wpis manifestu zapisanego przez to narzędzie zajmuje kilobajt lub dwa, więc sprawdź, czy to manifest zapisany przez przebieg" }, - "mp4.MinimumReasonPictures": { "hash": "sha256-2d553380ec9d", "other": "film o długości {{.Duration}} przy {{.FPS}} klatkach na sekundę z klatką kluczową co {{.Interval}} i nowym obrazem {{.Width}}x{{.Height}} co {{.Change}} zajmuje {{.Bytes}} B, a plik zawsze niesie pudełko free, które kosztuje {{.Free}} B nawet puste" }, + "mp4.MinimumReasonPictures": { "hash": "sha256-0c2a2c450da2", "other": "film o długości {{.Duration}} przy {{.FPS}} klatkach na sekundę z klatką kluczową co {{.Interval}} i nowym obrazem {{.Width}}x{{.Height}} co {{.Change}} zajmuje {{.Bytes}} B, a plik zawsze niesie blok dopełnienia, który kosztuje {{.Free}} B nawet pusty" }, "otlp.AFileHoldsWholeRecords": { "hash": "sha256-8bd4f63f9cb2", "other": "plik składa się z całych rekordów, a najdłuższy, jaki te ustawienia mogą zapisać, potrzebuje tyle" }, "otlp.AFileThisLargeAddsUpMore": { "hash": "sha256-f2957a096ca2", "other": "plik tej wielkości dodałby w jednej serii {{.Metric}} więcej czasu, niż da się zapisać z dokładnością do mikrosekundy. Wybierz mniejszy plik albo temporalność przyrostowo, gdzie dany rodzaj ją ma" }, "otlp.AFileThisLargeCollectsAfter": { "hash": "sha256-a18c86e7715d", "other": "plik tej wielkości zbierany co {{.Interval}} s datowałby swoje ostatnie zbiory po roku 2262. Wybierz wcześniejszy start, krótszy odstęp albo mniejszy plik" },