]> git.sesse.net Git - casparcg/blob - modules/psd/layer.cpp
Merge branch '2.1.0' of https://github.com/CasparCG/Server into 2.1.0
[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         long end_of_layer_info = position1 + extraDataSize;
86         
87         try
88         {
89                 while(stream.current_position() < end_of_layer_info)
90                 {
91                         read_chunk(stream);
92                 }
93         }
94         catch(PSDFileFormatException&)
95         {
96                 stream.set_position(end_of_layer_info);
97         }
98 }
99
100 void layer::read_chunk(BEFileInputStream& stream, bool isMetadata)
101 {
102         unsigned long signature = stream.read_long();
103         if(signature != '8BIM' && signature != '8B64')
104                 throw PSDFileFormatException();
105
106         unsigned long key = stream.read_long();
107         
108         if(isMetadata) stream.read_long();
109
110         unsigned long length = stream.read_long();
111         unsigned long end_of_chunk = stream.current_position() + length;
112
113         try
114         {
115                 switch(key)
116                 {
117                 case 'lspf':    //protection settings
118                         protection_flags_ = stream.read_long();
119                         break;
120
121                 case 'Txt2':    //text engine data
122                         break;
123
124                 case 'TySh':    //type tool object settings
125                         read_text_data(stream);
126                         break;
127                                 
128                 case 'shmd':    //metadata
129                         read_metadata(stream);
130                         break;
131                                 
132                 case 'lyvr':    //layer version
133                         break;
134
135                 case 'lnkD':    //linked layer
136                 case 'lnk2':    //linked layer
137                 case 'lnk3':    //linked layer
138                         break;
139                                 
140                 case 'tmln':
141                         read_timeline_data(stream);
142                         break;
143
144                 default:
145                         break;
146                 }
147         }
148         catch(PSDFileFormatException&)
149         {
150                 //ignore failed chunks silently
151         }
152
153         stream.set_position(end_of_chunk);
154 }
155
156 void layer::read_metadata(BEFileInputStream& stream)
157 {
158         unsigned long count = stream.read_long();
159         for(int index = 0; index < count; ++index)
160                 read_chunk(stream, true);
161 }
162
163 void layer::read_timeline_data(BEFileInputStream& stream)
164 {
165         stream.read_long();                                     //"descriptor version" should be 16
166         descriptor timeline_descriptor;
167         if(!timeline_descriptor.populate(stream))
168                 throw PSDFileFormatException();
169         else
170         {
171                 timeline_info_.swap(timeline_descriptor.items());
172         }
173 }
174
175 void layer::read_text_data(BEFileInputStream& stream)
176 {
177         std::wstring text;      //the text in the layer
178
179         stream.read_short();    //should be 1
180         stream.discard_bytes(6*8);      //just throw transformation info for now
181         stream.read_short();    //"text version" should be 50
182
183         //text data descriptor ('descriptor structure')
184         if(stream.read_long() != 16)    //"descriptor version" should be 16
185                 throw PSDFileFormatException();
186
187         descriptor text_descriptor;
188         if(!text_descriptor.populate(stream))
189                 throw PSDFileFormatException();
190         else
191         {
192                 auto text_info = text_descriptor.items().get_optional<std::wstring>(L"EngineData");
193                 if(text_info.is_initialized())
194                 {
195                         std::string str(text_info.get().begin(), text_info.get().end());
196                         read_pdf(text_layer_info_, str);
197                 }
198         }
199
200         stream.read_short();    //"warp version" should be 1
201
202         //warp data descriptor ('descriptor structure')
203         stream.read_long();                                     //"descriptor version" should be 16
204         descriptor warp_descriptor;
205         if(!warp_descriptor.populate(stream))
206                 throw PSDFileFormatException();
207         else
208                 stream.discard_bytes(4*8);      //top, left, right, bottom
209 }
210
211 void layer::layer_mask::read_mask_data(BEFileInputStream& stream)
212 {
213         unsigned long length = stream.read_long();
214         switch(length)
215         {
216         case 0:
217                 break;
218
219         case 20:
220                 rect_.top = stream.read_long();
221                 rect_.left = stream.read_long();
222                 rect_.bottom = stream.read_long();
223                 rect_.right = stream.read_long();
224
225                 default_value_ = stream.read_byte();
226                 flags_ = stream.read_byte();
227                 stream.discard_bytes(2);
228                 break;
229
230         case 36:
231                 stream.discard_bytes(18);       //we don't care about the user mask if there is a "total user mask"
232                 flags_ = stream.read_byte();
233                 default_value_ = stream.read_byte();
234                 rect_.top = stream.read_long();
235                 rect_.left = stream.read_long();
236                 rect_.bottom = stream.read_long();
237                 rect_.right = stream.read_long();
238                 break;
239
240         default:
241                 stream.discard_bytes(length);
242                 break;
243         };
244 }
245
246 bool layer::is_text() const
247 {
248         return !text_layer_info_.empty();
249 }
250 bool layer::has_timeline() const
251 {
252         return !timeline_info_.empty();
253 }
254
255
256 //TODO: implement
257 void layer::read_blending_ranges(BEFileInputStream& stream)
258 {
259         unsigned long length = stream.read_long();
260         stream.discard_bytes(length);
261 }
262
263 channel_ptr layer::get_channel(channel_type type)
264 {
265         auto end = channels_.end();
266         for(auto it = channels_.begin(); it != end; ++it)
267         {
268                 if((*it)->id() == type)
269                 {
270                         return (*it);
271                 }
272         }
273
274         return NULL;
275 }
276
277 void layer::read_channel_data(BEFileInputStream& stream)
278 {
279         image8bit_ptr img;
280         image8bit_ptr mask;
281
282         bool has_transparency(get_channel(psd::Transparency));
283
284         //std::clog << std::endl << "layer: " << std::string(name().begin(), name().end()) << std::endl;
285         
286         if(rect_.width() > 0 && rect_.height() > 0)
287         {
288                 img = std::make_shared<image8bit>(rect_.width(), rect_.height(), 4);
289                 //std::clog << std::dec << "has image: [width: " << rect_.width() << " height: " << rect_.height() << "]" << std::endl;
290
291                 if(!has_transparency)
292                         std::memset(img->data(), 255, img->width()*img->height()*img->channel_count());
293         }
294
295         if(masks_ > 0 && mask_.rect_.width() > 0 && mask_.rect_.height() > 0)
296         {
297                 mask = std::make_shared<image8bit>(mask_.rect_.width(), mask_.rect_.height(), 1);
298                 //std::clog << std::dec << "has mask: [width: " << mask_rect_.width() << " height: " << mask_rect_.height() << "]" << std::endl;
299         }
300
301         auto end = channels_.end();
302         for(auto it = channels_.begin(); it != end; ++it)
303         {
304                 image8bit_ptr target;
305                 unsigned char offset;
306                 bool discard_channel = false;
307
308                 //determine target bitmap and offset
309                 if((*it)->id() >= 3)
310                         discard_channel = true; //discard channels that doesn't contribute to the final image
311                 else if((*it)->id() >= -1)      //BGRA-data
312                 {
313                         target = img;
314                         offset = ((*it)->id() >= 0) ? 2 - (*it)->id() : 3;
315                 }
316                 else if(mask)   //mask
317                 {
318                         if((*it)->id() == -2 && masks_ == 2)    //if there are two mask-channels, discard the the one that's not the total mask
319                                 discard_channel = true;
320                         else
321                         {
322                                 target = mask;
323                                 offset = 0;
324                         }
325                 }
326
327                 //unsigned long cp = stream.current_position(); //for debug purposes only
328                 //std::clog << std::dec << "channel_id: " << (*it)->id() << ", reading data from: " << std::hex << cp << ", data_length: " << (*it)->data_length() << std::endl;
329
330                 if(!target)
331                         discard_channel = true;
332
333                 if(discard_channel)
334                 {
335                         //std::clog << "        -> discarding" << std::endl;
336                         stream.discard_bytes((*it)->data_length());
337                 }
338                 else
339                 {
340                         //std::clog << "        -> reading...";
341                         unsigned short encoding = stream.read_short();
342                         if(target)
343                         {
344                                 if(encoding == 0)
345                                         read_raw_image_data(stream, *it, target, offset);
346                                 else if(encoding == 1)
347                                         read_rle_image_data(stream, *it, target, offset);
348                                 else
349                                         throw PSDFileFormatException();
350                         }
351                         //std::clog << " " << std::hex << (stream.current_position() - cp) << " bytes read" << std::endl;
352                 }
353         }
354
355         if(img && has_transparency)
356         {
357                 caspar::image::image_view<caspar::image::bgra_pixel> view(img->data(), img->width(), img->height());
358                 caspar::image::premultiply(view);
359         }
360
361         image_ = img;
362         mask_.mask_ = mask;
363 }
364
365 void read_raw_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset)
366 {
367         unsigned long total_length = target->width() * target->height();
368         if(total_length != (channel->data_length() - 2))
369                 throw PSDFileFormatException();
370
371         unsigned char* data = target->data();
372
373         unsigned char stride = target->channel_count();
374         if(stride == 1)
375                 stream.read(reinterpret_cast<char*>(data + offset), total_length);
376         else
377         {
378                 for(unsigned long index=0; index < total_length; ++index)
379                         data[index*stride+offset] = stream.read_byte();
380         }
381 }
382
383 void read_rle_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset)
384 {
385         unsigned long width = target->width();
386         unsigned char stride = target->channel_count();
387         unsigned long height = target->height();
388
389         std::vector<unsigned short> scanline_lengths;
390         scanline_lengths.reserve(height);
391
392         for(unsigned long scanlineIndex=0; scanlineIndex < height; ++scanlineIndex)
393                 scanline_lengths.push_back(stream.read_short());
394
395         unsigned char* data = target->data();
396
397         for(unsigned long scanlineIndex=0; scanlineIndex < height; ++scanlineIndex)
398         {
399                 unsigned long colIndex = 0;
400                 unsigned char length = 0;
401                 do
402                 {
403                         length = 0;
404
405                         //Get controlbyte
406                         char controlByte = static_cast<char>(stream.read_byte());
407                         if(controlByte >= 0)
408                         {
409                                 //Read uncompressed string
410                                 length = controlByte+1;
411                                 for(unsigned long index=0; index < length; ++index)
412                                         data[(scanlineIndex*width+colIndex+index) * stride + offset] = stream.read_byte();
413                         }
414                         else if(controlByte > -128)
415                         {
416                                 //Repeat next byte
417                                 length = -controlByte+1;
418                                 unsigned value = stream.read_byte();
419                                 for(unsigned long index=0; index < length; ++index)
420                                         data[(scanlineIndex*width+colIndex+index) * stride + offset] = value;
421                         }
422
423                         colIndex += length;
424                 }
425                 while(colIndex < width);
426         }
427 }
428
429 }       //namespace psd
430 }       //namespace caspar