]> git.sesse.net Git - casparcg/commitdiff
* the psd-importer now extracts timeline-data
authorniklaspandersson <niklas.p.andersson@svt.se>
Wed, 14 Aug 2013 07:58:20 +0000 (09:58 +0200)
committerniklaspandersson <niklas.p.andersson@svt.se>
Wed, 14 Aug 2013 07:58:20 +0000 (09:58 +0200)
13 files changed:
.gitignore
casparcg.sln
modules/psd/descriptor.cpp
modules/psd/descriptor.h
modules/psd/doc.cpp
modules/psd/doc.h
modules/psd/layer.cpp
modules/psd/layer.h
modules/psd/util/bigendian_file_input_stream.cpp
modules/psd/util/bigendian_file_input_stream.h
modules/psd/util/pdf_reader.cpp
modules/psd/util/pdf_reader.h
test/psd-test/psd-test.cpp

index d21b4931daddd3451c0ad21aedd2e9ee4063646d..a3a3de79b96008912a89f87298488104f4a767a2 100644 (file)
 
 /test/psd-test/psd-test.vcxproj.user
 freetype
+tmp
+bin
index b582e83d8e9d2c75ddcab38e09113db387f79099..105f796619bc34d0d1dc635cfbcabc986b1ccbc8 100644 (file)
@@ -200,7 +200,6 @@ Global
                {156C91E0-8CAC-4DBA-A212-AAFDAFACD8BC}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
                {156C91E0-8CAC-4DBA-A212-AAFDAFACD8BC}.Debug|Win32.ActiveCfg = Debug|x64\r
                {156C91E0-8CAC-4DBA-A212-AAFDAFACD8BC}.Debug|x64.ActiveCfg = Debug|x64\r
-               {156C91E0-8CAC-4DBA-A212-AAFDAFACD8BC}.Debug|x64.Build.0 = Debug|x64\r
                {156C91E0-8CAC-4DBA-A212-AAFDAFACD8BC}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
                {156C91E0-8CAC-4DBA-A212-AAFDAFACD8BC}.Release|Mixed Platforms.Build.0 = Release|x64\r
                {156C91E0-8CAC-4DBA-A212-AAFDAFACD8BC}.Release|Win32.ActiveCfg = Release|x64\r
index 82dd18a26f1d7968e3c4cb49b9bcd759308d13a4..c512b20734d556da1c3615f01d883d2fa3a730f5 100644 (file)
 * Author: Niklas P Andersson, niklas.p.andersson@svt.se
 */
 
+#include <memory>
 #include "descriptor.h"
+#include <boost\property_tree\ptree.hpp>
 #include "misc.h"
 
 namespace caspar { namespace psd {
 
-bool descriptor::has_item(const std::wstring& key) const
-{
-       return (items_.find(key) != items_.end());
-}
+       class descriptor::context::scoped_holder
+       {
+               descriptor::context::ptr_type ctx_;
+       public:
+               explicit scoped_holder(const std::wstring& key, descriptor::context::ptr_type ctx) : ctx_(ctx) 
+               {
+                       Ptree *parent = ctx_->stack.back();
+                       Ptree *child = &parent->push_back(std::make_pair(key, Ptree()))->second;
+                       ctx_->stack.push_back(child);
+               }
+               ~scoped_holder()
+               {
+                       ctx_->stack.pop_back();
+               }
+       };
 
-const descriptor_item& descriptor::get_item(const std::wstring& key) const
-{
-       return (*(items_.find(key))).second;
-}
+       descriptor::descriptor() : context_(std::make_shared<context>())
+       {
+               context_->stack.push_back(&context_->root);
+       }
+       descriptor::descriptor(const std::wstring& key, context::ptr_type context) : context_(context)
+       {
+               Ptree *parent = context_->stack.back();
+               Ptree *child = &parent->push_back(std::make_pair(key, Ptree()))->second;
+               context->stack.push_back(child);
+       }
+       descriptor::~descriptor()
+       {
+               context_->stack.pop_back();
+       }
 
 bool descriptor::populate(BEFileInputStream& stream)
 {
@@ -45,58 +68,8 @@ bool descriptor::populate(BEFileInputStream& stream)
                unsigned long element_count = stream.read_long();
                for(int element_index = 0; element_index < element_count; ++element_index)
                {
-                       descriptor_item item;
-
                        std::wstring key = stream.read_id_string();
-                       item.type = stream.read_long();
-
-                       switch(item.type)
-                       {
-                       case 'obj ': break;
-                       case 'Objc': break;
-                       case 'VlLs': break;
-                       case 'doub': break;
-                       case 'UntF': break;
-
-                       case 'TEXT':
-                               {
-                                       item.text_text = stream.read_unicode_string();
-                               }
-                               break;
-                       case 'enum':
-                               {
-                                       item.enum_key = stream.read_id_string();
-                                       item.enum_val = stream.read_id_string();
-                               }
-                               break;
-
-                       case 'long':
-                               {
-                                       item.long_value = stream.read_long();
-                               }
-                               break;
-
-                       case 'bool': break;
-                       case 'GlbO': break;
-                       case 'type':
-                       case 'GlbC':
-                               break;
-                       case 'alis': break;
-
-                       case 'tdta':
-                               {
-                                       unsigned long rawdata_length = stream.read_long();
-                                       item.rawdata_data.resize(rawdata_length);
-                                       stream.read(item.rawdata_data.data(), rawdata_length);                          
-                               }
-                               break;
-
-                       default:
-                               //descriptor type not supported yet
-                               throw PSDFileFormatException();
-                       }
-
-                       items_.insert(std::pair<std::wstring, descriptor_item>(key, item));
+                       read_value(key, stream);
                }
        }
        catch(std::exception& ex)
@@ -107,5 +80,82 @@ bool descriptor::populate(BEFileInputStream& stream)
        return result;
 }
 
+void descriptor::read_value(const std::wstring& key, BEFileInputStream& stream)
+{
+       unsigned int type = stream.read_long();
+
+       switch(type)
+       {
+       case 'Objc': 
+               {
+                       descriptor desc(key, context_);
+                       desc.populate(stream);
+               }
+               break;
+
+       case 'doub': 
+               {
+                       context_->stack.back()->put(key, stream.read_double());
+               }
+               break;
+
+       case 'TEXT':
+               {
+                       context_->stack.back()->put(key, stream.read_unicode_string());
+               }
+               break;
+
+       case 'enum':
+               {
+                       context_->stack.back()->put(stream.read_id_string(), stream.read_id_string());
+               }
+               break;
+
+       case 'long':
+               {
+                       context_->stack.back()->put(key, stream.read_long());
+               }
+               break;
+
+       case 'bool': 
+               {
+                       context_->stack.back()->put(key, stream.read_byte());
+               }
+               break;
+
+       case 'VlLs': 
+               {
+                       context::scoped_holder list(key, context_);
+                       unsigned long count = stream.read_long();
+                       for(int i = 0; i < count; ++i)
+                       {
+                               read_value(L"", stream);
+                       }
+               }
+               break;
+
+       case 'tdta':
+               {
+                       unsigned long rawdata_length = stream.read_long();
+                       std::vector<char> rawdata(rawdata_length);
+                       stream.read(rawdata.data(), rawdata_length);
+
+                       std::wstring data_str(rawdata.begin(), rawdata.end());
+                       context_->stack.back()->put(key, data_str);
+               }
+               break;
+
+       case 'obj ': 
+       case 'UntF': 
+       case 'GlbO': 
+       case 'type':
+       case 'GlbC':
+       case 'alis':
+       default:
+               //descriptor type not supported yet
+               throw PSDFileFormatException();
+       }
+}
+
 }      //namespace psd
 }      //namespace caspar
\ No newline at end of file
index fb2d0f4ca73265480af9316f5e087cd9aa6d2ed8..968e47f624ffca540b41212e6e53ba591cd3cc87 100644 (file)
 #include <map>
 #include <string>
 #include <memory>
+#include <boost\property_tree\ptree.hpp>
 #include "util\bigendian_file_input_stream.h"
 
 namespace caspar { namespace psd {
 
-       struct descriptor_item
-       {
-               unsigned long type;
+       //struct descriptor_item
+       //{
+       //      unsigned long type;
 
-               std::wstring enum_key;
-               std::wstring enum_val;
+       //      std::wstring enum_key;
+       //      std::wstring enum_val;
 
-               std::wstring text_text;
+       //      std::wstring text_text;
 
-               unsigned long long_value;
-               
-               std::vector<char> rawdata_data;
-       };
+       //      unsigned long long_value;
+       //      
+       //      std::vector<char> rawdata_data;
+       //};
 
 class descriptor
 {
-       typedef std::map<std::wstring, descriptor_item> items_map;
+       typedef boost::property_tree::wptree Ptree;
+       struct context
+       {
+               typedef std::shared_ptr<context> ptr_type;
+
+               Ptree root;
+               std::vector<Ptree *> stack;
+
+               friend descriptor;
+               friend class scoped_holder;
+               class scoped_holder;
+       };
+       friend class context::scoped_holder;
+
+       descriptor(const descriptor&);
+       const descriptor& operator=(const descriptor&);
+       explicit descriptor(const std::wstring& key, context::ptr_type context);
 
 public:
+       descriptor();
+       ~descriptor();
+
        bool populate(BEFileInputStream& stream);
-       const descriptor_item& get_item(const std::wstring& key) const;
-       bool has_item(const std::wstring& key) const;
+       Ptree& items() const { return context_->root; }
 private:
-       items_map items_;
+       void read_value(const std::wstring& key, BEFileInputStream& stream);
+       context::ptr_type context_;
 };
 
 }      //namespace psd
index fbfd2d2b945d8985453bcc98a1939a90e81f6b4b..46cb3cd109c2822b022d56418451cdbc3efcd145 100644 (file)
@@ -20,6 +20,7 @@
 */
 
 #include "doc.h"
+#include "descriptor.h"
 #include <iostream>
 
 namespace caspar { namespace psd {
@@ -93,70 +94,89 @@ void psd_document::read_image_resources()
                                std::wstring name = input_.read_pascal_string(2);
 
                                unsigned long resource_length = input_.read_long();
+                               unsigned long end_of_chunk = input_.current_position() + resource_length;
 
-                               //TODO: read actual data
-                               switch(resource_id)
+                               try
                                {
-                               case 1026:              //layer group information. describes linked layers
+                                       //TODO: read actual data
+                                       switch(resource_id)
                                        {
-                                               int layer_count = resource_length / 2;
-                                               for(int i = 0; i < layer_count; ++i)
+                                       case 1026:              //layer group information. describes linked layers
                                                {
-                                                       short id = input_.read_short();
+                                                       int layer_count = resource_length / 2;
+                                                       for(int i = 0; i < layer_count; ++i)
+                                                       {
+                                                               short id = input_.read_short();
 
-                                                       if(i == layers_.size())
-                                                               layers_.push_back(std::make_shared<layer>());
+                                                               if(i == layers_.size())
+                                                                       layers_.push_back(std::make_shared<layer>());
 
-                                                       layers_[i]->set_link_group_id(id);
-                                               }
+                                                               layers_[i]->set_link_group_id(id);
+                                                       }
 
-                                       }
-                                       break;
-
-                               case 1005:
-                                       {       
-                                               ////resolutionInfo
-                                               //struct ResolutionInfo
-                                               //{
-                                               //Fixed hRes;
-                                               //int16 hResUnit;
-                                               //int16 widthUnit;
-                                               //Fixed vRes;
-                                               //int16 vResUnit;
-                                               //int16 heightUnit;
-                                               //};
-                                       }
-                               case 1006:              //names of alpha channels
-                               case 1008:              //caption
-                               case 1010:              //background color
-                               case 1024:              //layer state info (2 bytes containing the index of target layer (0 = bottom layer))
-                               case 1028:              //IPTC-NAA. File Info...
-                               case 1029:              //image for raw format files
-                               case 1036:              //thumbnail resource
-                               case 1045:              //unicode Alpha names (Unicode string (4 bytes length followed by string))
-                               case 1053:              //alpha identifiers (4 bytes of length, followed by 4 bytes each for every alpha identifier.)
-                               case 1060:              //XMP metadata
-                               case 1065:              //layer comps
-                               case 1069:              //layer selection ID(s)
-                               case 1072:              //layer group(s) enabled id
-                               case 1075:              //timeline information
-                               case 1077:              //DisplayInfo
-                               case 2999:              //name of clipping path
-                               default:
-                                       {
-                                               if(resource_id >= 2000 && resource_id <=2997)   //path information
+                                               }
+                                               break;
+                                       case 1075:              //timeline information
                                                {
+                                                       int desc_ver = input_.read_long();      //descriptor version, should be 16
+                                                       descriptor timeline_descriptor;
+                                                       if(!timeline_descriptor.populate(input_))
+                                                               throw PSDFileFormatException();
+                                                       else
+                                                       {
+                                                               timeline_desc_.swap(timeline_descriptor.items());
+                                                       }
                                                }
-                                               else if(resource_id >= 4000 && resource_id <= 4999)     //plug-in resources
+                                               break;
+
+                                       case 1005:
+                                               {       
+                                                       ////resolutionInfo
+                                                       //struct ResolutionInfo
+                                                       //{
+                                                       //Fixed hRes;
+                                                       //int16 hResUnit;
+                                                       //int16 widthUnit;
+                                                       //Fixed vRes;
+                                                       //int16 vResUnit;
+                                                       //int16 heightUnit;
+                                                       //};
+                                               }
+                                       case 1006:              //names of alpha channels
+                                       case 1008:              //caption
+                                       case 1010:              //background color
+                                       case 1024:              //layer state info (2 bytes containing the index of target layer (0 = bottom layer))
+                                       case 1028:              //IPTC-NAA. File Info...
+                                       case 1029:              //image for raw format files
+                                       case 1036:              //thumbnail resource
+                                       case 1045:              //unicode Alpha names (Unicode string (4 bytes length followed by string))
+                                       case 1053:              //alpha identifiers (4 bytes of length, followed by 4 bytes each for every alpha identifier.)
+                                       case 1060:              //XMP metadata
+                                       case 1065:              //layer comps
+                                       case 1069:              //layer selection ID(s)
+                                       case 1072:              //layer group(s) enabled id
+                                       case 1077:              //DisplayInfo
+                                       case 2999:              //name of clipping path
+                                       default:
                                                {
+                                                       if(resource_id >= 2000 && resource_id <=2997)   //path information
+                                                       {
+                                                       }
+                                                       else if(resource_id >= 4000 && resource_id <= 4999)     //plug-in resources
+                                                       {
+                                                       }
                                                }
+                                               input_.discard_bytes(resource_length);
+                                               break;
                                        }
-                                       input_.discard_bytes(resource_length);
-                                       break;
-                               }
 
-                               if(resource_length & 1 == 1)    //each resource is padded to an even amount of bytes
-                                       input_.discard_bytes(1);
+                                       if(resource_length & 1 == 1)    //each resource is padded to an even amount of bytes
+                                               input_.discard_bytes(1);
+                               }
+                               catch(PSDFileFormatException&)
+                               {
+                                       input_.set_position(end_of_chunk);
+                               }
                        }
                }
                catch(PSDFileFormatException& ex)
index d382b7193146c233044e1c94da7363782fadd944..762d283a36b977e9021490c90ee790e82b963d8a 100644 (file)
@@ -68,6 +68,14 @@ public:
        {
                return filename_;
        }
+       bool has_timeline() const
+       {
+               return !timeline_desc_.empty();
+       }
+       const boost::property_tree::wptree& timeline() const 
+       {
+               return timeline_desc_;
+       }
 
 
        bool parse(const std::wstring& s);
@@ -78,16 +86,17 @@ private:
        void read_image_resources();
        void read_layers();
 
-       std::wstring                            filename_;
-       BEFileInputStream                       input_;
+       std::wstring                                    filename_;
+       BEFileInputStream                               input_;
 
-       std::vector<layer_ptr>          layers_;
+       std::vector<layer_ptr>                  layers_;
 
-       unsigned short                          channels_;
-       unsigned long                           width_;
-       unsigned long                           height_;
-       unsigned short                          depth_;
-       psd::color_mode                         color_mode_;
+       unsigned short                                  channels_;
+       unsigned long                                   width_;
+       unsigned long                                   height_;
+       unsigned short                                  depth_;
+       psd::color_mode                                 color_mode_;
+       boost::property_tree::wptree    timeline_desc_;
 };
 
 }      //namespace psd
index e0aca51a95342dfe64761c3d47af33e1049866bc..fc9be9794bc92671fd5f18d829b72665052362ac 100644 (file)
@@ -82,64 +82,130 @@ void layer::populate(BEFileInputStream& stream)
        name_ = stream.read_pascal_string(4);
 
        //Aditional Layer Information
-       unsigned long end_of_layer_info = position1 + extraDataSize;
+       long end_of_layer_info = position1 + extraDataSize;
        
        try
        {
                while(stream.current_position() < end_of_layer_info)
                {
-                       unsigned long signature = stream.read_long();
-                       if(signature != '8BIM' && signature != '8B64')
-                               throw PSDFileFormatException();
+                       read_chunk(stream);
+               }
+       }
+       catch(PSDFileFormatException&)
+       {
+               stream.set_position(end_of_layer_info);
+       }
+}
 
-                       unsigned long key = stream.read_long();
-                       unsigned long length = stream.read_long();
-                       unsigned long end_of_chunk = stream.current_position() + length;
+void layer::read_chunk(BEFileInputStream& stream, bool isMetadata)
+{
+       unsigned long signature = stream.read_long();
+       if(signature != '8BIM' && signature != '8B64')
+               throw PSDFileFormatException();
 
-                       if(key == 'lspf')
-                       {
-                               protection_flags_ = stream.read_long();
-                       }
-                       else if(key == 'TySh')  //type tool object settings
-                       {
-                               std::wstring text;      //the text in the layer
+       unsigned long key = stream.read_long();
+       
+       if(isMetadata) stream.read_long();
 
-                               stream.read_short();    //should be 1
-                               stream.discard_bytes(6*8);      //just throw transformation info for now
-                               stream.read_short();    //"text version" should be 50
-                               stream.read_long();             //"descriptor version" should be 16
+       unsigned long length = stream.read_long();
+       unsigned long end_of_chunk = stream.current_position() + length;
 
-                               //text data descriptor ('descriptor structure')
-                               descriptor text_descriptor;
-                               if(!text_descriptor.populate(stream))
-                                       throw PSDFileFormatException();
-                               else
-                               {
-                                       if(text_descriptor.has_item(L"EngineData"))
-                                       {
-                                               const descriptor_item& text_data = text_descriptor.get_item(L"EngineData");
-                                               read_pdf(text_layer_info_, text_data.rawdata_data);
-                                       }
-                               }
-
-                               stream.read_short();    //"warp version" should be 1
-                               stream.read_long();             //"descriptor version" should be 16
-
-                               //warp data descriptor ('descriptor structure')
-                               descriptor warp_descriptor;
-                               if(!text_descriptor.populate(stream))
-                                       throw PSDFileFormatException();
+       try
+       {
+               switch(key)
+               {
+               case 'lspf':    //protection settings
+                       protection_flags_ = stream.read_long();
+                       break;
+
+               case 'Txt2':    //text engine data
+                       break;
+
+               case 'TySh':    //type tool object settings
+                       read_text_data(stream);
+                       break;
+                               
+               case 'shmd':    //metadata
+                       read_metadata(stream);
+                       break;
+                               
+               case 'lyvr':    //layer version
+                       break;
+
+               case 'lnkD':    //linked layer
+               case 'lnk2':    //linked layer
+               case 'lnk3':    //linked layer
+                       break;
+                               
+               case 'tmln':
+                       read_timeline_data(stream);
+                       break;
+
+               default:
+                       break;
+               }
+       }
+       catch(PSDFileFormatException&)
+       {
+               //ignore failed chunks silently
+       }
 
-                               stream.discard_bytes(4*8);      //top, left, right, bottom
-                       }
+       stream.set_position(end_of_chunk);
+}
 
-                       stream.set_position(end_of_chunk);
-               }
+void layer::read_metadata(BEFileInputStream& stream)
+{
+       unsigned long count = stream.read_long();
+       for(int index = 0; index < count; ++index)
+               read_chunk(stream, true);
+}
+
+void layer::read_timeline_data(BEFileInputStream& stream)
+{
+       stream.read_long();                                     //"descriptor version" should be 16
+       descriptor timeline_descriptor;
+       if(!timeline_descriptor.populate(stream))
+               throw PSDFileFormatException();
+       else
+       {
+               timeline_info_.swap(timeline_descriptor.items());
        }
-       catch(PSDFileFormatException& ex)
+}
+
+void layer::read_text_data(BEFileInputStream& stream)
+{
+       std::wstring text;      //the text in the layer
+
+       stream.read_short();    //should be 1
+       stream.discard_bytes(6*8);      //just throw transformation info for now
+       stream.read_short();    //"text version" should be 50
+
+       //text data descriptor ('descriptor structure')
+       if(stream.read_long() != 16)    //"descriptor version" should be 16
+               throw PSDFileFormatException();
+
+       descriptor text_descriptor;
+       if(!text_descriptor.populate(stream))
+               throw PSDFileFormatException();
+       else
        {
-               stream.set_position(end_of_layer_info);
+               auto text_info = text_descriptor.items().get_optional<std::wstring>(L"EngineData");
+               if(text_info.is_initialized())
+               {
+                       std::string str(text_info.get().begin(), text_info.get().end());
+                       read_pdf(text_layer_info_, str);
+               }
        }
+
+       stream.read_short();    //"warp version" should be 1
+
+       //warp data descriptor ('descriptor structure')
+       stream.read_long();                                     //"descriptor version" should be 16
+       descriptor warp_descriptor;
+       if(!warp_descriptor.populate(stream))
+               throw PSDFileFormatException();
+       else
+               stream.discard_bytes(4*8);      //top, left, right, bottom
 }
 
 void layer::layer_mask::read_mask_data(BEFileInputStream& stream)
@@ -181,6 +247,11 @@ bool layer::is_text() const
 {
        return !text_layer_info_.empty();
 }
+bool layer::has_timeline() const
+{
+       return !timeline_info_.empty();
+}
+
 
 //TODO: implement
 void layer::read_blending_ranges(BEFileInputStream& stream)
index fe2c339a1ea5bf2f080e7a9d7a6e47f7b3bcbb3f..ebffbaf8781323f128975ca00954cef2738b91cf 100644 (file)
@@ -47,9 +47,9 @@ public:
                friend class layer;
        public:
 
-               bool enabled() { return (flags_ & 2) == 0; }
-               bool linked() { return (flags_ & 1) == 0;  }
-               bool inverted() { return (flags_ & 4) == 4; }
+               bool enabled() const { return (flags_ & 2) == 0; }
+               bool linked() const { return (flags_ & 1) == 0;  }
+               bool inverted() const { return (flags_ & 4) == 4; }
 
                void read_mask_data(BEFileInputStream&);
 
@@ -88,9 +88,12 @@ public:
 
        bool visible() { return (flags_ & 2) == 0; }    //the (PSD file-format) documentation is is saying the opposite but what the heck
        bool is_position_protected() { return (protection_flags_& 4) == 4; }
+       int     protection_flags() const { return protection_flags_; }
        bool is_text() const;
+       bool has_timeline() const;
 
        const boost::property_tree::wptree& text_data() const { return text_layer_info_; }
+       const boost::property_tree::wptree& timeline_data() const { return timeline_info_; }
 
        const image8bit_ptr& image() const { return image_; }
 
@@ -102,7 +105,11 @@ public:
 
 private:
        channel_ptr get_channel(channel_type);
+       void read_chunk(BEFileInputStream& stream, bool isMetadata = false);
        void read_blending_ranges(BEFileInputStream&);
+       void read_text_data(BEFileInputStream&);
+       void read_metadata(BEFileInputStream& stream);
+       void read_timeline_data(BEFileInputStream&);
 
        caspar::psd::rect<long>                 rect_;
        std::vector<channel_ptr>                channels_;
@@ -120,6 +127,7 @@ private:
        image8bit_ptr                                   image_;
 
        boost::property_tree::wptree    text_layer_info_;
+       boost::property_tree::wptree    timeline_info_;
 };
 
 }      //namespace psd
index fabb6ea88516995d1ac0646888457ba2481d55b7..70848fce2f7268691d238a5e6792a0437f325cfc 100644 (file)
@@ -81,6 +81,14 @@ unsigned long BEFileInputStream::read_long()
 
        return SWAP32(in);
 }
+double BEFileInputStream::read_double()
+{
+       char data[8];
+       for(int i = 0; i < 8; ++i)
+               data[7-i] = read_byte();
+
+       return *reinterpret_cast<double*>(data);
+}
 
 void BEFileInputStream::read(char* buf, unsigned long length)
 {
index 41020f867a76064255d71b0aa70f6d270bf7e85a..9a225694a44a174e98336841d283c78f70396493 100644 (file)
@@ -66,6 +66,7 @@ public:
        std::wstring read_pascal_string(unsigned char padding = 1);
        std::wstring read_unicode_string();
        std::wstring read_id_string();
+       double read_double();
 
        void discard_bytes(unsigned long);
        void discard_to_next_word();
index 45c73988b0a7ff26dc3549bdea127678b55decff..6bd926c21b5caa6792247ea430edb56e8accf9bf 100644 (file)
@@ -245,17 +245,17 @@ struct pdf_grammar : qi::grammar<Iterator, qi::space_type>
        };
 };
 
-bool read_pdf(boost::property_tree::wptree& tree, const std::vector<char>& v)
+bool read_pdf(boost::property_tree::wptree& tree, const std::string& s)
 {
-       typedef std::vector<char>::const_iterator iterator_type;
+       typedef std::string::const_iterator iterator_type;
 
        pdf_grammar<iterator_type> g;
        bool result = false;
        
        try
        {
-               auto it = v.begin();
-               result = qi::phrase_parse(it, v.end(), g, qi::space);
+               auto it = s.begin();
+               result = qi::phrase_parse(it, s.end(), g, qi::space);
                if(result)
                        tree.swap(g.context.root);
        }
index 8ca71e09741262e5a78af9199d6859aafb6fa13f..ba86508518ea2dbe70deb7f1bb605019cf42ea6b 100644 (file)
 #pragma once
 
 #include <boost/property_tree/ptree.hpp>
-#include <vector>
+#include <string>
 
 namespace caspar { namespace psd { 
 
-bool read_pdf(boost::property_tree::wptree& tree, const std::vector<char>& v);
+bool read_pdf(boost::property_tree::wptree& tree, const std::string& s);
 
 }      //namespace psd
 }      //namespace caspar
\ No newline at end of file
index c42b6eba4a95f157876e609db2bd2a81588eadd3..721f9a31b5ef0cfe1c479eb1ff12c1471d89bd56 100644 (file)
 
 int _tmain(int argc, _TCHAR* argv[])
 {
-       caspar::psd::psd_document doc;
-       doc.parse(L"C:\\Lokala Filer\\Utveckling\\CasparCG\\Server 2.1\\shell\\media\\test1.psd");
-
-       std::wstringstream trace;
-
-       trace << L"<doc filename='" << doc.filename() << L"' color_mode='" << caspar::psd::color_mode_to_string(doc.color_mode()) << L"' color_depth='" << doc.color_depth() << L"' channel_count='" << doc.channels_count() << L"' width='" << doc.width() << L"' height='" << doc.height() << L"'>" << std::endl;
-       
-       auto end = doc.layers().end();
-       for(auto it = doc.layers().begin(); it != end; ++it)
+       if(argc > 1)
        {
-               caspar::psd::layer_ptr layer = (*it);
-               trace << L"     <layer name='" << layer->name() << L"' opacity='" << layer->opacity() << L"' flags='" << std::hex << layer->flags() << std::dec << "'>" << std::endl;
-               if(layer->image())
-                       trace << L"             <bounding-box left='" << layer->rect().left << "' top='" << layer->rect().top << "' right='" << layer->rect().right << "' bottom='" << layer->rect().bottom << "' />" << std::endl;
-               if(layer->mask())
-                       trace << L"             <mask default-value='" << layer->mask_info().default_value_ << "' flags='" <<  std::hex << (unsigned short) layer->mask_info().flags_ << std::dec << "' left='" << layer->mask_info().rect_.left << "' top='" << layer->mask_info().rect_.top << "' right='" << layer->mask_info().rect_.right << "' bottom='" << layer->mask_info().rect_.bottom << "' />" << std::endl;
-               if(layer->is_text())
+               caspar::psd::psd_document doc;
+               if(doc.parse(argv[1]))
                {
-                       boost::property_tree::xml_writer_settings<wchar_t> w(' ', 3);
-                       boost::property_tree::write_xml(trace, (*it)->text_data(), w);
-               }
-               trace << L"     </layer>" << std::endl;
-       }
+                       std::wstringstream trace;
 
-       trace << L"</doc>" << std::endl;
+                       trace << L"<doc filename='" << doc.filename() << L"' color_mode='" << caspar::psd::color_mode_to_string(doc.color_mode()) << L"' color_depth='" << doc.color_depth() << L"' channel_count='" << doc.channels_count() << L"' width='" << doc.width() << L"' height='" << doc.height() << L"'>" << std::endl;
        
-       std::ofstream log("psd-log.txt");
-       log << caspar::u8(trace.str());
-       std::cout << caspar::u8(trace.str());
+                       auto end = doc.layers().end();
+                       for(auto it = doc.layers().begin(); it != end; ++it)
+                       {
+                               caspar::psd::layer_ptr layer = (*it);
+                               trace << L"     <layer name='" << layer->name() << L"' opacity='" << layer->opacity() << L"' visible='" << layer->visible() << L"' protection-flags='" << std::hex << layer->protection_flags() << std::dec << L"'>" << std::endl;
+                               //if(layer->image())
+                               //      trace << L"             <bounding-box left='" << layer->rect().left << L"' top='" << layer->rect().top << L"' right='" << layer->rect().right << L"' bottom='" << layer->rect().bottom << L"' />" << std::endl;
+                               //if(layer->mask())
+                               //      trace << L"             <mask default-value='" << layer->mask_info().default_value_ << L"' enabled=" << layer->mask_info().enabled() << L" linked=" << layer->mask_info().linked() << L" inverted=" << layer->mask_info().inverted() << L" left='" << layer->mask_info().rect_.left << L"' top='" << layer->mask_info().rect_.top << "' right='" << layer->mask_info().rect_.right << "' bottom='" << layer->mask_info().rect_.bottom << "' />" << std::endl;
+                               if(layer->is_text())
+                               {
+                                       trace << L"                     <text value='" << (*it)->text_data().get(L"EngineDict.Editor.Text", L"") << L"' />" << std::endl;
+                                       //boost::property_tree::xml_writer_settings<wchar_t> w(' ', 3);
+                                       //boost::property_tree::write_xml(trace, (*it)->text_data(), w);
+                               }
+                               if(layer->has_timeline())
+                               {
+                                       trace << L"                     <timeline>" << std::endl;
+                                       boost::property_tree::xml_writer_settings<wchar_t> w(' ', 3);
+                                       boost::property_tree::write_xml(trace, (*it)->timeline_data(), w);
+                                       trace << L"                     </timeline>" << std::endl;
+                               }
+                               trace << L"     </layer>" << std::endl;
+                       }
+
+                       trace << L"</doc>" << std::endl;
        
+                       std::ofstream log("psd-log.txt");
+                       log << caspar::u8(trace.str());
+                       std::cout << caspar::u8(trace.str());
+               }
+       }
        return 0;
 }