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"
26 namespace caspar { namespace psd {
28 layer_ptr Layer::create(BEFileInputStream& stream)
30 layer_ptr result(std::make_shared<Layer>());
31 result->rect_.top = stream.read_long();
32 result->rect_.left = stream.read_long();
33 result->rect_.bottom = stream.read_long();
34 result->rect_.right = stream.read_long();
36 //Get info about the channels in the layer
37 unsigned short channelCount = stream.read_short();
38 for(int channelIndex = 0; channelIndex < channelCount; ++channelIndex)
40 short channel_id = static_cast<short>(stream.read_short());
41 unsigned long data_length = stream.read_long();
46 channel_ptr channel(std::make_shared<Channel>(channel_id, data_length));
47 result->channels_.push_back(channel);
50 unsigned long blendModeSignature = stream.read_long();
51 if(blendModeSignature != '8BIM')
52 throw PSDFileFormatException();
54 unsigned long blendModeKey = stream.read_long();
55 result->blendMode_ = IntToBlendMode(blendModeKey);
57 result->opacity_ = stream.read_byte();
58 result->baseClipping_ = stream.read_byte() == 1 ? false : true;
59 result->flags_ = stream.read_byte();
61 stream.discard_bytes(1);
63 unsigned long extraDataSize = stream.read_long();
64 long position1 = stream.current_position();
65 result->read_mask_data(stream);
66 result->ReadBlendingRanges(stream);
68 result->name_ = stream.read_pascal_string(4);
70 //Aditional Layer Information
71 unsigned long end_of_layer_info = position1 + extraDataSize;
75 while(stream.current_position() < end_of_layer_info)
77 unsigned long signature = stream.read_long();
78 if(signature != '8BIM' && signature != '8B64')
79 throw PSDFileFormatException();
81 unsigned long key = stream.read_long();
82 unsigned long length = stream.read_long();
83 unsigned long end_of_chunk = stream.current_position() + length;
85 if(key == 'TySh') //type tool object settings
87 std::wstring text; //the text in the layer
89 stream.read_short(); //should be 1
90 stream.discard_bytes(6*8); //just throw transformation info for now
91 stream.read_short(); //"text version" should be 50
92 stream.read_long(); //"descriptor version" should be 16
94 //text data descriptor ('descriptor structure')
95 descriptor text_descriptor;
96 if(!text_descriptor.populate(stream))
97 throw PSDFileFormatException();
99 stream.read_short(); //"warp version" should be 1
100 stream.read_long(); //"descriptor version" should be 16
102 //warp data descriptor ('descriptor structure')
103 descriptor warp_descriptor;
104 if(!text_descriptor.populate(stream))
105 throw PSDFileFormatException();
107 stream.discard_bytes(4*8); //top, left, right, bottom
110 stream.set_position(end_of_chunk);
113 catch(PSDFileFormatException& ex)
115 stream.set_position(end_of_layer_info);
121 void Layer::read_mask_data(BEFileInputStream& stream)
123 unsigned long length = stream.read_long();
126 mask_rect_.top = stream.read_long();
127 mask_rect_.left = stream.read_long();
128 mask_rect_.bottom = stream.read_long();
129 mask_rect_.right = stream.read_long();
131 default_mask_value_ = stream.read_byte();
132 mask_flags_ = stream.read_byte();
135 stream.discard_bytes(2);
138 //Override user mask with total user mask
139 mask_flags_ = stream.read_byte();
140 default_mask_value_ = stream.read_byte();
141 mask_rect_.top = stream.read_long();
142 mask_rect_.left = stream.read_long();
143 mask_rect_.bottom = stream.read_long();
144 mask_rect_.right = stream.read_long();
150 void Layer::ReadBlendingRanges(BEFileInputStream& stream)
152 unsigned long length = stream.read_long();
153 stream.discard_bytes(length);
156 channel_ptr Layer::get_channel(ChannelType type)
158 auto end = channels_.end();
159 for(auto it = channels_.begin(); it != end; ++it)
161 if((*it)->id() == type)
170 void Layer::read_channel_data(BEFileInputStream& stream)
174 //std::clog << std::endl << "layer: " << std::string(name().begin(), name().end()) << std::endl;
176 if(rect_.width() > 0 && rect_.height() > 0)
178 img = std::make_shared<image8bit>(rect_.width(), rect_.height(), std::min<unsigned char>(channels_.size() - masks_, 4));
179 //std::clog << std::dec << "has image: [width: " << rect_.width() << " height: " << rect_.height() << "]" << std::endl;
181 if(!get_channel(psd::Transparency))
182 std::memset(img->data(), (unsigned long)(255<<24), rect_.width()*rect_.height());
185 if(masks_ > 0 && mask_rect_.width() > 0 && mask_rect_.height() > 0)
187 mask = std::make_shared<image8bit>(mask_rect_.width(), mask_rect_.height(), 1);
188 //std::clog << std::dec << "has mask: [width: " << mask_rect_.width() << " height: " << mask_rect_.height() << "]" << std::endl;
191 auto end = channels_.end();
192 for(auto it = channels_.begin(); it != end; ++it)
194 image8bit_ptr target;
195 unsigned char offset;
196 bool discard_channel = false;
198 //determine target bitmap and offset
200 discard_channel = true; //discard channels that doesn't contribute to the final image
201 else if((*it)->id() >= -1) //RGBA-data
204 offset = ((*it)->id() >= 0) ? 2 - (*it)->id() : 3;
208 if((*it)->id() == -2 && masks_ == 2) //if there are two mask-channels, discard the the one that's not the total mask for now
209 discard_channel = true;
217 unsigned long cp = stream.current_position(); //TODO: remove, for debug purposes only
218 //std::clog << std::dec << "channel_id: " << (*it)->id() << ", reading data from: " << std::hex << cp << ", data_length: " << (*it)->data_length() << std::endl;
221 discard_channel = true;
225 //std::clog << " -> discarding" << std::endl;
226 stream.discard_bytes((*it)->data_length());
230 //std::clog << " -> reading...";
231 unsigned short encoding = stream.read_short();
235 read_raw_image_data(stream, *it, target, offset);
236 else if(encoding == 1)
237 read_rle_image_data(stream, *it, target, offset);
239 throw PSDFileFormatException();
241 //std::clog << " " << std::hex << (stream.current_position() - cp) << " bytes read" << std::endl;
249 void Layer::read_raw_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset)
251 unsigned long total_length = target->width() * target->height();
252 if(total_length != (channel->data_length() - 2))
253 throw PSDFileFormatException();
255 unsigned char* data = target->data();
257 unsigned char stride = target->channel_count();
259 stream.read(reinterpret_cast<char*>(data + offset), total_length);
262 for(unsigned long index=0; index < total_length; ++index)
263 data[index*stride+offset] = stream.read_byte();
267 void Layer::read_rle_image_data(BEFileInputStream& stream, const channel_ptr& channel, image8bit_ptr target, unsigned char offset)
269 unsigned long width = target->width();
270 unsigned char stride = target->channel_count();
271 unsigned long height = target->height();
273 std::vector<unsigned short> scanline_lengths;
274 scanline_lengths.reserve(height);
276 for(unsigned long scanlineIndex=0; scanlineIndex < height; ++scanlineIndex)
277 scanline_lengths.push_back(stream.read_short());
279 unsigned char* data = target->data();
281 for(unsigned long scanlineIndex=0; scanlineIndex < height; ++scanlineIndex)
283 unsigned long colIndex = 0;
284 unsigned char length = 0;
290 char controlByte = static_cast<char>(stream.read_byte());
293 //Read uncompressed string
294 length = controlByte+1;
295 for(unsigned long index=0; index < length; ++index)
296 data[(scanlineIndex*width+colIndex+index) * stride + offset] = stream.read_byte();
298 else if(controlByte > -128)
301 length = -controlByte+1;
302 unsigned value = stream.read_byte();
303 for(unsigned long index=0; index < length; ++index)
304 data[(scanlineIndex*width+colIndex+index) * stride + offset] = value;
309 while(colIndex < width);
314 //image_ptr Layer::read_image(BEFileInputStream& stream)
318 // unsigned char channels = (channels_.size() > 3) ? 4 : 3;
320 // image = std::make_shared<Image>(static_cast<unsigned short>(rect_.width()), static_cast<unsigned short>(rect_.height()), channels);
322 // channel_ptr pChannel = get_channel(ColorRed);
323 // if(pChannel != NULL)
324 // pChannel->GetChannelImageData(stream, image, 0);
326 // pChannel = get_channel(ColorGreen);
327 // if(pChannel != NULL)
328 // pChannel->GetChannelImageData(stream, image, 1);
330 // pChannel = get_channel(ColorBlue);
331 // if(pChannel != NULL)
332 // pChannel->GetChannelImageData(stream, image, 2);
334 // pChannel = get_channel(Transparency);
335 // if(channels == 4 && pChannel != NULL)
336 // pChannel->GetChannelImageData(stream, image, 3);