2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
4 * This file is part of CasparCG (www.casparcg.com).
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.
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.
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/>.
19 * Author: Niklas P Andersson, niklas.p.andersson@svt.se
23 #include "descriptor.h"
24 #include "util\pdf_reader.h"
26 typedef unsigned char uint8_t;
28 #include "../image/util/image_algorithms.h"
29 #include "../image/util/image_view.h"
31 namespace caspar { namespace psd {
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);
36 layer_ptr layer::create(BEFileInputStream& stream)
38 layer_ptr result(std::make_shared<layer>());
39 result->populate(stream);
43 void layer::populate(BEFileInputStream& stream)
45 rect_.top = stream.read_long();
46 rect_.left = stream.read_long();
47 rect_.bottom = stream.read_long();
48 rect_.right = stream.read_long();
50 //Get info about the channels in the layer
51 unsigned short channelCount = stream.read_short();
52 for(int channelIndex = 0; channelIndex < channelCount; ++channelIndex)
54 short channel_id = static_cast<short>(stream.read_short());
55 unsigned long data_length = stream.read_long();
60 channel_ptr channel(std::make_shared<Channel>(channel_id, data_length));
61 channels_.push_back(channel);
64 unsigned long blendModeSignature = stream.read_long();
65 if(blendModeSignature != '8BIM')
66 throw PSDFileFormatException();
68 unsigned long blendModeKey = stream.read_long();
69 blend_mode_ = int_to_blend_mode(blendModeKey);
71 opacity_ = stream.read_byte();
72 baseClipping_ = stream.read_byte() == 1 ? false : true;
73 flags_ = stream.read_byte();
75 stream.discard_bytes(1);
77 unsigned long extraDataSize = stream.read_long();
78 long position1 = stream.current_position();
79 mask_.read_mask_data(stream);
80 read_blending_ranges(stream);
82 name_ = stream.read_pascal_string(4);
84 //Aditional Layer Information
85 long end_of_layer_info = position1 + extraDataSize;
89 while(stream.current_position() < end_of_layer_info)
94 catch(PSDFileFormatException&)
96 stream.set_position(end_of_layer_info);
100 void layer::read_chunk(BEFileInputStream& stream, bool isMetadata)
102 unsigned long signature = stream.read_long();
103 if(signature != '8BIM' && signature != '8B64')
104 throw PSDFileFormatException();
106 unsigned long key = stream.read_long();
108 if(isMetadata) stream.read_long();
110 unsigned long length = stream.read_long();
111 unsigned long end_of_chunk = stream.current_position() + length;
117 case 'lspf': //protection settings
118 protection_flags_ = stream.read_long();
121 case 'Txt2': //text engine data
124 case 'TySh': //type tool object settings
125 read_text_data(stream);
128 case 'shmd': //metadata
129 read_metadata(stream);
132 case 'lyvr': //layer version
135 case 'lnkD': //linked layer
136 case 'lnk2': //linked layer
137 case 'lnk3': //linked layer
141 read_timeline_data(stream);
148 catch(PSDFileFormatException&)
150 //ignore failed chunks silently
153 stream.set_position(end_of_chunk);
156 void layer::read_metadata(BEFileInputStream& stream)
158 unsigned long count = stream.read_long();
159 for(int index = 0; index < count; ++index)
160 read_chunk(stream, true);
163 void layer::read_timeline_data(BEFileInputStream& stream)
165 stream.read_long(); //"descriptor version" should be 16
166 descriptor timeline_descriptor;
167 if(!timeline_descriptor.populate(stream))
168 throw PSDFileFormatException();
171 timeline_info_.swap(timeline_descriptor.items());
175 void layer::read_text_data(BEFileInputStream& stream)
177 std::wstring text; //the text in the layer
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
183 //text data descriptor ('descriptor structure')
184 if(stream.read_long() != 16) //"descriptor version" should be 16
185 throw PSDFileFormatException();
187 descriptor text_descriptor;
188 if(!text_descriptor.populate(stream))
189 throw PSDFileFormatException();
192 auto text_info = text_descriptor.items().get_optional<std::wstring>(L"EngineData");
193 if(text_info.is_initialized())
195 std::string str(text_info.get().begin(), text_info.get().end());
196 read_pdf(text_layer_info_, str);
200 stream.read_short(); //"warp version" should be 1
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();
208 stream.discard_bytes(4*8); //top, left, right, bottom
211 void layer::layer_mask::read_mask_data(BEFileInputStream& stream)
213 unsigned long length = stream.read_long();
220 rect_.top = stream.read_long();
221 rect_.left = stream.read_long();
222 rect_.bottom = stream.read_long();
223 rect_.right = stream.read_long();
225 default_value_ = stream.read_byte();
226 flags_ = stream.read_byte();
227 stream.discard_bytes(2);
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();
241 stream.discard_bytes(length);
246 bool layer::is_text() const
248 return !text_layer_info_.empty();
250 bool layer::has_timeline() const
252 return !timeline_info_.empty();
257 void layer::read_blending_ranges(BEFileInputStream& stream)
259 unsigned long length = stream.read_long();
260 stream.discard_bytes(length);
263 channel_ptr layer::get_channel(channel_type type)
265 auto end = channels_.end();
266 for(auto it = channels_.begin(); it != end; ++it)
268 if((*it)->id() == type)
277 void layer::read_channel_data(BEFileInputStream& stream)
282 bool has_transparency(get_channel(psd::Transparency));
284 //std::clog << std::endl << "layer: " << std::string(name().begin(), name().end()) << std::endl;
286 if(rect_.width() > 0 && rect_.height() > 0)
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;
291 if(!has_transparency)
292 std::memset(img->data(), 255, img->width()*img->height()*img->channel_count());
295 if(masks_ > 0 && mask_.rect_.width() > 0 && mask_.rect_.height() > 0)
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;
301 auto end = channels_.end();
302 for(auto it = channels_.begin(); it != end; ++it)
304 image8bit_ptr target;
305 unsigned char offset;
306 bool discard_channel = false;
308 //determine target bitmap and offset
310 discard_channel = true; //discard channels that doesn't contribute to the final image
311 else if((*it)->id() >= -1) //BGRA-data
314 offset = ((*it)->id() >= 0) ? 2 - (*it)->id() : 3;
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;
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;
331 discard_channel = true;
335 //std::clog << " -> discarding" << std::endl;
336 stream.discard_bytes((*it)->data_length());
340 //std::clog << " -> reading...";
341 unsigned short encoding = stream.read_short();
345 read_raw_image_data(stream, *it, target, offset);
346 else if(encoding == 1)
347 read_rle_image_data(stream, *it, target, offset);
349 throw PSDFileFormatException();
351 //std::clog << " " << std::hex << (stream.current_position() - cp) << " bytes read" << std::endl;
355 if(img && has_transparency)
357 caspar::image::image_view<caspar::image::bgra_pixel> view(img->data(), img->width(), img->height());
358 caspar::image::premultiply(view);
365 void read_raw_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset)
367 unsigned long total_length = target->width() * target->height();
368 if(total_length != (channel->data_length() - 2))
369 throw PSDFileFormatException();
371 unsigned char* data = target->data();
373 unsigned char stride = target->channel_count();
375 stream.read(reinterpret_cast<char*>(data + offset), total_length);
378 for(unsigned long index=0; index < total_length; ++index)
379 data[index*stride+offset] = stream.read_byte();
383 void read_rle_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset)
385 unsigned long width = target->width();
386 unsigned char stride = target->channel_count();
387 unsigned long height = target->height();
389 std::vector<unsigned short> scanline_lengths;
390 scanline_lengths.reserve(height);
392 for(unsigned long scanlineIndex=0; scanlineIndex < height; ++scanlineIndex)
393 scanline_lengths.push_back(stream.read_short());
395 unsigned char* data = target->data();
397 for(unsigned long scanlineIndex=0; scanlineIndex < height; ++scanlineIndex)
399 unsigned long colIndex = 0;
400 unsigned char length = 0;
406 char controlByte = static_cast<char>(stream.read_byte());
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();
414 else if(controlByte > -128)
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;
425 while(colIndex < width);