|
13 | 13 | #### XCF #### |
14 | 14 | def openLayer_XCF(file: str) -> LayeredImage: |
15 | 15 | """Open an .xcf file into a layered image.""" |
16 | | - from gimpformats.gimpXcfDocument import GimpDocument |
| 16 | + from gimpformats.gimpXcfDocument import GimpDocument, GimpGroup |
17 | 17 |
|
18 | 18 | blendLookup = { |
19 | 19 | 0: BlendType.NORMAL, |
@@ -67,66 +67,44 @@ def openLayer_XCF(file: str) -> LayeredImage: |
67 | 67 | project = GimpDocument(file) |
68 | 68 | # Iterate the layers and create a list of layers for each group, then remove |
69 | 69 | # these from the project layers |
70 | | - layers = project.layers[::-1] |
71 | | - index = 0 |
72 | | - groupIndex = 0 |
73 | | - groupLayers = [[]] |
74 | | - while index < len(layers): |
75 | | - layerOrGroup = layers[index] |
76 | | - if layerOrGroup.isGroup: |
77 | | - index -= 1 |
78 | | - while layers[index].itemPath is not None: |
79 | | - layer = layers[index] |
80 | | - groupLayers[groupIndex].append( |
| 70 | + |
| 71 | + root_group = project.walkTree() |
| 72 | + |
| 73 | + def rec_walk(group: GimpGroup) -> list[Group | Layer]: |
| 74 | + layers = [] |
| 75 | + for child in group.children[::-1]: |
| 76 | + if isinstance(child, GimpGroup): |
| 77 | + info = child.layer_options |
| 78 | + if info is not None: |
| 79 | + layers.append( |
| 80 | + Group( |
| 81 | + name=str(info.name), |
| 82 | + layers=rec_walk(child), |
| 83 | + dimensions=(info.width, info.height), |
| 84 | + offsets=(0, 0), |
| 85 | + opacity=info.opacity, |
| 86 | + visible=info.visible, |
| 87 | + blendmode=blendModeLookup(info.blendMode, blendLookup), |
| 88 | + ) |
| 89 | + ) |
| 90 | + else: |
| 91 | + layers.append( |
81 | 92 | Layer( |
82 | | - name=layer.name, |
83 | | - image=layer.image, |
84 | | - dimensions=(layer.width, layer.height), |
| 93 | + name=str(child.name), |
| 94 | + image=child.image, |
| 95 | + dimensions=(child.width, child.height), |
85 | 96 | offsets=( |
86 | | - layer.xOffset - layerOrGroup.xOffset, |
87 | | - layer.yOffset - layerOrGroup.yOffset, |
| 97 | + child.xOffset, |
| 98 | + child.yOffset, |
88 | 99 | ), |
89 | | - opacity=layer.opacity, |
90 | | - visible=layer.visible, |
91 | | - blendmode=blendModeLookup(layer.blendMode, blendLookup), |
| 100 | + opacity=child.opacity, |
| 101 | + visible=child.visible, |
| 102 | + blendmode=blendModeLookup(child.blendMode, blendLookup), |
92 | 103 | ) |
93 | 104 | ) |
94 | | - layers.pop(index) |
95 | | - index -= 1 |
96 | | - index += 2 |
97 | | - groupIndex += 1 |
98 | | - groupLayers.append([]) |
99 | | - else: |
100 | | - index += 1 |
101 | | - # Iterate the clean project layers and add the group layers in |
102 | | - groupIndex = 0 |
103 | | - layersAndGroups = [] |
104 | | - for layerOrGroup in layers: |
105 | | - if layerOrGroup.isGroup: |
106 | | - layersAndGroups.append( |
107 | | - Group( |
108 | | - name=layerOrGroup.name, |
109 | | - layers=groupLayers[groupIndex][::-1], |
110 | | - dimensions=(layerOrGroup.width, layerOrGroup.height), |
111 | | - offsets=(layerOrGroup.xOffset, layerOrGroup.yOffset), |
112 | | - opacity=layerOrGroup.opacity, |
113 | | - visible=layerOrGroup.visible, |
114 | | - blendmode=blendModeLookup(layerOrGroup.blendMode, blendLookup), |
115 | | - ) |
116 | | - ) |
117 | | - groupIndex += 1 |
118 | | - else: |
119 | | - layersAndGroups.append( |
120 | | - Layer( |
121 | | - name=layerOrGroup.name, |
122 | | - image=layerOrGroup.image, |
123 | | - dimensions=(layerOrGroup.width, layerOrGroup.height), |
124 | | - offsets=(layerOrGroup.xOffset, layerOrGroup.yOffset), |
125 | | - opacity=layerOrGroup.opacity, |
126 | | - visible=layerOrGroup.visible, |
127 | | - blendmode=blendModeLookup(layerOrGroup.blendMode, blendLookup), |
128 | | - ) |
129 | | - ) |
| 105 | + return layers |
| 106 | + |
| 107 | + layersAndGroups = rec_walk(root_group) |
130 | 108 |
|
131 | 109 | return LayeredImage(layersAndGroups, (project.width, project.height)) |
132 | 110 |
|
|
0 commit comments