# SpineAtlas
Modify atlas data and export frames or convert other atlas-like data to spine atlas
## Installation
Install the latest version of `SpineAtlas` from PyPI:
```bash
pip install SpineAtlas
```
## Usage
# Opening and saving atlas
```python
from SpineAtlas import ReadAtlasFile
atlas = ReadAtlasFile('1.atlas')
# The code will automatically determine the format of Atlas
atlas.version = False # Convert to Atlas 3.0 format
atlas.version = True # Convert to Atlas 4.0 format
atlas.SaveAtlas('1_v4.atlas')
```
# Check if the atlas is missing a textures
```python
from SpineAtlas import ReadAtlasFile
atlas = ReadAtlasFile('1.atlas')
# If the texture and atlas are in the same directory, you don't need to pass the path
miss = atlas.CheckTextures()
# If `miss` is empty, it means there is no missing textures
```
# Modify the texture scaling of the atlas
```python
from SpineAtlas import ReadAtlasFile
atlas = ReadAtlasFile('1.atlas')
# If the texture and atlas are in the same directory, you don't need to pass the path
atlas.ReScale()
atlas.SaveAtlas('1_scale.atlas')
```
# Export atlas frames
```python
from SpineAtlas import ReadAtlasFile
atlas = ReadAtlasFile('1.atlas')
# If the texture and atlas are in the same directory, you don't need to pass the texture path
# mode : ['Normal', 'Premul', 'NonPremul']
# --- Normal - do not process the texture
# --- Premul - convert the texture to premultiplied
# --- NonPremul - convert the texture to non-premultiplied
atlas.SaveFrames(path='1_frames', mode='Premul')
```
# Convert other formats to `Spine Atlas`
```python
from SpineAtlas import Atlas, AtlasTex, AtlasFrame
'''
{
Texture:
Texture_Name: str
Texture_Wdith: int
Texture_Height: int
Frame:
[
[
Frame_Name: str
Cut_X: int
Cut_Y: int
Cut_Wdith: int
Cut_Height: int
Original_X: int
Original_Y: int
Original_Wdith: int
Original_Height: int
Rotate: int
],
...
]
}
'''
TextureDict = {...}
frames = []
for i in TextureDict['Frame']:
frames.append(AtlasFrame(i['Frame_Name'], i['Cut_X'], i['Cut_Y'], i['Cut_Wdith'], i['Cut_Height'], i['Original_X'], i['Original_Y'], i['Original_Wdith'], i['Original_Height'], i['Rotate']))
tex = TextureDict['Texture']
texture = AtlasTex(tex['Texture_Name'], tex['Texture_Wdith'], tex['Texture_Height'], frames=frames)
atlas = Atlas([texture])
atlas.SaveAtlas('1.atlas')
```
# Recalculate the clipping anchor point
```python
from SpineAtlas import ReadAtlasFile, Anchor
'''
class Anchor(IntEnum):
TOP_LEFT = 1
TOP_CENTER = 2
TOP_RIGHT = 3
CENTER_LEFT = 4
CENTER = 5
CENTER_RIGHT = 6
BOTTOM_LEFT = 7
BOTTOM_CENTER = 8
BOTTOM_RIGHT = 9
'''
atlas = ReadAtlasFile('1.atlas')
# The default anchor point for Spine Atlas clipping is the top left corner
atlas.cutp = Anchor.BOTTOM_LEFT
atlas.ReOffset() # Recalculate clipping X/Y starting from the upper left corner
atlas.SaveAtlas('1_1_ReOffset.atlas')
```
# Recalculate the Offset anchor point
```python
from SpineAtlas import ReadAtlasFile, Anchor
'''
class Anchor(IntEnum):
TOP_LEFT = 1
TOP_CENTER = 2
TOP_RIGHT = 3
CENTER_LEFT = 4
CENTER = 5
CENTER_RIGHT = 6
BOTTOM_LEFT = 7
BOTTOM_CENTER = 8
BOTTOM_RIGHT = 9
'''
atlas = ReadAtlasFile('1.atlas')
# The default anchor point for Spine Atlas Offset is the bottom left corner
atlas.offp = Anchor.TOP_LEFT
atlas.ReOffset() # Recalculate Offset X/Y starting from the bottom left corner
atlas.SaveAtlas('1_1_ReOffset.atlas')
```
# Convert image to premultiplied/non-premultiplied
```python
from PIL.Image import open as imgop
from SpineAtlas import ImgPremultiplied, ImgNonPremultiplied
img = imgop('1.png')
tex = ImgPremultiplied(img)
tex.save('1_premultiplied.png')
tex = ImgNonPremultiplied(img)
tex.save('1_non-premultiplied.png')
```
Raw data
{
"_id": null,
"home_page": "https://github.com/Rin-Wood/SpineAtlas",
"name": "SpineAtlas",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": "spine, Python, atlas, SpineAtlas",
"author": "wood",
"author_email": "miraclerinwood@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/cb/61/076b62beef2a0dcb981538fc4769fed935ba9030ec02a57b5b07d3dd335b/spineatlas-1.0.11.tar.gz",
"platform": null,
"description": "# SpineAtlas\nModify atlas data and export frames or convert other atlas-like data to spine atlas\n\n## Installation\nInstall the latest version of `SpineAtlas` from PyPI:\n\n```bash\npip install SpineAtlas\n```\n\n## Usage\n# Opening and saving atlas\n```python\nfrom SpineAtlas import ReadAtlasFile\n\natlas = ReadAtlasFile('1.atlas')\n# The code will automatically determine the format of Atlas\natlas.version = False # Convert to Atlas 3.0 format\natlas.version = True # Convert to Atlas 4.0 format\natlas.SaveAtlas('1_v4.atlas')\n```\n# Check if the atlas is missing a textures\n```python\nfrom SpineAtlas import ReadAtlasFile\n\natlas = ReadAtlasFile('1.atlas')\n# If the texture and atlas are in the same directory, you don't need to pass the path\nmiss = atlas.CheckTextures()\n# If `miss` is empty, it means there is no missing textures\n```\n# Modify the texture scaling of the atlas\n```python\nfrom SpineAtlas import ReadAtlasFile\n\natlas = ReadAtlasFile('1.atlas')\n# If the texture and atlas are in the same directory, you don't need to pass the path\natlas.ReScale()\natlas.SaveAtlas('1_scale.atlas')\n```\n# Export atlas frames\n```python\nfrom SpineAtlas import ReadAtlasFile\n\natlas = ReadAtlasFile('1.atlas')\n# If the texture and atlas are in the same directory, you don't need to pass the texture path\n# mode : ['Normal', 'Premul', 'NonPremul']\n# --- Normal - do not process the texture\n# --- Premul - convert the texture to premultiplied\n# --- NonPremul - convert the texture to non-premultiplied\natlas.SaveFrames(path='1_frames', mode='Premul')\n```\n# Convert other formats to `Spine Atlas`\n```python\nfrom SpineAtlas import Atlas, AtlasTex, AtlasFrame\n\n'''\n{\nTexture:\n Texture_Name: str\n Texture_Wdith: int\n Texture_Height: int\n\t\nFrame:\n[\n [\n Frame_Name: str\n Cut_X: int\n Cut_Y: int\n Cut_Wdith: int\n Cut_Height: int\n Original_X: int\n Original_Y: int\n Original_Wdith: int\n Original_Height: int\n Rotate: int\n ],\n ...\n]\n}\n'''\nTextureDict = {...}\nframes = []\nfor i in TextureDict['Frame']:\n frames.append(AtlasFrame(i['Frame_Name'], i['Cut_X'], i['Cut_Y'], i['Cut_Wdith'], i['Cut_Height'], i['Original_X'], i['Original_Y'], i['Original_Wdith'], i['Original_Height'], i['Rotate']))\ntex = TextureDict['Texture']\ntexture = AtlasTex(tex['Texture_Name'], tex['Texture_Wdith'], tex['Texture_Height'], frames=frames)\natlas = Atlas([texture])\natlas.SaveAtlas('1.atlas')\n```\n# Recalculate the clipping anchor point\n```python\nfrom SpineAtlas import ReadAtlasFile, Anchor\n\n'''\nclass Anchor(IntEnum):\n TOP_LEFT = 1\n TOP_CENTER = 2\n TOP_RIGHT = 3\n CENTER_LEFT = 4\n CENTER = 5\n CENTER_RIGHT = 6\n BOTTOM_LEFT = 7\n BOTTOM_CENTER = 8\n BOTTOM_RIGHT = 9\n'''\n\natlas = ReadAtlasFile('1.atlas')\n# The default anchor point for Spine Atlas clipping is the top left corner\natlas.cutp = Anchor.BOTTOM_LEFT\natlas.ReOffset() # Recalculate clipping X/Y starting from the upper left corner\natlas.SaveAtlas('1_1_ReOffset.atlas')\n```\n# Recalculate the Offset anchor point\n```python\nfrom SpineAtlas import ReadAtlasFile, Anchor\n\n'''\nclass Anchor(IntEnum):\n TOP_LEFT = 1\n TOP_CENTER = 2\n TOP_RIGHT = 3\n CENTER_LEFT = 4\n CENTER = 5\n CENTER_RIGHT = 6\n BOTTOM_LEFT = 7\n BOTTOM_CENTER = 8\n BOTTOM_RIGHT = 9\n'''\n\natlas = ReadAtlasFile('1.atlas')\n# The default anchor point for Spine Atlas Offset is the bottom left corner\natlas.offp = Anchor.TOP_LEFT\natlas.ReOffset() # Recalculate Offset X/Y starting from the bottom left corner\natlas.SaveAtlas('1_1_ReOffset.atlas')\n```\n# Convert image to premultiplied/non-premultiplied\n```python\nfrom PIL.Image import open as imgop\nfrom SpineAtlas import ImgPremultiplied, ImgNonPremultiplied\n\nimg = imgop('1.png')\n\ntex = ImgPremultiplied(img)\ntex.save('1_premultiplied.png')\n\ntex = ImgNonPremultiplied(img)\ntex.save('1_non-premultiplied.png')\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Python spine atlas parsing",
"version": "1.0.11",
"project_urls": {
"Homepage": "https://github.com/Rin-Wood/SpineAtlas"
},
"split_keywords": [
"spine",
" python",
" atlas",
" spineatlas"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "0fe76d390dca99a0d5d420b627e959b07b333dfda9d4188a8b51f08ac58c609e",
"md5": "6a7fd38840498081531a0e73c3776c70",
"sha256": "afdb1259ea966773acb1cbfd980185406acefd8231e21b45cb3e85c643874e55"
},
"downloads": -1,
"filename": "spineatlas-1.0.11-py3-none-any.whl",
"has_sig": false,
"md5_digest": "6a7fd38840498081531a0e73c3776c70",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 9008,
"upload_time": "2025-07-21T11:39:30",
"upload_time_iso_8601": "2025-07-21T11:39:30.321408Z",
"url": "https://files.pythonhosted.org/packages/0f/e7/6d390dca99a0d5d420b627e959b07b333dfda9d4188a8b51f08ac58c609e/spineatlas-1.0.11-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "cb61076b62beef2a0dcb981538fc4769fed935ba9030ec02a57b5b07d3dd335b",
"md5": "4f1e3f2ba4406ae3023cc2787407b8aa",
"sha256": "0d6c242171b82d85942e4a4a7e3e2449295fa23d425905241c26a9fe5bf6279c"
},
"downloads": -1,
"filename": "spineatlas-1.0.11.tar.gz",
"has_sig": false,
"md5_digest": "4f1e3f2ba4406ae3023cc2787407b8aa",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 9885,
"upload_time": "2025-07-21T11:39:31",
"upload_time_iso_8601": "2025-07-21T11:39:31.534153Z",
"url": "https://files.pythonhosted.org/packages/cb/61/076b62beef2a0dcb981538fc4769fed935ba9030ec02a57b5b07d3dd335b/spineatlas-1.0.11.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-21 11:39:31",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Rin-Wood",
"github_project": "SpineAtlas",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "spineatlas"
}