Skip to main content

Crate csp_format

Crate csp_format 

Source
Expand description

Read, verify and write CLIP STUDIO PAINT files (.clip / .cmc).

The format is not published; everything here was learnt from real files and is written down in the repository’s docs/spec/. Input files are never modified: files are read into memory, and changes are written only by an explicit save. This crate is not made or endorsed by CELSYS.

§Reading

ClipFile opens a .clip: the canvas settings, the layer tree, every table of the embedded SQLite database, and the pixels, vectors and texts of the layers. CmcFile opens a .cmc (a multi-page work) and lists its pages in reading order.

use csp_format::{ClipFile, CmcFile};

let file = ClipFile::open("page0001.clip")?;
for (layer, depth) in file.layers.flatten() {
    println!("{}{} ({})", "  ".repeat(depth), layer.name, layer.kind.name());
    if let Some((image, (x, y))) = file.layer_pixels(layer)? {
        println!("  {}x{} px at ({x}, {y})", image.width, image.height);
    }
}

let work = CmcFile::open("work.cmc")?;
for path in work.page_paths(std::path::Path::new("."))? {
    println!("{}", path.display());
}

§Writing

A file saved without changes is byte-identical to the input. Changes go through ClipFile’s methods (edit) or straight into its database; new canvases and works are made with NewCanvas and NewWork.

use csp_format::{ClipFile, LayerKind, NewCanvas, RgbaImage};

let mut file = ClipFile::create(&NewCanvas { width: 640, height: 480, ..NewCanvas::default() })?;
let mut image = RgbaImage::new(64, 64);
image.fill([200, 30, 30, 255]);
let id = file.add_raster_layer("red square", &image, (10, 20))?;
file.set_layer_opacity(id, 0.5)?;

let reopened = ClipFile::from_bytes(file.to_bytes()?)?;
let layer = reopened.layers.get(id).unwrap();
assert_eq!(layer.kind, LayerKind::Raster);
let (pixels, (x, y)) = reopened.layer_pixels(layer)?.unwrap();
assert_eq!(pixels.pixel((10 - x) as u32, (20 - y) as u32), [200, 30, 30, 255]);
assert_eq!(pixels.pixel((9 - x) as u32, (20 - y) as u32)[3], 0);

§Rendering and checking

render::render composites the layers (blend modes, clipping, masks, effects, corrections, gradients, vectors) into an image, and verify::check_clip runs every self-check (round trips of each part, references between tables and chunks).

§Modules

Items hidden from these docs are used by the project’s investigation tools and are not part of the stable API.

Re-exports§

pub use clip::ClipFile;
pub use cmc::CmcFile;
pub use create::NewCanvas;
pub use error::Error;
pub use error::Result;
pub use image::GrayImage;
pub use image::RgbaImage;
pub use model::Canvas;
pub use model::Layer;
pub use model::LayerKind;
pub use model::LayerTree;
pub use version::VersionInfo;
pub use work::NewWork;
pub use rusqlite;

Modules§

animation
Animation (R17): timelines, tracks, keyframes, cels, the 2D camera and onion skin settings, how a frame is evaluated, and edits.
blank
Pages and works made from settings alone, without a CSP-made template of the work. Moved from name-studio’s clip-core (write/blank.rs).
clip
A .clip file: container + database + external chunks, with typed access and lossless saving.
cmc
Comic / multi-page projects (.cmc): a plain SQLite file next to the pages.
cmc_pages
A work (.cmc) for given page files, made from a template work (from name-studio’s clip-core write_cmc).
cmt
“cmt “ documents: CSP’s binary tree format for animation track mixers (Track.TrackActionMixer and TrackActionMixer2).
container
The CSF chunk container (“CSFCHUNK”) that wraps every .clip file.
copy
Copying layers from another .clip (from name-studio’s clip-core).
correction
Correction layers (色調補正レイヤー): Layer.FilterLayerInfo holds u32 type, u32 size and the settings; CSP stores no pixels and applies the correction to the image below the layer when it draws.
create
New .clip files without a template (R13).
database
Access to the SQLite database embedded in .clip files (and .cmc / .sut, which are plain SQLite files).
edit
Editing an opened .clip (R12): layer pixels, layer properties, adding and removing layers, and the stored preview.
effect
Layer effects (Layer.LayerEffectInfo): border (フチ), tone, watercolour edge, line extraction and their options, and the border drawing.
error
Error type shared by every reader and writer in this crate.
gradient
Gradient layers (Layer.GradationFillInfo, R10): CSP saves no pixels for them and draws the gradient when it opens the file.
image
Plain in-memory images and PNG input / output.
material
Image material layers (画像素材レイヤー, R10): CSP keeps the original image (Layer.ResizableOriginalMipmap) and its placement (Layer.ResizableImageInfo), and draws the transformed image when it opens the file; the render mipmap is often not stored.
model
Typed view of the Project, Canvas and Layer tables of a .clip.
offscreen
Raster pixels: the Offscreen table and its block data.
render
Compositing the stored layer pixels into a canvas image (R10).
schema
CSP’s own schema registry inside every .clip / .cmc database.
story
The texts of a page’s story info layers (Layer.ComicStoryInfoType): (作品情報) holds 作品名・話数・サブタイトル in its first block, 作者名 and ページ番号 in the blocks of its attributes array; (ノンブル) holds the ノンブル. CSP marks each block with the part it is (record 0x2e) and draws them afresh from these blocks, so a part’s text, style run length and block width are written together. Moved from name-studio’s clip-core (write/story.rs, write/page.rs).
text
Text layers: TextLayerString (UTF-8) and its attributes.
tone
The tone layer effect (トーン, section EffectTone of Layer.LayerEffectInfo): the layer drawn as a black-and-white halftone screen.
vector
Vector data (VectorObjectList.VectorData, an external chunk).
vector_build
New vector objects: lines and コマ枠 (frame) borders (from name-studio’s clip-core).
verify
Self-checks of a .clip file, used for corpus validation (V1) and for checking written files (V4). Each check records counts, not artwork.
version
Which CSP version saved a file, and what older versions will make of it.
work
New comic works (.cmc and its page files) without a template (R18).