├── .gitignore
├── LICENSE
├── pom.xml
├── psd-analizer
├── build.xml
└── src
│ └── analizer
│ └── PsdAnalizer.java
├── psd-image
├── .classpath
├── .project
├── .settings
│ └── org.eclipse.jdt.core.prefs
├── pom.xml
├── psd-image.iml
└── src
│ └── psd
│ ├── Layer.java
│ ├── LayersContainer.java
│ └── Psd.java
├── psd-parser
├── .classpath
├── .project
├── pom.xml
├── psd-parser.iml
└── src
│ └── psd
│ ├── parser
│ ├── BlendMode.java
│ ├── ColorMode.java
│ ├── ColorModeSectionParser.java
│ ├── PsdFileParser.java
│ ├── PsdInputStream.java
│ ├── header
│ │ ├── Header.java
│ │ ├── HeaderSectionHandler.java
│ │ └── HeaderSectionParser.java
│ ├── imageresource
│ │ ├── ImageResourceSectionHandler.java
│ │ └── ImageResourceSectionParser.java
│ ├── layer
│ │ ├── BlendingRanges.java
│ │ ├── Channel.java
│ │ ├── ImagePlaneParser.java
│ │ ├── LayerAdditionalInformationParser.java
│ │ ├── LayerHandler.java
│ │ ├── LayerParser.java
│ │ ├── LayerType.java
│ │ ├── LayersSectionHandler.java
│ │ ├── LayersSectionParser.java
│ │ ├── Mask.java
│ │ └── additional
│ │ │ ├── LayerEffectsHandler.java
│ │ │ ├── LayerEffectsParser.java
│ │ │ ├── LayerIdHandler.java
│ │ │ ├── LayerIdParser.java
│ │ │ ├── LayerMetaDataHandler.java
│ │ │ ├── LayerMetaDataParser.java
│ │ │ ├── LayerSectionDividerHandler.java
│ │ │ ├── LayerSectionDividerParser.java
│ │ │ ├── LayerTypeToolHandler.java
│ │ │ ├── LayerTypeToolParser.java
│ │ │ ├── LayerUnicodeNameHandler.java
│ │ │ ├── LayerUnicodeNameParser.java
│ │ │ ├── Matrix.java
│ │ │ └── effects
│ │ │ ├── BevelEffect.java
│ │ │ ├── DropShadowEffect.java
│ │ │ ├── GlowEffect.java
│ │ │ ├── PSDEffect.java
│ │ │ └── SolidFillEffect.java
│ └── object
│ │ ├── PsdBoolean.java
│ │ ├── PsdDescriptor.java
│ │ ├── PsdDouble.java
│ │ ├── PsdEnum.java
│ │ ├── PsdList.java
│ │ ├── PsdLong.java
│ │ ├── PsdObject.java
│ │ ├── PsdObjectFactory.java
│ │ ├── PsdText.java
│ │ ├── PsdTextData.java
│ │ └── PsdUnitFloat.java
│ └── util
│ └── BufferedImageBuilder.java
└── psd-tool
├── .classpath
├── .project
├── pom.xml
├── psd-tool.iml
└── src
└── psdtool
├── MainFrame.java
├── PsdView.java
├── TreeLayerModel.java
└── UiLauncher.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | psd-library
5 | psd-library-parent
6 | 2.0-SNAPSHOT
7 | pom
8 |
9 | psd-image
10 | psd-parser
11 | psd-tool
12 |
13 |
14 |
15 | encontra-snapshots
16 | http://nexus.inevo.pt/content/repositories/encontra-snapshots
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/psd-analizer/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/psd-analizer/src/analizer/PsdAnalizer.java:
--------------------------------------------------------------------------------
1 | package analizer;
2 |
3 | import java.io.BufferedWriter;
4 | import java.io.File;
5 | import java.io.FileWriter;
6 | import java.io.IOException;
7 | import java.util.Map;
8 | import java.util.logging.ConsoleHandler;
9 | import java.util.logging.Handler;
10 | import java.util.logging.Level;
11 | import java.util.logging.LogRecord;
12 | import java.util.logging.Logger;
13 |
14 | import javax.imageio.ImageIO;
15 |
16 | import psd.base.PsdImage;
17 | import psd.layer.PsdLayer;
18 | import psd.layer.PsdLayerType;
19 | import psd.layer.PsdTextLayerTypeTool;
20 | import psd.rawObjects.PsdTextData;
21 |
22 | public class PsdAnalizer {
23 | private static Logger logger = Logger.getLogger("app");
24 |
25 | public static void main(String[] args) {
26 | if (args.length < 2) {
27 | System.out.println("java -jar psd-analizer.jar source.psd dest.dir");
28 | return;
29 | }
30 | configureLogs();
31 |
32 | long startTime = System.currentTimeMillis();
33 | logger.info("reading: " + args[0]);
34 |
35 | try {
36 | processPsd(new File(args[0]), new File(args[1]));
37 | } catch (Exception e) {
38 | e.printStackTrace();
39 | }
40 |
41 | long finishTime = System.currentTimeMillis();
42 | long time = finishTime - startTime;
43 | String timeStr = "" + (time / 1000) + "." + (time % 1000);
44 | logger.info("Time: " + timeStr + " sec.");
45 | }
46 |
47 | private static void configureLogs() {
48 | Logger psdLogger = Logger.getLogger("");
49 | psdLogger.setLevel(Level.ALL);
50 | Handler[] handlers = psdLogger.getHandlers();
51 | for (Handler handler : handlers) {
52 | psdLogger.removeHandler(handler);
53 | }
54 |
55 | psdLogger.addHandler(new ConsoleHandler() {
56 | public void publish(LogRecord rec) {
57 | System.out.println(rec.getLevel() + ": " + rec.getMessage());
58 | }
59 | });
60 | }
61 |
62 | private static void processPsd(File inputFile, File outputDir) throws IOException {
63 | PsdImage psdFile = new PsdImage(inputFile);
64 | outputDir.mkdirs();
65 |
66 | int num = 0;
67 | int total = psdFile.getLayers().size();
68 | for (PsdLayer layer : psdFile.getLayers()) {
69 | logger.info("processing: " + layer.getName() + " - " + (num * 100 / total) + "%");
70 | writeLayer(psdFile, layer, outputDir);
71 | num++;
72 | }
73 | }
74 |
75 | private static void writeLayer(PsdImage psd, PsdLayer layer, File baseDir) throws IOException {
76 | if (layer.getType() == PsdLayerType.NORMAL) {
77 | String path = getPath(layer);
78 | File outFile = new File(baseDir, path + ".png");
79 | outFile.getParentFile().mkdirs();
80 | if (layer.getImage() != null) {
81 | ImageIO.write(layer.getImage(), "png", outFile);
82 | } else {
83 | logger.warning("!!!!NULL layer: " + layer.getName());
84 | }
85 | BufferedWriter writer = new BufferedWriter(new FileWriter(new File(baseDir, path + ".txt")));
86 | writer.write("psd"); writer.newLine();
87 | writer.write("width: " + psd.getWidth()); writer.newLine();
88 | writer.write("height: " + psd.getHeight()); writer.newLine();
89 | writer.newLine();
90 | writer.write("layer"); writer.newLine();
91 | writer.write("left: " + layer.getLeft()); writer.newLine();
92 | writer.write("top: " + layer.getTop()); writer.newLine();
93 | writer.newLine();
94 | writer.write("right: " + (layer.getLeft() + layer.getWidth())); writer.newLine();
95 | writer.write("bottom: " + (layer.getTop() + layer.getHeight())); writer.newLine();
96 | writer.newLine();
97 | writer.write("width: " + layer.getWidth()); writer.newLine();
98 | writer.write("height: " + layer.getHeight()); writer.newLine();
99 |
100 | if (layer.getTypeTool() != null) {
101 | writeTypeTool(writer, layer.getTypeTool());
102 | }
103 | writer.close();
104 | }
105 | }
106 |
107 | private static void writeTypeTool(BufferedWriter writer, PsdTextLayerTypeTool typeTool) throws IOException {
108 | writer.newLine();
109 | writer.newLine();
110 | writer.write("-*- text layer -*-");
111 | writer.newLine();
112 |
113 | writer.write("TEXT: " + typeTool.get("Txt "));
114 | writer.newLine();
115 | writer.write("METRICS: ");
116 | writer.newLine();
117 |
118 | PsdTextData textData = (PsdTextData) typeTool.get("EngineData");
119 | Map properties = textData.getProperties();
120 | writeMap(writer, properties, 0);
121 | }
122 |
123 | private static void writeMap(BufferedWriter writer, Map map, int level) throws IOException {
124 | writeTabs(writer, level); writer.write("{"); writer.newLine();
125 |
126 | for (String key : map.keySet()) {
127 | writeTabs(writer, level + 1); writer.write(key + ": ");
128 | Object value = map.get(key);
129 | if (value instanceof Map) {
130 | writer.newLine();
131 | writeMap(writer, (Map) value, level + 1);
132 | } else {
133 | writer.write(String.valueOf(value));
134 | writer.newLine();
135 | }
136 | }
137 | writeTabs(writer, level); writer.write("}"); writer.newLine();
138 | }
139 |
140 | private static void writeTabs(BufferedWriter writer, int tabsCount) throws IOException {
141 | while (tabsCount > 0) {
142 | writer.write("\t");
143 | tabsCount--;
144 | }
145 | }
146 |
147 | private static String getPath(PsdLayer layer) {
148 | String dir = "";
149 | if (layer.getParent() != null) {
150 | dir = getPath(layer.getParent()) + "/";
151 | }
152 | return dir + layer.getName();
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/psd-image/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/psd-image/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | psd-image
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/psd-image/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | #Sat Nov 27 14:24:01 EET 2010
2 | eclipse.preferences.version=1
3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
6 | org.eclipse.jdt.core.compiler.compliance=1.6
7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
12 | org.eclipse.jdt.core.compiler.source=1.6
13 |
--------------------------------------------------------------------------------
/psd-image/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | psd-library
5 | psd-image
6 | 2.0-SNAPSHOT
7 | jar
8 |
9 | ..
10 | psd-library
11 | psd-library-parent
12 | 2.0-SNAPSHOT
13 |
14 |
15 | src
16 |
17 |
18 | maven-compiler-plugin
19 |
20 | 1.6
21 | 1.6
22 |
23 |
24 |
25 |
26 |
27 |
28 | psd-library
29 | psd-parser
30 | 2.0-SNAPSHOT
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/psd-image/psd-image.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/psd-image/src/psd/Layer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd;
20 |
21 | import psd.parser.BlendMode;
22 | import psd.parser.layer.*;
23 | import psd.parser.layer.additional.*;
24 | import psd.parser.layer.additional.effects.PSDEffect;
25 | import psd.util.BufferedImageBuilder;
26 |
27 | import java.awt.image.*;
28 | import java.util.*;
29 |
30 | public class Layer implements LayersContainer {
31 | private int top = 0;
32 | private int left = 0;
33 | private int bottom = 0;
34 | private int right = 0;
35 |
36 | private int alpha = 255;
37 |
38 | private boolean visible = true;
39 | private boolean clippingLoaded;
40 |
41 | private String name;
42 |
43 | private BufferedImage image;
44 | private LayerType type = LayerType.NORMAL;
45 |
46 | private BlendMode layerBlendMode;
47 | private BlendingRanges layerBlendingRanges;
48 | private Mask mask;
49 |
50 | private ArrayList layers = new ArrayList();
51 |
52 | private ArrayList layerEffects = new ArrayList();
53 |
54 | public Layer(LayerParser parser) {
55 | parser.setHandler(new LayerHandler() {
56 | @Override
57 | public void boundsLoaded(int left, int top, int right, int bottom) {
58 | Layer.this.left = left;
59 | Layer.this.top = top;
60 | Layer.this.right = right;
61 | Layer.this.bottom = bottom;
62 | }
63 |
64 | @Override
65 | public void blendModeLoaded(BlendMode blendMode) {
66 | Layer.this.setLayerBlendMode(blendMode);
67 | }
68 |
69 | @Override
70 | public void blendingRangesLoaded(BlendingRanges ranges) {
71 | Layer.this.setLayerBlendingRanges(ranges);
72 | }
73 |
74 | @Override
75 | public void opacityLoaded(int opacity) {
76 | Layer.this.alpha = opacity;
77 | }
78 |
79 | @Override
80 | public void clippingLoaded(boolean clipping) {
81 | Layer.this.setClippingLoaded(clipping);
82 | }
83 |
84 | @Override
85 | public void flagsLoaded(boolean transparencyProtected, boolean visible, boolean obsolete, boolean isPixelDataIrrelevantValueUseful, boolean pixelDataIrrelevant) {
86 | Layer.this.visible = visible;
87 | }
88 |
89 | @Override
90 | public void nameLoaded(String name) {
91 | Layer.this.name = name;
92 | }
93 |
94 | @Override
95 | public void channelsLoaded(List channels) {
96 | BufferedImageBuilder imageBuilder = new BufferedImageBuilder(channels, getWidth(), getHeight());
97 | image = imageBuilder.makeImage();
98 | }
99 |
100 | @Override
101 | public void maskLoaded(Mask mask) {
102 | Layer.this.setMask(mask);
103 | }
104 |
105 | });
106 |
107 | parser.putAdditionalInformationParser(LayerSectionDividerParser.TAG, new LayerSectionDividerParser(new LayerSectionDividerHandler() {
108 | @Override
109 | public void sectionDividerParsed(LayerType type) {
110 | Layer.this.type = type;
111 | }
112 | }));
113 |
114 | parser.putAdditionalInformationParser(LayerEffectsParser.TAG, new LayerEffectsParser(new LayerEffectsHandler() {
115 | @Override
116 | public void handleEffects(List effects) {
117 | layerEffects.addAll(effects);
118 | }
119 | }));
120 |
121 | parser.putAdditionalInformationParser(LayerUnicodeNameParser.TAG, new LayerUnicodeNameParser(new LayerUnicodeNameHandler() {
122 | @Override
123 | public void layerUnicodeNameParsed(String unicodeName) {
124 | name = unicodeName;
125 | }
126 | }));
127 | }
128 |
129 | public void addLayer(Layer layer) {
130 | layers.add(layer);
131 | }
132 |
133 | @Override
134 | public Layer getLayer(int index) {
135 | return layers.get(index);
136 | }
137 |
138 | @Override
139 | public int indexOfLayer(Layer layer) {
140 | return layers.indexOf(layer);
141 | }
142 |
143 | @Override
144 | public int getLayersCount() {
145 | return layers.size();
146 | }
147 |
148 | public BufferedImage getImage() {
149 | return image;
150 | }
151 |
152 | public List getEffectsList() {
153 | return layerEffects;
154 | }
155 |
156 | public int getX() {
157 | return left;
158 | }
159 |
160 | public int getY() {
161 | return top;
162 | }
163 |
164 | public int getWidth() {
165 | return right - left;
166 | }
167 |
168 | public int getHeight() {
169 | return bottom - top;
170 | }
171 |
172 | public LayerType getType() {
173 | return type;
174 | }
175 |
176 | public boolean isVisible() {
177 | return visible;
178 | }
179 |
180 | @Override
181 | public String toString() {
182 | return name;
183 | }
184 |
185 | public int getAlpha() {
186 | return alpha;
187 | }
188 |
189 | public boolean isClippingLoaded() {
190 | return clippingLoaded;
191 | }
192 |
193 | public void setClippingLoaded(boolean clippingLoaded) {
194 | this.clippingLoaded = clippingLoaded;
195 | }
196 |
197 | public BlendMode getLayerBlendMode() {
198 | return layerBlendMode;
199 | }
200 |
201 | public void setLayerBlendMode(BlendMode layerBlendMode) {
202 | this.layerBlendMode = layerBlendMode;
203 | }
204 |
205 | public BlendingRanges getLayerBlendingRanges() {
206 | return layerBlendingRanges;
207 | }
208 |
209 | public void setLayerBlendingRanges(BlendingRanges layerBlendingRanges) {
210 | this.layerBlendingRanges = layerBlendingRanges;
211 | }
212 |
213 | public Mask getMask() {
214 | return mask;
215 | }
216 |
217 | public void setMask(Mask mask) {
218 | this.mask = mask;
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/psd-image/src/psd/LayersContainer.java:
--------------------------------------------------------------------------------
1 | package psd;
2 |
3 | public interface LayersContainer {
4 | public Layer getLayer(int index);
5 | public int indexOfLayer(Layer layer);
6 | public int getLayersCount();
7 | }
8 |
--------------------------------------------------------------------------------
/psd-image/src/psd/Psd.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd;
20 |
21 | import java.io.*;
22 | import java.util.*;
23 |
24 | import psd.parser.*;
25 | import psd.parser.header.*;
26 | import psd.parser.layer.*;
27 |
28 | public class Psd implements LayersContainer {
29 | private Header header;
30 | private List layers = new ArrayList();
31 | private Layer baseLayer;
32 | private String name;
33 |
34 | public Psd(InputStream stream) throws IOException {
35 | name = "unknown name";
36 |
37 | PsdFileParser parser = new PsdFileParser();
38 | parser.getHeaderSectionParser().setHandler(new HeaderSectionHandler() {
39 | @Override
40 | public void headerLoaded(Header header) {
41 | Psd.this.header = header;
42 | }
43 | });
44 |
45 | final List fullLayersList = new ArrayList();
46 | parser.getLayersSectionParser().setHandler(new LayersSectionHandler() {
47 | @Override
48 | public void createLayer(LayerParser parser) {
49 | fullLayersList.add(new Layer(parser));
50 | }
51 |
52 | @Override
53 | public void createBaseLayer(LayerParser parser) {
54 | baseLayer = new Layer(parser);
55 | if (fullLayersList.isEmpty()) {
56 | fullLayersList.add(baseLayer);
57 | }
58 | }
59 | });
60 |
61 | parser.parse(stream);
62 |
63 | layers = makeLayersHierarchy(fullLayersList);
64 | }
65 |
66 | public Psd(File psdFile) throws IOException {
67 | name = psdFile.getName();
68 |
69 | PsdFileParser parser = new PsdFileParser();
70 | parser.getHeaderSectionParser().setHandler(new HeaderSectionHandler() {
71 | @Override
72 | public void headerLoaded(Header header) {
73 | Psd.this.header = header;
74 | }
75 | });
76 |
77 | final List fullLayersList = new ArrayList();
78 | parser.getLayersSectionParser().setHandler(new LayersSectionHandler() {
79 | @Override
80 | public void createLayer(LayerParser parser) {
81 | fullLayersList.add(new Layer(parser));
82 | }
83 |
84 | @Override
85 | public void createBaseLayer(LayerParser parser) {
86 | baseLayer = new Layer(parser);
87 | if (fullLayersList.isEmpty()) {
88 | fullLayersList.add(baseLayer);
89 | }
90 | }
91 | });
92 |
93 | BufferedInputStream stream = new BufferedInputStream(new FileInputStream(psdFile));
94 | parser.parse(stream);
95 | stream.close();
96 |
97 | layers = makeLayersHierarchy(fullLayersList);
98 | }
99 |
100 | private List makeLayersHierarchy(List layers) {
101 | LinkedList> layersStack = new LinkedList>();
102 | ArrayList rootLayers = new ArrayList();
103 | for (Layer layer : layers) {
104 | switch (layer.getType()) {
105 | case HIDDEN: {
106 | layersStack.addFirst(new LinkedList());
107 | break;
108 | }
109 | case FOLDER: {
110 | assert !layersStack.isEmpty();
111 | LinkedList folderLayers = layersStack.removeFirst();
112 | for (Layer l : folderLayers) {
113 | layer.addLayer(l);
114 | }
115 | }
116 | // break isn't needed
117 | case NORMAL: {
118 | if (layersStack.isEmpty()) {
119 | rootLayers.add(layer);
120 | } else {
121 | layersStack.getFirst().add(layer);
122 | }
123 | break;
124 | }
125 | default:
126 | assert false;
127 | }
128 | }
129 | return rootLayers;
130 | }
131 |
132 | public int getWidth() {
133 | return header.getWidth();
134 | }
135 |
136 | public int getHeight() {
137 | return header.getHeight();
138 | }
139 |
140 | public int getChannelsCount() {
141 | return header.getChannelsCount();
142 | }
143 |
144 | public int getDepth(){
145 | return header.getDepth();
146 | }
147 |
148 | public ColorMode getColorMode() {
149 | return header.getColorMode();
150 | }
151 |
152 | @Override
153 | public Layer getLayer(int index) {
154 | return layers.get(index);
155 | }
156 |
157 | @Override
158 | public int indexOfLayer(Layer layer) {
159 | return layers.indexOf(layer);
160 | }
161 |
162 | @Override
163 | public int getLayersCount() {
164 | return layers.size();
165 | }
166 |
167 | @Override
168 | public String toString() {
169 | return name;
170 | }
171 |
172 | public Layer getBaseLayer() {
173 | return this.baseLayer;
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/psd-parser/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/psd-parser/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | psd-parser
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/psd-parser/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | psd-library
5 | psd-parser
6 | 2.0-SNAPSHOT
7 | jar
8 |
9 | ..
10 | psd-library
11 | psd-library-parent
12 | 2.0-SNAPSHOT
13 |
14 |
15 | src
16 |
17 |
18 | maven-compiler-plugin
19 |
20 | 1.6
21 | 1.6
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/psd-parser/psd-parser.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/BlendMode.java:
--------------------------------------------------------------------------------
1 | package psd.parser;
2 |
3 | public enum BlendMode {
4 | NORMAL("norm"),
5 | DISSOLVE("diss"),
6 | DARKEN("dark"),
7 | MULTIPLY("mul "),
8 | COLOR_BURN("idiv"),
9 | LINEAR_BURN("lbrn"),
10 | LIGHTEN("lite"),
11 | SCREEN("scrn"),
12 | COLOR_DODGE("div "),
13 | LINEAR_DODGE("lddg"),
14 | OVERLAY("over"),
15 | SOFT_LIGHT("sLit"),
16 | HARD_LIGHT("hLit"),
17 | VIVID_LIGHT("vLit"),
18 | LINEAR_LIGHT("lLit"),
19 | PIN_LIGHT("pLit"),
20 | HARD_MIX("hMix"),
21 | DIFFERENCE("diff"),
22 | EXCLUSION("smud"),
23 | HUE("hue "),
24 | SATURATION("sat "),
25 | COLOR("colr"),
26 | LUMINOSITY("lum "),
27 | PASS_THROUGH("pass");
28 |
29 | private String name;
30 |
31 | private BlendMode(String name) {
32 | this.name = name;
33 | }
34 |
35 | public static BlendMode getByName(String name) {
36 | for (BlendMode mode : values()) {
37 | if (mode.name.equals(name)) {
38 | return mode;
39 | }
40 | }
41 | return null;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/ColorMode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser;
20 |
21 | public enum ColorMode {
22 | BITMAP, // 0
23 | GRAYSCALE, // 1
24 | INDEXED, // 2
25 | RGB, // 3
26 | CMYK, // 4
27 | UNKNOWN_5, // 5,
28 | UNKNOWN_6, // 6
29 | MULTICHANNEL, // 7
30 | DUOTONE, // 8
31 | LAB, // 9
32 | }
33 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/ColorModeSectionParser.java:
--------------------------------------------------------------------------------
1 | package psd.parser;
2 |
3 | import java.io.IOException;
4 |
5 | public class ColorModeSectionParser {
6 |
7 | public void parse(PsdInputStream stream) throws IOException {
8 | int colorMapLength = stream.readInt();
9 | stream.skipBytes(colorMapLength);
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/PsdFileParser.java:
--------------------------------------------------------------------------------
1 | package psd.parser;
2 |
3 | import java.io.*;
4 |
5 | import psd.parser.header.HeaderSectionParser;
6 | import psd.parser.imageresource.ImageResourceSectionParser;
7 | import psd.parser.layer.LayersSectionParser;
8 |
9 | public class PsdFileParser {
10 | private HeaderSectionParser headerParser;
11 | private ColorModeSectionParser colorModeSectionParser;
12 | private ImageResourceSectionParser imageResourceSectionParser;
13 | private LayersSectionParser layersSectionParser;
14 |
15 | public PsdFileParser() {
16 | headerParser = new HeaderSectionParser();
17 | colorModeSectionParser = new ColorModeSectionParser();
18 | imageResourceSectionParser = new ImageResourceSectionParser();
19 | layersSectionParser = new LayersSectionParser(headerParser.getHeader());
20 | }
21 |
22 | public HeaderSectionParser getHeaderSectionParser() {
23 | return headerParser;
24 | }
25 |
26 | public ImageResourceSectionParser getImageResourceSectionParser() {
27 | return imageResourceSectionParser;
28 | }
29 |
30 | public LayersSectionParser getLayersSectionParser() {
31 | return layersSectionParser;
32 | }
33 |
34 | public void parse(InputStream inputStream) throws IOException {
35 | PsdInputStream stream = new PsdInputStream(inputStream);
36 | headerParser.parse(stream);
37 | colorModeSectionParser.parse(stream);
38 | imageResourceSectionParser.parse(stream);
39 | layersSectionParser.parse(stream);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/PsdInputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser;
20 |
21 | import java.io.DataInputStream;
22 | import java.io.EOFException;
23 | import java.io.IOException;
24 | import java.io.InputStream;
25 |
26 | public class PsdInputStream extends InputStream {
27 |
28 | private int pos;
29 | private int markPos;
30 | private final DataInputStream in;
31 |
32 | public PsdInputStream(InputStream in) {
33 | this.in = new DataInputStream(in);
34 | pos = 0;
35 | markPos = 0;
36 | }
37 |
38 | @Override
39 | public int available() throws IOException {
40 | return in.available();
41 | }
42 |
43 | @Override
44 | public void close() throws IOException {
45 | in.close();
46 | }
47 |
48 | @Override
49 | public synchronized void mark(int readlimit) {
50 | in.mark(readlimit);
51 | markPos = pos;
52 | }
53 |
54 | @Override
55 | public synchronized void reset() throws IOException {
56 | in.reset();
57 | pos = markPos;
58 | }
59 |
60 | @Override
61 | public boolean markSupported() {
62 | return in.markSupported();
63 | }
64 |
65 | @Override
66 | public int read(byte[] b, int off, int len) throws IOException {
67 | int res = in.read(b, off, len);
68 | if (res != -1) {
69 | pos += res;
70 | }
71 | return res;
72 | }
73 |
74 | @Override
75 | public int read(byte[] b) throws IOException {
76 | int res = in.read(b);
77 | if (res != -1) {
78 | pos += res;
79 | }
80 | return res;
81 | }
82 |
83 | @Override
84 | public int read() throws IOException {
85 | int res = in.read();
86 | if (res != -1) {
87 | pos++;
88 | }
89 | return res;
90 | }
91 |
92 | @Override
93 | public long skip(long n) throws IOException {
94 | long skip = in.skip(n);
95 | pos += skip;
96 | return skip;
97 | }
98 |
99 | public String readString(int len) throws IOException {
100 | // read string of specified length
101 | byte[] bytes = new byte[len];
102 | read(bytes);
103 | return new String(bytes, "ISO-8859-1");
104 | }
105 |
106 | public String readPsdString() throws IOException {
107 | int size = readInt();
108 | if (size == 0) {
109 | size = 4;
110 | }
111 | return readString(size);
112 | }
113 |
114 | public int readBytes(byte[] bytes, int n) throws IOException {
115 | // read multiple bytes from input
116 | if (bytes == null)
117 | return 0;
118 | int r = 0;
119 | r = read(bytes, 0, n);
120 | if (r < n) {
121 | throw new IOException("format error. readed=" + r + " needed=" + n);
122 | }
123 | return r;
124 | }
125 |
126 | public byte readByte() throws IOException {
127 | int ch = read();
128 | if (ch < 0) {
129 | throw new EOFException();
130 | }
131 | return (byte) (ch);
132 | }
133 |
134 | public int readUnsignedByte() throws IOException {
135 | int res = in.readUnsignedByte();
136 | if (res != -1) {
137 | pos++;
138 | }
139 | return res;
140 | }
141 |
142 | public short readShort() throws IOException {
143 | int ch1 = read();
144 | int ch2 = read();
145 | if ((ch1 | ch2) < 0) {
146 | throw new EOFException();
147 | }
148 | return (short) ((ch1 << 8) + (ch2 << 0));
149 | }
150 |
151 | public int readInt() throws IOException {
152 | int ch1 = read();
153 | int ch2 = read();
154 | int ch3 = read();
155 | int ch4 = read();
156 | if ((ch1 | ch2 | ch3 | ch4) < 0) {
157 | throw new EOFException();
158 | }
159 | return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
160 | }
161 |
162 | public boolean readBoolean() throws IOException {
163 | int ch = read();
164 | if (ch < 0) {
165 | throw new EOFException();
166 | }
167 | return (ch != 0);
168 | }
169 |
170 | public final long readLong() throws IOException {
171 | int c1 = read();
172 | int c2 = read();
173 | int c3 = read();
174 | int c4 = read();
175 | int c5 = read();
176 | int c6 = read();
177 | int c7 = read();
178 | int c8 = read();
179 | return (((long) c1 << 56) + ((long) (c2 & 255) << 48)
180 | + ((long) (c3 & 255) << 40) + ((long) (c4 & 255) << 32)
181 | + ((long) (c5 & 255) << 24) + ((c6 & 255) << 16)
182 | + ((c7 & 255) << 8) + (c8 & 255));
183 | }
184 |
185 | public final double readDouble() throws IOException {
186 | return Double.longBitsToDouble(readLong());
187 | }
188 |
189 | public int skipBytes(int n) throws IOException {
190 | int total = 0;
191 | int cur;
192 | while ((total < n) && ((cur = (int) skip(n - total)) > 0)) {
193 | total += cur;
194 | }
195 | return total;
196 | }
197 |
198 | public int getPos() {
199 | return pos;
200 | }
201 |
202 | }
203 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/header/Header.java:
--------------------------------------------------------------------------------
1 | package psd.parser.header;
2 |
3 | import psd.parser.ColorMode;
4 |
5 | public class Header {
6 | int channelsCount;
7 | int width;
8 | int height;
9 | int depth;
10 | ColorMode colorMode;
11 |
12 | public int getChannelsCount() {
13 | return channelsCount;
14 | }
15 |
16 | public int getWidth() {
17 | return width;
18 | }
19 |
20 | public int getHeight() {
21 | return height;
22 | }
23 |
24 | public int getDepth() {
25 | return depth;
26 | }
27 |
28 | public ColorMode getColorMode() {
29 | return colorMode;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/header/HeaderSectionHandler.java:
--------------------------------------------------------------------------------
1 | package psd.parser.header;
2 |
3 | public interface HeaderSectionHandler {
4 | public void headerLoaded(Header header);
5 | }
6 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/header/HeaderSectionParser.java:
--------------------------------------------------------------------------------
1 | package psd.parser.header;
2 |
3 | import java.io.IOException;
4 |
5 | import psd.parser.ColorMode;
6 | import psd.parser.PsdInputStream;
7 |
8 | public class HeaderSectionParser {
9 |
10 | private static final String FILE_SIGNATURE = "8BPS";
11 | private static final int FILE_VERSION = 1;
12 |
13 | private HeaderSectionHandler handler;
14 | private Header header = new Header();
15 |
16 | public void setHandler(HeaderSectionHandler handler) {
17 | this.handler = handler;
18 | }
19 |
20 | public void parse(PsdInputStream psdStream) throws IOException {
21 | String fileSignature = psdStream.readString(4);
22 | if (!fileSignature.equals(FILE_SIGNATURE)) {
23 | throw new IOException("file signature error");
24 | }
25 |
26 | int ver = psdStream.readShort();
27 | if (ver != FILE_VERSION) {
28 | throw new IOException("file version error ");
29 | }
30 |
31 | psdStream.skipBytes(6); // reserved
32 |
33 | header.channelsCount = psdStream.readShort();
34 | header.height = psdStream.readInt();
35 | header.width = psdStream.readInt();
36 | header.depth = psdStream.readShort();
37 | int colorModeIndex = psdStream.readShort();
38 | header.colorMode = ColorMode.values()[colorModeIndex];
39 | if (handler != null) {
40 | handler.headerLoaded(header);
41 | }
42 | }
43 |
44 | public Header getHeader() {
45 | return header;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/imageresource/ImageResourceSectionHandler.java:
--------------------------------------------------------------------------------
1 | package psd.parser.imageresource;
2 |
3 | import psd.parser.object.PsdDescriptor;
4 |
5 |
6 | public interface ImageResourceSectionHandler {
7 | public void imageResourceManiSectionParsed(PsdDescriptor descriptor);
8 | }
9 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/imageresource/ImageResourceSectionParser.java:
--------------------------------------------------------------------------------
1 | package psd.parser.imageresource;
2 |
3 | import java.io.IOException;
4 |
5 | import psd.parser.PsdInputStream;
6 | import psd.parser.object.PsdDescriptor;
7 |
8 | public class ImageResourceSectionParser {
9 | private static final String PSD_TAG = "8BIM";
10 | private ImageResourceSectionHandler handler;
11 |
12 | public void setHandler(ImageResourceSectionHandler handler) {
13 | this.handler = handler;
14 | }
15 |
16 | public void parse(PsdInputStream stream) throws IOException {
17 | int length = stream.readInt();
18 | int pos = stream.getPos();
19 | while (length > 0) {
20 | String tag = stream.readString(4);
21 | if (!tag.equals(PSD_TAG) && !tag.equals("MeSa")) {
22 | throw new IOException("Format error: Invalid image resources section.: " + tag);
23 | }
24 | length -= 4;
25 | int id = stream.readShort();
26 | length -= 2;
27 |
28 | int sizeOfName = stream.readByte() & 0xFF;
29 | if ((sizeOfName & 0x01) == 0)
30 | sizeOfName++;
31 | @SuppressWarnings("unused")
32 | String name = stream.readString(sizeOfName);
33 | length -= sizeOfName + 1;
34 |
35 | int sizeOfData = stream.readInt();
36 | length -= 4;
37 | if ((sizeOfData & 0x01) == 1)
38 | sizeOfData++;
39 | length -= sizeOfData;
40 | int storePos = stream.getPos();
41 |
42 | // TODO FIXME Is id correct?
43 | if (sizeOfData > 0 && tag.equals(PSD_TAG) && id >= 4000 && id < 5000) {
44 | String key = stream.readString(4);
45 | if (key.equals("mani")) {
46 | stream.skipBytes(12 + 12); // unknown data
47 | PsdDescriptor descriptor = new PsdDescriptor(stream);
48 | if (handler != null) {
49 | handler.imageResourceManiSectionParsed(descriptor);
50 | }
51 | }
52 | }
53 | stream.skipBytes(sizeOfData - (stream.getPos() - storePos));
54 | }
55 | stream.skipBytes(length - (stream.getPos() - pos));
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/BlendingRanges.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer;
2 |
3 | public class BlendingRanges {
4 | int grayBlackSrc; // Composite gray blend source. Contains 2 black values followed by 2 white values. Present but irrelevant for Lab & Grayscale.
5 | int grayWhiteSrc;
6 | int grayBlackDst; // Composite gray blend destination range
7 | int grayWhiteDst;
8 | int numberOfBlendingChannels;
9 | int[] channelBlackSrc;// channel source range
10 | int[] channelWhiteSrc;
11 | int[] channelBlackDst;// First channel destination range
12 | int[] channelWhiteDst;
13 | }
14 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/Channel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.layer;
20 |
21 | import java.io.IOException;
22 |
23 | import psd.parser.PsdInputStream;
24 |
25 | public class Channel {
26 | public static final int ALPHA = -1;
27 | public static final int RED = 0;
28 | public static final int GREEN = 1;
29 | public static final int BLUE = 2;
30 |
31 | private int id;
32 | private int dataLength;
33 | private byte[] data;
34 |
35 | public Channel(PsdInputStream stream) throws IOException {
36 | id = stream.readShort();
37 | dataLength = stream.readInt();
38 | }
39 |
40 | public Channel(int id) {
41 | this.id = id;
42 | }
43 |
44 | public int getId() {
45 | return id;
46 | }
47 |
48 | public int getDataLength() {
49 | return dataLength;
50 | }
51 |
52 | public void setData(byte[] data) {
53 | this.data = data;
54 | }
55 |
56 | public byte[] getData() {
57 | return data;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/ImagePlaneParser.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer;
2 |
3 | import java.io.IOException;
4 |
5 | import psd.parser.PsdInputStream;
6 |
7 | public class ImagePlaneParser {
8 |
9 | private final PsdInputStream stream;
10 |
11 | public ImagePlaneParser(PsdInputStream stream) {
12 | this.stream = stream;
13 | }
14 |
15 | public byte[] readPlane(int w, int h) throws IOException {
16 | int compression = stream.readShort();
17 | switch (compression) {
18 | case 0:
19 | return readPlaneUncompressed(w, h);
20 | case 1:
21 | return parsePlaneRleCompressed(w, h, readLineLengths(h), 0);
22 | default:
23 | throw new IOException("invalid compression: " + compression);
24 | }
25 | }
26 |
27 | private short[] readLineLengths(int h) throws IOException {
28 | short[] lineLengths = new short[h];
29 | for (int i = 0; i < h; i++) {
30 | lineLengths[i] = stream.readShort();
31 | }
32 | return lineLengths;
33 | }
34 |
35 | public byte[] readPlane(int w, int h, short[] lineLengths, int planeNum) throws IOException {
36 | boolean rleEncoded = lineLengths != null;
37 |
38 | if (rleEncoded) {
39 | return parsePlaneRleCompressed(w, h, lineLengths, planeNum);
40 | } else {
41 | return readPlaneUncompressed(w, h);
42 | }
43 | }
44 |
45 | private byte[] parsePlaneRleCompressed(int w, int h, short[] lineLengths, int planeNum) throws IOException {
46 |
47 | byte[] b = new byte[w * h];
48 | byte[] s = new byte[w * 2];
49 | int pos = 0;
50 | int lineIndex = planeNum * h;
51 | for (int i = 0; i < h; i++) {
52 | int len = lineLengths[lineIndex++];
53 | stream.readBytes(s, len);
54 | decodeRLE(s, 0, len, b, pos);
55 | pos += w;
56 | }
57 | return b;
58 | }
59 |
60 | private void decodeRLE(byte[] src, int srcIndex, int slen, byte[] dst, int dstIndex) throws IOException {
61 | int sIndex = srcIndex;
62 | int dIndex = dstIndex;
63 | try {
64 | int max = sIndex + slen;
65 | while (sIndex < max) {
66 | byte b = src[sIndex++];
67 | int n = (int) b;
68 | if (n < 0) {
69 | n = 1 - n;
70 | b = src[sIndex++];
71 | for (int i = 0; i < n; i++) {
72 | dst[dIndex++] = b;
73 | }
74 | } else {
75 | n = n + 1;
76 | System.arraycopy(src, sIndex, dst, dIndex, n);
77 | dIndex += n;
78 | sIndex += n;
79 | }
80 | }
81 | } catch (Exception e) {
82 | throw new IOException("format error " + e);
83 | }
84 | }
85 |
86 | private byte[] readPlaneUncompressed(int w, int h) throws IOException {
87 | int size = w * h;
88 | byte[] b = new byte[size];
89 | stream.readBytes(b, size);
90 | return b;
91 | }
92 |
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/LayerAdditionalInformationParser.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer;
2 |
3 | import java.io.IOException;
4 |
5 | import psd.parser.PsdInputStream;
6 |
7 | public interface LayerAdditionalInformationParser {
8 | public void parse(PsdInputStream stream, String tag, int size) throws IOException;
9 | }
10 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/LayerHandler.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer;
2 |
3 | import psd.parser.BlendMode;
4 |
5 | import java.util.List;
6 |
7 | public interface LayerHandler {
8 | public void boundsLoaded(int left, int top, int right, int bottom);
9 |
10 | public void blendModeLoaded(BlendMode blendMode);
11 |
12 | public void opacityLoaded(int opacity);
13 |
14 | public void clippingLoaded(boolean clipping);
15 |
16 | public void flagsLoaded(boolean transparencyProtected, boolean visible, boolean obsolete, boolean isPixelDataIrrelevantValueUseful, boolean pixelDataIrrelevant);
17 |
18 | public void nameLoaded(String name);
19 |
20 | public void channelsLoaded(List channels);
21 |
22 | public void maskLoaded(Mask mask);
23 |
24 | public void blendingRangesLoaded(BlendingRanges ranges);
25 | }
26 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/LayerParser.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer;
2 |
3 | import java.io.IOException;
4 | import java.util.*;
5 |
6 | import psd.parser.BlendMode;
7 | import psd.parser.PsdInputStream;
8 |
9 | public class LayerParser {
10 |
11 | private List channels;
12 | private LayerHandler handler;
13 | private Map additionalInformationParsers;
14 | private LayerAdditionalInformationParser defaultAdditionalInformationParser;
15 | private int width = -1;
16 | private int height = -1;
17 |
18 | public LayerParser() {
19 | handler = null;
20 | additionalInformationParsers = new HashMap();
21 | defaultAdditionalInformationParser = null;
22 | }
23 |
24 | public void putAdditionalInformationParser(String tag, LayerAdditionalInformationParser parser) {
25 | additionalInformationParsers.put(tag, parser);
26 | }
27 |
28 | public void setDefaultAdditionalInformationParser(LayerAdditionalInformationParser parser) {
29 | defaultAdditionalInformationParser = parser;
30 | }
31 |
32 | public void setHandler(LayerHandler handler) {
33 | this.handler = handler;
34 | }
35 |
36 | public void parse(PsdInputStream stream) throws IOException {
37 | parseBounds(stream);
38 | parseChannelsInfo(stream);
39 |
40 | String tag = stream.readString(4);
41 | if (!tag.equals("8BIM")) {
42 | throw new IOException("format error");
43 | }
44 | parseBlendMode(stream);
45 | parseOpacity(stream);
46 | parseClipping(stream);
47 | parseFlags(stream);
48 | int filler = stream.readByte(); // filler. must be zero
49 | assert filler == 0;
50 | parseExtraData(stream);
51 | }
52 |
53 | public void fireBoundsChanged(int left, int top, int right, int bottom) {
54 | if (handler != null) {
55 | handler.boundsLoaded(left, top, right, bottom);
56 | }
57 | }
58 |
59 | public void fireChannelsLoaded(List channels) {
60 | if (handler != null) {
61 | handler.channelsLoaded(channels);
62 | }
63 | }
64 |
65 | private void parseBounds(PsdInputStream stream) throws IOException {
66 | int top = stream.readInt();
67 | int left = stream.readInt();
68 | int bottom = stream.readInt();
69 | int right = stream.readInt();
70 | width = right - left;
71 | height = bottom - top;
72 | if (handler != null) {
73 | handler.boundsLoaded(left, top, right, bottom);
74 | }
75 | }
76 |
77 | private void parseChannelsInfo(PsdInputStream stream) throws IOException {
78 | int channelsCount = stream.readShort();
79 | channels = new ArrayList();
80 | for (int j = 0; j < channelsCount; j++) {
81 | channels.add(new Channel(stream));
82 | }
83 | }
84 |
85 | private void parseBlendMode(PsdInputStream stream) throws IOException {
86 | String blendMode = stream.readString(4);
87 | if (handler != null) {
88 | handler.blendModeLoaded(BlendMode.getByName(blendMode));
89 | }
90 | }
91 |
92 | private void parseOpacity(PsdInputStream stream) throws IOException {
93 | int opacity = stream.readByte() & 0xff;
94 | if (handler != null) {
95 | handler.opacityLoaded(opacity);
96 | }
97 | }
98 |
99 | private void parseClipping(PsdInputStream stream) throws IOException {
100 | boolean clipping = stream.readBoolean();
101 | if (handler != null) {
102 | handler.clippingLoaded(clipping);
103 | }
104 | }
105 |
106 | private void parseFlags(PsdInputStream stream) throws IOException {
107 | int flags = stream.readByte();
108 | boolean transparencyProtected = (flags & 0x01) != 0;
109 | boolean visible = ((flags >> 1) & 0x01) == 0;
110 | boolean obsolete = ((flags >> 2) & 0x01) != 0;
111 | boolean isPixelDataIrrelevantValueUseful = ((flags >> 3) & 0x01) != 0;
112 | boolean pixelDataIrrelevant = false;
113 | if (isPixelDataIrrelevantValueUseful) { // tells if bit 4 has useful information
114 | pixelDataIrrelevant = ((flags >> 4) & 0x01) != 0;
115 | }
116 |
117 | if (handler != null) {
118 | handler.flagsLoaded(transparencyProtected, visible, obsolete,
119 | isPixelDataIrrelevantValueUseful, pixelDataIrrelevant);
120 | }
121 | }
122 |
123 | private void parseExtraData(PsdInputStream stream) throws IOException {
124 | int extraSize = stream.readInt();
125 | int extraPos = stream.getPos();
126 |
127 | parseMaskAndAdjustmentData(stream);
128 | parseBlendingRangesData(stream);
129 | parseName(stream);
130 | parseAdditionalSections(stream, extraSize + extraPos);
131 |
132 | stream.skipBytes(extraSize - (stream.getPos() - extraPos));
133 | }
134 |
135 | private void parseMaskAndAdjustmentData(PsdInputStream stream) throws IOException {
136 | int size = stream.readInt();
137 | assert size == 0 || size == 20 || size == 36;
138 | if (size > 0) {
139 | Mask mask = new Mask();
140 | mask.top = stream.readInt();
141 | mask.left = stream.readInt();
142 | mask.bottom = stream.readInt();
143 | mask.right = stream.readInt();
144 | mask.defaultColor = stream.readByte() & 0xff;
145 | assert mask.defaultColor == 0 || mask.defaultColor == 255;
146 |
147 | byte flags = stream.readByte();
148 | mask.relative = (flags & 0x01) != 0;
149 | mask.disabled = ((flags >> 1) & 0x01) != 0;
150 | mask.invert = ((flags >> 2) & 0x01) != 0;
151 | if (size == 20) {
152 | stream.skipBytes(2);
153 | } else {
154 | byte realFlags = stream.readByte();
155 | mask.relative = (realFlags & 0x01) != 0;
156 | mask.disabled = ((realFlags >> 1) & 0x01) != 0;
157 | mask.invert = ((realFlags >> 2) & 0x01) != 0;
158 |
159 | mask.defaultColor = stream.readByte() & 0xff;
160 | assert mask.defaultColor == 0 || mask.defaultColor == 255;
161 |
162 | mask.top = stream.readInt();
163 | mask.left = stream.readInt();
164 | mask.bottom = stream.readInt();
165 | mask.right = stream.readInt();
166 | }
167 | if (handler != null) {
168 | handler.maskLoaded(mask);
169 | }
170 | }
171 | }
172 |
173 | private void parseBlendingRangesData(PsdInputStream stream) throws IOException {
174 | int size = stream.readInt();
175 | int pos = stream.getPos();
176 | BlendingRanges ranges = new BlendingRanges();
177 |
178 | // Composite gray blend source. Contains 2 black values followed by 2
179 | // white values. Present but irrelevant for Lab & Grayscale.
180 | ranges.grayBlackSrc = stream.readShort() & 0xffff;
181 | ranges.grayWhiteSrc = stream.readShort() & 0xffff;
182 |
183 | // Composite gray blend destination range
184 | ranges.grayBlackDst = stream.readShort() & 0xffff;
185 | ranges.grayWhiteDst = stream.readShort() & 0xffff;
186 |
187 | ranges.numberOfBlendingChannels = (size - 8) / 8;
188 | if (ranges.numberOfBlendingChannels > 0) {
189 | ranges.channelBlackSrc = new int[ranges.numberOfBlendingChannels];
190 | ranges.channelWhiteSrc = new int[ranges.numberOfBlendingChannels];
191 | ranges.channelBlackDst = new int[ranges.numberOfBlendingChannels];
192 | ranges.channelWhiteDst = new int[ranges.numberOfBlendingChannels];
193 |
194 | for (int i = 0; i < ranges.numberOfBlendingChannels; i++) {
195 | // channel source range
196 | ranges.channelBlackSrc[i] = stream.readShort() & 0xffff;
197 | ranges.channelWhiteSrc[i] = stream.readShort() & 0xffff;
198 |
199 | // channel destination range
200 | ranges.channelBlackDst[i] = stream.readShort() & 0xffff;
201 | ranges.channelWhiteDst[i] = stream.readShort() & 0xffff;
202 | }
203 |
204 | if (handler != null) {
205 | handler.blendingRangesLoaded(ranges);
206 | }
207 | } else {
208 | // invalid blending channels
209 | stream.skipBytes(size - (stream.getPos() - pos));
210 | }
211 | }
212 |
213 | private void parseName(PsdInputStream stream) throws IOException {
214 | // Layer name: Pascal string, padded to a multiple of 4 bytes.
215 | int size = stream.readByte() & 0xFF;
216 | size = ((size + 1 + 3) & ~0x03) - 1;
217 | byte[] str = new byte[size];
218 | int strSize = str.length;
219 | int readBytesCount = stream.read(str);
220 | assert readBytesCount == size;
221 | for (int i = 0; i < str.length; i++) {
222 | if (str[i] == 0) {
223 | strSize = i;
224 | break;
225 | }
226 | }
227 | String name = new String(str, 0, strSize, "ISO-8859-1");
228 | if (handler != null) {
229 | handler.nameLoaded(name);
230 | }
231 | }
232 |
233 | private void parseAdditionalSections(PsdInputStream stream, int endPos) throws IOException {
234 | while (stream.getPos() < endPos) {
235 | String tag = stream.readString(4);
236 | if (!tag.equals("8BIM")) {
237 | throw new IOException("layer information signature error");
238 | }
239 | tag = stream.readString(4);
240 |
241 | int size = stream.readInt();
242 | size = (size + 1) & ~0x01;
243 | int prevPos = stream.getPos();
244 |
245 | LayerAdditionalInformationParser additionalParser = additionalInformationParsers.get(tag);
246 | if (additionalParser == null) {
247 | additionalParser = defaultAdditionalInformationParser;
248 | }
249 |
250 | if (additionalParser != null) {
251 | additionalParser.parse(stream, tag, size);
252 | }
253 |
254 | stream.skipBytes(prevPos + size - stream.getPos());
255 | }
256 | }
257 |
258 | public void parseImageSection(PsdInputStream stream) throws IOException {
259 | ImagePlaneParser planeParser = new ImagePlaneParser(stream);
260 | for (Channel channel : channels) {
261 | switch (channel.getId()) {
262 | case Channel.ALPHA:
263 | case Channel.RED:
264 | case Channel.GREEN:
265 | case Channel.BLUE:
266 | channel.setData(planeParser.readPlane(width, height));
267 | break;
268 | default:
269 | stream.skipBytes(channel.getDataLength());
270 | // layer mask
271 | }
272 | }
273 | if (handler != null) {
274 | handler.channelsLoaded(channels);
275 | }
276 | }
277 | }
278 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/LayerType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.layer;
20 |
21 | public enum LayerType {
22 | NORMAL,
23 | FOLDER,
24 | HIDDEN
25 | }
26 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/LayersSectionHandler.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer;
2 |
3 | public interface LayersSectionHandler {
4 | public void createLayer(LayerParser parser);
5 | public void createBaseLayer(LayerParser parser);
6 | }
7 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/LayersSectionParser.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer;
2 |
3 | import java.io.IOException;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import psd.parser.*;
8 | import psd.parser.header.Header;
9 |
10 | public class LayersSectionParser {
11 |
12 | private LayersSectionHandler handler;
13 | private final Header header;
14 |
15 | public LayersSectionParser(Header header) {
16 | this.header = header;
17 | }
18 |
19 | public void setHandler(LayersSectionHandler handler) {
20 | this.handler = handler;
21 | }
22 |
23 | public void parse(PsdInputStream stream) throws IOException {
24 | // read layer header info
25 | int length = stream.readInt();
26 | int pos = stream.getPos();
27 |
28 | if (length > 0) {
29 | int size = stream.readInt();
30 | if ((size & 0x01) != 0) {
31 | size++;
32 | }
33 | if (size > 0) {
34 | int layersCount = stream.readShort();
35 | if (layersCount < 0) {
36 | layersCount = -layersCount;
37 | }
38 |
39 | List parsers = new ArrayList(layersCount);
40 | for (int i = 0; i < layersCount; i++) {
41 | LayerParser layerParser = new LayerParser();
42 | parsers.add(layerParser);
43 | if (handler != null) {
44 | handler.createLayer(layerParser);
45 | }
46 | layerParser.parse(stream);
47 | }
48 |
49 | for (LayerParser layerParser : parsers) {
50 | layerParser.parseImageSection(stream);
51 | }
52 | }
53 |
54 | int maskSize = length - (stream.getPos() - pos);
55 | stream.skipBytes(maskSize);
56 | }
57 |
58 | parseBaseLayer(stream);
59 | }
60 |
61 | private void parseBaseLayer(PsdInputStream stream) throws IOException {
62 | LayerParser baseLayerParser = new LayerParser();
63 | if (handler != null) {
64 | handler.createBaseLayer(baseLayerParser);
65 | }
66 | baseLayerParser.fireBoundsChanged(0, 0, header.getWidth(), header.getHeight());
67 |
68 | ArrayList channels = new ArrayList(header.getChannelsCount());
69 | for (int j = 0; j < header.getChannelsCount(); j++) {
70 | channels.add(new Channel(j == 3 ? -1 : j));
71 | }
72 | //run-length-encoding
73 | boolean rle = stream.readShort() == 1;
74 | short[] lineLengths = null;
75 | if (rle) {
76 | int nLines = header.getHeight() * header.getChannelsCount();
77 | lineLengths = new short[nLines];
78 |
79 | for (int i = 0; i < nLines; i++) {
80 | lineLengths[i] = stream.readShort();
81 | }
82 | }
83 |
84 | ImagePlaneParser planeParser = new ImagePlaneParser(stream);
85 | int planeNumber = 0;
86 | for (Channel c : channels) {
87 | c.setData(planeParser.readPlane(header.getWidth(), header.getHeight(), lineLengths, planeNumber));
88 | planeNumber++;
89 | }
90 | baseLayerParser.fireChannelsLoaded(channels);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/Mask.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer;
2 |
3 | public class Mask {
4 | int top; // Rectangle enclosing layer mask: Top, left, bottom, right
5 | int left;
6 | int bottom;
7 | int right;
8 | int defaultColor; // 0 or 255
9 | boolean relative; // position relative to layer
10 | boolean disabled; // layer mask disabled
11 | boolean invert; // invert layer mask when blending
12 | //byte*mask_data;
13 |
14 | public int getLeft() {
15 | return left;
16 | }
17 |
18 | public int getTop() {
19 | return top;
20 | }
21 |
22 | public int getRight() {
23 | return right;
24 | }
25 |
26 | public int getBottom() {
27 | return bottom;
28 | }
29 |
30 | public int getWidth() {
31 | return right - left;
32 | }
33 |
34 | public int getHeight() {
35 | return bottom - top;
36 | }
37 |
38 | public int getDefaultColor() {
39 | return defaultColor;
40 | }
41 |
42 | public boolean isRelative() {
43 | return relative;
44 | }
45 |
46 | public boolean isDisabled() {
47 | return disabled;
48 | }
49 |
50 | public boolean isInvert() {
51 | return invert;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerEffectsHandler.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional;
2 |
3 | import psd.parser.layer.additional.effects.PSDEffect;
4 |
5 | import java.util.List;
6 |
7 | public interface LayerEffectsHandler {
8 |
9 | public void handleEffects(List effects);
10 | }
11 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerEffectsParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.layer.additional;
20 |
21 | import psd.parser.BlendMode;
22 | import psd.parser.PsdInputStream;
23 | import psd.parser.layer.LayerAdditionalInformationParser;
24 | import psd.parser.layer.additional.effects.*;
25 |
26 | import java.awt.*;
27 | import java.io.IOException;
28 | import java.util.ArrayList;
29 | import java.util.List;
30 |
31 | /**
32 | * Contains the effects applied in this layer.
33 | * For now it only supports some effects.
34 | */
35 | public class LayerEffectsParser implements LayerAdditionalInformationParser {
36 |
37 | /**
38 | * Tag that represents the layer effects section.
39 | */
40 | public static final String TAG = "lrFX";
41 |
42 | /**
43 | * Layer effects handler (will receive the parsed effects).
44 | */
45 | private final LayerEffectsHandler handler;
46 |
47 | public LayerEffectsParser(LayerEffectsHandler handler) {
48 | this.handler = handler;
49 | }
50 |
51 | public void parse(PsdInputStream stream, String tag, int size) throws IOException {
52 |
53 | List effects = new ArrayList();
54 |
55 | int version = stream.readShort();
56 | int numEffects = stream.readShort();
57 | int remainingSize = 0;
58 |
59 | for (int i = 0; i < numEffects ; i++) {
60 |
61 | //check signature
62 | String sig = stream.readString(4);
63 | if (!sig.equals("8BIM")) {
64 | throw new Error("layer effect information signature error");
65 | }
66 |
67 | //check effect ID
68 | String effID = stream.readString(4);
69 |
70 | if (effID.equals("cmnS")) {
71 | //common state info
72 | //skip
73 | /*
74 | 4 Size of next three items: 7
75 | 4 Version: 0
76 | 1 Visible: always true
77 | 2 Unused: always 0
78 | */
79 | stream.skipBytes(11);
80 | } else if (effID.equals("dsdw")) {
81 | //drop shadow
82 | remainingSize = stream.readInt();
83 | PSDEffect ef = parseDropShadow(stream,false);
84 | effects.add(ef);
85 | } else if (effID.equals("isdw")) {
86 | //inner drop shadow
87 | remainingSize = stream.readInt();
88 | PSDEffect ef = parseDropShadow(stream,true);
89 | effects.add(ef);
90 | } else if (effID.equals("oglw")) {
91 | //outer glow
92 | remainingSize = stream.readInt();
93 | PSDEffect ef = parseGlow(stream,false);
94 | effects.add(ef);
95 | } else if (effID.equals("iglw")) {
96 | //inner glow
97 | remainingSize = stream.readInt();
98 | PSDEffect ef = parseGlow(stream,true);
99 | effects.add(ef);
100 | } else if (effID.equals("bevl")) {
101 | //bevel
102 | remainingSize = stream.readInt();
103 | PSDEffect ef = parseBevel(stream);
104 | effects.add(ef);
105 | } else if (effID.equals("sofi")) {
106 | //solid fill
107 | remainingSize = stream.readInt();
108 | PSDEffect ef = parseSolidFill(stream);
109 | effects.add(ef);
110 | } else {
111 | remainingSize = stream.readInt();
112 | stream.skipBytes(remainingSize);
113 | if (handler != null) {
114 | handler.handleEffects(effects);
115 | }
116 | return;
117 | }
118 | }
119 |
120 | if (handler != null) {
121 | handler.handleEffects(effects);
122 | }
123 | }
124 |
125 | /**
126 | * Parses the stream to create a DropShadow effect (outer and inner).
127 | * @param stream
128 | * @param inner
129 | * @return
130 | * @throws IOException
131 | */
132 | private PSDEffect parseDropShadow(PsdInputStream stream, boolean inner) throws IOException {
133 |
134 | int version = stream.readInt(); //0 (Photoshop 5.0) or 2 (Photoshop 5.5)
135 | int blur = stream.readShort(); //Blur value in pixels (8)
136 | int intensity = stream.readInt(); //Intensity as a percent (10?)
137 | int angle = stream.readInt(); //Angle in degrees (120)
138 | int distance = stream.readInt(); //Distance in pixels (25)
139 |
140 | //2 bytes for space
141 | stream.skipBytes(4);
142 |
143 | int colorR = stream.readUnsignedByte();
144 | stream.skipBytes(1);
145 | int colorG = stream.readUnsignedByte();
146 | stream.skipBytes(1);
147 | int colorB = stream.readUnsignedByte();
148 |
149 | Color colorValue = new Color(colorR, colorG, colorB);
150 |
151 | stream.skipBytes(3);
152 |
153 | String blendSig = stream.readString(4);
154 | if (!blendSig.equals("8BIM")){
155 | throw new Error("Invalid Blend mode signature for Effect: " + blendSig );
156 | }
157 |
158 | /*
159 | 4 bytes.
160 | Blend mode key.
161 | */
162 | String blendModeKey = stream.readString(4);
163 | boolean effectIsEnabled = stream.readBoolean(); //1 Effect enabled
164 | boolean useInAllEFX = stream.readBoolean(); //1 Use this angle in all of the layer effects
165 | float alpha = new Float(stream.readUnsignedByte()/255.0); //1 Opacity as a percent
166 |
167 | //get native color
168 | stream.skipBytes(4); //2 bytes for space
169 | colorR = stream.readUnsignedByte();
170 | stream.skipBytes(1);
171 | colorG = stream.readUnsignedByte();
172 | stream.skipBytes(1);
173 | colorB = stream.readUnsignedByte();
174 | stream.skipBytes(1);
175 |
176 | Color nativeColor = new Color(colorR, colorG, colorB);
177 |
178 | /*create a dropshadow effect*/
179 | DropShadowEffect effect = new DropShadowEffect(inner);
180 | effect.setAlpha(alpha);
181 | effect.setAngle(180-angle);
182 | effect.setBlur(blur);
183 | effect.setColor(colorValue);
184 | effect.setDistance(distance);
185 | effect.setIntensity(intensity);
186 | effect.setQuality(4);
187 | effect.setStrength(1);
188 | effect.setUseInAllEFX(useInAllEFX);
189 | effect.setEnabled(effectIsEnabled);
190 | effect.setBlendMode(BlendMode.getByName(blendModeKey));
191 |
192 | return effect;
193 | }
194 |
195 | /**
196 | * Parses the stream to create a Glow effect (outer and inner).
197 | * @param stream
198 | * @param inner
199 | * @return
200 | * @throws IOException
201 | */
202 | private PSDEffect parseGlow(PsdInputStream stream, boolean inner) throws IOException {
203 |
204 | int version = stream.readInt(); //0 (Photoshop 5.0) or 2 (Photoshop 5.5)
205 | int blur = stream.readShort(); //Blur value in pixels (8)
206 | int intensity = stream.readInt(); //Intensity as a percent (10?) (not working)
207 |
208 | //2 bytes for space
209 | stream.skipBytes(4);
210 | int colorR = stream.readUnsignedByte();
211 | stream.skipBytes(1);
212 | int colorG = stream.readUnsignedByte();
213 | stream.skipBytes(1);
214 | int colorB = stream.readUnsignedByte();
215 |
216 | Color colorValue = new Color(colorR, colorG, colorB);
217 |
218 | stream.skipBytes(3);
219 |
220 | String blendSig = stream.readString(4);
221 | if (!blendSig.equals("8BIM")){
222 | throw new Error("Invalid Blend mode signature for Effect: " + blendSig );
223 | }
224 |
225 | /*
226 | 4 bytes.
227 | Blend mode key.
228 | */
229 | String blendModeKey = stream.readString(4);
230 | boolean effectIsEnabled = stream.readBoolean(); //1 Effect enabled
231 | float alpha = new Float(stream.readUnsignedByte()/255.0); //1 Opacity as a percent
232 |
233 | if (version == 2){
234 |
235 | boolean invert = false;
236 | if (inner) invert = stream.readBoolean();
237 |
238 | //get native color
239 | stream.skipBytes(3);
240 | colorR = stream.readUnsignedByte();
241 | stream.skipBytes(1);
242 | colorG = stream.readUnsignedByte();
243 | stream.skipBytes(1);
244 | colorB = stream.readUnsignedByte();
245 | stream.skipBytes(2);
246 |
247 | Color nativeColor = new Color(colorR, colorG, colorB);
248 | }
249 |
250 | /*Create the glow effect*/
251 | GlowEffect effect = new GlowEffect(inner);
252 | effect.setAlpha(alpha);
253 | effect.setBlendMode(BlendMode.getByName(blendModeKey));
254 | effect.setBlur(blur);
255 | effect.setColor(colorValue);
256 | effect.setEnabled(effectIsEnabled);
257 | effect.setQuality(4);
258 | effect.setStrength(1);
259 | effect.setVersion(version);
260 | effect.setIntensity(intensity);
261 |
262 | return effect;
263 | }
264 |
265 | /**
266 | * Parses the stream to create a Bevel effect
267 | * @param stream
268 | * @return
269 | * @throws IOException
270 | */
271 | private PSDEffect parseBevel(PsdInputStream stream) throws IOException {
272 |
273 | int version = stream.readInt(); //0 (Photoshop 5.0) or 2 (Photoshop 5.5)
274 | int angle = stream.readShort(); //Angle in degrees
275 | int strength = stream.readInt(); //Strength. Depth in pixels
276 | int blur = stream.readInt(); //Blur value in pixels
277 |
278 | stream.skipBytes(2);
279 |
280 | // Highlight blend mode: 4 bytes for signature and 4 bytes for the key
281 | String blendSig = stream.readString(4);
282 | if (!blendSig.equals("8BIM")){
283 | throw new Error("Invalid Blend mode signature for Effect: " + blendSig );
284 | }
285 |
286 | /*
287 | 4 bytes.
288 | Blend mode key.
289 | */
290 | String blendModeKey = stream.readString(4);
291 |
292 | //Shadow blend mode: 4 bytes for signature and 4 bytes for the key
293 | String blendSigShadow = stream.readString(4);
294 | if (!blendSigShadow.equals("8BIM")){
295 | throw new Error("Invalid Blend mode signature for Effect: " + blendSigShadow );
296 | }
297 |
298 | /*
299 | 4 bytes.
300 | Blend mode Shadow key.
301 | */
302 | String blendModeShadowKey = stream.readString(4);
303 |
304 | //Highlight color: 2 bytes for space followed by 4 * 2 byte color component
305 | stream.skipBytes(3);
306 |
307 | int colorR = stream.readUnsignedByte();
308 | stream.skipBytes(1);
309 | int colorG = stream.readUnsignedByte();
310 | stream.skipBytes(1);
311 | int colorB = stream.readUnsignedByte();
312 |
313 | stream.skipBytes(2);
314 |
315 | Color highlightColor = new Color(colorR, colorG, colorB);
316 |
317 | //Shadow color: 2 bytes for space followed by 4 * 2 byte color component
318 | stream.skipBytes(3);
319 |
320 | colorR = stream.readUnsignedByte();
321 | stream.skipBytes(1);
322 | colorG = stream.readUnsignedByte();
323 | stream.skipBytes(1);
324 | colorB = stream.readUnsignedByte();
325 |
326 | Color shadowColor = new Color(colorR, colorG, colorB);
327 |
328 | stream.skipBytes(2);
329 |
330 | //Bevel style
331 | int bevelStyle = stream.readUnsignedByte();
332 |
333 | //Hightlight opacity as a percent
334 | float highlightOpacity = new Float(stream.readUnsignedByte()/255.0);
335 |
336 | //Shadow opacity as a percent
337 | float shadowOpacity = new Float(stream.readUnsignedByte()/255.0);
338 |
339 | //Effect enabled
340 | boolean isEffectEnabled = stream.readBoolean();
341 |
342 | //Use this angle in all of the layer effects
343 | boolean useInAllLayerEffects = stream.readBoolean();
344 |
345 | //Bevel Up or down
346 | int direction = stream.readUnsignedByte();
347 |
348 | Color realHighlightColor = null, realShadowColor = null;
349 | if (version == 2) {
350 | //Real Highlight color: 2 bytes for space followed by 4 * 2 byte color component
351 | stream.skipBytes(3);
352 |
353 | int realColorR = stream.readUnsignedByte();
354 | stream.skipBytes(1);
355 | int realColorG = stream.readUnsignedByte();
356 | stream.skipBytes(1);
357 | int realColorB = stream.readUnsignedByte();
358 |
359 | realHighlightColor = new Color(realColorR, realColorG, realColorB);
360 |
361 | stream.skipBytes(2);
362 |
363 | //Real Shadow color: 2 bytes for space followed by 4 * 2 byte color component
364 | stream.skipBytes(3);
365 |
366 | int realShadowColorR = stream.readUnsignedByte();
367 | stream.skipBytes(1);
368 | int realShadowColorG = stream.readUnsignedByte();
369 | stream.skipBytes(1);
370 | int realShadowColorB = stream.readUnsignedByte();
371 |
372 | realShadowColor = new Color(realShadowColorR, realShadowColorG, realShadowColorB);
373 |
374 | stream.skipBytes(2);
375 | }
376 |
377 | BevelEffect effect = new BevelEffect();
378 | effect.setAngle(angle);
379 | effect.setVersion(version);
380 | effect.setUseInAllLayerEffects(useInAllLayerEffects);
381 | effect.setStrength(strength);
382 | effect.setBevelStyle(bevelStyle);
383 | effect.setBlendMode(BlendMode.getByName(blendModeKey));
384 | effect.setBlendShadowMode(BlendMode.getByName(blendModeShadowKey));
385 | effect.setBlur(blur);
386 | effect.setDirection(direction);
387 | effect.setEnabled(isEffectEnabled);
388 | effect.setHighlightColor(highlightColor);
389 | effect.setHighlightOpacity(highlightOpacity);
390 | effect.setShadowColor(shadowColor);
391 | effect.setShadowOpacity(shadowOpacity);
392 |
393 | if (realHighlightColor != null) {
394 | effect.setRealHighlightColor(realHighlightColor);
395 | effect.setRealShadowColor(realShadowColor);
396 | }
397 |
398 | return effect;
399 | }
400 |
401 | /**
402 | * Parses the stream to create a SolidFill effect.
403 | * @param stream
404 | * @return
405 | * @throws IOException
406 | */
407 | private PSDEffect parseSolidFill(PsdInputStream stream) throws IOException {
408 |
409 | int version = stream.readInt(); //Version: 2
410 |
411 | String blendSig = stream.readString(4);
412 | if (!blendSig.equals("8BIM")){
413 | throw new Error("Invalid Blend mode signature for Effect: " + blendSig );
414 | }
415 |
416 | String blendModeKey = stream.readString(4);
417 |
418 | //Highlight color: 2 bytes for space followed by 4 * 2 byte color component
419 | stream.skipBytes(3);
420 |
421 | int colorR = stream.readUnsignedByte();
422 | stream.skipBytes(1);
423 | int colorG = stream.readUnsignedByte();
424 | stream.skipBytes(1);
425 | int colorB = stream.readUnsignedByte();
426 |
427 | Color highlightColor = new Color(colorR, colorG, colorB);
428 |
429 | stream.skipBytes(2);
430 |
431 | float opacity = new Float(stream.readUnsignedByte()/255.0);
432 |
433 | boolean effectEnabled = stream.readBoolean();
434 |
435 | //Highlight color: 2 bytes for space followed by 4 * 2 byte color component
436 | stream.skipBytes(3);
437 |
438 | colorR = stream.readUnsignedByte();
439 | stream.skipBytes(1);
440 | colorG = stream.readUnsignedByte();
441 | stream.skipBytes(1);
442 | colorB = stream.readUnsignedByte();
443 |
444 | Color nativeColor = new Color(colorR, colorG, colorB);
445 |
446 | stream.skipBytes(2);
447 |
448 | SolidFillEffect effect = new SolidFillEffect();
449 | effect.setVersion(version);
450 | effect.setBlendMode(BlendMode.getByName(blendModeKey));
451 | effect.setEnabled(effectEnabled);
452 | effect.setHighlightColor(highlightColor);
453 | effect.setOpacity(opacity);
454 | effect.setNativeColor(nativeColor);
455 |
456 | return effect;
457 | }
458 | }
459 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerIdHandler.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional;
2 |
3 | public interface LayerIdHandler {
4 | public void layerIdParsed(int id);
5 | }
6 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerIdParser.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional;
2 |
3 | import java.io.IOException;
4 |
5 | import psd.parser.PsdInputStream;
6 | import psd.parser.layer.LayerAdditionalInformationParser;
7 |
8 | public class LayerIdParser implements LayerAdditionalInformationParser {
9 |
10 | public static final String TAG = "lyid";
11 | private final LayerIdHandler handler;
12 |
13 | public LayerIdParser(LayerIdHandler handler) {
14 | this.handler = handler;
15 | }
16 |
17 | @Override
18 | public void parse(PsdInputStream stream, String tag, int size) throws IOException {
19 | int layerId = stream.readInt();
20 | if (handler != null) {
21 | handler.layerIdParsed(layerId);
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerMetaDataHandler.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional;
2 |
3 | import psd.parser.object.PsdDescriptor;
4 |
5 | public interface LayerMetaDataHandler {
6 |
7 | public void metaDataMlstSectionParsed(PsdDescriptor descriptor);
8 | }
9 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerMetaDataParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.layer.additional;
20 |
21 | import java.io.IOException;
22 |
23 | import psd.parser.PsdInputStream;
24 | import psd.parser.layer.LayerAdditionalInformationParser;
25 | import psd.parser.object.*;
26 |
27 | public class LayerMetaDataParser implements LayerAdditionalInformationParser {
28 |
29 | public static final String TAG = "shmd";
30 | private final LayerMetaDataHandler handler;
31 |
32 | public LayerMetaDataParser(LayerMetaDataHandler handler) {
33 | this.handler = handler;
34 | }
35 |
36 | @Override
37 | public void parse(PsdInputStream stream, String tag, int size) throws IOException {
38 | int countOfMetaData = stream.readInt();
39 | for (int i = 0; i < countOfMetaData; i++) {
40 | String dataTag = stream.readString(4);
41 | if (!dataTag.equals("8BIM")) {
42 | throw new IOException("layer meta data section signature error");
43 | }
44 | String key = stream.readString(4);
45 |
46 | @SuppressWarnings("unused")
47 | int copyOnSheetDuplication = stream.readByte();
48 |
49 | stream.skipBytes(3); // padding
50 | int len = stream.readInt();
51 | int pos = stream.getPos();
52 | if (key.equals("mlst")) {
53 | parseMlstSection(stream);
54 | } else {
55 | }
56 |
57 | stream.skipBytes(len - (stream.getPos() - pos));
58 | }
59 | }
60 |
61 | private void parseMlstSection(PsdInputStream stream) throws IOException {
62 | stream.skipBytes(4); // ???
63 | PsdDescriptor descriptor = new PsdDescriptor(stream);
64 | if (handler != null) {
65 | handler.metaDataMlstSectionParsed(descriptor);
66 | }
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerSectionDividerHandler.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional;
2 |
3 | import psd.parser.layer.LayerType;
4 |
5 | public interface LayerSectionDividerHandler {
6 | public void sectionDividerParsed(LayerType type);
7 | }
8 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerSectionDividerParser.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional;
2 |
3 | import java.io.IOException;
4 |
5 | import psd.parser.PsdInputStream;
6 | import psd.parser.layer.LayerAdditionalInformationParser;
7 | import psd.parser.layer.LayerType;
8 |
9 | public class LayerSectionDividerParser implements LayerAdditionalInformationParser {
10 |
11 | public static final String TAG = "lsct";
12 |
13 | private final LayerSectionDividerHandler handler;
14 |
15 | public LayerSectionDividerParser(LayerSectionDividerHandler handler) {
16 | this.handler = handler;
17 | }
18 |
19 | @Override
20 | public void parse(PsdInputStream stream, String tag, int size) throws IOException {
21 | int dividerType = stream.readInt();
22 | LayerType type = LayerType.NORMAL;
23 | switch (dividerType) {
24 | case 1:
25 | case 2:
26 | type = LayerType.FOLDER;
27 | break;
28 | case 3:
29 | type = LayerType.HIDDEN;
30 | break;
31 | }
32 | handler.sectionDividerParsed(type);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerTypeToolHandler.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional;
2 |
3 | import psd.parser.object.PsdDescriptor;
4 |
5 | public interface LayerTypeToolHandler {
6 |
7 | public void typeToolTransformParsed(Matrix transform);
8 | public void typeToolDescriptorParsed(int version, PsdDescriptor descriptor);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerTypeToolParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.layer.additional;
20 |
21 | import psd.parser.PsdInputStream;
22 | import psd.parser.layer.LayerAdditionalInformationParser;
23 | import psd.parser.object.*;
24 | import java.io.*;
25 |
26 | /**
27 | * contains meta data of a text layer like font type, font size, raw text ...)
28 | */
29 | public class LayerTypeToolParser implements LayerAdditionalInformationParser {
30 |
31 | public static final String TAG = "TySh";
32 |
33 | private final LayerTypeToolHandler handler;
34 |
35 | public LayerTypeToolParser(LayerTypeToolHandler handler) {
36 | this.handler = handler;
37 | }
38 |
39 | @Override
40 | public void parse(PsdInputStream stream, String tag, int size) throws IOException {
41 | byte[] data = new byte[size];
42 | stream.readBytes(data, size);
43 |
44 | PsdInputStream dataStream = new PsdInputStream(new ByteArrayInputStream(data));
45 | int version = dataStream.readShort();
46 | assert version == 1;
47 | Matrix transform = new Matrix(dataStream);
48 | if (handler != null) {
49 | handler.typeToolTransformParsed(transform);
50 | }
51 |
52 | int descriptorVersion = dataStream.readShort();
53 | if (descriptorVersion == 50) {
54 | int xTextDescriptorVersion = dataStream.readInt();
55 | PsdDescriptor descriptor = new PsdDescriptor(new PsdInputStream(dataStream));
56 | if (handler != null) {
57 | handler.typeToolDescriptorParsed(xTextDescriptorVersion, descriptor);
58 | }
59 | } else {
60 | // unknown data
61 | assert false;
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerUnicodeNameHandler.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional;
2 |
3 | public interface LayerUnicodeNameHandler {
4 | public void layerUnicodeNameParsed(String unicodeName);
5 | }
6 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/LayerUnicodeNameParser.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional;
2 |
3 | import java.io.IOException;
4 |
5 | import psd.parser.PsdInputStream;
6 | import psd.parser.layer.LayerAdditionalInformationParser;
7 |
8 | public class LayerUnicodeNameParser implements LayerAdditionalInformationParser {
9 |
10 | public static final String TAG = "luni";
11 | private final LayerUnicodeNameHandler handler;
12 |
13 | public LayerUnicodeNameParser(LayerUnicodeNameHandler handler) {
14 | this.handler = handler;
15 | }
16 |
17 | @Override
18 | public void parse(PsdInputStream stream, String tag, int size) throws IOException {
19 | int len = stream.readInt();
20 | StringBuilder name = new StringBuilder(len);
21 | for (int i = 0; i < len; i++) {
22 | name.append((char) stream.readShort());
23 | }
24 | if (handler != null) {
25 | handler.layerUnicodeNameParsed(name.toString());
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/Matrix.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional;
2 |
3 | import java.io.*;
4 |
5 | public class Matrix {
6 |
7 | private double m11, m12, m13;
8 | private double m21, m22, m23;
9 |
10 | public Matrix() {
11 | m11 = 1;
12 | m12 = 0;
13 | m13 = 0;
14 | m21 = 0;
15 | m22 = 1;
16 | m23 = 0;
17 | }
18 |
19 | public Matrix(InputStream stream) throws IOException {
20 | DataInputStream dataStream;
21 | if (stream instanceof DataInputStream) {
22 | dataStream = (DataInputStream) stream;
23 | } else {
24 | dataStream = new DataInputStream(stream);
25 | }
26 | m11 = dataStream.readDouble();
27 | m12 = dataStream.readDouble();
28 | m13 = dataStream.readDouble();
29 | m21 = dataStream.readDouble();
30 | m22 = dataStream.readDouble();
31 | m23 = dataStream.readDouble();
32 | }
33 |
34 | public double m11() {
35 | return m11;
36 | }
37 |
38 | public double m12() {
39 | return m12;
40 | }
41 |
42 | public double m13() {
43 | return m13;
44 | }
45 |
46 | public double m21() {
47 | return m21;
48 | }
49 |
50 | public double m22() {
51 | return m22;
52 | }
53 |
54 | public double m23() {
55 | return m23;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/effects/BevelEffect.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional.effects;
2 |
3 | import psd.parser.BlendMode;
4 |
5 | import java.awt.*;
6 |
7 | public class BevelEffect extends PSDEffect {
8 |
9 | private int angle;
10 | private int strength;
11 | private int blur;
12 | private BlendMode blendMode;
13 | private BlendMode blendShadowMode;
14 | private Color highlightColor;
15 | private Color shadowColor;
16 | private int bevelStyle;
17 | private float highlightOpacity;
18 | private float shadowOpacity;
19 | private boolean useInAllLayerEffects;
20 | private int direction;
21 | private Color realHighlightColor;
22 | private Color realShadowColor;
23 |
24 | public BevelEffect(){
25 | super("bevl");
26 | }
27 |
28 | public int getAngle() {
29 | return angle;
30 | }
31 |
32 | public void setAngle(int angle) {
33 | this.angle = angle;
34 | }
35 |
36 | public int getStrength() {
37 | return strength;
38 | }
39 |
40 | public void setStrength(int strength) {
41 | this.strength = strength;
42 | }
43 |
44 | public int getBlur() {
45 | return blur;
46 | }
47 |
48 | public void setBlur(int blur) {
49 | this.blur = blur;
50 | }
51 |
52 | public BlendMode getBlendMode() {
53 | return blendMode;
54 | }
55 |
56 | public void setBlendMode(BlendMode blendMode) {
57 | this.blendMode = blendMode;
58 | }
59 |
60 | public BlendMode getBlendShadowMode() {
61 | return blendShadowMode;
62 | }
63 |
64 | public void setBlendShadowMode(BlendMode blendShadowMode) {
65 | this.blendShadowMode = blendShadowMode;
66 | }
67 |
68 | public Color getHighlightColor() {
69 | return highlightColor;
70 | }
71 |
72 | public void setHighlightColor(Color highlightColor) {
73 | this.highlightColor = highlightColor;
74 | }
75 |
76 | public Color getShadowColor() {
77 | return shadowColor;
78 | }
79 |
80 | public void setShadowColor(Color shadowColor) {
81 | this.shadowColor = shadowColor;
82 | }
83 |
84 | public int getBevelStyle() {
85 | return bevelStyle;
86 | }
87 |
88 | public void setBevelStyle(int bevelStyle) {
89 | this.bevelStyle = bevelStyle;
90 | }
91 |
92 | public float getHighlightOpacity() {
93 | return highlightOpacity;
94 | }
95 |
96 | public void setHighlightOpacity(float highlightOpacity) {
97 | this.highlightOpacity = highlightOpacity;
98 | }
99 |
100 | public float getShadowOpacity() {
101 | return shadowOpacity;
102 | }
103 |
104 | public void setShadowOpacity(float shadowOpacity) {
105 | this.shadowOpacity = shadowOpacity;
106 | }
107 |
108 | public boolean isUseInAllLayerEffects() {
109 | return useInAllLayerEffects;
110 | }
111 |
112 | public void setUseInAllLayerEffects(boolean useInAllLayerEffects) {
113 | this.useInAllLayerEffects = useInAllLayerEffects;
114 | }
115 |
116 | public int getDirection() {
117 | return direction;
118 | }
119 |
120 | public void setDirection(int direction) {
121 | this.direction = direction;
122 | }
123 |
124 | public Color getRealHighlightColor() {
125 | return realHighlightColor;
126 | }
127 |
128 | public void setRealHighlightColor(Color realHighlightColor) {
129 | this.realHighlightColor = realHighlightColor;
130 | }
131 |
132 | public Color getRealShadowColor() {
133 | return realShadowColor;
134 | }
135 |
136 | public void setRealShadowColor(Color realShadowColor) {
137 | this.realShadowColor = realShadowColor;
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/effects/DropShadowEffect.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional.effects;
2 |
3 | import psd.parser.BlendMode;
4 |
5 | import java.awt.*;
6 |
7 | public class DropShadowEffect extends PSDEffect {
8 |
9 | public static String REGULAR = "dsdw";
10 | public static String INNER = "isdw";
11 |
12 | private boolean inner = false;
13 |
14 | private float alpha;
15 | private int angle;
16 | private int blur;
17 | private Color color;
18 | private int quality;
19 | private int distance;
20 | private int strength;
21 | private int intensity;
22 | private boolean useInAllEFX;
23 | private BlendMode blendMode;
24 |
25 | public DropShadowEffect() {}
26 |
27 | public DropShadowEffect(boolean inner){
28 | super();
29 | this.setInner(inner);
30 | if (inner){
31 | setName(INNER);
32 | } else {
33 | setName(REGULAR);
34 | }
35 | }
36 |
37 | public boolean isInner(){
38 | return inner;
39 | }
40 |
41 | public void setInner(boolean inner) {
42 | this.inner = inner;
43 | if (inner){
44 | setName(INNER);
45 | } else {
46 | setName(REGULAR);
47 | }
48 | }
49 |
50 | public float getAlpha() {
51 | return alpha;
52 | }
53 |
54 | public void setAlpha(float alpha) {
55 | this.alpha = alpha;
56 | }
57 |
58 | public int getAngle() {
59 | return angle;
60 | }
61 |
62 | public void setAngle(int angle) {
63 | this.angle = angle;
64 | }
65 |
66 | public int getBlur() {
67 | return blur;
68 | }
69 |
70 | public void setBlur(int blur) {
71 | this.blur = blur;
72 | }
73 |
74 | public Color getColor() {
75 | return color;
76 | }
77 |
78 | public void setColor(Color color) {
79 | this.color = color;
80 | }
81 |
82 | public int getQuality() {
83 | return quality;
84 | }
85 |
86 | public void setQuality(int quality) {
87 | this.quality = quality;
88 | }
89 |
90 | public int getDistance() {
91 | return distance;
92 | }
93 |
94 | public BlendMode getBlendMode(){
95 | return this.blendMode;
96 | }
97 |
98 | public void setDistance(int distance) {
99 | this.distance = distance;
100 | }
101 |
102 | public int getStrength() {
103 | return strength;
104 | }
105 |
106 | public int getVersion() {
107 | return version;
108 | }
109 |
110 | public void setStrength(int strength) {
111 | this.strength = strength;
112 | }
113 |
114 | public int getIntensity() {
115 | return intensity;
116 | }
117 |
118 | public void setIntensity(int intensity) {
119 | this.intensity = intensity;
120 | }
121 |
122 | public boolean isUseInAllEFX() {
123 | return useInAllEFX;
124 | }
125 |
126 | public void setUseInAllEFX(boolean useInAllEFX) {
127 | this.useInAllEFX = useInAllEFX;
128 | }
129 |
130 | public void setBlendMode(BlendMode mode){
131 | this.blendMode = mode;
132 | }
133 |
134 | public void setVersion(int version) {
135 | this.version = version;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/effects/GlowEffect.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional.effects;
2 |
3 | import psd.parser.BlendMode;
4 |
5 | import java.awt.*;
6 |
7 | public class GlowEffect extends PSDEffect {
8 |
9 | public static String REGULAR = "oglw";
10 | public static String INNER = "iglw";
11 |
12 | private boolean inner = false;
13 | private int version;
14 |
15 | private float alpha;
16 | private int blur;
17 | private Color color;
18 | private int quality;
19 | private int strength;
20 | private int intensity;
21 | private BlendMode blendMode;
22 |
23 | public GlowEffect() {}
24 |
25 | public GlowEffect(boolean inner){
26 | super();
27 | this.setInner(inner);
28 | if (inner){
29 | setName(INNER);
30 | } else {
31 | setName(REGULAR);
32 | }
33 | }
34 |
35 | public boolean isInner(){
36 | return inner;
37 | }
38 |
39 | public void setInner(boolean inner) {
40 | this.inner = inner;
41 | if (inner){
42 | setName(INNER);
43 | } else {
44 | setName(REGULAR);
45 | }
46 | }
47 |
48 | public float getAlpha() {
49 | return alpha;
50 | }
51 |
52 | public void setAlpha(float alpha) {
53 | this.alpha = alpha;
54 | }
55 |
56 | public int getBlur() {
57 | return blur;
58 | }
59 |
60 | public void setBlur(int blur) {
61 | this.blur = blur;
62 | }
63 |
64 | public Color getColor() {
65 | return color;
66 | }
67 |
68 | public void setColor(Color color) {
69 | this.color = color;
70 | }
71 |
72 | public int getQuality() {
73 | return quality;
74 | }
75 |
76 | public void setQuality(int quality) {
77 | this.quality = quality;
78 | }
79 |
80 | public BlendMode getBlendMode(){
81 | return this.blendMode;
82 | }
83 |
84 | public int getStrength() {
85 | return strength;
86 | }
87 |
88 | public int getVersion() {
89 | return version;
90 | }
91 |
92 | public void setStrength(int strength) {
93 | this.strength = strength;
94 | }
95 |
96 | public void setBlendMode(BlendMode mode){
97 | this.blendMode = mode;
98 | }
99 |
100 | public void setVersion(int version) {
101 | this.version = version;
102 | }
103 |
104 | public int getIntensity() {
105 | return intensity;
106 | }
107 |
108 | public void setIntensity(int intensity) {
109 | this.intensity = intensity;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/effects/PSDEffect.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional.effects;
2 |
3 | /**
4 | * Generic Effect class.
5 | * Holds the common properties of all the PSD effects.
6 | */
7 | public abstract class PSDEffect {
8 |
9 | protected String name;
10 | protected boolean isEnabled;
11 | protected int version;
12 |
13 | public PSDEffect(String name){
14 | this.name = name;
15 | }
16 |
17 | public PSDEffect() {}
18 |
19 | public String getName() {
20 | return name;
21 | }
22 |
23 | public boolean isEnabled() {
24 | return isEnabled;
25 | }
26 |
27 | public void setName(String name) {
28 | this.name = name;
29 | }
30 |
31 | public void setEnabled(boolean enabled){
32 | this.isEnabled = enabled;
33 | }
34 |
35 | public void setVersion(int version) {
36 | this.version = version;
37 | }
38 |
39 | public int getVersion() {
40 | return version;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/layer/additional/effects/SolidFillEffect.java:
--------------------------------------------------------------------------------
1 | package psd.parser.layer.additional.effects;
2 |
3 | import psd.parser.BlendMode;
4 |
5 | import java.awt.*;
6 |
7 | public class SolidFillEffect extends PSDEffect {
8 |
9 | private BlendMode blendMode;
10 | private Color highlightColor;
11 | private float opacity;
12 | private Color nativeColor;
13 |
14 | public SolidFillEffect(){
15 | super("sofi");
16 | }
17 |
18 | public BlendMode getBlendMode() {
19 | return blendMode;
20 | }
21 |
22 | public void setBlendMode(BlendMode blendMode) {
23 | this.blendMode = blendMode;
24 | }
25 |
26 | public Color getHighlightColor() {
27 | return highlightColor;
28 | }
29 |
30 | public void setHighlightColor(Color highlightColor) {
31 | this.highlightColor = highlightColor;
32 | }
33 |
34 | public float getOpacity() {
35 | return opacity;
36 | }
37 |
38 | public void setOpacity(float opacity) {
39 | this.opacity = opacity;
40 | }
41 |
42 | public Color getNativeColor() {
43 | return nativeColor;
44 | }
45 |
46 | public void setNativeColor(Color nativeColor) {
47 | this.nativeColor = nativeColor;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/object/PsdBoolean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.object;
20 |
21 | import java.io.IOException;
22 |
23 | import psd.parser.PsdInputStream;
24 |
25 | /**
26 | * The Class PsdBoolean.
27 | */
28 | public class PsdBoolean extends PsdObject {
29 |
30 | /** The value. */
31 | private final boolean value;
32 |
33 | /**
34 | * Instantiates a new psd boolean.
35 | *
36 | * @param stream the stream
37 | * @throws IOException Signals that an I/O exception has occurred.
38 | */
39 | public PsdBoolean(PsdInputStream stream) throws IOException {
40 | value = stream.readBoolean();
41 | logger.finest("PsdBoolean.value: " + value );
42 | }
43 |
44 | /**
45 | * Gets the value.
46 | *
47 | * @return the value
48 | */
49 | public boolean getValue() {
50 | return value;
51 | }
52 |
53 | /* (non-Javadoc)
54 | * @see java.lang.Object#toString()
55 | */
56 | @Override
57 | public String toString() {
58 | return "bool:" + value;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/object/PsdDescriptor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.object;
20 |
21 | import java.io.IOException;
22 | import java.util.*;
23 |
24 | import psd.parser.PsdInputStream;
25 |
26 | /**
27 | * The Class PsdDescriptor holds meta data of a layer.
28 | *
29 | * @author Dmitry Belsky
30 | */
31 | public class PsdDescriptor extends PsdObject {
32 |
33 | /** The class id or layer type. */
34 | private final String classId;
35 |
36 | /** a map containing all values of the descriptor */
37 | private final HashMap objects = new HashMap();
38 |
39 | /**
40 | * Instantiates a new psd descriptor.
41 | *
42 | * @param stream the stream
43 | * @throws IOException Signals that an I/O exception has occurred.
44 | */
45 | public PsdDescriptor(PsdInputStream stream) throws IOException {
46 | // Unicode string: name from classID
47 | int nameLen = stream.readInt() * 2;
48 | stream.skipBytes(nameLen);
49 |
50 | classId = stream.readPsdString();
51 | int itemsCount = stream.readInt();
52 | logger.finest("PsdDescriptor.itemsCount: " + itemsCount);
53 | for (int i = 0; i < itemsCount; i++) {
54 | String key = stream.readPsdString().trim();
55 | logger.finest("PsdDescriptor.key: " + key);
56 | objects.put(key, PsdObjectFactory.loadPsdObject(stream));
57 | }
58 | }
59 |
60 | /**
61 | * Gets the class id.
62 | *
63 | * @return the class id
64 | */
65 | public String getClassId() {
66 | return classId;
67 | }
68 |
69 | /**
70 | * Gets the objects.
71 | *
72 | * @return the objects
73 | */
74 | public Map getObjects() {
75 | return objects;
76 | }
77 |
78 | /**
79 | * Gets the.
80 | *
81 | * @param key the key
82 | * @return the psd object
83 | */
84 | public PsdObject get(String key) {
85 | return objects.get(key);
86 | }
87 |
88 | /**
89 | * Contains key.
90 | *
91 | * @param key the key
92 | * @return true, if successful
93 | */
94 | public boolean containsKey(String key) {
95 | return objects.containsKey(key);
96 | }
97 |
98 | /* (non-Javadoc)
99 | * @see java.lang.Object#toString()
100 | */
101 | @Override
102 | public String toString() {
103 | return "Objc:" + objects.toString();
104 | }
105 |
106 | }
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/object/PsdDouble.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.object;
20 |
21 | import java.io.IOException;
22 |
23 | import psd.parser.PsdInputStream;
24 |
25 | // TODO: Auto-generated Javadoc
26 | /**
27 | * The Class PsdDouble.
28 | *
29 | * @author Dmitry Belsky
30 | */
31 | public class PsdDouble extends PsdObject {
32 |
33 | /** The value. */
34 | private final double value;
35 |
36 | /**
37 | * Instantiates a new psd double.
38 | *
39 | * @param stream the stream
40 | * @throws IOException Signals that an I/O exception has occurred.
41 | */
42 | public PsdDouble(PsdInputStream stream) throws IOException {
43 | value = stream.readDouble();
44 | logger.finest("PsdDouble.value: " + value);
45 | }
46 |
47 | /**
48 | * Gets the value.
49 | *
50 | * @return the value
51 | */
52 | public double getValue() {
53 | return value;
54 | }
55 |
56 | /* (non-Javadoc)
57 | * @see java.lang.Object#toString()
58 | */
59 | @Override
60 | public String toString() {
61 | return "doub:" + value;
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/object/PsdEnum.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.object;
20 |
21 | import java.io.IOException;
22 |
23 | import psd.parser.PsdInputStream;
24 |
25 | // TODO: Auto-generated Javadoc
26 | /**
27 | * The Class PsdEnum.
28 | *
29 | * @author Dmitry Belsky
30 | */
31 | public class PsdEnum extends PsdObject {
32 |
33 | /** The type id. */
34 | private final String typeId;
35 |
36 | /** The value. */
37 | private final String value;
38 |
39 | /**
40 | * Instantiates a new psd enum.
41 | *
42 | * @param stream the stream
43 | * @throws IOException Signals that an I/O exception has occurred.
44 | */
45 | public PsdEnum(PsdInputStream stream) throws IOException {
46 |
47 | typeId = stream.readPsdString();
48 | value = stream.readPsdString();
49 | logger.finest("PsdEnum.typeId " + typeId + " PsdEnum.value: " + value);
50 | }
51 |
52 | /**
53 | * Gets the type id.
54 | *
55 | * @return the type id
56 | */
57 | public String getTypeId() {
58 | return typeId;
59 | }
60 |
61 | /**
62 | * Gets the value.
63 | *
64 | * @return the value
65 | */
66 | public String getValue() {
67 | return value;
68 | }
69 |
70 | /* (non-Javadoc)
71 | * @see java.lang.Object#toString()
72 | */
73 | @Override
74 | public String toString() {
75 | return "enum:<" + typeId + ":" + value + ">";
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/object/PsdList.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.object;
20 |
21 | import java.io.IOException;
22 | import java.util.ArrayList;
23 | import java.util.Iterator;
24 |
25 | import psd.parser.PsdInputStream;
26 |
27 | // TODO: Auto-generated Javadoc
28 | /**
29 | * The Class PsdList.
30 | *
31 | * @author Dmitry Belsky
32 | */
33 | public class PsdList extends PsdObject implements Iterable {
34 |
35 | /** The objects. */
36 | private ArrayList objects = new ArrayList();
37 |
38 | /**
39 | * Instantiates a new psd list.
40 | *
41 | * @param stream the stream
42 | * @throws IOException Signals that an I/O exception has occurred.
43 | */
44 | public PsdList(PsdInputStream stream) throws IOException {
45 | int itemsCount = stream.readInt();
46 | logger.finest("PsdList.itemsCount: " + itemsCount);
47 | for (int i = 0; i < itemsCount; i++) {
48 | objects.add(PsdObjectFactory.loadPsdObject(stream));
49 | }
50 | }
51 |
52 | /* (non-Javadoc)
53 | * @see java.lang.Iterable#iterator()
54 | */
55 | @Override
56 | public Iterator iterator() {
57 | return objects.iterator();
58 | }
59 |
60 | /**
61 | * Size.
62 | *
63 | * @return the int
64 | */
65 | public int size() {
66 | return objects.size();
67 | }
68 |
69 | /**
70 | * Gets the.
71 | *
72 | * @param i the i
73 | * @return the psd object
74 | */
75 | public PsdObject get(int i) {
76 | return objects.get(i);
77 | }
78 |
79 | /* (non-Javadoc)
80 | * @see java.lang.Object#toString()
81 | */
82 | @Override
83 | public String toString() {
84 | return "VlLs:" + objects.toString();
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/object/PsdLong.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.object;
20 |
21 | import java.io.IOException;
22 |
23 | import psd.parser.PsdInputStream;
24 |
25 | // TODO: Auto-generated Javadoc
26 | /**
27 | * The Class PsdLong.
28 | *
29 | * @author Dmitry Belsky
30 | */
31 | public class PsdLong extends PsdObject {
32 |
33 | /** The value. */
34 | private final int value;
35 |
36 | /**
37 | * Instantiates a new psd long.
38 | *
39 | * @param stream the stream
40 | * @throws IOException Signals that an I/O exception has occurred.
41 | */
42 | public PsdLong(PsdInputStream stream) throws IOException {
43 | value = stream.readInt();
44 | logger.finest("PsdLong.value: " + value);
45 | }
46 |
47 | /**
48 | * Gets the value.
49 | *
50 | * @return the value
51 | */
52 | public int getValue() {
53 | return value;
54 | }
55 |
56 | /* (non-Javadoc)
57 | * @see java.lang.Object#toString()
58 | */
59 | @Override
60 | public String toString() {
61 | return "long:" + value;
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/object/PsdObject.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.object;
20 |
21 | import java.util.logging.Logger;
22 |
23 |
24 | public class PsdObject {
25 |
26 | /** The Constant logger. */
27 | protected static final Logger logger = Logger.getLogger("psd.objects");
28 |
29 | protected PsdObject() {
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/object/PsdObjectFactory.java:
--------------------------------------------------------------------------------
1 | package psd.parser.object;
2 |
3 | import java.io.IOException;
4 |
5 | import psd.parser.PsdInputStream;
6 |
7 | public class PsdObjectFactory {
8 |
9 | /**
10 | * Load psd object.
11 | *
12 | * @param stream the stream
13 | * @return the psd object
14 | * @throws IOException Signals that an I/O exception has occurred.
15 | */
16 | public static PsdObject loadPsdObject(PsdInputStream stream)
17 | throws IOException {
18 |
19 | String type = stream.readString(4);
20 | PsdObject.logger.finest("loadPsdObject.type: " + type);
21 | if (type.equals("Objc")) {
22 | return new PsdDescriptor(stream);
23 | } else if (type.equals("VlLs")) {
24 | return new PsdList(stream);
25 | } else if (type.equals("doub")) {
26 | return new PsdDouble(stream);
27 | } else if (type.equals("long")) {
28 | return new PsdLong(stream);
29 | } else if (type.equals("bool")) {
30 | return new PsdBoolean(stream);
31 | } else if (type.equals("UntF")) {
32 | return new PsdUnitFloat(stream);
33 | } else if (type.equals("enum")) {
34 | return new PsdEnum(stream);
35 | } else if (type.equals("TEXT")) {
36 | return new PsdText(stream);
37 | } else if (type.equals("tdta")) {
38 | return new PsdTextData(stream);
39 | } else {
40 | throw new IOException("UNKNOWN TYPE <" + type + ">");
41 | }
42 |
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/object/PsdText.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.object;
20 |
21 | import java.io.IOException;
22 |
23 | import psd.parser.PsdInputStream;
24 |
25 | // TODO: Auto-generated Javadoc
26 | /**
27 | * The Class PsdText.
28 | *
29 | * @author Dmitry Belsky
30 | */
31 | public class PsdText extends PsdObject {
32 |
33 | /** The value. */
34 | private final String value;
35 |
36 | /**
37 | * Instantiates a new psd text.
38 | *
39 | * @param stream the stream
40 | * @throws IOException Signals that an I/O exception has occurred.
41 | */
42 | public PsdText(PsdInputStream stream) throws IOException {
43 | int textSize = stream.readInt();
44 | StringBuffer buffer = new StringBuffer(textSize);
45 | boolean stopReading = false;
46 | for (int ti = 0; ti < textSize; ti++) {
47 | char b = (char) stream.readShort();
48 | if (b == 0) {
49 | stopReading = true;
50 | }
51 | if (!stopReading) {
52 | if (b == 13 || b == 10) {
53 | buffer.append('\n');
54 | } else {
55 | buffer.append(b);
56 | }
57 | }
58 | }
59 | value = buffer.toString();
60 |
61 | logger.finest("PsdText.value: " + value);
62 | }
63 |
64 | /**
65 | * Gets the value.
66 | *
67 | * @return the value
68 | */
69 | public String getValue() {
70 | return value;
71 | }
72 |
73 | /* (non-Javadoc)
74 | * @see java.lang.Object#toString()
75 | */
76 | @Override
77 | public String toString() {
78 | return value;
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/psd-parser/src/psd/parser/object/PsdTextData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of java-psd-library.
3 | *
4 | * This library is free software: you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public License
6 | * as published by the Free Software Foundation, either version 3 of
7 | * the License, or (at your option) any later version.
8 |
9 | * This library is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 |
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program. If not, see
16 | * .
17 | */
18 |
19 | package psd.parser.object;
20 |
21 | import java.io.*;
22 | import java.util.*;
23 | import psd.parser.PsdInputStream;
24 |
25 | public class PsdTextData extends PsdObject {
26 |
27 | private Map properties;
28 | private int cachedByte = -1;
29 | private boolean useCachedByte;
30 |
31 | public PsdTextData(PsdInputStream stream) throws IOException {
32 | int size = stream.readInt();
33 | int startPos = stream.getPos();
34 | properties = readMap(stream);
35 | assert startPos + size == stream.getPos();
36 | }
37 |
38 | /**
39 | * Gets the properties.
40 | *
41 | * @return the properties
42 | */
43 | public Map getProperties() {
44 | return properties;
45 | }
46 |
47 | private Map readMap(PsdInputStream stream) throws IOException {
48 | skipWhitespaces(stream);
49 | char c = (char) readByte(stream);
50 |
51 | if (c == ']') {
52 | return null;
53 | } else if (c == '<') {
54 | skipString(stream, "<");
55 | }
56 | HashMap map = new HashMap();
57 | while (true) {
58 | skipWhitespaces(stream);
59 | c = (char) readByte(stream);
60 | if (c == '>') {
61 | skipString(stream, ">");
62 | return map;
63 | } else {
64 | assert c == '/' : "unknown char: " + c + ", byte: " + (byte) c;
65 | String name = readName(stream);
66 | skipWhitespaces(stream);
67 | c = (char) lookForwardByte(stream);
68 | if (c == '<') {
69 | map.put(name, readMap(stream));
70 | } else {
71 | map.put(name, readValue(stream));
72 | }
73 | }
74 | }
75 | }
76 |
77 | private String readName(PsdInputStream stream) throws IOException {
78 | String name = "";
79 | while (true) {
80 | char c = (char) readByte(stream);
81 | if (c == ' ' || c == 10) {
82 | break;
83 | }
84 | name += c;
85 | }
86 | return name;
87 | }
88 |
89 | private Object readValue(PsdInputStream stream) throws IOException {
90 | char c = (char) readByte(stream);
91 | if (c == ']') {
92 | return null;
93 | } else if (c == '(') {
94 | // unicode string
95 | String string = "";
96 | int stringSignature = readShort(stream) & 0xFFFF;
97 | assert stringSignature == 0xFEFF;
98 | while (true) {
99 | byte b1 = readByte(stream);
100 | if (b1 == ')') {
101 | return string;
102 | }
103 | byte b2 = readByte(stream);
104 | if (b2 == '\\') {
105 | b2 = readByte(stream);
106 | }
107 | if (b2 == 13) {
108 | string += '\n';
109 | } else {
110 | string += (char) ((b1 << 8) | b2);
111 | }
112 | }
113 | } else if (c == '[') {
114 | ArrayList