Está en la página 1de 20

 

Anime Studio 
Document File Format 

   

 
   
 
 

Anime Studio Document File Format 
 
● Introduction 
● Document Overview 
○ Zip Container 
○ JSON Project Document (Project.animeproj) 
● Document Structure 
○ Document Header 
○ Styles 
○ Layer Comps 
○ Camera Movements and Timeline Markers 
○ Layer Definitions 
○ Document View State (optional preference) 
● How to find what you are looking for from the old format within the new format? 
● How to edit the new format using a text editor 
● How to edit the new document format with a scripting tool 
● Tools for Beautifying JSON 
● Recommended JSON editors 
● Python Scripts 
 
   

  

   
 
 

Introduction 
With  Anime  Studio  11.0,  the  product  team  released  a  brand  new  document  file  format.  The 
older  .anme  format  was  replaced  with  a  new  ​ JSON­based  format  (file  extension:  .anime). 
Using  a  standard  format  like  JSON  made  it  easier  to  maintain  a  format  that  is   both 
backward  and  forward compatible as newer versions of Anime Studio are released. It can do 
that  because  the  JSON  format  can  organize  data  in  a  specific  yet  flexible  hierarchy.  This 
hierarchy can allow us to add,  and in some cases  delete data values without breaking the file 
format. 
In  order  for   the  document  to  save  space  on  user's  storage  devices,  the   document  format  is 
also  compressed  in  a  container  using  the Zip file format. Since JSON is a text based format, 
Zip dramatically reduces its size on disk.  
One  of  the  reasons  we  picked   both  JSON  and Zip is  they are both popular and widely used. 
That  makes  it  easier  for  users  to  be  able  to  use  third  party libraries and scripting languages 
to  manage  and  manipulate  the  document  if  they  feel  inclined.   For  example,  the  scripting 
language  Python  has  both  JSON  parsing  and  Zip  compression  decompression   built­in. 
Using  a  small  bit  of   scripting,  it  is  quite  easy  to  open,  query,  modify,  and  save  an  existing 
document. We'll show an example of this later in the document. 
One  note  about  the  pre­11.0  document  format.  Anime  Studio  will  continue  to  read  the  old 
format   for  the  foreseeable  future.  We  realize  there is a lot of content out there. While the old 
format   is  considered  deprecated,  the  application  should  continue  to   read  and  convert 
documents as old as Anime Studio 6. 
   

  

   
 
 

Document Overview 
If  you  were   to  try  to  open  up  a  .anime  file  in  a  text  editor  or  hex  editor,  you  most  likely 
wouldn't  understand  what  you  were  looking  at.  This  is  because  the  .anime  format  is  using 
the Zip compressed file format as a container for the real data of the document. 
 

 
 

Zip Container 
Zip  compression  shrinks  down  the  size  of  the  data  by  looking  for  duplicated  items  in  the 
document  and  replacing  it  with  binary  data  that  is  significantly  smaller  than  the  original 
information.  Since  JSON  is  a  text  based  format, the amount of compression we  get is rather 
dramatic.  We've   seen  document  data  reduce  in  size  on  disk  from  250  MB  down  to  about   4 
MB!  
If  you  were   to rename your ​ MyAnimeDocument.anime file to ​ MyAnimeDocument.zip​ , you 
could  expand  the  .anime  file  using  any  Zip decompression tool (eg StuffIt, WinZip, WinRAR, 
etc). One or two files should be created. 
■ Project.animeproj ­ the main project file 
■ preview.jpg ­ the project thumbnail image 
Project.animeproj  is  the  JSON  file  that  defines  all  the  main  data  about  your  Anime  Studio 
document  including  layers  and  styles.  The  whole  next   section  will  be  about  describing  this 
file. 
preview.jpg  is  the  optional  thumbnail  that  is   created  of  the  project  canvas  when  the 
document  was  saved.  This  file  is  used  by  the  thumbnail  previewer  on  Windows  and   the 
QuickLook  plugin  on  Mac.  The  reason  the  thumbnail is optionally in the archive is  the image 
file  will  not  be  created  if  thumbnail   creation  is  disabled  in  the  Documents  preferences. (See 
"Document thumbnail preview size") 

JSON Project Document (Project.animeproj) 
In  order  to  understand  how  the  Anime  Studio  project  document  works,  it  is  necessary  to 
review  some  of  the  basics  of   JSON.  Below  is  an   example  of  the   first  lines  of  the  project 
document. This document has been beautified to add whitespace and color. 

  

   
 
 

 
JSON  is  a  key­value   based  hierarchical  file  format.  This  means  that  you   associate  data 
values  from  the  document  by  using  a  specific  key. If you want to reference a particular bit of 
information   in  the  document,  you  just  have  to  search  for  its  key.  (In  the  screenshot  above, 
the  keys  are  in  blue.)  If  you   would  like  to  find  in  the  document  what date the document was 
created,  you'd   just search the JSON for the "created_date" key. The data value would be  the 
time stamp. Key­value pairs together are considered "properties" of the format. 
 
 
JSON Key/Value 

"created_date": "Fri Jan 22 17:59:49 2016" 
 
The  hierarchical  part  of  JSON  means  that  you  can  associate  one  or  more  pieces  of 
document  data  by  making  it  be  a  "parent"  or  "child" of that data. For example, Anime Studio 

  

   
 
 

uses  layers  to  define  objects  on  the  canvas  (eg  Vector,  Image,  Switch,  etc).  A  vector  layer 
may  be described  by many properties such as points, lines, curves. Those drawing types are 
in  turn  are  described  by  even  deeper  properties  such  as  their  location  on  the  canvas  and 
how  they  can  be   animated.  The  JSON  file  format  keeps  track  of  all  those  properties  by 
establishing  a  parent/child  relationship  between  them.  For  example,  this  is  a 
pseudo­hierarchical representation for a line in a vector layer: 
  All Layers ­> Vector Layer ­> Line ­> Line Properties 
With  JSON, you can also group related data into objects  and lists. Objects use { } syntax and 
lists  use  [  ]  syntax.  An  object  groups  properties  together  that  are  related  into  a  unified 
concept.  For  example,  if  you  wanted  to  define  a  background  color  based  on  it's  RGBA 
values, you may want to define it this way: 
 
 
Background Color Object 

"back_color": { 
  "r": 234, 
  "g": 234, 
  "b": 234, 
  "a": 255 
}, 
 
From  the  definition  it  becomes  clear  which  properties  are  considered  red,  green,  blue,  or 
alpha by looking at its keys. 
A  list  describes  properties,  objects,  or  even  other  lists  that  are  usually  the  same  type.  The 
advantage  of  lists  is  that  they  are  not  fixed  sizes.  So  you  can  define  as  many  items  as  you 
need. Here is how you may want to define a list of layer comps: 
 
 
Layer Comps Defined in a List 

"layercomps": ["Background","Character 1", "Character 2", ... ] 
 
(Note  that  the  example  above  isn't  exactly  how  layer  comps  are  defined  in  the  .anime  file 
format. Properties were removed for brevity.) 
Objects  and  lists  are  what   make  JSON  a  really  powerful  part  of  the  format  because  to  add 
new  data,  you  just  have  to  add  a   new  property  or  object.  Parsers  that  read  and understand 
JSON  typically  ignore  information  they  don't  understand.  So  let's  say  we  add  in  Anime 
Studio  15.0  a  new  property  with  a  key  of "my_new_animation_feature". When Anime Studio 
11.0   opens  that  file,  it  just  ignores  that  feature. This is good news if the new feature was not 
an  integral  feature  of  the  document.  If  it  is  an  important  feature,  you  will  have  to use Anime 
Studio 15.0 to make use of it. 

  

   
 
 

Document Structure 
Now  that  we  have  JSON  basics  under  control,  let's  start  going  through  some  of  the  guts  of  
the format. Within the JSON document there are a number of different sections: 
■ Document Header 
■ Camera Movements and Timeline Markers 
■ Styles 
■ Layer Comps 
■ Layer Definitions 
■ Document View State 
Each  section  mostly  correlates   to  the  old  .anme  format.  The  big  difference  is  that  in  the old 
format   not  all  items  used  a   key  to   define  its  value.  On  the  surface,  that  means that the new 
JSON  file  format  is  a  bit  bigger  and  a  bit more verbose than the old format. The positive is  it 
typically makes it much more easier to find the data values you are looking for. 
For  those  who  wish  to  understand  more  about  each  of  the  document  sections,  they  will  be 
described in more detail below. 
 

Document Header 
The  document  header  contains  general  or  project­wide  information  about  the  document.  It 
lives  at   the  very  top  of  the  document.  In  the  example  below  you  can  see  that  the  header 
includes version information, a creation date, as well as a comment the application writes. 
There are three versions specified in the header: 
● major_version 
● version 
● rev_version 
Anime   Studio  can  use  each  of  these  version  numbers  in  different  ways.  "major_version"  is 
the  major  document  version.  We  hope  this  never  happens,  but  if  we  have to  change the file 
format   so  radically  so  that  old  versions  of  our  software  can't  read  it,  this  number  will 
increase.  "version"  is  the  document  version.  It  is used mostly to let the application know that 
this  document  is  newer  or  older  than  what  the  current  application  can  open.  If  the  version 
number  is  newer,  a  warning  will  be  given  to  the  user   that  the  document  has  been  created 
with  a  newer  version  of  the  document.  Finally,  rev_version  is  just  a  revision  number.  This 
revision number is used mostly for internal purposes. 
The  "project_data"  object  contains  properties  that  are  specific  to  this  project.  Most   of  these 
properties  come  directly  from  the  ​ Project  Settings  dialog  (File­>Project  Settings)  in   the 
application. 
● width/height ­ The project width and height in pixels (eg 720p or 480p) of the export 
● start_frame/end_frame ­ The starting and ending frame of the animation 
● fps ­ frames per second of the animation 
● back_color ­ background color of the canvas 
● depth_of_field/focus_distance/focus_range/focus_blur ­ depth of field properties 
 
 
Document Header 

  

   
 
 

"mime_type": "application/x­vnd.lm_mohodoc", 
"version": 1021, 
"major_version": 1, 
"rev_version": 0, 
"comment":  "Created  in Moho version 12.0, Copyright ©  1999­2016 Smith Micro Software, 
Inc.", 
"created_date": "Fri Jan 22 17:59:49 2016", 
"project_data": { 
  "width": 852, 
  "height": 480, 
  "start_frame": 1, 
  "end_frame": 48, 
  "fps": 24, 
  "back_color": { 
    "r": 234, 
    "g": 234, 
    "b": 234, 
    "a": 255 
  }, 
  "noise_grain": 0, 
  "pixelation": 0, 
  "antialiasing": true, 
  "depth_sort": false, 
  "distance_sort": false, 
  "depth_of_field": false, 
  "focus_distance": 2, 
  "focus_range": 1, 
  "focus_blur": 0.050625, 
  "global_render_style_fill_style": 0, 
  "global_render_style_line_style": 0, 
  "global_render_style_layer_style": 0, 
  "global_render_style_minimize_randomness": true, 
  "stereo_mode": 0, 
  "stereo_separation": ­1, 
  "extra_swf_frame": false, 
  "color_palette": "Basic Colors.png", 
  "soundtrack": "" 

 

Styles 
All the global styles of the document are defined in this section.  
For each style there is a: 
● name 
● unique identifier 
● line and fill color 
● brush name 
● brush properties 
 

  

   
 
 

 
Styles 

"styles": [ 
  { 
    "type": "Style", 
    "name": "Dragon_Tongue_Shading", 
    "uuid": "0ff99f9b­299b­4497­9f73­6c38dda5e952", 
    "define_fill_color": true, 
    "fill_color": { ... } 
    "define_line_width": true, 
    "line_width": 0.001389, 
    "define_line_col": true, 
    "line_color": { ... } 
    "line_caps": 1, 
    "brush_name": "Brush504.png", 
    "brush_align": false, 
    "brush_jitter": 6.283185, 
    "brush_spacing": 0, 
    "brush_angle_drift": 0, 
    "brush_randomize": false, 
    "brush_merged_alpha": false, 
    "brush_tint": true 
  }, 
  { 
    "type": "Style", 
    "name": "Dragon_Wing_Dark", 
    ... 
  } 

 

Layer Comps 
Layer  comps  are  used  to  focus  on  certain  layers  when  composing  or  rendering.  You  can 
manage the creation, deletion, or updating of layer comps in the Layers palette. 
Layer comps in the document are defined by three items: 
■ Name 
■ Unique identifier (UUID) 
■ A list of layer IDs 
 
   

  

   
 
 

 
Layer Comps 

"layercomps": [ 
    { 
      "name": "Background", 
      "uuid": "B85FA8AD­2CB1­43C4­89E5­3B86138CAC40", 
      "layer_ids": [ 
        "DE907C68­CD6C­4353­A5C7­4D416E208BA7" 
      ] 
    }, 
    { 
      "name": "Character 1", 
      "uuid": "ABC86A51­B354­43E9­9D2C­5064D8DAD0B0", 
      "layer_ids": [ 
        "11A8AB8B­F7A6­4E7B­987C­F08F546E95EF", 
        "75BAC57E­C083­470F­B812­09CF8F2AE032", 
        "DE907C68­CD6C­4353­A5C7­4D416E208BA7" 
      ] 
    }, 
... 
  ], 
 
The  "layer_ids"  key  specifies  a  list  of  layer  IDs  that  are  UUIDs.  In  the  layers  section  of  the 
document, each layer has a unique layer ID. 

Camera Movements and Timeline Markers 
Camera movements and timeline markers are defined in the "animated_values" object. 
 
 
Camera Movements and Timeline Markers 

"animated_values": { 
    "camera_track": { ... }, 
    "camera_zoom": { ... }, 
    "camera_roll": { ... }, 
    "camera_pan_tilt": { ... }, 
    "timeline_markers": { ... } 
  }, 
 

Layer Definitions 
The  layers  section  of  the  document  is  undoubtably  the  largest  section  of  any  .anime 
document.  Quite  simply,  it  defines  all  of   the  layers  and  their  attributes.  Here  are  the current 
layer types: 
■ Vector Layer (aka Mesh Layer) 
■ Image Layer (includes image and movie types) 
■ Audio Layer 

  

   
 
 

■ Group Layer 
■ Switch Layer 
■ Bone Layer 
■ Particle Layer 
■ Note Layer 
■ Text Layer 
■ Patch Layer 
■ Poser Layer (aka Mesh 3D Layer) 
Each  of  the  layers  in   the  Project.animeproj  JSON  file  will  have  numerous  properties 
associated  with  it.   In  fact  it  is  too  many  to  name  in this document. There are  some common  
properties  like  type,  name,  and  unique  ID,  but  then  there  will   also  be  a  number  of  layer  
specific  properties.  For  example,  an  image  layer  requires  that  there  be  a  path  to  the  image 
file (eg MyPhoto.png) 
 
 
Layers 

"layers": [ 
  { 
   "type": "ImageLayer", 
   "name": "Background", 
   ... 
  }, 
  { 
   "type": "MeshLayer", 
   "name": "Character 1", 
   ... 
  }, 
  ... 

 

Document View State (optional preference) 
In  Anime  Studio  11,  there  is  a  new  checkbox  in  the  Documents   Preferences  to  save  the 
document  view  state  within  the  document.  Enabling  "Save  and  restore  view  settings  in  the 
document"  will  add  a   new  "documentviewstate"  object.  Documents  that  don't  save  the  view 
state, will just use the default values when they are opened. 
An  example  view  state  property  that  can  be  saved  with  the  document  happens  when  you 
select  View­>Show  Rule of  Thirds in the main menu.  Each time you open that document, the 
canvas will show the Rule of Thirds grid. 
 
   

  
10 
   
 
 

 
Document View State 

"documentviewstate": { 
  "DocState_viewportSetting": 1, 
  "DocState_gridOn": false, 
  "DocState_gridStyle": 0, 
  "DocState_gridSize": 20, 
  "DocState_gridSnappingOn": true, 
  "DocState_showOutputOnly": false, 
  "DocState_showVideoSafeZones": false, 
  "DocState_showRuleOfThirds": true, 
  "DocState_viewPortLeftWidthPct": 1, 
  "DocState_viewPortTopWidthPct": 1, 
  "DocState_zoom0": 0.9, 
  "DocState_viewOffset0": { ... }, 
  "DocState_rotation0": 0, 
  "DocState_stereo0": false, 
  "DocState_enableOutsideView0": false, 
  "DocState_outsideViewPitch0": 0, 
  "DocState_outsideViewYaw0": 0, 
  "DocState_outsideViewRadius0": 0, 
  "DocState_outsideViewAttn0": { ... }, 
  ... 
  "DocState_playStart": ­1, 
  "DocState_playEnd": ­1 

 

How to find what you are looking for from the old format within the new 
format? 
The  old  .anme   document  format  that was used in Anime Studio 10  and earlier was a custom 
format.  While  the  format  was text based, there were some format issues that made it difficult 
to  add  new  properties  without  breaking  the  format.  Since  you  just  had  to  drag  and  drop  a 
.anme  file  into  a  text  editor, it was relatively trivial to make changes  if you knew some  basics 
about  the format. The good  news is that the new document format tries to mimic the sections 
of  the  old  format.  There  was  a  Document  Header,  Layer  Comp,  Style,  and  Layer  section  to 
the  document.  If  you  have  an  older  .anme  file,  opened  it  Anime  Studio  11,   converted  the 
document  to  .anime  and  than  compared  the  documents  side­by­side,  a  lot  would  match up. 
The  main  big difference is  every property now ​ must have a key associated with values. That 
means  that  it should be easier to find a certain value in the document if you know  it's key. So 
if  you  want  to  change  a  value  of  an  Image  Layer,  all  you'd  need  to  do  is  search  for 
"ImageLayer"  in  the  JSON  file.  Find  the  specific  image  layer  if there is more than one. Then 
you  just  find  the  property  that  you  want  to change. For example, if you wanted to  enable  the 
Toon  Effect  on  that  image   layer,  you'd  continue  your  search  and  look  for  the  key  
"toon_effect". 

  
11 
   
 
 

The  keys  may  make  the  file  format  be more verbose looking, but the few times we have had 


to  open  up  a  document to check out  a property,  we find it easier to really drill down into what 
specific properties are. 
There  are  two  areas  were  it  will  actually  be  easier  to   understand  in  the new  format than the 
old format. 
1. Finding specific layers 
2. Finding type information about that layer. 
In  the  old  format,  layers  were  defined  by  an  ID  number.  You'd  used  to  have  to  search 
through  the  file  and  where  a  new  layer  was  starting  you  had  to  know  that  a  Image  Layer 
started with 2 and than you could search for this: 
 
 
layer_type 2 

  ... 

 
 
Here were all the ID numbers: 
■ Vector Layer = ​ 1 
■ Image Layer = ​ 2 
■ Group Layer = ​ 3 
■ Bone Layer = ​ 4 
■ Switch Layer = ​ 5 
■ Particle Layer = ​ 6 
■ Note Layer = ​ 7 
■ Poser/3D Layer = ​ 8 
■ Audio Layer = ​ 9 
■ Patch Layer = ​ 10 
■ Text Layer = ​ 11 
In the new format each layer has a "type" key that has one of the following values: 
● Vector Layer = ​ "MeshLayer" 
● Image Layer = ​ "ImageLayer" 
● Group Layer = ​ "GroupLayer" 
● Bone Layer = ​ "BoneLayer" 
● Switch Layer = ​ "SwitchLayer" 
● Particle Layer = ​ "ParticleLayer" 
● Note Layer = ​ "NoteLayer" 
● Poser/3D Layer = ​ "Mesh3DLayer" 
● Audio Layer = ​ "AudioLayer" 
● Patch Layer = ​ "PatchLayer" 
● Text Layer = ​ "TextLayer" 
No  more  searching  by  layer  ID.  Once  you  are in the JSON object for the layer, you then just 
navigate down to set its property. This should be relatively easy for top level properties of the 
layer  (eg  "name",  "path").  Note  that  most  of  the  layers  make  use  of  complex properties. For 

  
12 
   
 
 

example,  a  vector   layer  may  be  made  up  100s  of  shapes.  Those  shapes  may have 100s of 
points. Editing one of these points may be extremely difficult using just the document file. 
 

How to edit the new format using a text editor 
1. Copy  the  Anime  Studio  document  from  ​ MyAnimeDocument.anime  to  a  new  file 
named ​ MyAnimeDocument.zip​ . 
2. Expand  the  .zip  file  using  a  decompression  tool  like  StuffIt,  WinZip,  WinRAR,  or  the  
Zip mechanism built into your machine. 
3. There should be two files that are expanded: ​ Project.animeproj​  and ​ preview.jpg 
4. Beautify the ​ Project.animeproj​  file. (See below) 
5. Open the ​ Project.animeproj​  file in a text editor. 
6. Make your edits to the text file 
7. Zip the ​ Project.animeproj  ​ using a compression tool like above. Make sure to choose 
the .zip format, not 7z or RAR. 
8. Name the archive ​ MyModfiedAnimeDocument.zip 
9. Once zipped, rename the document to ​ MyModifiedAnimeDocument.anime​ . 
10. Try and open in Anime Studio. 
In  step  4  you  will  most  likely  need  to  "beautify"  or  "pretty"  up  the  ​ Project.animeproj   file 
before  it  is  edited  in  the  Text  Editor.  In  order  to  save  space  on  the  user's  computer,  the 
Project.animeproj  file   had  all  unnecessary  whitespace characters (spaces, tabs, new  lines) 
removed  by  Anime  Studio  when  saved.  Beautifying  means  that  you  are  adding all that back 
in  just  so  that  it  will  be  easy  to  edit.  There  are  a  number  of   tools  that  will  do  this  for   you. In 
the  section  below,  there  will  be  links  to  beautifiers.  The  sample  code  provided  below  also 
show how to beautify programmatically.  
There  is  no  need  to  remove  all  of the whitespace/newline characters after making your edits 
in step 6. The next time that the document is saved, the whitespace will again be removed. 
In  step  7, it is not necessary to Zip the preview.jpg file. This is purely optional. The thumbnail  
preview will be regenerated the next time the document is saved. 
Also   in  step  7,  keep  in  mind  that  some  Zip  tools  use  their   own  Zip  format  for  compression  
(eg  WinZip).  Make  sure  you  specify  in  the  application  preferences  the  most  "portable" 
version of the .zip format. That is usually LZ compression. 

How to edit the new document format with a scripting tool 
Editing  the  new  document  format  with  a  scripting  tool  follows  the  same  general  path  as 
manually  editing  from  the   section  previous.  The  difference  is  you  can  automate  the  Zip 
compression/decompression   as  well  as  the  browsing/editing  of  the  JSON.  At  the  bottom  of 
this  document  there  are  two  Python  scripts   that  you  can  use as an example. Other scripting 
languages  have  support  for  Zip  and  JSON,  either  through  builtin  support  or  by  using  a 
library. 
   

  
13 
   
 
 

 
Scripting Pseudo Code 

// Unzip the .anime file 
... 
  
// Open the Project.animeproj file 
... 
  
// Use the JSON parser to look for 1 or more keys 
... 
  
// Print/Edit the values for the key(s) 
... 
  
// Close the Project.animeproj file 
... 
  
// Zip the Project.animeproj back to the original .anime file 
... 
 
 

Tools for Beautifying JSON 
With  AnimeStudio  removing  all  of  the  whitespace  and  newline  characters  from  the  
document,  it  will  be  necessary  to  beautify  to  text  to  make  it  easier  to  search  for  keys  and 
values. Here are a list of tools we use within Smith Micro to help beautify. 
JQ​ ­ JSON Query Utility ­ Command­line tool for Mac or Windows 
BBEdit or TextWrangler JSON Text Filter Beautifier​  (Mac only) 
JS Beautifier​
 (Web) 
JSON Beautifier & Formatter​   (Web) 
JSON Beautifier​   (Web) 
 

Recommended JSON editors 
JSON  editors  can  help  you  visualize  a  JSON  file  by  syntax  coloring and collapsing lists and 
objects. 
JSON Editor Online​  (Web) 
Notepad++​  with​ ​
JSTool​
 plugin (Windows) 
Xcode​ (Mac) 
BBEdit​  ​
 or​TextWrangler​  (Mac) 
Keep  in  mind  that  JSON  is   just  text.  So  it  can  be  opened  with  your  favorite  text  editor.  It 
might not have syntax coloring, but it can get the job done. 
   

  
14 
   
 
 

Python Scripts 
Below  are  two  Python   2.x  scripts.  The  first  one  just extracts 1 or more  .anime  files to JSON. 
MyAnimeDocument.anime become MyAnimeDocument.json. 
 
 
Extract to JSON 

1  #!/usr/bin/env python 
2  """Extract To JSON ­ Takes 1 or more .anime file and converts it to JSON 
3     extract_to_json.py <.anime files> 
4  """ 
5  import​  os 
6  import​  os.path 
7  import​  json 
8  import​  shut 
9  import​  sys 
10  import​  zipfile 
11    
12  def​  ExtractToJSON(animepath, beautify = False): 
13     ​ (​
if ​not ​ os.path.exists(animepath)): 
14        ​
print ​ 'ERROR: %s does not exist' % ​ animepath 
15        ​
return 
16    
17     ​
# Get the folder and the file name for the path 
18     folder, animefilename = os.path.split(animepath) 
19     ​
print ​ 'Extracting from ' +​  animefilename ​ + '...' 
20    
21     ​
# Open the .anime file 
22     with zipfile.ZipFile(animepath) as zip_file: 
23        ​
# Iterate over all of the items in the zip file 
24        ​
for ​ item ​ in ​
zip_file.namelist(): 
25           filename = os.path.basename(item) 
26    
27           ​
# skip everything except the .animeproj file, which is JSON 
28           ​
if ​filename !​ = 'Project.animeproj'​ : 
29              ​continue 
30           ​
# Create the extracted .json path name 
31           filename, ext = os.path.splitext(animefilename) 
32           filename ​ += '.json' 
33           jsonpath = os.path.join(folder, filename) 
34           ​
# Load the JSON from the zip file and dump it beautified to the .json path 
35           source = zip_file.​ open​
(item) 
36           ​
if​
 (beautify): 
37              json_obj = json.load(source) 
38              json.dump(json_obj, ​ file​
(jsonpath, ​"wb"​ ), sort_keys=False) 
39           ​
else​ : 
40              shutil.copyfileobj(source, ​ file​
(jsonpath, ​ "wb"​)) 
41    

  
15 
   
 
 

42  def​  Usage(): 


43     ​
print ​
'%s <.anime files> ­ Extract .anime to JSON' %​
 os.path.basename(sys.argv[0]) 
44    
45  def ​ perform(): 
46     numArgs = ​ len​
(sys.argv) 
47     ​
if​
 numArgs == ​ 1​: 
48        Usage() 
49        ​
return 
50    
51     ​
for​ animepath ​in ​
sys.argv[​1​:]: 
52        ExtractToJSON(os.path.normpath(animepath)) 
53    
54  if ​
__name__ ​ == '__main__'​ :   
55    perform() 
 
 
   

  
16 
   
 
 

This  second  script  allows  you  to   list,   extract   or   update  an  existing  .anime  without  even 
opening the file. 
 
 
Anime Util ­ Manipulate a .anime file 

1  #!/usr/bin/env python 
2  """anime_util ­ Manipulate a .anime file 
3     Commands are list, extract, and update. 
4     list prints the paths of image and audio layers. 
5     extract saves the Project.animeproj to a desired location. 
6     update replaces existing paths with the one supplied. 
7     anime_util.py ­h |command| for help. 
8  """ 
9  import​  zipfile 
10  import ​ json 
11  import ​ argparse 
12  import ​ os 
13  import ​ sys 
14    
15  def ​ extractProject(animeFile): 
16      ​"""Return the Project.animeproj extracted from a zip file as a string.""" 
17      zf = zipfile.ZipFile(animeFile) 
18      ​for ​filename ​ in ​
[ ​
'Project.animeproj' ​ ]: 
19          data = zf.read(filename) 
20    
21      ​return ​ data 
22    
23  def ​ writeProject(animeFile, projectData): 
24    ​  """Write data back into Project.animeproj in a zip file""" 
25      zf = zipfile.ZipFile(animeFile, mode=​ "w"​

26      zf.writestr(​ 'Project.animeproj'​ , projectData) 
27    
28  def ​ printLayerInfo(layer): 
29      ​"""Print the path of an image or audio layer.""" 
30      ​if ​
layer.has_key(​ 'image_path'​ ): 
31          ​print ​"image:"​ , layer[​'image_path'​ ] 
32    
33      ​if​
 layer.has_key(​ 'audio_path'​ ): 
34          ​print ​"audio:"​ , layer[​'audio_path'​ ] 
35    
36  def ​ updateLayerInfo(layer, update): 
37     ​ """Replace the path of an image or audio layer.""" 
38      ​if ​
layer.has_key(​ 'image_path'​ ): 
39          path = layer[​ 'image_path'​ ] 
40          layer[​ 'image_path'​ ] = path.replace(update[​ 0​ 1​
], update[​ ]) 
41    
42      ​if ​
layer.has_key(​ 'audio_path'​ ): 
43          path = layer[​ 'audio_path'​ ] 
44          layer[​ 'audio_path'​ ] = path.replace(update[​ 0​ 1​
], update[​ ]) 

  
17 
   
 
 

45    
46  def ​ isContainerLayer(layer): 
47     ​
 """Return True if the layer is a group or switch layer.""" 
48      ​
type ​ = layer[​ 'type'​] 
49      ​
return​  ​
type ​ == "GroupLayer" or​  ​
type ​ == ​"SwitchLayer" 
50    
51  def ​ iterateContainerLayer(groupLayer, update=None): 
52      """Iterate  a  group  or  switch   layer  descending  into  sub   groups  and  updating  or 
  printing layers otherwise.""" 
53      ​
for ​layer ​ in ​groupLayer: 
54          ​
if ​
isContainerLayer(layer): 
55              iterateContainerLayer(layer[​ 'layers'​], update) 
56          ​
else​ : 
57              ​
if ​
update: 
58                  updateLayerInfo(layer, update) 
59              ​
else​ : 
60                  printLayerInfo(layer) 
61    
62    
63  def ​ iterateLayers(path, update=None): 
64     ​
 """Iterate the root project layers.""" 
65      projectPath = path 
66      projectData = extractProject(projectPath) 
67    
68      ​
if ​
len​ (projectData) > ​ 0​: 
69          jsonData = json.loads(projectData) 
70          layers = jsonData[​ 'layers'​

71          iterateContainerLayer(layers, update) 
72          ​
if ​
update: 
73              writeProject(projectPath, json.dumps(jsonData)) 
74              iterateContainerLayer(layers) 
75    
76  def ​ extractProjectFile(animeFile, projectFilepath = None): 
77     ​
 """Iterate Project.animeproj to projectFilePath.""" 
78      jsonData = extractProject(animeFile) 
79    
80      ​  ​
if​len​ (jsonData) > ​ 0​: 
81          jsonData = json.loads(jsonData) 
82          ​
if ​
projectFilepath: 
83              output = ​ file​
(projectFilepath, ​ 'wb'​) 
84          ​
else​ : 
85              output = ​ (​
file​'Project.animeproj'​ , ​
'wb'​) 
86    
87          json.dump(jsonData, output, sort_keys=False, indent=​ 4​

88      ​
else​ : 
89          parser.error(​ "Project.animeproj is empty"​ ) 
90    
91     
92    
93  def ​ perform(): 

  
18 
   
 
 

94    parser   =  argparse.ArgumentParser(description=​ "Open  a  .anime  file  and  print 


  and/or update the paths of image and audio layers"​ ) 
95      subParsers = parser.add_subparsers(​ help​ =​
"commands"​ , dest=​
"command"​ ) 
96    parser_list  =  subParsers.add_parser(​ ,  ​
"list"​ help​ =​"list  image  and   audio  paths  in 
  Anime Studio file (.anime)."​ ) 
97      parser_list.add_argument(​ 'path'​ , ​
help​ =​
"path to Anime Studio file"​ ) 
98    
99    parser_extract  =  subParsers.add_parser(​ "extract"​,  ​ help​=​"extract 
  Project.animeproj from Anime Studio file (.anime)."​ ) 
100      parser_extract.add_argument(​ 'path'​ , ​
help​ =​
"path to Anime Studio file"​ ) 
101    parser_extract.add_argument(​ 'projectFile'​ ,  metavar=​ 'project  file'​,  ​
help​=​
"path  to  
  save Anime Studio project file"​ ) 
102    parser_extract.add_argument(​ '­b'​, '­­beautify'​ , action=​ "store_true"​ , ​
help​ =​
"beautify  
  the project file"​ ) 
103    
104    parser_update   =  subParsers.add_parser(​ "update"​ ,  ​help​=​
"update  image  and 
  audio paths in Anime Studio file (.anime)."​ ) 
105      parser_update.add_argument(​ 'existing'​ , ​
help​ =​"existing path(s) in file"​ ) 
106      parser_update.add_argument(​ 'new'​ , ​help​ =​
"path to replace existing path(s) with"​ ) 
      parser_update.add_argument(​ 'path'​ , ​
help​ =​
"path to Anime Studio file"​ ) 
107    
108      args = parser.parse_args() 
109    
110      path = os.path.abspath(args.path) 
111      ​
if not​ os.path.exists(path): 
112          parser.error(​ "%s does not exist." % ​ path) 
113    
114      ​
if not ​ path.endswith(​ ".anime"​ ): 
115          parser.error(​ "%s is not an Anime Studio (.anime) file." %​  path) 
116    
117      updateInfo = None 
118      ​
if ​
args.command ​ == "update"​ : 
119          updateInfo ​ =​
 (args.existing, args.new) 
120    
121      ​
if ​
args.command​  == "extract"​: 
122          extractProjectFile(path, os.path.abspath(args.projectFile)) 
123      ​
else​ : 
124          iterateLayers(path, update=updateInfo) 
125    
126  if ​
__name__​  == '__main__'​ : 
127      perform() 
128 
 

  
19