~ubuntu-branches/debian/jessie/f-spot/jessie

« back to all changes in this revision

Viewing changes to src/Imaging/Ciff.cs

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane
  • Date: 2010-08-11 22:17:42 UTC
  • mfrom: (2.4.9 experimental)
  • Revision ID: james.westby@ubuntu.com-20100811221742-2qv3a5uya7gfe1t1
* New upstream release 0.7.2 "Retooled"
  + Third release of the unstable 0.7 development series. Features a
    fully restructured source tree with full Monodevelop build
    support. Solves some of the regressions introduced in 0.7.1.
  + Reorganized source tree for clarity, builds with Monodevelop.
  + Switched from QueuedSqliteDatabase to HyenaSqliteConnection (Mike
    Gemünde)
  + Build tweaks (Christian Krause)
  + More GtkBuilder transition (Eric Faehnrich) 
  + Reliability improvements (lots of them) for metadata handling (Mike
    Gemünde, Ruben Vermeersch)
  + Prune empty directories when deleting photos, import usability
    enhancements (Mike Wallick)
  + Big race-condition fix in import (Paul Wellner Bou)
  + Loads of improvements to Taglib#, in terms of handling broken files,
    extra format support (Pentax, Panasonic, Leica), stability and
    correctness (Ruben Vermeersch)
    - Runs out of memory Importing photo with suspect EXIF data
      (LP: #272822)
    - Metadata parsing of broken file causes large memory allocation
      (LP: #597720)
    - Photo import: cancel & copy have same keyboard shortcut (LP: #244423)
    - Facebook export will not create new album (LP: #563495)
    - Allow export to iPod (LP: #518344)
  + Reporting of import errors.
  + Speedups to repeated imports of the same directory.
  + Piles of cleanups and general stability improvements.
  + Over 50 bugs closed (http://bit.ly/cqpC3y)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
using System;
2
 
using FSpot.Utils;
3
 
using Hyena;
4
 
using TagLib.Image;
5
 
 
6
 
namespace FSpot.Imaging.Ciff {
7
 
        internal enum Tag {
8
 
                JpgFromRaw = 0x2007,
9
 
        }
10
 
 
11
 
        public enum EntryType : ushort {
12
 
                Byte = 0x0000,
13
 
                Ascii = 0x0800,
14
 
                Short = 0x1000,
15
 
                Int = 0x1800,
16
 
                Struct = 0x2000,
17
 
                Directory1 = 0x2800,
18
 
                Directory2 = 0x2800,
19
 
        }
20
 
        
21
 
        public enum Mask {
22
 
                Type = 0x3800,
23
 
        }
24
 
 
25
 
        /* See http://www.sno.phy.queensu.ca/~phil/exiftool/canon_raw.html */
26
 
        internal struct Entry {
27
 
                internal Tag Tag;
28
 
                internal uint Size;
29
 
                internal uint Offset;
30
 
 
31
 
                public Entry (byte [] data, int pos, bool little)
32
 
                {
33
 
                        Tag = (Tag) BitConverter.ToUInt16 (data, pos, little);
34
 
                        Size = BitConverter.ToUInt32 (data, pos + 2, little);
35
 
                        Offset = BitConverter.ToUInt32 (data, pos + 6, little);
36
 
                }       
37
 
        }
38
 
 
39
 
        class ImageDirectory {
40
 
                System.Collections.ArrayList entry_list;
41
 
                uint Count;
42
 
                bool little;
43
 
                uint start;
44
 
                long DirPosition; 
45
 
                System.IO.Stream stream;
46
 
 
47
 
                public ImageDirectory (System.IO.Stream stream, uint start, long end, bool little)
48
 
                {
49
 
                        this.start = start;
50
 
                        this.little = little;
51
 
                        this.stream = stream;
52
 
 
53
 
                        entry_list = new System.Collections.ArrayList ();
54
 
                        
55
 
                        stream.Position = end - 4;
56
 
                        byte [] buf = new byte [10];
57
 
                        stream.Read (buf, 0, 4);
58
 
                        uint directory_pos  = BitConverter.ToUInt32 (buf, 0, little);
59
 
                        DirPosition = start + directory_pos;
60
 
 
61
 
                        stream.Position = DirPosition;
62
 
                        stream.Read (buf, 0, 2);
63
 
 
64
 
                        Count = BitConverter.ToUInt16 (buf, 0, little);
65
 
                        
66
 
                        for (int i = 0; i < Count; i++)
67
 
                        {
68
 
                                stream.Read (buf, 0, 10);
69
 
                                Log.DebugFormat ("reading {0} {1}", i, stream.Position);
70
 
                                Entry entry = new Entry (buf, 0, little);
71
 
                                entry_list.Add (entry);
72
 
                        }
73
 
                }                       
74
 
 
75
 
                public ImageDirectory ReadDirectory (Tag tag)
76
 
                {
77
 
                        foreach (Entry e in entry_list) {
78
 
                                if (e.Tag == tag) {
79
 
                                        uint subdir_start = this.start + e.Offset;
80
 
                                        ImageDirectory subdir = new ImageDirectory (stream, subdir_start, subdir_start + e.Size, little);
81
 
                                        return subdir;
82
 
                                }
83
 
                        }
84
 
                        return null;
85
 
                }
86
 
                
87
 
                public byte [] ReadEntry (int pos)
88
 
                {
89
 
                        Entry e = (Entry) entry_list [pos];
90
 
 
91
 
                        stream.Position = this.start + e.Offset;                        
92
 
 
93
 
                        byte [] data = new byte [e.Size];
94
 
                        stream.Read (data, 0, data.Length);
95
 
 
96
 
                        return data;
97
 
                }
98
 
                
99
 
                public byte [] ReadEntry (Tag tag) 
100
 
                {
101
 
                        int pos = 0;
102
 
                        foreach (Entry e in entry_list) {
103
 
                                if (e.Tag == tag)
104
 
                                        return ReadEntry (pos);
105
 
                                pos++;
106
 
                        }
107
 
                        return null;
108
 
                }
109
 
        }
110
 
        
111
 
        public class CiffFile : BaseImageFile {
112
 
                ImageDirectory root;
113
 
                bool little;
114
 
                System.IO.Stream stream;
115
 
                
116
 
                ImageDirectory Root {
117
 
                        get {
118
 
                                if (root == null) {
119
 
                                        stream = PixbufStream ();
120
 
                                        root = Load (stream);
121
 
                                }
122
 
                                
123
 
                                return root;
124
 
                        }
125
 
                }
126
 
 
127
 
                public CiffFile (SafeUri uri) : base (uri)
128
 
                {
129
 
                }
130
 
 
131
 
                private ImageDirectory Load (System.IO.Stream stream)
132
 
                {
133
 
                        byte [] header = new byte [26];  // the spec reserves the first 26 bytes as the header block
134
 
                        stream.Read (header, 0, header.Length);
135
 
 
136
 
                        uint start;
137
 
                        
138
 
                        little = (header [0] == 'I' && header [1] == 'I');
139
 
                        
140
 
                        start = BitConverter.ToUInt32 (header, 2, little);
141
 
                        
142
 
                        // HEAP is the type CCDR is the subtype
143
 
                        if (System.Text.Encoding.ASCII.GetString (header, 6, 8) != "HEAPCCDR") 
144
 
                                throw new ImageFormatException ("Invalid Ciff Header Block");
145
 
                        
146
 
                        long end = stream.Length;
147
 
                        return new ImageDirectory (stream, start, end, little);
148
 
                }
149
 
 
150
 
                public override System.IO.Stream PixbufStream ()
151
 
                {
152
 
                        byte [] data = GetEmbeddedJpeg ();
153
 
                        
154
 
                        if (data != null)
155
 
                                return new System.IO.MemoryStream (data);
156
 
                        else    
157
 
                                return DCRawFile.RawPixbufStream (Uri);
158
 
                }
159
 
 
160
 
                private byte [] GetEmbeddedJpeg ()
161
 
                {
162
 
                        return Root.ReadEntry (Tag.JpgFromRaw);
163
 
                }
164
 
 
165
 
                protected override void Close ()
166
 
                {
167
 
                        if (stream != null) {
168
 
                                stream.Close ();
169
 
                                stream = null;
170
 
                        }
171
 
                }
172
 
        }
173
 
}