]> git.sesse.net Git - casparcg/blob - modules/psd/layer.cpp
binding between linked layers in psd-import/scene-producer
[casparcg] / modules / psd / layer.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 "layer.h"
23 #include "descriptor.h"
24 #include "util\pdf_reader.h"
25
26 typedef unsigned char uint8_t;
27 #include <algorithm>
28 #include "../image/util/image_algorithms.h"
29 #include "../image/util/image_view.h"
30
31 namespace caspar { namespace psd {
32
33 void read_raw_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset);
34 void read_rle_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset);
35
36 layer_ptr layer::create(BEFileInputStream& stream)
37 {
38         layer_ptr result(std::make_shared<layer>());
39         result->populate(stream);
40         return result;
41 }
42
43 void layer::populate(BEFileInputStream& stream)
44 {
45         rect_.top = stream.read_long();
46         rect_.left = stream.read_long();
47         rect_.bottom = stream.read_long();
48         rect_.right = stream.read_long();
49
50         //Get info about the channels in the layer
51         unsigned short channelCount = stream.read_short();
52         for(int channelIndex = 0; channelIndex < channelCount; ++channelIndex)
53         {
54                 short channel_id = static_cast<short>(stream.read_short());
55                 unsigned long data_length = stream.read_long();
56
57                 if(channel_id <= -2)
58                         masks_++;
59
60                 channel_ptr channel(std::make_shared<Channel>(channel_id, data_length));
61                 channels_.push_back(channel);
62         }
63
64         unsigned long blendModeSignature = stream.read_long();
65         if(blendModeSignature != '8BIM')
66                 throw PSDFileFormatException();
67
68         unsigned long blendModeKey = stream.read_long();
69         blend_mode_ = int_to_blend_mode(blendModeKey);
70
71         opacity_ = stream.read_byte();
72         baseClipping_ = stream.read_byte() == 1 ? false : true;
73         flags_ = stream.read_byte();
74
75         stream.discard_bytes(1);
76
77         unsigned long extraDataSize = stream.read_long();
78         long position1 = stream.current_position();
79         mask_.read_mask_data(stream);
80         read_blending_ranges(stream);
81
82         name_ = stream.read_pascal_string(4);
83
84         //Aditional Layer Information
85         unsigned long end_of_layer_info = position1 + extraDataSize;
86         
87         try
88         {
89                 while(stream.current_position() < end_of_layer_info)
90                 {
91                         unsigned long signature = stream.read_long();
92                         if(signature != '8BIM' && signature != '8B64')
93                                 throw PSDFileFormatException();
94
95                         unsigned long key = stream.read_long();
96                         unsigned long length = stream.read_long();
97                         unsigned long end_of_chunk = stream.current_position() + length;
98
99                         if(key == 'lspf')
100                         {
101                                 protection_flags_ = stream.read_long();
102                         }
103                         else if(key == 'TySh')  //type tool object settings
104                         {
105                                 std::wstring text;      //the text in the layer
106
107                                 stream.read_short();    //should be 1
108                                 stream.discard_bytes(6*8);      //just throw transformation info for now
109                                 stream.read_short();    //"text version" should be 50
110                                 stream.read_long();             //"descriptor version" should be 16
111
112                                 //text data descriptor ('descriptor structure')
113                                 descriptor text_descriptor;
114                                 if(!text_descriptor.populate(stream))
115                                         throw PSDFileFormatException();
116                                 else
117                                 {
118                                         if(text_descriptor.has_item(L"EngineData"))
119                                         {
120                                                 const descriptor_item& text_data = text_descriptor.get_item(L"EngineData");
121                                                 read_pdf(text_layer_info_, text_data.rawdata_data);
122                                         }
123                                 }
124
125                                 stream.read_short();    //"warp version" should be 1
126                                 stream.read_long();             //"descriptor version" should be 16
127
128                                 //warp data descriptor ('descriptor structure')
129                                 descriptor warp_descriptor;
130                                 if(!text_descriptor.populate(stream))
131                                         throw PSDFileFormatException();
132
133                                 stream.discard_bytes(4*8);      //top, left, right, bottom
134                         }
135
136                         stream.set_position(end_of_chunk);
137                 }
138         }
139         catch(PSDFileFormatException& ex)
140         {
141                 stream.set_position(end_of_layer_info);
142         }
143 }
144
145 void layer::layer_mask::read_mask_data(BEFileInputStream& stream)
146 {
147         unsigned long length = stream.read_long();
148         switch(length)
149         {
150         case 0:
151                 break;
152
153         case 20:
154                 rect_.top = stream.read_long();
155                 rect_.left = stream.read_long();
156                 rect_.bottom = stream.read_long();
157                 rect_.right = stream.read_long();
158
159                 default_value_ = stream.read_byte();
160                 flags_ = stream.read_byte();
161                 stream.discard_bytes(2);
162                 break;
163
164         case 36:
165                 stream.discard_bytes(18);       //we don't care about the user mask if there is a "total user mask"
166                 flags_ = stream.read_byte();
167                 default_value_ = stream.read_byte();
168                 rect_.top = stream.read_long();
169                 rect_.left = stream.read_long();
170                 rect_.bottom = stream.read_long();
171                 rect_.right = stream.read_long();
172                 break;
173
174         default:
175                 stream.discard_bytes(length);
176                 break;
177         };
178 }
179
180 bool layer::is_text() const
181 {
182         return !text_layer_info_.empty();
183 }
184
185 //TODO: implement
186 void layer::read_blending_ranges(BEFileInputStream& stream)
187 {
188         unsigned long length = stream.read_long();
189         stream.discard_bytes(length);
190 }
191
192 channel_ptr layer::get_channel(channel_type type)
193 {
194         auto end = channels_.end();
195         for(auto it = channels_.begin(); it != end; ++it)
196         {
197                 if((*it)->id() == type)
198                 {
199                         return (*it);
200                 }
201         }
202
203         return NULL;
204 }
205
206 void layer::read_channel_data(BEFileInputStream& stream)
207 {
208         image8bit_ptr img;
209         image8bit_ptr mask;
210
211         bool has_transparency(get_channel(psd::Transparency));
212
213         //std::clog << std::endl << "layer: " << std::string(name().begin(), name().end()) << std::endl;
214         
215         if(rect_.width() > 0 && rect_.height() > 0)
216         {
217                 img = std::make_shared<image8bit>(rect_.width(), rect_.height(), 4);
218                 //std::clog << std::dec << "has image: [width: " << rect_.width() << " height: " << rect_.height() << "]" << std::endl;
219
220                 if(!has_transparency)
221                         std::memset(img->data(), 255, img->width()*img->height()*img->channel_count());
222         }
223
224         if(masks_ > 0 && mask_.rect_.width() > 0 && mask_.rect_.height() > 0)
225         {
226                 mask = std::make_shared<image8bit>(mask_.rect_.width(), mask_.rect_.height(), 1);
227                 //std::clog << std::dec << "has mask: [width: " << mask_rect_.width() << " height: " << mask_rect_.height() << "]" << std::endl;
228         }
229
230         auto end = channels_.end();
231         for(auto it = channels_.begin(); it != end; ++it)
232         {
233                 image8bit_ptr target;
234                 unsigned char offset;
235                 bool discard_channel = false;
236
237                 //determine target bitmap and offset
238                 if((*it)->id() >= 3)
239                         discard_channel = true; //discard channels that doesn't contribute to the final image
240                 else if((*it)->id() >= -1)      //BGRA-data
241                 {
242                         target = img;
243                         offset = ((*it)->id() >= 0) ? 2 - (*it)->id() : 3;
244                 }
245                 else if(mask)   //mask
246                 {
247                         if((*it)->id() == -2 && masks_ == 2)    //if there are two mask-channels, discard the the one that's not the total mask
248                                 discard_channel = true;
249                         else
250                         {
251                                 target = mask;
252                                 offset = 0;
253                         }
254                 }
255
256                 //unsigned long cp = stream.current_position(); //for debug purposes only
257                 //std::clog << std::dec << "channel_id: " << (*it)->id() << ", reading data from: " << std::hex << cp << ", data_length: " << (*it)->data_length() << std::endl;
258
259                 if(!target)
260                         discard_channel = true;
261
262                 if(discard_channel)
263                 {
264                         //std::clog << "        -> discarding" << std::endl;
265                         stream.discard_bytes((*it)->data_length());
266                 }
267                 else
268                 {
269                         //std::clog << "        -> reading...";
270                         unsigned short encoding = stream.read_short();
271                         if(target)
272                         {
273                                 if(encoding == 0)
274                                         read_raw_image_data(stream, *it, target, offset);
275                                 else if(encoding == 1)
276                                         read_rle_image_data(stream, *it, target, offset);
277                                 else
278                                         throw PSDFileFormatException();
279                         }
280                         //std::clog << " " << std::hex << (stream.current_position() - cp) << " bytes read" << std::endl;
281                 }
282         }
283
284         if(img && has_transparency)
285         {
286                 caspar::image::image_view<caspar::image::bgra_pixel> view(img->data(), img->width(), img->height());
287                 caspar::image::premultiply(view);
288         }
289
290         image_ = img;
291         mask_.mask_ = mask;
292 }
293
294 void read_raw_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset)
295 {
296         unsigned long total_length = target->width() * target->height();
297         if(total_length != (channel->data_length() - 2))
298                 throw PSDFileFormatException();
299
300         unsigned char* data = target->data();
301
302         unsigned char stride = target->channel_count();
303         if(stride == 1)
304                 stream.read(reinterpret_cast<char*>(data + offset), total_length);
305         else
306         {
307                 for(unsigned long index=0; index < total_length; ++index)
308                         data[index*stride+offset] = stream.read_byte();
309         }
310 }
311
312 void read_rle_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset)
313 {
314         unsigned long width = target->width();
315         unsigned char stride = target->channel_count();
316         unsigned long height = target->height();
317
318         std::vector<unsigned short> scanline_lengths;
319         scanline_lengths.reserve(height);
320
321         for(unsigned long scanlineIndex=0; scanlineIndex < height; ++scanlineIndex)
322                 scanline_lengths.push_back(stream.read_short());
323
324         unsigned char* data = target->data();
325
326         for(unsigned long scanlineIndex=0; scanlineIndex < height; ++scanlineIndex)
327         {
328                 unsigned long colIndex = 0;
329                 unsigned char length = 0;
330                 do
331                 {
332                         length = 0;
333
334                         //Get controlbyte
335                         char controlByte = static_cast<char>(stream.read_byte());
336                         if(controlByte >= 0)
337                         {
338                                 //Read uncompressed string
339                                 length = controlByte+1;
340                                 for(unsigned long index=0; index < length; ++index)
341                                         data[(scanlineIndex*width+colIndex+index) * stride + offset] = stream.read_byte();
342                         }
343                         else if(controlByte > -128)
344                         {
345                                 //Repeat next byte
346                                 length = -controlByte+1;
347                                 unsigned value = stream.read_byte();
348                                 for(unsigned long index=0; index < length; ++index)
349                                         data[(scanlineIndex*width+colIndex+index) * stride + offset] = value;
350                         }
351
352                         colIndex += length;
353                 }
354                 while(colIndex < width);
355         }
356 }
357
358 }       //namespace psd
359 }       //namespace caspar