Acornβs native file format is used to losslessly store layer data, editable text, layer filters, an optional composite of the image, and various metadata. Its advantage over other common formats such as PNG or JPEG is that it preserves all this native information without flattening the layer data or vector graphics.
You might be thinking "But closed file formats are a big drawback, right?". In Acornβs case, thatβs not a concernβitβs actually very easy to extract all the layer and image information, because the file is simply a SQLite database. SQLite is the most widely used database engine in the world, itβs open source, and itβs supported by virtually every programming language.
Identifying an Acorn Image
Acorn images are SQLite database files which end with .acorn
.
Inspecting an Acorn Image with SQLite
If you are on macOS, you can use the Terminal app to open and inspect an Acorn file with the following command:
/usr/bin/sqlite3 /path/to/acorn_file.acorn
To inspect the layout of the database, you can type .schema
to get a list of tables.
The SQLite Database Schema
| CREATE TABLE image_attributes ( name text, value blob);
CREATE TABLE layers (id text, parent_id text, sequence integer, uti text, name text, data blob);
CREATE TABLE layer_attributes ( id text, name text, value blob);
|
Acorn sets the SQLite application_id to 'Acrn'
, which when viewed as a four byte number is 1097036398
. You can view this with the SQLite statement PRAGMA application_id;
The image_attributes Table
The image_attributes
table is a simple key value store which contains information about the image such as the bits per pixel, the DPI, the size of the image, the color profile, the composite image, and more. Most of the keys are self describing. Here is an example of some of the data in this table:
| sqlite> select * from image_attributes limit 10;
βββββββββββββββββββββββ¬ββββββββββββββ
β name β value β
βββββββββββββββββββββββΌββββββββββββββ€
β imageSize β {902, 1889} β
β dpi β {72, 72} β
β bitsPerPixel β 32 β
β bitsPerComponent β 8 β
β acorn.showsGrid β 0 β
β acorn.gridUsesDots β 0 β
β acorn.scalesGrid β 1 β
β acorn.gridBlendMode β normal β
β acorn.gridSpacing β 10 β
β acorn.fileVersion β 4 β
βββββββββββββββββββββββ΄ββββββββββββββ
|
Since the type of data stored in value
column is binary data, you can actually quickly export a composite of the image with this SQLite command:
SELECT writefile('/tmp/myfile.tiff', value) from image_attributes where name = 'composite'
This will write out the composite of the image as a TIFF image.
Note
The format of the composite of an Acorn file is either TIFF or PNG, depending on what version of Acorn was used to last edit the image and the bit depth of the image. To determine if you're dealing with a PNG or TIFF file, you write out the image and inspect it via the file system, or use the following SQLite query:
select hex(substr(value, 1, 4)) from image_attributes where name = 'composite'
4D4D002A
is the header for TIFF, 89504E47
is the header for PNG.
The layers Table
The layers
table stores all the layer information for the image. As of Acorn 8, there are three types of layers: group, bitmap, and shape (vector).
The id
column is a unique ID to each layer.
The parent_id
column is a reference to the parent group that the layer is a part of. If this value is empty or nil, then the layer is not part of a group.
The sequence
lets the enclosing group know what order the layer appears in.
The uti
column is the format of the layer. There are a number of different formats as described:
com.acorn.group
is a group layer and contains no information for the data column.
com.flyingmeat.acorn.shapelayer
is shape / vector layer, and the data column contains an XML representation of the layer.
public.png
or public.tiff
is a bitmap / raster layer, and the data column contains the encoded layer image. Mask layers also store their layer data this way.
The name
column is a UTF-8 string for the layer name.
And finally the data
column is the actual layer data for the layer.
Note
The format of a mask layer is the same as a bitmap layer. The ID for a mask layer has a prefix of mask-
. So if you have a shape layer with an id
of abc-123
, then the mask for that layer would have an id of mask-abc-123
.
The layer_attributes Table
Similar to the image_attributes
table, the layer_attributes
table contains metadata about a layer. The id
column matches with the id
column of the layers
table, and then the name
and value
columns act as a key value store. Here is an example of a three layered image, with the layer ids of 49a5d80a-78d2-4578-979d-1c8ee9674307
, 945a5bd2-61c3-4e93-a8c1-ad7f85957d33
, and 0cc3af32-d73b-48db-8063-c67a63da9a87
:
| sqlite> select * from layer_attributes;
ββββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β id β name β value β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 49a5d80a-78d2-4578-979d-1c8ee9674307 β visible β 1 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 49a5d80a-78d2-4578-979d-1c8ee9674307 β locked β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 49a5d80a-78d2-4578-979d-1c8ee9674307 β blendMode β normal β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 49a5d80a-78d2-4578-979d-1c8ee9674307 β opacity β 1.0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 49a5d80a-78d2-4578-979d-1c8ee9674307 β acorn.maskLinked β 1 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 49a5d80a-78d2-4578-979d-1c8ee9674307 β acorn.maskEnabled β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 49a5d80a-78d2-4578-979d-1c8ee9674307 β acorn.layerStylesEnabled β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 49a5d80a-78d2-4578-979d-1c8ee9674307 β acorn.styleChainSelectionBlendMode β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 49a5d80a-78d2-4578-979d-1c8ee9674307 β frame β {{0, 0}, {902, 1889}} β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 49a5d80a-78d2-4578-979d-1c8ee9674307 β shouldApplyStyleChainToSelection β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 945a5bd2-61c3-4e93-a8c1-ad7f85957d33 β visible β 1 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 945a5bd2-61c3-4e93-a8c1-ad7f85957d33 β locked β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 945a5bd2-61c3-4e93-a8c1-ad7f85957d33 β blendMode β passThrough β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 945a5bd2-61c3-4e93-a8c1-ad7f85957d33 β opacity β 1.0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 945a5bd2-61c3-4e93-a8c1-ad7f85957d33 β acorn.maskLinked β 1 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 945a5bd2-61c3-4e93-a8c1-ad7f85957d33 β acorn.maskEnabled β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 945a5bd2-61c3-4e93-a8c1-ad7f85957d33 β acorn.layerStylesEnabled β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 945a5bd2-61c3-4e93-a8c1-ad7f85957d33 β acorn.styleChainSelectionBlendMode β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 945a5bd2-61c3-4e93-a8c1-ad7f85957d33 β groupIsExpanded β 1 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0cc3af32-d73b-48db-8063-c67a63da9a87 β visible β 1 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0cc3af32-d73b-48db-8063-c67a63da9a87 β locked β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0cc3af32-d73b-48db-8063-c67a63da9a87 β blendMode β normal β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0cc3af32-d73b-48db-8063-c67a63da9a87 β opacity β 1.0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0cc3af32-d73b-48db-8063-c67a63da9a87 β acorn.maskLinked β 1 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0cc3af32-d73b-48db-8063-c67a63da9a87 β acorn.maskEnabled β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0cc3af32-d73b-48db-8063-c67a63da9a87 β acorn.layerStylesEnabled β 1 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0cc3af32-d73b-48db-8063-c67a63da9a87 β acorn.styleChainSelectionBlendMode β 0 β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0cc3af32-d73b-48db-8063-c67a63da9a87 β acorn.layerStylesList β <?xml version="1.0" encoding="UTF-8"?> β
β β β <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http:/ β
β β β /www.apple.com/DTDs/PropertyList-1.0.dtd"> β
β β β <plist version="1.0"> β
β β β <array> β
β β β <dict> β
β β β <key>class</key> β
β β β <string>TSMerlinFilter</string> β
β β β <key>enabled</key> β
β β β <true/> β
β β β <key>name</key> β
β β β <string>TSGaussianBlurClampFilter</string> β
β β β <key>params</key> β
β β β <dict> β
β β β <key>CIAttributeFilterName</key> β
β β β <string>TSGaussianBlurClampFilter</s β
β β β tring> β
β β β <key>inputOption</key> β
β β β <integer>1</integer> β
β β β <key>inputRadius</key> β
β β β <integer>10</integer> β
β β β </dict> β
β β β </dict> β
β β β </array> β
β β β </plist> β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0cc3af32-d73b-48db-8063-c67a63da9a87 β frame β {{34, -99}, {902, 1889}} β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0cc3af32-d73b-48db-8063-c67a63da9a87 β shouldApplyStyleChainToSelection β 0 β
ββββββββββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
Most of the names are self explanatory. You may notice that the value for the acorn.layerStylesList
is XML data. This is the information for the non-destructive filters assigned to this layer.
To export all the layer data to files, you can use the following SQLite statements:
| select writefile('/tmp/' || name || '.png', data) from layers where uti = 'public.png';
select writefile('/tmp/' || name || '.tiff', data) from layers where uti = 'public.tiff';
select writefile('/tmp/' || name || '.xml', data) from layers where uti = 'com.flyingmeat.acorn.shapelayer';
|
Sample Acorn images
- pizza.acorn, a multi-layer image with groups, shape layers, text, and a layer mask.
- mona.acorn, a simple single layer image with a composite.
Export Acorn Images With a Python Script
You can also easily export the layer data / images for a .acorn
file using Python 3. acorn_image_export.py is one such example.