]> git.sesse.net Git - casparcg/blob - modules/psd/psd_document.cpp
0dac03eca119a2b1299236bc903a081742b38ca3
[casparcg] / modules / psd / psd_document.cpp
1 /*
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
3 *
4 * This file is part of CasparCG (www.casparcg.com).
5 *
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Author: Niklas P Andersson, niklas.p.andersson@svt.se
20 */
21
22 #include "psd_document.h"
23 #include "descriptor.h"
24 #include <iostream>
25
26 #include <common/log.h>
27
28 namespace caspar { namespace psd {
29
30 psd_document::psd_document()
31 {
32 }
33
34 void psd_document::parse(const std::wstring& filename)
35 {
36         // Most of the parsing here is based on information from http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/
37         filename_ = filename;
38         input_.open(filename_);
39         read_header();
40         read_color_mode();
41         read_image_resources();
42         read_layers();
43 }
44
45 void psd_document::read_header()
46 {
47         auto signature = input_.read_long();
48         auto version = input_.read_short();
49         if(!(signature == '8BPS' && version == 1))
50                 CASPAR_THROW_EXCEPTION(psd_file_format_exception() << msg_info("!(signature == '8BPS' && version == 1)"));
51
52         input_.discard_bytes(6);
53         channels_= input_.read_short();
54         height_ = input_.read_long();
55         width_ = input_.read_long();
56         depth_ = input_.read_short();   //bits / channel
57
58         color_mode_ = int_to_color_mode(input_.read_short());
59 }
60
61 void psd_document::read_color_mode()
62 {
63         auto length = input_.read_long();
64         input_.discard_bytes(length);
65 }
66
67 void psd_document::read_image_resources()
68 {
69         auto section_length = input_.read_long();
70
71         if(section_length > 0)
72         {
73                 std::streamoff end_of_section = input_.current_position() + section_length;
74         
75                 try
76                 {
77                         while(input_.current_position() < end_of_section)
78                         {
79                                 auto signature = input_.read_long();
80                                 if(signature != '8BIM')
81                                         CASPAR_THROW_EXCEPTION(psd_file_format_exception() << msg_info("signature != '8BIM'"));
82
83                                 auto resource_id = input_.read_short();
84                                 
85                                 std::wstring name = input_.read_pascal_string(2);
86
87                                 auto resource_length = input_.read_long();
88                                 auto end_of_chunk = input_.current_position() + resource_length;
89
90                                 try
91                                 {
92                                         //TODO: read actual data
93                                         switch(resource_id)
94                                         {
95                                         case 1026:              //layer group information. describes linked layers
96                                                 {
97                                                         int layer_count = resource_length / 2;
98                                                         for(int i = 0; i < layer_count; ++i)
99                                                         {
100                                                                 int id = static_cast<std::int16_t>(input_.read_short());
101
102                                                                 if(i == layers_.size())
103                                                                         layers_.push_back(std::make_shared<layer>());
104
105                                                                 layers_[i]->set_link_group_id(id);
106                                                         }
107
108                                                 }
109                                                 break;
110                                         case 1075:              //timeline information
111                                                 {
112                                                         input_.read_long();     //descriptor version, should be 16
113                                                         descriptor timeline_descriptor(L"global timeline");
114                                                         timeline_descriptor.populate(input_);
115
116                                                         if (timeline_desc_.empty())
117                                                                 timeline_desc_.swap(timeline_descriptor.items());
118                                                 }
119                                                 break;
120
121                                         case 1005:
122                                                 {       
123                                                         ////resolutionInfo
124                                                         //struct ResolutionInfo
125                                                         //{
126                                                         //Fixed hRes;
127                                                         //int16 hResUnit;
128                                                         //int16 widthUnit;
129                                                         //Fixed vRes;
130                                                         //int16 vResUnit;
131                                                         //int16 heightUnit;
132                                                         //};
133                                                 }
134                                         case 1006:              //names of alpha channels
135                                         case 1008:              //caption
136                                         case 1010:              //background color
137                                         case 1024:              //layer state info (2 bytes containing the index of target layer (0 = bottom layer))
138                                         case 1028:              //IPTC-NAA. File Info...
139                                         case 1029:              //image for raw format files
140                                         case 1036:              //thumbnail resource
141                                         case 1045:              //unicode Alpha names (Unicode string (4 bytes length followed by string))
142                                         case 1053:              //alpha identifiers (4 bytes of length, followed by 4 bytes each for every alpha identifier.)
143                                         case 1060:              //XMP metadata
144                                         case 1065:              //layer comps
145                                         case 1069:              //layer selection ID(s)
146                                         case 1072:              //layer group(s) enabled id
147                                         case 1077:              //DisplayInfo
148                                         case 2999:              //name of clipping path
149                                         default:
150                                                 {
151                                                         if(resource_id >= 2000 && resource_id <=2997)   //path information
152                                                         {
153                                                         }
154                                                         else if(resource_id >= 4000 && resource_id <= 4999)     //plug-in resources
155                                                         {
156                                                         }
157                                                 }
158                                                 input_.discard_bytes(resource_length);
159                                                 break;
160                                         }
161
162                                         if((resource_length & 1) == 1)  //each resource is padded to an even amount of bytes
163                                                 input_.discard_bytes(1);
164                                 }
165                                 catch(psd_file_format_exception&)
166                                 {
167                                         input_.set_position(end_of_chunk);
168                                 }
169                         }
170                 }
171                 catch(psd_file_format_exception&)
172                 {
173                         //if an error occurs, just skip this section
174                         input_.set_position(end_of_section);
175                 }
176         }
177 }
178
179
180 void psd_document::read_layers()
181 {
182         //"Layer And Mask information"
183         auto total_length = input_.read_long(); //length of "Layer and Mask information"
184         auto end_of_layers = input_.current_position() + total_length;
185
186         try
187         {
188                 //"Layer info section"
189                 {
190                         auto layer_info_length = input_.read_long();    //length of "Layer info" section
191                         auto end_of_layers_info = input_.current_position() + layer_info_length;
192
193                         int layers_count = std::abs(static_cast<std::int16_t>(input_.read_short()));
194                         //std::clog << "Expecting " << layers_count << " layers" << std::endl;
195
196                         for(int layer_index = 0; layer_index < layers_count; ++layer_index)
197                         {
198                                 if(layer_index  == layers_.size())
199                                         layers_.push_back(std::make_shared<layer>());
200                                 
201                                 layers_[layer_index]->populate(input_, *this);
202                                 //std::clog << "Added layer: " << std::string(layers_[layerIndex]->name().begin(), layers_[layerIndex]->name().end()) << std::endl;
203                         }
204
205                         auto end = layers_.end();
206                         for(auto layer_it = layers_.begin(); layer_it != end; ++layer_it)
207                         {
208                                 (*layer_it)->read_channel_data(input_); //each layer reads it's "image data"
209                         }
210
211                         input_.set_position(end_of_layers_info);
212                 }
213
214                 //global layer mask info
215                 auto global_layer_mask_length = input_.read_long();
216                 input_.discard_bytes(global_layer_mask_length);
217
218         }
219         catch(std::exception&)
220         {
221                 CASPAR_LOG_CURRENT_EXCEPTION();
222                 input_.set_position(end_of_layers);
223         }
224 }
225
226 }       //namespace psd
227 }       //namespace caspar