* craft-raw: the file-format layer of camera raw files, with DNG and CRW
A new crate for #587 and #778: bytes in, the sensor data out as a neutral
RawImage (samples, CFA, levels, active area, crop, orientation, colour tags,
opcode lists, profile tables), and back for DNG. One Cargo feature per format:
dng (read and write), jxl (JPEG XL DNG), crw (through craft-crw).
The base is LightCraft's crates/raw at 5ff567a4: dng, dngwrite, tiffraw,
unpack, ljpeg, jxl, semantic, preview, the parsing half of opcodes, profile
and gaintable, the model and probe. Demosaicing and everything after it stay
with the develop pipeline.
Ported from PhotoCraft's and FilmCraft's DNG readers, each with a test: the
default crop's per-tag defaults, an unusable crop falling back to the active
area, non-finite white levels, the white default of a linearized image, the
AsShotWhiteXY range, 8-bit-only lossy JPEG, lossy tiles that must cover their
part of the image, and the CinemaDNG frame tags.
* craft-raw: Hasselblad 3FR and FFF (feature hasselblad)
RawFormat::CfaTiff decodes: the DNG-layout reader plus what these files add.
Uncompressed data or Hasselblad's lossless JPEG (selection value 8), RGGB when
no CFAPattern is stated, an FFF's colour matrix from the 3FR header it embeds,
and the 8-bit RGB preview handed on as a baseline TIFF.
Moved from LightCraft's vendor/hasselblad.rs at 5ff567a4 with its tests.
Ported from PhotoCraft's reader: four BlackLevel values without a
BlackLevelRepeatDim are one per CFA site in a file that is not a DNG.
* craft-raw: Minolta MRW, Epson ERF, Mamiya MEF and Kodak DCS520C
Four formats only LightCraft decodes, one feature each (mrw, erf, mef, kodak),
moved from its vendor modules at 5ff567a4 with their tests; the MRW block
container comes from lightcraft-meta. src/shared.rs holds the level helpers
the maker decoders share.
ERF and MEF state no white balance: the estimate LightCraft made from the
preview is develop-side work, so wb_multipliers is None for them here.
* craft-raw: shared scan budget for tagged previews, tile-sized lossy JPEG budget, bound on Deflate tile padding
Ported from storytold/lightcraft#3695. Candidate preview ranges are deduplicated and charged to one byte
budget and one header-walk budget; a lossy JPEG decoded for a tile may hold no more samples than the tile
rounded up to whole MCUs (and never more than Limits::max_lossy_tile_samples); a Deflate chunk whose nominal
size is mostly padding outside the image is refused before it is inflated.
* craft-raw: lossless JPEG sample bound per referenced byte; previews larger than the file are passed over
Ported from storytold/lightcraft#3910 (the parts whose code is in craft-raw today). check_image refuses a
lossless JPEG image that declares more than 32 samples per referenced byte, counted once per chunk that points
at the bytes so identical tiles stored once still decode. The Hasselblad RGB preview search passes over an
image whose pixel bytes exceed the file and still takes a smaller complete one.
* craft-raw: test for the Deflate padding bound
* craft-raw: Pentax PEF and Samsung SRW
Moved from LightCraft crates/raw (vendor/pef.rs, vendor/srw.rs) at 5ff567a4. The Huffman difference decoder
and bit reader that PEF shares with the Nikon, Panasonic and Sony codings become the huffman module.
* craft-raw: Canon CR2, with sRAW and mRAW
Moved from LightCraft crates/raw (vendor/cr2.rs, vendor/cr2/sraw.rs) at 5ff567a4. The white-balance presets a
CR2 lists come back as data in ColorData::kelvin_presets (the ordering from LightCraft's kelvin_presets.rs;
the temperature and tint arithmetic stays with the developer).
* craft-raw: an sRAW preview larger than the file is refused before its buffer is reserved
Ported from storytold/lightcraft#3910 (cr2::sraw::read_preview).
* WIP craft-raw: Nikon NEF/NRW (does not compile yet: limits threading, develop() calls in tests)
* craft-raw: Nikon NEF/NRW, with PhotoCraft's maker-note compression routing and 12-bit D4 white level
* craft-raw: Panasonic RW2 / RWL / RAW, every raw format
* craft-raw: RW2 format 8 refuses strips stating fewer bits than samples
Ported from storytold/lightcraft#3910.
* craft-raw: RW2 format 8 refuses samples above the declared bit depth
Ported from storytold/photocraft#11838.
* craft-raw: the RW2 format 8 robustness seed carries a valid stream
Its random payload decoded only while out-of-depth samples were clamped; mutations now start from a file that decodes.
---------
Co-authored-by: radialmonster <radial@gmail.com>
Co-authored-by: wnanbei <wnanbei@gmail.com>
* Add craft-crs: Camera Raw crs: settings in XMP, read and written, from PhotoCraft
The format half of PhotoCraft's Camera Raw settings files (crates/io/src/camera_raw_xmp.rs at
abeb16c96): the crs: settings of an XMP packet as written, Camera Raw's number and curve point
text, the crop and its orientation, a writer, and the toolkit marker. Which setting drives
which control stays in the app.
* craft-crs: structures carry their element and are written back
Local corrections and other structured settings were dropped, and an rdf:Seq of descriptions
read as empty strings. A structure now holds its crs: element, a sequence is only plain text
items, descriptions inside a structure are not read as top-level settings, and to_xmp writes
structures back.
* craft-crs: read packets through craft-metadata's XMP reader
One XMP reader for every crate: Settings::parse goes through craft_metadata::parse_xmp and
Settings::from_xmp takes its XmpData. Settings are kept by name (the reader's map has no file
order), structures are craft-metadata's XmpValue and are written back as rdf:parseType
Resource elements and rdf:Seq arrays. toolkit stays a bounded first-start-tag scan, as the
reader does not return x:xmptk.
craft-rtf and craft-dxf each carried tables for DOS 437, 737, 850, 852 and
857 (and craft-rtf one for 866). They are now one set in craft-codepage,
which takes craft-rtf's codepage module (Windows and Mac tables, OEM glyphs,
font charsets) and craft-dxf's DOS tables. craft_rtf::codepage re-exports it
unchanged; craft-dxf keeps its $DWGCODEPAGE names and Decoder and looks the
DOS tables up there.
Every byte of every code page either crate decodes is unchanged: the
public decoders of both crates were dumped over all 256 bytes of each page
(and the East Asian pairs) before and after, and the dumps are identical.
craft-mime now reads the DOS pages by their IANA names (IBM437, cp850,
ibm-852, 857...), which it read as UTF-8 before.
* Add craft-sheet: the cell positions, values and tables the spreadsheet formats share
craft-xls carried its own CellRef, Range, Value, CellError, Visibility, sheet-name
quoting, built-in number format table and indexed palette. craft-xlsx and craft-ods
need the same ones, so they move to a crate with no dependencies and craft-xls
re-exports them: an application gets one Value and one CellRef whichever file it read.
Added on the way: A1 parsing (CellRef::parse, Range::parse), Range::count and a1,
CellError::parse and the newer error values SpreadsheetML stores as text,
builtin_format_id for writers.
* Add craft-ods: OpenDocument spreadsheet tables on craft-odf
read() checks the spreadsheet mimetype, refuses an encrypted package, and reads the
tables of content.xml into sheets of cells that keep the file's terms: value type,
the raw value, displayed text, formula text, style name, covered cells, with
repeats expanded and merged ranges. Cell::value() gives the shown value, dates and
durations as serial numbers.
From GridCraft crates/xlsx/src/ods.rs and its tests (7e0d96d7), split from
GridCraft's document model and moved onto craft-odf and craft-xml's pull reader.
Options::only_sheet covers WordCraft's reader of one chosen sheet.
* Add craft-figma-rest: a typed model of the Figma REST file JSON
The neutral model for design files: the .fig and .sketch readers map onto
it and an application's importer takes it. Typed records for the document
tree, paints, effects, text styles, layout grids, constraints, export
settings and the component and style metadata; every record keeps the
fields it has no name for, so a file read and written loses nothing.
The vectorNetwork extension is typed and documented with the others.
The layer tree is converted level by level in both directions, and the
depth and node limits are checked on the JSON before any typed value is
built.
* craft-figma-rest: Warnings and style_name for the readers that build this shape
Moved from FigCraft's REST importer and .fig reader (crates/format/src/rest.rs
Warnings, fig.rs style_name), which the .fig and Sketch mappings share.
* craft-dxf: model, the drawing above the tags (header, tables, blocks, layouts)
Document::read indexes a tag list into header variables, table records,
blocks with their entities, the ENTITIES records (a POLYLINE with its
vertices, an INSERT with its attributes) and the objects, each a slice of the
tag list. The typed table records, LAYOUT and DICTIONARY are made on request.
Also the colour index palette, colour, lineweight and transparency values,
extended data lookup and the object coordinate system.
Merged from CADCraft's cadcraft-io dxf_read (5a6aa9b6) and VectorCraft's
vectorcraft-cad import (566f7208). Neither app's document types appear.
* craft-dxf: model entities (geometry, text, MTEXT columns, hatches, dimensions)
Entity::read types an entity record: the properties every entity has, and
LINE, POINT, CIRCLE, ARC, ELLIPSE, LWPOLYLINE, POLYLINE with its vertices
(2D, 3D, mesh, polyface), SPLINE, RAY, XLINE, TEXT, MTEXT with columns,
ATTDEF, INSERT with its attributes (multiline ones included), DIMENSION,
LEADER, SOLID, TRACE, 3DFACE, HATCH (polyline and edge loops, pattern lines,
seeds, gradient), VIEWPORT, IMAGE, WIPEOUT and TOLERANCE. Other types stay
readable from the record's tags. model::text has the caret encoding of
strings, both ways.
Merged from CADCraft's cadcraft-io dxf_read (5a6aa9b6) and VectorCraft's
vectorcraft-cad import (566f7208).
* craft-dxf: a hatch spline edge without fit data leaves the loop's source count
Before R2010 a spline edge has no 97 of its own, so the 97 after it counts the
loop's source entities. It was read as the edge's fit point count and the
sources were lost.
* craft-dxf: model::write, a drawing as tags (R12 to 2018)
Drawing::tags writes the header, classes, the nine symbol tables, blocks,
entities and (R2000 and later) the dictionaries, plot style placeholder and
layouts around the layers, linetypes, styles, dimension styles, blocks and
entities it is given, in the model's own types. entity_tags writes one entity
for a caller with its own file. Handles given with the content are kept;
the rest are numbered after them.
The file skeleton is VectorCraft's vectorcraft-cad writer.rs (566f7208); the
MTEXT column groups are CADCraft's dxf_read/mtext_dxf.rs column_tags
(5a6aa9b6).
* README: keep main's crate list after the merge
PhotoCraft's exr-crate wrapper (preview check, per-part and total size limits,
file-size plausibility, part ranking, one-part decode) and EffectCraft's
streaming channel filter, as one reader that returns a neutral model: part
headers with text attributes, and the kept channels in their stored type.
MailCraft crates/ews at a44a450: the request envelope and the escaping
element builder (soap.rs), and the judging of an answer's envelope, faults
and response messages (reply.rs, the response codes of error.rs), now read
with craft-xml in place of MailCraft's own XML reader. The operations, HTTP,
Autodiscover, authentication and sync stay in MailCraft.
Co-authored-by: Martin Ball <98639962+benandez@users.noreply.github.com>
MailCraft crates/jmap's protocol core at a44a450, moved as it is with all
its tests: session, requests with result references, responses, ids,
addresses and templates, credentials, retry and the judgement of HTTP
answers, over any HttpExchange. The mail client on top stays in MailCraft.
Co-authored-by: Martin Ball <98639962+benandez@users.noreply.github.com>
* Add craft-wordmodel: WordCraft's document model without its editing code
WordCraft's crates/doc (wordcraft-doc, at 07f97737) moved as it is, so the DOCX,
RTF, ODT and other text-format crates can read into and write from one model.
Module paths, type names and serde attributes are unchanged: an app that
re-exports the crate keeps its native file format.
Left in the app: range editing (edit.rs), IME text and equation editing. Not
model, and already in craft-libs: code pages (craft-rtf), the ZIP entry-count
check (craft-opc), the compound-file guard (craft-cfb). The paragraph walks
moved to walk.rs and the unit helpers of wordcraft-geom to geom.rs.
* craft-wordmodel: math_tree, the arguments of an equation node and a walk over its runs
The DOCX reader and writer walk an equation's runs. The walk and the child
accessors it uses were in WordCraft's equation editor (math_edit.rs), which
stays in the app; they are structure, not editing.
* craft-wordmodel: keep the document operations (edit.rs) with the model
The DOCX and RTF readers use them: alternative-format chunks are merged into
a document with adopt_blocks, and a reader formats ranges with format_range
and inserts objects. They operate on the document, not on a view, so they
belong beside it. The tests that drove them come back with them; the
paragraph walks stay in walk.rs and edit re-exports them.
base64 0.23, as WordCraft and craft-offcrypto use.
The WebP container code the apps wrote themselves: EffectCraft's chunk walk
(canvas, alpha, animation frames and their durations) and PhotoCraft's RIFF
writer around an encoded VP8 frame with alpha, ICC, EXIF and XMP chunks. The
codecs are not part of the crate.
* Add craft-sheet: the cell positions, values and tables the spreadsheet formats share
craft-xls carried its own CellRef, Range, Value, CellError, Visibility, sheet-name
quoting, built-in number format table and indexed palette. craft-xlsx and craft-ods
need the same ones, so they move to a crate with no dependencies and craft-xls
re-exports them: an application gets one Value and one CellRef whichever file it read.
Added on the way: A1 parsing (CellRef::parse, Range::parse), Range::count and a1,
CellError::parse and the newer error values SpreadsheetML stores as text,
builtin_format_id for writers.
* Add craft-xlsx: the part layer of XLSX and XLSB workbooks
Package::open finds the workbook part through craft-opc and reads the workbook
part, shared strings (runs and phonetic readings), the styles tables as indexed
tables, and a worksheet's rows one at a time with the rest of the part as a tree.
Binary workbooks give the same workbook, strings, rows and merged cells from their
records. Every other part stays reachable through Package::opc.
From GridCraft crates/xlsx (7e0d96d7): read.rs, sheet_read.rs, styles.rs, xml.rs
(string items, xstring escapes), xlsb.rs and its tests, split from GridCraft's
document model.
* craft-xlsx: XLSB opens up to 4 million cells, records counted once over the workbook
Binary workbooks over 1 million cells were refused, a quarter of what .xls allows,
and an allowance of 5 million records per part refused ordinary files: Excel writes
four records per non-empty row besides the cells, and one BrtCellBlank for every
formatted empty cell. Cells are now 4 million over the workbook (also the most
shared strings), text 256 MiB, and records 40 million for every part together, as
in craft-xls.
Ported from storytold/gridcraft#3807.
---------
Co-authored-by: kiwi4boy <kiwi4boy@gmail.com>
The format half of PhotoCraft's Paint.NET import (crates/io/src/pdn.rs and pdn/nrbf.rs at
abeb16c96): the PDN3 header, the .NET binary serialization graph, the layer list and blend
modes, and the chunked gzip pixel blocks. Surfaces, blend-mode mapping and warnings stay in
the app.
MailCraft crates/ical at a44a450: content lines, DATE/DATE-TIME values,
durations and text, the common subset of recurrence rules, and VTIMEZONE
definitions read and written, with their tests. Times are chrono values; the
zone database the writer needs is the caller's, through ZoneRules. The event
and to-do mapping onto MailCraft's model stays in MailCraft.
Co-authored-by: Martin Ball <98639962+benandez@users.noreply.github.com>
* craft-raw: the file-format layer of camera raw files, with DNG and CRW
A new crate for #587 and #778: bytes in, the sensor data out as a neutral
RawImage (samples, CFA, levels, active area, crop, orientation, colour tags,
opcode lists, profile tables), and back for DNG. One Cargo feature per format:
dng (read and write), jxl (JPEG XL DNG), crw (through craft-crw).
The base is LightCraft's crates/raw at 5ff567a4: dng, dngwrite, tiffraw,
unpack, ljpeg, jxl, semantic, preview, the parsing half of opcodes, profile
and gaintable, the model and probe. Demosaicing and everything after it stay
with the develop pipeline.
Ported from PhotoCraft's and FilmCraft's DNG readers, each with a test: the
default crop's per-tag defaults, an unusable crop falling back to the active
area, non-finite white levels, the white default of a linearized image, the
AsShotWhiteXY range, 8-bit-only lossy JPEG, lossy tiles that must cover their
part of the image, and the CinemaDNG frame tags.
* craft-raw: Hasselblad 3FR and FFF (feature hasselblad)
RawFormat::CfaTiff decodes: the DNG-layout reader plus what these files add.
Uncompressed data or Hasselblad's lossless JPEG (selection value 8), RGGB when
no CFAPattern is stated, an FFF's colour matrix from the 3FR header it embeds,
and the 8-bit RGB preview handed on as a baseline TIFF.
Moved from LightCraft's vendor/hasselblad.rs at 5ff567a4 with its tests.
Ported from PhotoCraft's reader: four BlackLevel values without a
BlackLevelRepeatDim are one per CFA site in a file that is not a DNG.
* craft-raw: Minolta MRW, Epson ERF, Mamiya MEF and Kodak DCS520C
Four formats only LightCraft decodes, one feature each (mrw, erf, mef, kodak),
moved from its vendor modules at 5ff567a4 with their tests; the MRW block
container comes from lightcraft-meta. src/shared.rs holds the level helpers
the maker decoders share.
ERF and MEF state no white balance: the estimate LightCraft made from the
preview is develop-side work, so wb_multipliers is None for them here.
* craft-raw: shared scan budget for tagged previews, tile-sized lossy JPEG budget, bound on Deflate tile padding
Ported from storytold/lightcraft#3695. Candidate preview ranges are deduplicated and charged to one byte
budget and one header-walk budget; a lossy JPEG decoded for a tile may hold no more samples than the tile
rounded up to whole MCUs (and never more than Limits::max_lossy_tile_samples); a Deflate chunk whose nominal
size is mostly padding outside the image is refused before it is inflated.
* craft-raw: lossless JPEG sample bound per referenced byte; previews larger than the file are passed over
Ported from storytold/lightcraft#3910 (the parts whose code is in craft-raw today). check_image refuses a
lossless JPEG image that declares more than 32 samples per referenced byte, counted once per chunk that points
at the bytes so identical tiles stored once still decode. The Hasselblad RGB preview search passes over an
image whose pixel bytes exceed the file and still takes a smaller complete one.
* craft-raw: test for the Deflate padding bound
* craft-raw: Pentax PEF and Samsung SRW
Moved from LightCraft crates/raw (vendor/pef.rs, vendor/srw.rs) at 5ff567a4. The Huffman difference decoder
and bit reader that PEF shares with the Nikon, Panasonic and Sony codings become the huffman module.
* craft-raw: Canon CR2, with sRAW and mRAW
Moved from LightCraft crates/raw (vendor/cr2.rs, vendor/cr2/sraw.rs) at 5ff567a4. The white-balance presets a
CR2 lists come back as data in ColorData::kelvin_presets (the ordering from LightCraft's kelvin_presets.rs;
the temperature and tint arithmetic stays with the developer).
* craft-raw: an sRAW preview larger than the file is refused before its buffer is reserved
Ported from storytold/lightcraft#3910 (cr2::sraw::read_preview).
* WIP craft-raw: Nikon NEF/NRW (does not compile yet: limits threading, develop() calls in tests)
* craft-raw: Nikon NEF/NRW, with PhotoCraft's maker-note compression routing and 12-bit D4 white level
---------
Co-authored-by: radialmonster <radial@gmail.com>
* Add craft-xcf: GIMP XCF reader from PhotoCraft
The format half of PhotoCraft's XCF import (crates/io/src/xcf.rs at abeb16c96): the header,
precisions, property lists with their length repairs, parasites, layer structures and item
paths, channels, and the uncompressed, RLE and zlib tiles. The mapping onto a document (blend
modes, surfaces, profiles, warnings) stays in the app.
* craft-xcf: an RLE run of zero length is an error
A long run (op 127 or 128) with a 16-bit length of 0 consumed input without producing output,
so a tile of them was work the pixel budget never charged.
Ported from storytold/photocraft#11138.
* craft-xcf: channel names are charged to the metadata budget
Layer names already were. Many channel pointers to one channel with a large name made a copy
per read, multiplying a small file into gigabytes of retained names.
Ported from storytold/photocraft#11138.
craft-xls carried its own CellRef, Range, Value, CellError, Visibility, sheet-name
quoting, built-in number format table and indexed palette. craft-xlsx and craft-ods
need the same ones, so they move to a crate with no dependencies and craft-xls
re-exports them: an application gets one Value and one CellRef whichever file it read.
Added on the way: A1 parsing (CellRef::parse, Range::parse), Range::count and a1,
CellError::parse and the newer error values SpreadsheetML stores as text,
builtin_format_id for writers.
LZW, ASCII85, ASCIIHex, RunLength, the TIFF and PNG predictors, bounded CCITT
fax decoding (through hayro-ccitt) with Group 4 encoding (through fax), and
the lossless JBIG2 encoder with its MQ coder, from pdfcraft-filters at
PdfCraft revision 80e26e674d1aa33078e83c8139875047f3289eb6.
The crate sits below craft-pdf and craft-tiff: it knows no container. The
PDF filter chain, Flate and the bounded JBIG2 decoding entry are not part of
it.
lightcraft-meta at 5b61ce1e, as one crate with a module per format: exif
(read, write, maker-note lens, focus point, tag listing), iptc, xmp (parse,
write, merge), gpx, and the JPEG, PNG, WebP, TIFF, RAF and CR3 containers.
They share Metadata, DateTime, Gps and Orientation.
Changed in the move:
- TIFF comes from craft-tiff; Point, Rect and Orientation are the crate's own.
- The app namespace is a parameter: parse_xmp_with, write_xmp_with and
MergeRules::namespaces take it, and XmpData no longer has lc_settings.
- The HEIF, PSD and MRW readers stay out, since craft-heif, craft-psd and
craft-raw read those containers; from_embedded takes the blocks they find.
* craft-dxf: model, the drawing above the tags (header, tables, blocks, layouts)
Document::read indexes a tag list into header variables, table records,
blocks with their entities, the ENTITIES records (a POLYLINE with its
vertices, an INSERT with its attributes) and the objects, each a slice of the
tag list. The typed table records, LAYOUT and DICTIONARY are made on request.
Also the colour index palette, colour, lineweight and transparency values,
extended data lookup and the object coordinate system.
Merged from CADCraft's cadcraft-io dxf_read (5a6aa9b6) and VectorCraft's
vectorcraft-cad import (566f7208). Neither app's document types appear.
* craft-dxf: model entities (geometry, text, MTEXT columns, hatches, dimensions)
Entity::read types an entity record: the properties every entity has, and
LINE, POINT, CIRCLE, ARC, ELLIPSE, LWPOLYLINE, POLYLINE with its vertices
(2D, 3D, mesh, polyface), SPLINE, RAY, XLINE, TEXT, MTEXT with columns,
ATTDEF, INSERT with its attributes (multiline ones included), DIMENSION,
LEADER, SOLID, TRACE, 3DFACE, HATCH (polyline and edge loops, pattern lines,
seeds, gradient), VIEWPORT, IMAGE, WIPEOUT and TOLERANCE. Other types stay
readable from the record's tags. model::text has the caret encoding of
strings, both ways.
Merged from CADCraft's cadcraft-io dxf_read (5a6aa9b6) and VectorCraft's
vectorcraft-cad import (566f7208).
* craft-dxf: a hatch spline edge without fit data leaves the loop's source count
Before R2010 a spline edge has no 97 of its own, so the 97 after it counts the
loop's source entities. It was read as the edge's fit point count and the
sources were lost.
* README: keep main's crate list after the merge
The container every OpenDocument file shares, moved from WordCraft
(crates/formats/src/odt/crypt.rs, odt/flat.rs, the package reading and
writing in odt/import.rs and odt/package.rs, crates/doc/src/zip_guard.rs
at 06c2ae6f) so that the ODT and ODS readers build on one copy.
- Package and PackageWriter: the ZIP with its mimetype and manifest,
within Limits (entries, bytes per file, bytes per package).
- Manifest: read by namespace whatever the prefix, as GridCraft's ODS
reader did; written as LibreOffice lays it out.
- crypt: AES-256-CBC with PBKDF2, read and written, with the per-file and
per-package key-derivation budgets.
- flat: a flat document to a package and back, for any media type (the
WordCraft code wrote the text one only).
- zip_guard: the entry-count check before zip parses a directory.
No document content is read here.
PdfCraft's pdfcraft-prc crate (revision
80e26e674d1aa33078e83c8139875047f3289eb6), moved whole with its tests. It reads
PRC (ISO 14739-1), the model format of PDF 3D annotations: the container, the
bit-level primitives, the schema, tessellations and the product tree.
The code is unchanged. The package and its README are renamed, the doctests
and tests import craft_prc, and the Double code table taken from prc-rs (MIT)
has its row in ATTRIBUTION.md and its licence in licenses/prc-rs.
The bottom layer every HTML reader in the Craft apps carried its own copy
of. The tokenizer is MailCraft's (crates/html/src/tokenizer.rs), with what
it dropped and capped turned into Options and Limits, a self-closing flag,
and raw_content for callers that read a style sheet's text. The character
references are WordCraft's (crates/formats/src/html/entity.rs at 06c2ae6f):
its name table and the 94 legacy names that decode without a semicolon,
with MailCraft's Latin-1 and Greek tables and its handling of numbers too
long to be numbers.
No tree, no CSS, no decoding of bytes.
* craft-zip: ZIP preflight, bounded entry read and Budget (from craft-archive, #129)
The ZIP half of the craft-archive proposal (#126, #129): an allocation-free check of the end
records and central directory that runs before a ZIP reader indexes the archive, a bounded
entry read that distrusts the declared size, and the named Budget both charge. The XML half
of #129 is not carried: craft-xml bounds XML now.
* craft-zip: Archive (entry-count guard, duplicate names, budgeted reads) and Writer
check_entry_count is craft-opc's guard: the declared entry count, ZIP64 included, checked on
the raw bytes before zip parses the central directory. Archive reads entries within a per-entry
limit and a total Budget through read_entry. Duplicate names are found by counting the central
directory headers against the entries zip kept. Writer is craft-opc's ZipOut: stored or deflated
entries, ZIP64 for large ones, one fixed timestamp.
---------
Co-authored-by: skylar taylor-barrick <hi@skylar.cc>
One walk over a GIF's blocks, without decompressing pixels: the logical
screen, each frame's position, delay, disposal and transparent colour, the
loop count and the first frame's colour table. Replaces PhotoCraft's two
block walkers and gives the other apps a header-only animation probe.
* craft-audio: integer PCM of WAV and AIFF files bit for bit, and minimal files around it
wav_pcm and aiff_pcm (feature decode-native) return a file's integer PCM as stored
(RawPcm: little-endian interleaved bytes, 8-bit unsigned, with channels, rate and
bits), built on the existing WAV and AIFF chunk parsers. pcm_wav_file,
pcm_wav_header, pcm_aiff_file and pcm_aiff_header (feature pcm-encode) write the
44-byte canonical WAVE header and the plain AIFF header around such bytes.
For essence embedded in AAF and OMF files, which is moved bit for bit and whose
descriptors hold a bare header as a summary. The writers are FilmCraft's
(filmcraft-interchange wav.rs); the readers replace its second WAV/AIFF parser
with this crate's.
* craft-timeline: exact media time, reports, media paths, ALE and CMX 3600 EDL
New crate for editorial timeline interchange (#782), moved from FilmCraft at
4bec22bd:
- time: filmcraft-time whole (Tick, FrameRate, TimeRange, SMPTE timecode,
feet+frames, typed-timecode parsing) with its tests.
- report: Report / Level / ReportEntry.
- path: file URL and path conversion, relative references joined to a folder.
- rate: timebase+ntsc and floating rates to exact rates, MAX_RATE.
- ale: AleDoc, parse, write, standard heading and columns.
- edl: the parser (events, lines, timecode fields, M2, AUD, comment extensions),
the frame-rate guess, and the line layout of the writer, on frame counts.
- Format, detect_text, decode_text.
Each format module gives the document as the format writes it. Mapping onto an
application's timeline stays in the application.
* craft-timeline: strip a UTF-8 byte order mark when parsing ALE files
An ALE saved with a BOM was refused as "not an ALE file": the mark made the
first line something other than "Heading".
Ported from storytold/filmcraft#4531.
* craft-aaf: AAF (Edit Protocol) and OMF 2.0 readers and writers over one composition model
New crate (#782), moved from FilmCraft's filmcraft-interchange at 4bec22bd:
the mob-style model types of comp.rs, aaf/{ids,store,read,write}.rs and
omf/{bento,read,write}.rs, with their structural and hostile-input tests
rebuilt on model documents instead of FilmCraft projects.
The container is craft-cfb, time and reports are craft-timeline's, and the
WAVE/AIFF wrappers of embedded PCM are craft-audio's. The writer's identity
(company, product, version, AAF product id) is passed in instead of being
FilmCraft's. The private tags and properties FilmCraft wrote keep their names
so existing files read back.
The mapping between the model and an application's project stays in the
application.
---------
Co-authored-by: NetterSilver <133535268+Silvertree2010@users.noreply.github.com>
* craft-mime: strict base64, mailto links and code page labels from MailCraft
What MailCraft's mime and charset crates still had that craft-mime did not:
strict RFC 4648 base64 (crates/charset), mailto: links (RFC 6068,
crates/mime) and the Windows code page to charset label table (crates/pst).
With these, MailCraft's charset crate has nothing craft-mime lacks.
* Add craft-vcard: vCard reader and writer from MailCraft
MailCraft crates/vcard at a44a450: vCard 2.1, 3.0 and 4.0 read, 3.0 written,
with its limits and tests. The model is the crate's own Contact (the vCard
fields of MailCraft's); the birthday is a chrono::NaiveDate. Character sets
and strict base64 come from craft-mime.
---------
Co-authored-by: Martin Ball <98639962+benandez@users.noreply.github.com>
* craft-media: MPEG-2 transport and program stream demuxer from FilmCraft (feature `mpegts`)
Moves filmcraft-mpegts (storytold/filmcraft@4bec22b) into craft_media::mpegts.
ByteSource is the crate's trait, Error is written without thiserror so the
feature has no dependencies, and Codec::codec_id() and Stream::codec_params()
map streams to CodecId. Adds Container::MpegTs and Container::MpegPs, an
ffprobe oracle test over ten ffmpeg-made files, and hostile-input tests.
* craft-media: module order after merging main
`craft_lottie::model` is the Lottie document as the file has it: one
struct per object of the lottie-spec 1.0 object model (animation, assets,
layers by type, transform, masks, effects, shape items, text, markers,
fonts, glyphs), one field per key. `Animation::read` reads within
`Limits` (bytes, nesting, layers, assets, shape items); `to_json` writes.
Keys the model does not name, values of another type than expected, and
layers and shape items of an unknown type stay in `extra` and are written
back, so a document survives a read and a write. Animatable properties
stay JSON (`Animated`) and are read with `read_prop`.
* craft-svg paths: a shape carries the name of its Inkscape layer
Shape::layer is the inkscape:label (else the id) of the innermost
<g inkscape:groupmode="layer"> around the element, so a CAD or cutter
import can keep the drawing's layers.
* craft-svg guard: bound attributes per element and over the document; find entities holding markup
too_wide is the attribute check of storytold/figcraft#2251: an XML
reader checks each attribute against the earlier ones on its element,
so an element with millions of them is quadratic work before any other
limit applies. entity_holds_markup lets a caller refuse a document type
whose entities become elements, as PhotoCraft does.
* craft-svg: feature `tree`, usvg behind one bounded entry point
usvg 0.48.1 (Apache-2.0 OR MIT), re-exported as craft_svg::tree::usvg,
so every app parses with one version and one set of checks:
tree::parse runs svgz, the entity, attribute and nesting guards, the
reference-chain height (VectorCraft's depth::height, on this crate's
cascade), then usvg. tree::image_resolver bounds embedded SVGs
(FigCraft's budget::resolver). tree::draw bounds what drawing a tree
with resvg allocates (PhotoCraft's svg/limits.rs).
Part of #778 and #789.
The format half of PhotoCraft's OpenRaster import and export (crates/io/src/ora.rs at
abeb16c96): the archive and its mimetype, stack.xml as a tree of layers and stacks with the
attributes the file has, the 0.0.6 group isolation rule, and a writer. PNG coding, blend-mode
mapping, rendering and warnings stay in the app.
stack.xml is read with craft-xml and the archive with the zip crate.
* craft-y4m: YUV4MPEG2 reader
FilmCraft's Y4M reader as a crate: the stream header, colour space layouts,
a frame index built from the FRAME lines through a read callback, and plane
ranges. The media source and frame types stay in the app.
* craft-y4m: a header parameter starting with a multi-byte character is ignored
Port of storytold/filmcraft#4562: the tag of a stream header parameter is its
first character, not its first byte, so a parameter such as `éX` is skipped
like any other unknown tag instead of being split inside the character.
---------
Co-authored-by: NetterSilver <133535268+Silvertree2010@users.noreply.github.com>
Moved from WordCraft's crates/docx/src/crypt.rs (07f97737): agile and
standard decryption, agile encryption, the ISO and legacy protection
password hashes. The compound file is read and written with craft-cfb
and the descriptor parsed with craft-xml.
From GridCraft's crates/xlsx/src/crypto.rs (5cf52c5f): check(), named
unsupported schemes, rights-managed files, the password key encryptor
chosen by its URI, and independent key vectors.
The [MS-PST] reader of MailCraft crates/pst at a44a450, moved as it is: the
node database, heap, property and table contexts, folders, messages,
recipients, attachments, named properties, recurrence blobs and list
streams, with its limits, salvage and tests.
Left in MailCraft for now: the compressed-RTF and RTF text reading and the
code-page name table, which are not part of the .pst format.
Co-authored-by: Martin Ball <98639962+benandez@users.noreply.github.com>
The OpenEXR naming layer PhotoCraft and EffectCraft each have: layer and
channel names, the channels that make a colour picture, and Cryptomatte IDs,
metadata keys, manifests and rank channels. No decoder dependency; decoding
follows in later changes.
* Add craft-kra: Krita archives, maindoc.xml and tiled pixel files, from PhotoCraft
The format half of PhotoCraft's Krita import (crates/io/src/kra.rs and kra/tiles.rs at
abeb16c96): the archive and its mimetype, maindoc.xml as a tree of nodes with the attributes
Krita writes, the tiled pixel files and their LZF compression. The mapping onto a document
(blend modes, surfaces, warnings) stays in the app.
maindoc.xml is read with craft-xml and the archive with the zip crate.
* craft-kra: a default pixel is read under a one-pixel limit
The .defaultpixel member (1 to 8 bytes) was inflated under the 1 GiB layer-file limit before
its size was checked.
Ported from storytold/photocraft#11138.
* craft-kra: the tile table is not reserved from the declared count
A tiled file may declare one record per eight bytes of its size. Reserving that many up front
is 3 GiB for a 1 GiB member that holds none of them. Reserve 65,536 records at first and grow
as records are read, never past the declared count.
Ported from storytold/photocraft#13309.
Document::read indexes a tag list into header variables, table records,
blocks with their entities, the ENTITIES records (a POLYLINE with its
vertices, an INSERT with its attributes) and the objects, each a slice of the
tag list. The typed table records, LAYOUT and DICTIONARY are made on request.
Also the colour index palette, colour, lineweight and transparency values,
extended data lookup and the object coordinate system.
Merged from CADCraft's cadcraft-io dxf_read (5a6aa9b6) and VectorCraft's
vectorcraft-cad import (566f7208). Neither app's document types appear.
FilmCraft's clean-room Radiance HDR reader as a crate: flat, old and new
run-length scan lines, all eight axis orders, to linear float RGB. Scan lines
are validated before the float picture is allocated.
* craft-raw: the file-format layer of camera raw files, with DNG and CRW
A new crate for #587 and #778: bytes in, the sensor data out as a neutral
RawImage (samples, CFA, levels, active area, crop, orientation, colour tags,
opcode lists, profile tables), and back for DNG. One Cargo feature per format:
dng (read and write), jxl (JPEG XL DNG), crw (through craft-crw).
The base is LightCraft's crates/raw at 5ff567a4: dng, dngwrite, tiffraw,
unpack, ljpeg, jxl, semantic, preview, the parsing half of opcodes, profile
and gaintable, the model and probe. Demosaicing and everything after it stay
with the develop pipeline.
Ported from PhotoCraft's and FilmCraft's DNG readers, each with a test: the
default crop's per-tag defaults, an unusable crop falling back to the active
area, non-finite white levels, the white default of a linearized image, the
AsShotWhiteXY range, 8-bit-only lossy JPEG, lossy tiles that must cover their
part of the image, and the CinemaDNG frame tags.
* craft-raw: Hasselblad 3FR and FFF (feature hasselblad)
RawFormat::CfaTiff decodes: the DNG-layout reader plus what these files add.
Uncompressed data or Hasselblad's lossless JPEG (selection value 8), RGGB when
no CFAPattern is stated, an FFF's colour matrix from the 3FR header it embeds,
and the 8-bit RGB preview handed on as a baseline TIFF.
Moved from LightCraft's vendor/hasselblad.rs at 5ff567a4 with its tests.
Ported from PhotoCraft's reader: four BlackLevel values without a
BlackLevelRepeatDim are one per CFA site in a file that is not a DNG.
* craft-raw: Minolta MRW, Epson ERF, Mamiya MEF and Kodak DCS520C
Four formats only LightCraft decodes, one feature each (mrw, erf, mef, kodak),
moved from its vendor modules at 5ff567a4 with their tests; the MRW block
container comes from lightcraft-meta. src/shared.rs holds the level helpers
the maker decoders share.
ERF and MEF state no white balance: the estimate LightCraft made from the
preview is develop-side work, so wb_multipliers is None for them here.
* craft-raw: shared scan budget for tagged previews, tile-sized lossy JPEG budget, bound on Deflate tile padding
Ported from storytold/lightcraft#3695. Candidate preview ranges are deduplicated and charged to one byte
budget and one header-walk budget; a lossy JPEG decoded for a tile may hold no more samples than the tile
rounded up to whole MCUs (and never more than Limits::max_lossy_tile_samples); a Deflate chunk whose nominal
size is mostly padding outside the image is refused before it is inflated.
* craft-raw: lossless JPEG sample bound per referenced byte; previews larger than the file are passed over
Ported from storytold/lightcraft#3910 (the parts whose code is in craft-raw today). check_image refuses a
lossless JPEG image that declares more than 32 samples per referenced byte, counted once per chunk that points
at the bytes so identical tiles stored once still decode. The Hasselblad RGB preview search passes over an
image whose pixel bytes exceed the file and still takes a smaller complete one.
* craft-raw: test for the Deflate padding bound
* craft-raw: Pentax PEF and Samsung SRW
Moved from LightCraft crates/raw (vendor/pef.rs, vendor/srw.rs) at 5ff567a4. The Huffman difference decoder
and bit reader that PEF shares with the Nikon, Panasonic and Sony codings become the huffman module.
* craft-raw: Canon CR2, with sRAW and mRAW
Moved from LightCraft crates/raw (vendor/cr2.rs, vendor/cr2/sraw.rs) at 5ff567a4. The white-balance presets a
CR2 lists come back as data in ColorData::kelvin_presets (the ordering from LightCraft's kelvin_presets.rs;
the temperature and tint arithmetic stays with the developer).
* craft-raw: an sRAW preview larger than the file is refused before its buffer is reserved
Ported from storytold/lightcraft#3910 (cr2::sraw::read_preview).
---------
Co-authored-by: radialmonster <radial@gmail.com>
Reads a 3MF package into the crate's Scene: mesh objects, component
objects and build items with their transforms (as a node hierarchy; an
object placed several times is one mesh), the unit, base materials,
colour groups, texture coordinate groups and their textures.
The package is opened with craft-opc (3MF is an OPC package) and the model
part is read with craft-xml's pull reader, so a large part never becomes a
tree. read_model_part reads a model part on its own.
Ported from storytold/deckcraft#743 (crates/mesh/src/threemf.rs). What
that reader did for DeckCraft and stays there: baking placements into
world-space triangles, the turn to Y-up, scaling to metres, and decoding
the textures. Here placements stay nodes, positions stay in the file's
unit and axes (Model::unit says which), and a texture is its bytes.
Co-authored-by: uvxszi <uvxszi@gmail.com>
The layer every EPS reader and writer in the apps had its own copy of: where the PostScript
and the previews are behind the binary header (read and write), the header comments with
the bounding boxes (also deferred to the trailer), the EPSI preview bitmap, ASCII85 both
ways, and telling EPS, PostScript and PostScript- or PDF-based Illustrator files apart.
No PostScript interpreter.
From storytold/vectorcraft at 6e873b80 (crates/eps: lib.rs, import.rs, import/preview.rs,
ps.rs) and storytold/designcraft at 513f77b8 (crates/images/src/eps.rs).
FilmCraft's clean-room Targa reader and PhotoCraft's run-length writer in one
crate. The reader returns RGBA8 and names the layout the file stored; the
writer's packets end with their scan line.
One implementation of DPX (SMPTE ST 268) and Kodak Cineon for the apps that
each carried their own: PhotoCraft (reader, writer, Cineon, header metadata),
FilmCraft (Y'CbCr descriptors, ABGR, packed 10/12-bit) and EffectCraft
(Cineon in both byte orders, pixel aspect ratio, 12-bit method B).
The crate returns code values and header fields; colour conversion and
orientation stay in the apps.
* Add craft-raster-codecs: DDS, DICOM, FITS, IFF/ILBM, PCX, PNM and XPM from PhotoCraft
One module per format, moved from photocraft-codecs at 63b641b5 with its tests.
Decoders return one flat Image and take Limits; encoders take an image already in a
layout the format stores. Layout planning, colour and the document mapping stay in the app.
* craft-raster-codecs: PCX reads four 8-bit planes as RGBA and version 4 headers; pcx::dimensions
Four 8-bit planes are red, green, blue and alpha: they decode to RGBA instead of being
refused. Version 4 (PC Paintbrush for Windows) headers are accepted. pcx::dimensions gives the
pixel size from the header without decoding.
Ported from the PCX reader of storytold/designcraft#2011.
---------
Co-authored-by: subha-2025 <218455239+subha-2025@users.noreply.github.com>
* Add craft-kiwi: the kiwi binary schema format, decoded and encoded
The generic kiwi decoder and encoder from FigCraft's .fig import and export
(crates/format/src/fig/kiwi.rs at 3b9bf8c9), moved as it is: binary schema
decode and encode, the compact text form of a schema, message decode into a
tree keyed by field name, and message encode checked against the schema.
The value budget that follows a .fig file's compressed size stays with the
.fig reader; here decode_message_within takes the budget and
DEFAULT_MAX_VALUES is the floor FigCraft used.
* Add craft-fig: the .fig container, read and written
The app-independent half of FigCraft's .fig import and export
(crates/format/src/fig at 3b9bf8c9): the ZIP archive with its image
budget, the chunked canvas (deflate, zlib and zstd chunks), the value
budget that follows the compressed canvas, images carried in the
message's blobs, and the vector network and geometry blob encodings.
The message stays a craft-kiwi tree read by field name; mapping it onto
a document stays in the app.
* craft-kiwi: no scan per field in schema decode; the text form keeps the limits
Schema::decode compared each message field id with every earlier one: 20
definitions of 10 000 fields, within every cap, took a billion
comparisons. A set per definition now.
Schema::parse applies the definition and field caps of the binary form,
looks type names up in an index instead of scanning the lines per field,
accepts a struct or message without fields, and refuses two fields of one
name and a message field id that is 0 (it ends a message) or repeated.
Moved from MailCraft's crates/assuan at a44a45013d1c. The code is unchanged apart
from the crate name and doc wording that named the app. The S-expression reader,
socket-file reader, limits and all 60 tests come with it.
* Add craft-xls: Excel 97-2003 (.xls, BIFF8) workbook reader
Moved from GridCraft's gridcraft-xlsx crate (crates/xlsx/src/xls.rs and
xls/ at 5cf52c5f), where it read into GridCraft's own workbook model.
Here it reads into a model of the file's own terms: cells, formulas as
A1 text, one CellFormat per XF, ColInfo and Row records in file units,
defined names, print areas as formula text.
The container is read with craft-cfb. RString cells and the fixture
writer in craft_xls::testing come from WordCraft's mail-merge reader
(crates/formats/src/sheet/xls.rs).
* craft-xls: report the sheet the workbook was saved on
Window1's itabCur, counted over every BoundSheet8 record, as
Workbook::active_sheet (an index into the worksheets that were read).
Whether to open on a hidden sheet is the caller's choice.
Ported from storytold/gridcraft#3551.
---------
Co-authored-by: Daniele Mori <3956663+Morzilla@users.noreply.github.com>
Moved from GridCraft at 5cf52c5f: the encoding detection, delimiter
sniffing, record parser and field quoting of crates/xlsx/src/csv.rs,
and the SYLK reader of crates/engine/src/io/sylk.rs.
Fields stay text and the SYLK reader returns its own Sheet; typed
values, dates and the workbook stay in GridCraft.
* craft-raw: the file-format layer of camera raw files, with DNG and CRW
A new crate for #587 and #778: bytes in, the sensor data out as a neutral
RawImage (samples, CFA, levels, active area, crop, orientation, colour tags,
opcode lists, profile tables), and back for DNG. One Cargo feature per format:
dng (read and write), jxl (JPEG XL DNG), crw (through craft-crw).
The base is LightCraft's crates/raw at 5ff567a4: dng, dngwrite, tiffraw,
unpack, ljpeg, jxl, semantic, preview, the parsing half of opcodes, profile
and gaintable, the model and probe. Demosaicing and everything after it stay
with the develop pipeline.
Ported from PhotoCraft's and FilmCraft's DNG readers, each with a test: the
default crop's per-tag defaults, an unusable crop falling back to the active
area, non-finite white levels, the white default of a linearized image, the
AsShotWhiteXY range, 8-bit-only lossy JPEG, lossy tiles that must cover their
part of the image, and the CinemaDNG frame tags.
* craft-raw: Hasselblad 3FR and FFF (feature hasselblad)
RawFormat::CfaTiff decodes: the DNG-layout reader plus what these files add.
Uncompressed data or Hasselblad's lossless JPEG (selection value 8), RGGB when
no CFAPattern is stated, an FFF's colour matrix from the 3FR header it embeds,
and the 8-bit RGB preview handed on as a baseline TIFF.
Moved from LightCraft's vendor/hasselblad.rs at 5ff567a4 with its tests.
Ported from PhotoCraft's reader: four BlackLevel values without a
BlackLevelRepeatDim are one per CFA site in a file that is not a DNG.
* craft-raw: Minolta MRW, Epson ERF, Mamiya MEF and Kodak DCS520C
Four formats only LightCraft decodes, one feature each (mrw, erf, mef, kodak),
moved from its vendor modules at 5ff567a4 with their tests; the MRW block
container comes from lightcraft-meta. src/shared.rs holds the level helpers
the maker decoders share.
ERF and MEF state no white balance: the estimate LightCraft made from the
preview is develop-side work, so wb_multipliers is None for them here.
* craft-raw: shared scan budget for tagged previews, tile-sized lossy JPEG budget, bound on Deflate tile padding
Ported from storytold/lightcraft#3695. Candidate preview ranges are deduplicated and charged to one byte
budget and one header-walk budget; a lossy JPEG decoded for a tile may hold no more samples than the tile
rounded up to whole MCUs (and never more than Limits::max_lossy_tile_samples); a Deflate chunk whose nominal
size is mostly padding outside the image is refused before it is inflated.
* craft-raw: lossless JPEG sample bound per referenced byte; previews larger than the file are passed over
Ported from storytold/lightcraft#3910 (the parts whose code is in craft-raw today). check_image refuses a
lossless JPEG image that declares more than 32 samples per referenced byte, counted once per chunk that points
at the bytes so identical tiles stored once still decode. The Hasselblad RGB preview search passes over an
image whose pixel bytes exceed the file and still takes a smaller complete one.
* craft-raw: test for the Deflate padding bound
* craft-raw: Pentax PEF and Samsung SRW
Moved from LightCraft crates/raw (vendor/pef.rs, vendor/srw.rs) at 5ff567a4. The Huffman difference decoder
and bit reader that PEF shares with the Nikon, Panasonic and Sony codings become the huffman module.
---------
Co-authored-by: radialmonster <radial@gmail.com>
The archive half of FigCraft's Penpot import and export
(crates/format/src/penpot.rs and penpot/embedded_fonts.rs at 3b9bf8c9):
ZIP validation, the manifest, bounded JSON members with the shared byte
and value budgets, pages, page shapes, media objects, font signatures,
and the archive writer. Members are handed out as the JSON the file
holds; mapping shapes stays in the app.
Duplicate member names are now refused: the ZIP reader keeps one member
per name, so the per-name check FigCraft has never fires. The directory's
own member count is compared instead.