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->rect_.top = stream.read_long();
40 result->rect_.left = stream.read_long();
41 result->rect_.bottom = stream.read_long();
42 result->rect_.right = stream.read_long();
44 //Get info about the channels in the layer
45 unsigned short channelCount = stream.read_short();
46 for(int channelIndex = 0; channelIndex < channelCount; ++channelIndex)
48 short channel_id = static_cast<short>(stream.read_short());
49 unsigned long data_length = stream.read_long();
54 channel_ptr channel(std::make_shared<Channel>(channel_id, data_length));
55 result->channels_.push_back(channel);
58 unsigned long blendModeSignature = stream.read_long();
59 if(blendModeSignature != '8BIM')
60 throw PSDFileFormatException();
62 unsigned long blendModeKey = stream.read_long();
63 result->blend_mode_ = int_to_blend_mode(blendModeKey);
65 result->opacity_ = stream.read_byte();
66 result->baseClipping_ = stream.read_byte() == 1 ? false : true;
67 result->flags_ = stream.read_byte();
69 stream.discard_bytes(1);
71 unsigned long extraDataSize = stream.read_long();
72 long position1 = stream.current_position();
73 result->mask_.read_mask_data(stream);
74 result->read_blending_ranges(stream);
76 result->name_ = stream.read_pascal_string(4);
78 //Aditional Layer Information
79 unsigned long end_of_layer_info = position1 + extraDataSize;
83 while(stream.current_position() < end_of_layer_info)
85 unsigned long signature = stream.read_long();
86 if(signature != '8BIM' && signature != '8B64')
87 throw PSDFileFormatException();
89 unsigned long key = stream.read_long();
90 unsigned long length = stream.read_long();
91 unsigned long end_of_chunk = stream.current_position() + length;
93 if(key == 'TySh') //type tool object settings
95 std::wstring text; //the text in the layer
97 stream.read_short(); //should be 1
98 stream.discard_bytes(6*8); //just throw transformation info for now
99 stream.read_short(); //"text version" should be 50
100 stream.read_long(); //"descriptor version" should be 16
102 //text data descriptor ('descriptor structure')
103 descriptor text_descriptor;
104 if(!text_descriptor.populate(stream))
105 throw PSDFileFormatException();
108 if(text_descriptor.has_item(L"EngineData"))
110 const descriptor_item& text_data = text_descriptor.get_item(L"EngineData");
111 read_pdf(result->text_layer_info_, text_data.rawdata_data);
115 stream.read_short(); //"warp version" should be 1
116 stream.read_long(); //"descriptor version" should be 16
118 //warp data descriptor ('descriptor structure')
119 descriptor warp_descriptor;
120 if(!text_descriptor.populate(stream))
121 throw PSDFileFormatException();
123 stream.discard_bytes(4*8); //top, left, right, bottom
126 stream.set_position(end_of_chunk);
129 catch(PSDFileFormatException& ex)
131 stream.set_position(end_of_layer_info);
137 void layer::layer_mask::read_mask_data(BEFileInputStream& stream)
139 unsigned long length = stream.read_long();
146 rect_.top = stream.read_long();
147 rect_.left = stream.read_long();
148 rect_.bottom = stream.read_long();
149 rect_.right = stream.read_long();
151 default_value_ = stream.read_byte();
152 flags_ = stream.read_byte();
153 stream.discard_bytes(2);
157 stream.discard_bytes(18); //we don't care about the user mask if there is a "total user mask"
158 flags_ = stream.read_byte();
159 default_value_ = stream.read_byte();
160 rect_.top = stream.read_long();
161 rect_.left = stream.read_long();
162 rect_.bottom = stream.read_long();
163 rect_.right = stream.read_long();
167 stream.discard_bytes(length);
172 bool layer::is_text() const
174 return !text_layer_info_.empty();
178 void layer::read_blending_ranges(BEFileInputStream& stream)
180 unsigned long length = stream.read_long();
181 stream.discard_bytes(length);
184 channel_ptr layer::get_channel(channel_type type)
186 auto end = channels_.end();
187 for(auto it = channels_.begin(); it != end; ++it)
189 if((*it)->id() == type)
198 void layer::read_channel_data(BEFileInputStream& stream)
203 bool has_transparency(get_channel(psd::Transparency));
205 //std::clog << std::endl << "layer: " << std::string(name().begin(), name().end()) << std::endl;
207 if(rect_.width() > 0 && rect_.height() > 0)
209 img = std::make_shared<image8bit>(rect_.width(), rect_.height(), std::min<unsigned char>(channels_.size() - masks_, 4));
210 //std::clog << std::dec << "has image: [width: " << rect_.width() << " height: " << rect_.height() << "]" << std::endl;
212 if(!has_transparency)
213 std::memset(img->data(), (unsigned long)(255<<24), rect_.width()*rect_.height());
216 if(masks_ > 0 && mask_.rect_.width() > 0 && mask_.rect_.height() > 0)
218 mask = std::make_shared<image8bit>(mask_.rect_.width(), mask_.rect_.height(), 1);
219 //std::clog << std::dec << "has mask: [width: " << mask_rect_.width() << " height: " << mask_rect_.height() << "]" << std::endl;
222 auto end = channels_.end();
223 for(auto it = channels_.begin(); it != end; ++it)
225 image8bit_ptr target;
226 unsigned char offset;
227 bool discard_channel = false;
229 //determine target bitmap and offset
231 discard_channel = true; //discard channels that doesn't contribute to the final image
232 else if((*it)->id() >= -1) //BGRA-data
235 offset = ((*it)->id() >= 0) ? 2 - (*it)->id() : 3;
239 if((*it)->id() == -2 && masks_ == 2) //if there are two mask-channels, discard the the one that's not the total mask
240 discard_channel = true;
248 //unsigned long cp = stream.current_position(); //for debug purposes only
249 //std::clog << std::dec << "channel_id: " << (*it)->id() << ", reading data from: " << std::hex << cp << ", data_length: " << (*it)->data_length() << std::endl;
252 discard_channel = true;
256 //std::clog << " -> discarding" << std::endl;
257 stream.discard_bytes((*it)->data_length());
261 //std::clog << " -> reading...";
262 unsigned short encoding = stream.read_short();
266 read_raw_image_data(stream, *it, target, offset);
267 else if(encoding == 1)
268 read_rle_image_data(stream, *it, target, offset);
270 throw PSDFileFormatException();
272 //std::clog << " " << std::hex << (stream.current_position() - cp) << " bytes read" << std::endl;
276 if(img && has_transparency)
278 caspar::image::image_view<caspar::image::bgra_pixel> view(img->data(), img->width(), img->height());
279 caspar::image::premultiply(view);
286 void read_raw_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset)
288 unsigned long total_length = target->width() * target->height();
289 if(total_length != (channel->data_length() - 2))
290 throw PSDFileFormatException();
292 unsigned char* data = target->data();
294 unsigned char stride = target->channel_count();
296 stream.read(reinterpret_cast<char*>(data + offset), total_length);
299 for(unsigned long index=0; index < total_length; ++index)
300 data[index*stride+offset] = stream.read_byte();
304 void read_rle_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset)
306 unsigned long width = target->width();
307 unsigned char stride = target->channel_count();
308 unsigned long height = target->height();
310 std::vector<unsigned short> scanline_lengths;
311 scanline_lengths.reserve(height);
313 for(unsigned long scanlineIndex=0; scanlineIndex < height; ++scanlineIndex)
314 scanline_lengths.push_back(stream.read_short());
316 unsigned char* data = target->data();
318 for(unsigned long scanlineIndex=0; scanlineIndex < height; ++scanlineIndex)
320 unsigned long colIndex = 0;
321 unsigned char length = 0;
327 char controlByte = static_cast<char>(stream.read_byte());
330 //Read uncompressed string
331 length = controlByte+1;
332 for(unsigned long index=0; index < length; ++index)
333 data[(scanlineIndex*width+colIndex+index) * stride + offset] = stream.read_byte();
335 else if(controlByte > -128)
338 length = -controlByte+1;
339 unsigned value = stream.read_byte();
340 for(unsigned long index=0; index < length; ++index)
341 data[(scanlineIndex*width+colIndex+index) * stride + offset] = value;
346 while(colIndex < width);