]> git.sesse.net Git - casparcg/blob - modules/psd/psd_document.cpp
a69c75913072db98714386fe310ecf21c3e8dce8
[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 namespace caspar { namespace psd {
27
28 psd_document::psd_document()
29         : channels_(0)
30         , width_(0)
31         , height_(0)
32         , depth_(0)
33         , color_mode_(psd::color_mode::InvalidColorMode)
34 {
35 }
36
37 void psd_document::parse(const std::wstring& filename)
38 {
39         filename_ = filename;
40         input_.open(filename_);
41         read_header();
42         read_color_mode();
43         read_image_resources();
44         read_layers();
45 }
46
47 void psd_document::read_header()
48 {
49         auto signature = input_.read_long();
50         auto version = input_.read_short();
51         if(!(signature == '8BPS' && version == 1))
52                 CASPAR_THROW_EXCEPTION(psd_file_format_exception() << msg_info("!(signature == '8BPS' && version == 1)"));
53
54         input_.discard_bytes(6);
55         channels_= input_.read_short();
56         height_ = input_.read_long();
57         width_ = input_.read_long();
58         depth_ = input_.read_short();   //bits / channel
59
60         color_mode_ = int_to_color_mode(input_.read_short());
61 }
62
63 void psd_document::read_color_mode()
64 {
65         auto length = input_.read_long();
66         input_.discard_bytes(length);
67 }
68
69 void psd_document::read_image_resources()
70 {
71         unsigned long section_length = input_.read_long();
72
73         if(section_length > 0)
74         {
75                 std::streamoff end_of_section = input_.current_position() + section_length;
76         
77                 try
78                 {
79                         while(input_.current_position() < end_of_section)
80                         {
81                                 auto signature = input_.read_long();
82                                 if(signature != '8BIM')
83                                         CASPAR_THROW_EXCEPTION(psd_file_format_exception() << msg_info("signature != '8BIM'"));
84
85                                 auto resource_id = input_.read_short();
86                                 
87                                 std::wstring name = input_.read_pascal_string(2);
88
89                                 auto resource_length = input_.read_long();
90                                 auto end_of_chunk = input_.current_position() + resource_length;
91
92                                 try
93                                 {
94                                         //TODO: read actual data
95                                         switch(resource_id)
96                                         {
97                                         case 1026:              //layer group information. describes linked layers
98                                                 {
99                                                         int layer_count = resource_length / 2;
100                                                         for(int i = 0; i < layer_count; ++i)
101                                                         {
102                                                                 short id = input_.read_short();
103
104                                                                 if(i == layers_.size())
105                                                                         layers_.push_back(std::make_shared<layer>());
106
107                                                                 layers_[i]->set_link_group_id(id);
108                                                         }
109
110                                                 }
111                                                 break;
112                                         case 1075:              //timeline information
113                                                 {
114                                                         input_.read_long();     //descriptor version, should be 16
115                                                         descriptor timeline_descriptor(L"global timeline");
116                                                         timeline_descriptor.populate(input_);
117
118                                                         if (timeline_desc_.empty())
119                                                                 timeline_desc_.swap(timeline_descriptor.items());
120                                                 }
121                                                 break;
122
123                                         case 1005:
124                                                 {       
125                                                         ////resolutionInfo
126                                                         //struct ResolutionInfo
127                                                         //{
128                                                         //Fixed hRes;
129                                                         //int16 hResUnit;
130                                                         //int16 widthUnit;
131                                                         //Fixed vRes;
132                                                         //int16 vResUnit;
133                                                         //int16 heightUnit;
134                                                         //};
135                                                 }
136                                         case 1006:              //names of alpha channels
137                                         case 1008:              //caption
138                                         case 1010:              //background color
139                                         case 1024:              //layer state info (2 bytes containing the index of target layer (0 = bottom layer))
140                                         case 1028:              //IPTC-NAA. File Info...
141                                         case 1029:              //image for raw format files
142                                         case 1036:              //thumbnail resource
143                                         case 1045:              //unicode Alpha names (Unicode string (4 bytes length followed by string))
144                                         case 1053:              //alpha identifiers (4 bytes of length, followed by 4 bytes each for every alpha identifier.)
145                                         case 1060:              //XMP metadata
146                                         case 1065:              //layer comps
147                                         case 1069:              //layer selection ID(s)
148                                         case 1072:              //layer group(s) enabled id
149                                         case 1077:              //DisplayInfo
150                                         case 2999:              //name of clipping path
151                                         default:
152                                                 {
153                                                         if(resource_id >= 2000 && resource_id <=2997)   //path information
154                                                         {
155                                                         }
156                                                         else if(resource_id >= 4000 && resource_id <= 4999)     //plug-in resources
157                                                         {
158                                                         }
159                                                 }
160                                                 input_.discard_bytes(resource_length);
161                                                 break;
162                                         }
163
164                                         if((resource_length & 1) == 1)  //each resource is padded to an even amount of bytes
165                                                 input_.discard_bytes(1);
166                                 }
167                                 catch(psd_file_format_exception&)
168                                 {
169                                         input_.set_position(end_of_chunk);
170                                 }
171                         }
172                 }
173                 catch(psd_file_format_exception&)
174                 {
175                         //if an error occurs, just skip this section
176                         input_.set_position(end_of_section);
177                 }
178         }
179 }
180
181
182 void psd_document::read_layers()
183 {
184         //"Layer And Mask information"
185         auto total_length = input_.read_long(); //length of "Layer and Mask information"
186         auto end_of_layers = input_.current_position() + total_length;
187
188         try
189         {
190                 //"Layer info section"
191                 {
192                         auto layer_info_length = input_.read_long();    //length of "Layer info" section
193                         auto end_of_layers_info = input_.current_position() + layer_info_length;
194
195                         auto layers_count = std::abs(static_cast<short>(input_.read_short()));
196                         //std::clog << "Expecting " << layers_count << " layers" << std::endl;
197
198                         for(int layer_index = 0; layer_index < layers_count; ++layer_index)
199                         {
200                                 if(layer_index  == layers_.size())
201                                         layers_.push_back(std::make_shared<layer>());
202                                 
203                                 layers_[layer_index]->populate(input_, *this);
204                                 //std::clog << "Added layer: " << std::string(layers_[layerIndex]->name().begin(), layers_[layerIndex]->name().end()) << std::endl;
205                         }
206
207                         auto end = layers_.end();
208                         for(auto layer_it = layers_.begin(); layer_it != end; ++layer_it)
209                         {
210                                 (*layer_it)->read_channel_data(input_); //each layer reads it's "image data"
211                         }
212
213                         input_.set_position(end_of_layers_info);
214                 }
215
216                 //global layer mask info
217                 auto global_layer_mask_length = input_.read_long();
218                 input_.discard_bytes(global_layer_mask_length);
219
220         }
221         catch(std::exception&)
222         {
223                 input_.set_position(end_of_layers);
224         }
225 }
226
227 }       //namespace psd
228 }       //namespace caspar