PageRenderTime 42ms CodeModel.GetById 14ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/Platters/classes/photoshop/Layer.cs

http://skimpt.googlecode.com/
C# | 968 lines | 592 code | 212 blank | 164 comment | 36 complexity | 0f1c85b34ef98cbbeeab9424e61d17d7 MD5 | raw file
  1/////////////////////////////////////////////////////////////////////////////////
  2// Copyright (C) 2006, Frank Blumenberg
  3// 
  4// See License.txt for complete licensing and attribution information.
  5// Permission is hereby granted, free of charge, to any person obtaining a copy 
  6// of this software and associated documentation files (the "Software"), to deal
  7// in the Software without restriction, including without limitation the rights
  8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
  9// copies of the Software, and to permit persons to whom the Software is 
 10// furnished to do so, subject to the following conditions:
 11// 
 12// The above copyright notice and this permission notice shall be included in all
 13// copies or substantial portions of the Software.
 14// 
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 21// THE SOFTWARE.
 22// 
 23/////////////////////////////////////////////////////////////////////////////////
 24
 25/////////////////////////////////////////////////////////////////////////////////
 26//
 27// This code contains code from the Endogine sprite engine by Jonas Beckeman.
 28// http://www.endogine.com/CS/
 29//
 30/////////////////////////////////////////////////////////////////////////////////
 31
 32using System;
 33using System.Collections.Generic;
 34using System.Collections.Specialized;
 35using System.Text;
 36using System.Drawing;
 37using System.IO;
 38using System.Diagnostics;
 39
 40namespace Photoshop
 41{
 42  public class Layer
 43  {
 44    ///////////////////////////////////////////////////////////////////////////
 45
 46    public class Channel
 47    {
 48      private Layer m_layer;
 49      /// <summary>
 50      /// The layer to which this channel belongs
 51      /// </summary>
 52      public Layer Layer
 53      {
 54        get { return m_layer; }
 55      }
 56
 57
 58      private short m_id;
 59      /// <summary>
 60      /// 0 = red, 1 = green, etc.
 61      /// &#x2013;1 = transparency mask
 62      /// &#x2013;2 = user supplied layer mask
 63      /// </summary>
 64      public short ID
 65      {
 66        get { return m_id; }
 67        set { m_id = value; }
 68      }
 69
 70      /// <summary>
 71      /// The length of the compressed channel data.
 72      /// </summary>
 73      public int Length;
 74
 75      private byte[] m_data;
 76      /// <summary>
 77      /// The compressed raw channel data
 78      /// </summary>
 79      public byte[] Data
 80      {
 81        get { return m_data; }
 82        set { m_data = value; }
 83      }
 84
 85      /// <summary>
 86      /// The raw image data from the channel.
 87      /// </summary>
 88      public byte[] m_imageData;
 89
 90      public byte[] ImageData
 91      {
 92        get { return m_imageData; }
 93        set { m_imageData = value; }
 94      }
 95
 96      private ImageCompression m_imageCompression;
 97      public ImageCompression ImageCompression
 98      {
 99        get { return m_imageCompression; }
100        set { m_imageCompression = value; }
101      }
102
103      //////////////////////////////////////////////////////////////////
104
105      internal Channel(short id, Layer layer)
106      {
107        m_id = id;
108        m_layer = layer;
109        m_layer.Channels.Add(this);
110        m_layer.SortedChannels.Add(this.ID, this);
111      }
112
113      internal Channel(BinaryReverseReader reader, Layer layer)
114      {
115        Debug.WriteLine("Channel started at " + reader.BaseStream.Position.ToString());
116        
117        m_id = reader.ReadInt16();
118        Length = reader.ReadInt32();
119
120        m_layer = layer;
121      }
122
123      internal void Save(BinaryReverseWriter writer)
124      {
125        Debug.WriteLine("Channel Save started at " + writer.BaseStream.Position.ToString());
126
127        writer.Write(m_id);
128
129        CompressImageData();
130
131        writer.Write(Data.Length+2); // 2 bytes for the image compression
132      }
133
134      //////////////////////////////////////////////////////////////////
135
136      internal void LoadPixelData(BinaryReverseReader reader)
137      {
138        Debug.WriteLine("Channel.LoadPixelData started at " + reader.BaseStream.Position.ToString());
139
140        m_data = reader.ReadBytes((int)Length);
141
142        using (BinaryReverseReader readerImg = DataReader)
143        {
144          m_imageCompression = (ImageCompression)readerImg.ReadInt16();
145
146          int bytesPerRow = 0;
147
148          switch (m_layer.PsdFile.Depth)
149          {
150            case 1:
151              bytesPerRow = m_layer.m_rect.Width;//NOT Shure
152              break;
153            case 8:
154              bytesPerRow = m_layer.m_rect.Width;
155              break;
156            case 16:
157              bytesPerRow = m_layer.m_rect.Width * 2;
158              break;
159          }
160
161          m_imageData = new byte[m_layer.m_rect.Height * bytesPerRow];
162
163          switch (m_imageCompression)
164          {
165            case ImageCompression.Raw:
166              readerImg.Read(m_imageData, 0, m_imageData.Length);
167              break;
168            case ImageCompression.Rle:
169              {
170                int[] rowLenghtList = new int[m_layer.m_rect.Height];
171                for (int i = 0; i < rowLenghtList.Length; i++)
172                  rowLenghtList[i] = readerImg.ReadInt16();
173
174                for (int i = 0; i < m_layer.m_rect.Height; i++)
175                {
176                  int rowIndex = i * m_layer.m_rect.Width;
177                  RleHelper.DecodedRow(readerImg.BaseStream, m_imageData, rowIndex, bytesPerRow);
178
179                  //if (rowLenghtList[i] % 2 == 1)
180                  //  readerImg.ReadByte();
181                }
182              }
183              break;
184            default:
185              break;
186          }
187        }
188      }
189
190      private void CompressImageData()
191      {
192        if (m_imageCompression == ImageCompression.Rle)
193        {
194          MemoryStream dataStream = new MemoryStream();
195          BinaryReverseWriter writer = new BinaryReverseWriter(dataStream);
196
197          // we will write the correct lengths later, so remember 
198          // the position
199          long lengthPosition = writer.BaseStream.Position;
200
201          int[] rleRowLenghs = new int[m_layer.m_rect.Height];
202
203          if (m_imageCompression == ImageCompression.Rle)
204          {
205            for (int i = 0; i < rleRowLenghs.Length; i++)
206            {
207              writer.Write((short)0x1234);
208            }
209          }
210
211          //---------------------------------------------------------------
212
213          int bytesPerRow = 0;
214
215          switch (m_layer.PsdFile.Depth)
216          {
217            case 1:
218              bytesPerRow = m_layer.m_rect.Width;//NOT Shure
219              break;
220            case 8:
221              bytesPerRow = m_layer.m_rect.Width;
222              break;
223            case 16:
224              bytesPerRow = m_layer.m_rect.Width * 2;
225              break;
226          }
227
228          //---------------------------------------------------------------
229
230          for (int row = 0; row < m_layer.m_rect.Height; row++)
231          {
232            int rowIndex = row * m_layer.m_rect.Width;
233            rleRowLenghs[row] = RleHelper.EncodedRow(writer.BaseStream, m_imageData, rowIndex, bytesPerRow);
234          }
235
236          //---------------------------------------------------------------
237
238          long endPosition = writer.BaseStream.Position;
239
240          writer.BaseStream.Position = lengthPosition;
241
242          for (int i = 0; i < rleRowLenghs.Length; i++)
243          {
244            writer.Write((short)rleRowLenghs[i]);
245          }
246
247          writer.BaseStream.Position = endPosition;
248
249          dataStream.Close();
250
251          m_data = dataStream.ToArray();
252
253          dataStream.Dispose();
254
255        }
256        else
257        {
258          m_data = (byte[])m_imageData.Clone();
259        }
260      }
261
262      internal void SavePixelData(BinaryReverseWriter writer)
263      {
264        Debug.WriteLine("Channel SavePixelData started at " + writer.BaseStream.Position.ToString());
265
266        writer.Write((short)m_imageCompression);
267        writer.Write(m_imageData);
268      }
269
270      //////////////////////////////////////////////////////////////////
271
272      public BinaryReverseReader DataReader
273      {
274        get
275        {
276          if (m_data == null)
277            return null;
278
279          return new BinaryReverseReader(new System.IO.MemoryStream(this.m_data));
280        }
281      }
282    }
283
284    ///////////////////////////////////////////////////////////////////////////
285
286    public class Mask
287    {
288      private Layer m_layer;
289      /// <summary>
290      /// The layer to which this mask belongs
291      /// </summary>
292      public Layer Layer
293      {
294        get { return m_layer; }
295      }
296
297      private Rectangle m_rect = Rectangle.Empty;
298      /// <summary>
299      /// The rectangle enclosing the mask.
300      /// </summary>
301      public Rectangle Rect
302      {
303        get { return m_rect; }
304        set { m_rect = value; }
305      }
306
307      private byte m_defaultColor;
308      public byte DefaultColor
309      {
310        get { return m_defaultColor; }
311        set { m_defaultColor = value; }
312      }
313
314
315      private static  int m_positionIsRelativeBit = BitVector32.CreateMask();
316      private static int m_disabledBit = BitVector32.CreateMask(m_positionIsRelativeBit);
317      private static int m_invertOnBlendBit = BitVector32.CreateMask(m_disabledBit);
318
319      private BitVector32 m_flags = new BitVector32();
320      /// <summary>
321      /// If true, the position of the mask is relative to the layer.
322      /// </summary>
323      public bool PositionIsRelative
324      {
325        get
326        {
327          return m_flags[m_positionIsRelativeBit];
328        }
329        set
330        {
331          m_flags[m_positionIsRelativeBit] = value;
332        }
333      }
334
335      public bool Disabled
336      {
337        get { return m_flags[m_disabledBit]; }
338        set { m_flags[m_disabledBit] = value; }
339      }
340
341      /// <summary>
342      /// if true, invert the mask when blending.
343      /// </summary>
344      public bool InvertOnBlendBit
345      {
346        get { return m_flags[m_invertOnBlendBit]; }
347        set { m_flags[m_invertOnBlendBit] = value; }
348      }
349
350      ///////////////////////////////////////////////////////////////////////////
351
352      internal Mask(Layer layer)
353      {
354        m_layer = layer;
355        m_layer.MaskData = this;
356      }
357
358      ///////////////////////////////////////////////////////////////////////////
359
360      internal Mask(BinaryReverseReader reader, Layer layer)
361      {
362        Debug.WriteLine("Mask started at " + reader.BaseStream.Position.ToString());
363
364        m_layer = layer;
365
366        uint maskLength = reader.ReadUInt32();
367
368        if (maskLength <= 0)
369          return;
370
371        long startPosition = reader.BaseStream.Position;
372
373        //-----------------------------------------------------------------------
374
375        m_rect = new Rectangle();
376        m_rect.Y = reader.ReadInt32();
377        m_rect.X = reader.ReadInt32();
378        m_rect.Height = reader.ReadInt32() - m_rect.Y;
379        m_rect.Width = reader.ReadInt32() - m_rect.X;
380
381        m_defaultColor = reader.ReadByte();
382
383        //-----------------------------------------------------------------------
384
385        byte flags = reader.ReadByte();
386        m_flags = new BitVector32(flags);
387
388        //-----------------------------------------------------------------------
389
390        if (maskLength == 36)
391        {
392          BitVector32 realFlags = new BitVector32(reader.ReadByte());
393
394          byte realUserMaskBackground = reader.ReadByte();
395
396          Rectangle rect = new Rectangle();
397          rect.Y = reader.ReadInt32();
398          rect.X = reader.ReadInt32();
399          rect.Height = reader.ReadInt32() - m_rect.Y;
400          rect.Width = reader.ReadInt32() - m_rect.X;
401        }
402
403
404        // there is other stuff following, but we will ignore this.
405        reader.BaseStream.Position = startPosition + maskLength;
406      }
407
408      ///////////////////////////////////////////////////////////////////////////
409
410      public void Save(BinaryReverseWriter writer)
411      {
412        Debug.WriteLine("Mask Save started at " + writer.BaseStream.Position.ToString());
413
414        if (m_rect.IsEmpty)
415        {
416          writer.Write((uint)0);
417          return;
418        }
419
420        using (new LengthWriter(writer))
421        {
422          writer.Write(m_rect.Top);
423          writer.Write(m_rect.Left);
424          writer.Write(m_rect.Bottom);
425          writer.Write(m_rect.Right);
426
427          writer.Write(m_defaultColor);
428
429          writer.Write((byte)m_flags.Data);
430
431          // padding 2 bytes so that size is 20
432          writer.Write((int)0);
433        }
434      }
435
436      //////////////////////////////////////////////////////////////////
437
438      /// <summary>
439      /// The raw image data from the channel.
440      /// </summary>
441      public byte[] m_imageData;
442
443      public byte[] ImageData
444      {
445        get { return m_imageData; }
446        set { m_imageData = value; }
447      }
448
449      internal void LoadPixelData(BinaryReverseReader reader)
450      {
451        Debug.WriteLine("Mask.LoadPixelData started at " + reader.BaseStream.Position.ToString());
452
453        if (m_rect.IsEmpty || m_layer.SortedChannels.ContainsKey(-2) == false)
454          return;
455
456        Channel maskChannel = m_layer.SortedChannels[-2];
457
458
459        maskChannel.Data = reader.ReadBytes((int)maskChannel.Length);
460
461
462        using (BinaryReverseReader readerImg = maskChannel.DataReader)
463        {
464          maskChannel.ImageCompression = (ImageCompression)readerImg.ReadInt16();
465
466          int bytesPerRow = 0;
467
468          switch (m_layer.PsdFile.Depth)
469          {
470            case 1:
471              bytesPerRow = m_rect.Width;//NOT Shure
472              break;
473            case 8:
474              bytesPerRow = m_rect.Width;
475              break;
476            case 16:
477              bytesPerRow = m_rect.Width * 2;
478              break;
479          }
480
481          maskChannel.ImageData = new byte[m_rect.Height * bytesPerRow];
482          // Fill Array
483          for (int i = 0; i < maskChannel.ImageData.Length; i++)
484          {
485            maskChannel.ImageData[i] = 0xAB;
486          }
487
488          m_imageData = (byte[])maskChannel.ImageData.Clone();
489
490          switch (maskChannel.ImageCompression)
491          {
492            case ImageCompression.Raw:
493              readerImg.Read(maskChannel.ImageData, 0, maskChannel.ImageData.Length);
494              break;
495            case ImageCompression.Rle:
496              {
497                int[] rowLenghtList = new int[m_rect.Height];
498
499                for (int i = 0; i < rowLenghtList.Length; i++)
500                  rowLenghtList[i] = readerImg.ReadInt16();
501
502                for (int i = 0; i < m_rect.Height; i++)
503                {
504                  int rowIndex = i * m_rect.Width;
505                  RleHelper.DecodedRow(readerImg.BaseStream, maskChannel.ImageData, rowIndex, bytesPerRow);
506                }
507              }
508              break;
509            default:
510              break;
511          }
512
513          m_imageData = (byte[])maskChannel.ImageData.Clone();
514
515        }
516      }
517
518      internal void SavePixelData(BinaryReverseWriter writer)
519      {
520        //writer.Write(m_data);
521      }
522
523
524      ///////////////////////////////////////////////////////////////////////////
525
526    }
527
528
529    ///////////////////////////////////////////////////////////////////////////
530
531    public class BlendingRanges
532    {
533      private Layer m_layer;
534      /// <summary>
535      /// The layer to which this channel belongs
536      /// </summary>
537      public Layer Layer
538      {
539        get { return m_layer; }
540      }
541
542      private byte[] m_data = new byte[0];
543
544      public byte[] Data
545      {
546        get { return m_data; }
547        set { m_data = value; }
548      }
549
550      ///////////////////////////////////////////////////////////////////////////
551
552      public BlendingRanges(Layer layer)
553      {
554        m_layer = layer;
555        m_layer.BlendingRangesData = this;
556      }
557
558      ///////////////////////////////////////////////////////////////////////////
559
560      public BlendingRanges(BinaryReverseReader reader, Layer layer)
561      {
562        Debug.WriteLine("BlendingRanges started at " + reader.BaseStream.Position.ToString());
563
564        m_layer = layer;
565        int dataLength = reader.ReadInt32();
566        if (dataLength <= 0)
567          return;
568
569        m_data = reader.ReadBytes(dataLength);
570      }
571
572      ///////////////////////////////////////////////////////////////////////////
573
574      public void Save(BinaryReverseWriter writer)
575      {
576        Debug.WriteLine("BlendingRanges Save started at " + writer.BaseStream.Position.ToString());
577
578        writer.Write((uint)m_data.Length);
579        writer.Write(m_data);
580      }
581    }
582
583    ///////////////////////////////////////////////////////////////////////////
584
585    public class AdjusmentLayerInfo
586    {
587      private Layer m_layer;
588      /// <summary>
589      /// The layer to which this info belongs
590      /// </summary>
591      internal Layer Layer
592      {
593        get { return m_layer; }
594      }
595
596      private string m_key;
597      public string Key
598      {
599        get { return m_key; }
600        set { m_key = value; }
601      }
602
603      private byte[] m_data;
604      public byte[] Data
605      {
606        get { return m_data; }
607        set { m_data = value; }
608      }
609
610      public AdjusmentLayerInfo(string key, Layer layer)
611      {
612        m_key = key;
613        m_layer = layer;
614        m_layer.AdjustmentInfo.Add(this);
615      }
616
617      public AdjusmentLayerInfo(BinaryReverseReader reader, Layer layer)
618      {
619        Debug.WriteLine("AdjusmentLayerInfo started at " + reader.BaseStream.Position.ToString());
620
621        m_layer = layer;
622
623        string signature = new string(reader.ReadChars(4));
624        if (signature != "8BIM")
625        {
626          throw new IOException("Could not read an image resource");
627        }
628
629        m_key = new string(reader.ReadChars(4));
630
631        uint dataLength = reader.ReadUInt32();
632        m_data = reader.ReadBytes((int)dataLength);
633      }
634
635      public void Save(BinaryReverseWriter writer)
636      {
637        Debug.WriteLine("AdjusmentLayerInfo Save started at " + writer.BaseStream.Position.ToString());
638
639        string signature = "8BIM";
640
641        writer.Write(signature.ToCharArray());
642        writer.Write(m_key.ToCharArray());
643        writer.Write((uint)m_data.Length);
644        writer.Write(m_data);
645      }
646
647      //////////////////////////////////////////////////////////////////
648
649      public BinaryReverseReader DataReader
650      {
651        get
652        {
653          return new BinaryReverseReader(new System.IO.MemoryStream(this.m_data));
654        }
655      }
656    }
657
658
659    ///////////////////////////////////////////////////////////////////////////
660
661    private PsdFile m_psdFile;
662    internal PsdFile PsdFile
663    {
664      get { return m_psdFile; }
665    }
666
667    private Rectangle m_rect = Rectangle.Empty;
668    /// <summary>
669    /// The rectangle containing the contents of the layer.
670    /// </summary>
671    public Rectangle Rect
672    {
673      get { return m_rect; }
674      set { m_rect = value; }
675    }
676
677
678    /// <summary>
679    /// Channel information.
680    /// </summary>
681    private List<Channel> m_channels = new List<Channel>();
682
683    public List<Channel> Channels
684    {
685      get { return m_channels; }
686    }
687
688    private SortedList<short, Channel> m_sortedChannels = new SortedList<short, Channel>();
689    public SortedList<short, Channel> SortedChannels
690    {
691      get
692      {
693        return m_sortedChannels;
694      }
695    }
696
697    private string m_blendModeKey="norm";
698    /// <summary>
699    /// The blend mode key for the layer
700    /// </summary>
701    /// <remarks>
702    /// <list type="table">
703    /// </item>
704    /// <term>norm</term><description>normal</description>
705    /// <term>dark</term><description>darken</description>
706    /// <term>lite</term><description>lighten</description>
707    /// <term>hue </term><description>hue</description>
708    /// <term>sat </term><description>saturation</description>
709    /// <term>colr</term><description>color</description>
710    /// <term>lum </term><description>luminosity</description>
711    /// <term>mul </term><description>multiply</description>
712    /// <term>scrn</term><description>screen</description>
713    /// <term>diss</term><description>dissolve</description>
714    /// <term>over</term><description>overlay</description>
715    /// <term>hLit</term><description>hard light</description>
716    /// <term>sLit</term><description>soft light</description>
717    /// <term>diff</term><description>difference</description>
718    /// <term>smud</term><description>exlusion</description>
719    /// <term>div </term><description>color dodge</description>
720    /// <term>idiv</term><description>color burn</description>
721    /// </list>
722    /// </remarks>
723    public string BlendModeKey
724    {
725      get { return m_blendModeKey; }
726      set
727      {
728        if (value.Length != 4) throw new ArgumentException("Key length must be 4");
729      }
730    }
731
732
733    private byte m_opacity;
734    /// <summary>
735    /// 0 = transparent ... 255 = opaque
736    /// </summary>
737    public byte Opacity
738    {
739      get { return m_opacity; }
740      set { m_opacity = value; }
741    }
742
743
744    private bool m_clipping;
745    /// <summary>
746    /// false = base, true = non&#x2013;base
747    /// </summary>
748    public bool Clipping
749    {
750      get { return m_clipping; }
751      set { m_clipping = value; }
752    }
753
754    private static int m_protectTransBit = BitVector32.CreateMask();
755    private static int m_visibleBit = BitVector32.CreateMask(m_protectTransBit);
756
757    BitVector32 m_flags = new BitVector32();
758
759    /// <summary>
760    /// If true, the layer is visible.
761    /// </summary>
762    public bool Visible
763    {
764      get { return !m_flags[m_visibleBit]; }
765      set { m_flags[m_visibleBit] = !value; }
766    }
767
768
769    /// <summary>
770    /// Protect the transparency
771    /// </summary>
772    public bool ProtectTrans
773    {
774      get { return m_flags[m_protectTransBit]; }
775      set { m_flags[m_protectTransBit] = value; }
776    }
777
778
779    private string m_name;
780    /// <summary>
781    /// The descriptive layer name
782    /// </summary>
783    public string Name
784    {
785      get { return m_name; }
786      set { m_name = value; }
787    }
788
789    private BlendingRanges m_blendingRangesData;
790    public Layer.BlendingRanges BlendingRangesData
791    {
792      get { return m_blendingRangesData; }
793      set { m_blendingRangesData = value; }
794    }
795
796    private Mask m_maskData;
797    public Layer.Mask MaskData
798    {
799      get { return m_maskData; }
800      set { m_maskData = value; }
801    }
802
803    private List<AdjusmentLayerInfo> m_adjustmentInfo = new List<AdjusmentLayerInfo>();
804    public List<Layer.AdjusmentLayerInfo> AdjustmentInfo
805    {
806      get { return m_adjustmentInfo; }
807      set { m_adjustmentInfo = value; }
808    }
809
810    ///////////////////////////////////////////////////////////////////////////
811
812    public Layer(PsdFile psdFile)
813    {
814      m_psdFile = psdFile;
815      m_psdFile.Layers.Add(this);
816    }
817
818    public Layer(BinaryReverseReader reader, PsdFile psdFile)
819    {
820      Debug.WriteLine("Layer started at " + reader.BaseStream.Position.ToString());
821
822      m_psdFile = psdFile;
823      m_rect = new Rectangle();
824      m_rect.Y = reader.ReadInt32();
825      m_rect.X = reader.ReadInt32();
826      m_rect.Height = reader.ReadInt32() - m_rect.Y;
827      m_rect.Width = reader.ReadInt32() - m_rect.X;
828
829      //-----------------------------------------------------------------------
830
831      int numberOfChannels = reader.ReadUInt16();
832      this.m_channels.Clear();
833      for (int channel = 0; channel < numberOfChannels; channel++)
834      {
835        Channel ch = new Channel(reader, this);
836        m_channels.Add(ch);
837        m_sortedChannels.Add(ch.ID, ch);
838      }
839
840      //-----------------------------------------------------------------------
841
842      string signature = new string(reader.ReadChars(4));
843      if (signature != "8BIM")
844        throw (new IOException("Layer Channelheader error!"));
845
846      m_blendModeKey = new string(reader.ReadChars(4));
847      m_opacity = reader.ReadByte();
848
849      m_clipping = reader.ReadByte() > 0;
850
851      //-----------------------------------------------------------------------
852
853      byte flags = reader.ReadByte();
854      m_flags = new BitVector32(flags);
855
856      //-----------------------------------------------------------------------
857
858      reader.ReadByte(); //padding
859
860      //-----------------------------------------------------------------------
861
862      Debug.WriteLine("Layer extraDataSize started at " + reader.BaseStream.Position.ToString());
863
864      // this is the total size of the MaskData, the BlendingRangesData, the 
865      // Name and the AdjustmenLayerInfo
866      uint extraDataSize = reader.ReadUInt32();
867
868
869
870      // remember the start position for calculation of the 
871      // AdjustmenLayerInfo size
872      long extraDataStartPosition = reader.BaseStream.Position;
873
874      m_maskData = new Mask(reader, this);
875      m_blendingRangesData = new BlendingRanges(reader, this);
876
877      //-----------------------------------------------------------------------
878
879      long namePosition = reader.BaseStream.Position;
880
881      m_name = reader.ReadPascalString();
882
883      int paddingBytes =(int)((reader.BaseStream.Position - namePosition) % 4);
884
885      Debug.Print("Layer {0} padding bytes after name", paddingBytes);
886      reader.ReadBytes(paddingBytes);
887
888      //-----------------------------------------------------------------------
889
890      m_adjustmentInfo.Clear();
891
892      long adjustmenLayerEndPos = extraDataStartPosition + extraDataSize;
893      while (reader.BaseStream.Position < adjustmenLayerEndPos)
894      {
895        try
896        {
897          m_adjustmentInfo.Add(new AdjusmentLayerInfo(reader, this));
898        }
899        catch
900        {
901          reader.BaseStream.Position = adjustmenLayerEndPos;
902        }
903      }
904
905
906      //-----------------------------------------------------------------------
907      // make shure we are not on a wrong offset, so set the stream position 
908      // manually
909      reader.BaseStream.Position = adjustmenLayerEndPos;
910    }
911
912    ///////////////////////////////////////////////////////////////////////////
913
914    public void Save(BinaryReverseWriter writer)
915    {
916      Debug.WriteLine("Layer Save started at " + writer.BaseStream.Position.ToString());
917
918      writer.Write(m_rect.Top);
919      writer.Write(m_rect.Left);
920      writer.Write(m_rect.Bottom);
921      writer.Write(m_rect.Right);
922
923      //-----------------------------------------------------------------------
924
925      writer.Write((short)m_channels.Count);
926      foreach (Channel ch in m_channels)
927        ch.Save(writer);
928
929      //-----------------------------------------------------------------------
930
931      string signature = "8BIM";
932      writer.Write(signature.ToCharArray());
933      writer.Write(m_blendModeKey.ToCharArray());
934      writer.Write(m_opacity);
935      writer.Write((byte)(m_clipping ? 1 : 0));
936
937      writer.Write((byte)m_flags.Data);
938
939      //-----------------------------------------------------------------------
940
941      writer.Write((byte)0);
942
943      //-----------------------------------------------------------------------
944
945      using (new LengthWriter(writer))
946      {
947        m_maskData.Save(writer);
948        m_blendingRangesData.Save(writer);
949
950        long namePosition = writer.BaseStream.Position;
951
952        writer.WritePascalString(m_name);
953
954        int paddingBytes = (int)((writer.BaseStream.Position - namePosition) % 4);
955        Debug.Print("Layer {0} write padding bytes after name", paddingBytes);
956
957        for (int i = 0; i < paddingBytes;i++ )
958          writer.Write((byte)0);
959
960        foreach (AdjusmentLayerInfo info in m_adjustmentInfo)
961        {
962          info.Save(writer);
963        }
964      }
965    }
966
967  }
968}