~ubuntu-branches/ubuntu/breezy/digikam/breezy

« back to all changes in this revision

Viewing changes to utilities/imageviewer/exifrestorer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Paul Telford
  • Date: 2004-09-23 17:21:39 UTC
  • Revision ID: james.westby@ubuntu.com-20040923172139-3b3ji0dvomon3lod
Tags: upstream-0.6.2
ImportĀ upstreamĀ versionĀ 0.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <qstring.h>
 
2
#include <fstream>
 
3
 
 
4
extern "C" {
 
5
#include <string.h>
 
6
}
 
7
 
 
8
#include "exifrestorer.h"
 
9
 
 
10
using namespace std;
 
11
 
 
12
ExifRestorer::ExifRestorer()
 
13
{
 
14
    jpegSections_.setAutoDelete(true);
 
15
    imageData_ = 0;
 
16
    exifData_ = 0;
 
17
    hasExif_ = false;
 
18
}
 
19
 
 
20
ExifRestorer::~ExifRestorer()
 
21
{
 
22
    clear();
 
23
}
 
24
 
 
25
void ExifRestorer::clear()
 
26
{
 
27
    jpegSections_.clear();
 
28
    if (exifData_)
 
29
        delete exifData_;
 
30
    exifData_ = 0;
 
31
    if (imageData_)
 
32
        delete imageData_;
 
33
    imageData_ = 0;
 
34
    hasExif_ = false;
 
35
}
 
36
 
 
37
 
 
38
int ExifRestorer::readFile(const QString& filename, ReadMode mode)
 
39
{
 
40
    clear();
 
41
 
 
42
    std::ifstream filestream;
 
43
 
 
44
    filestream.open(filename.latin1(), ios::binary | ios::in);
 
45
    if (!filestream.good()) {
 
46
        qWarning("Failed to Open file");
 
47
        return -1;
 
48
    }
 
49
 
 
50
    unsigned char header[2];
 
51
    filestream.read((char*)header, 2);
 
52
    if (filestream.gcount() != 2) {
 
53
        qWarning("Failed to read header");
 
54
        return -1;
 
55
    }
 
56
 
 
57
    unsigned char marker;
 
58
 
 
59
    if ((header[0] == 0xFF) && (header[1] == M_SOI)) {
 
60
 
 
61
        // Smells like a jpeg file
 
62
 
 
63
        bool found_SOSorEOI = false;
 
64
 
 
65
        while (!filestream.eof()) {
 
66
 
 
67
            // Padding bytes between sections
 
68
            for (int i=0; i<7; i++){
 
69
                filestream.read((char*)&marker, 1);
 
70
                if (marker != 0xFF) break;
 
71
                if (i >= 6){
 
72
                    // 0xff is legal padding, but if we get
 
73
                    // that many times, something's wrong.
 
74
                    qWarning("Too many padding bytes");
 
75
                    return -1;
 
76
                }
 
77
            }
 
78
 
 
79
            JpegSection *section = new JpegSection;
 
80
 
 
81
            // read data size
 
82
            unsigned char lh, ll;
 
83
            filestream.read((char*)&lh, 1);
 
84
            filestream.read((char*)&ll, 1);
 
85
            section->size = (lh << 8) | ll;
 
86
            if (section->size < 2) {
 
87
                qWarning("Invalid Marker found");
 
88
                return -1;
 
89
            }
 
90
 
 
91
            section->data = new unsigned char[section->size];
 
92
            section->data[0] =  lh;
 
93
            section->data[1] =  ll;
 
94
            filestream.read((char*)&(section->data[2]), section->size-2);
 
95
            if (filestream.gcount() != (unsigned)section->size-2) {
 
96
                qWarning("Premature File End");
 
97
                return -1;
 
98
            }
 
99
 
 
100
            section->type = marker;
 
101
            jpegSections_.append(section);
 
102
 
 
103
            //cout << (dec) << section->size << " ";
 
104
            //cout << (hex) << int(section->type) << endl;
 
105
 
 
106
            switch (marker) {
 
107
 
 
108
            case M_SOS: {
 
109
 
 
110
                int currPos, endPos;
 
111
                found_SOSorEOI=true;
 
112
 
 
113
                if (mode == EntireImage) {
 
114
 
 
115
                    currPos = filestream.tellg();
 
116
                    filestream.seekg(0,ios::end);
 
117
                    endPos = filestream.tellg();
 
118
                    filestream.seekg(currPos);
 
119
 
 
120
                    imageData_ = new JpegSection;
 
121
                    imageData_->size = endPos - currPos;
 
122
                    imageData_->data =
 
123
                        new unsigned char[imageData_->size];
 
124
 
 
125
                    filestream.read((char*)imageData_->data,
 
126
                                    imageData_->size);
 
127
                    imageData_->type = marker;
 
128
                }
 
129
 
 
130
                break;
 
131
            }
 
132
 
 
133
            case M_EOI: {
 
134
 
 
135
                found_SOSorEOI=true;
 
136
                break;
 
137
            }
 
138
 
 
139
            case M_COM: {
 
140
 
 
141
                break;
 
142
            }
 
143
 
 
144
            case M_JFIF: {
 
145
 
 
146
                break;
 
147
            }
 
148
 
 
149
            case M_EXIF: {
 
150
                if (section->data[2] == 'E' &&
 
151
                    section->data[3] == 'x'  &&
 
152
                    section->data[4] == 'i' &&
 
153
                    section->data[5] == 'f') {
 
154
                    hasExif_ = true;
 
155
                    exifData_ = new JpegSection;
 
156
                    exifData_->size = section->size;
 
157
                    exifData_->type = section->type;
 
158
                    exifData_->data =
 
159
                        new unsigned char[section->size];
 
160
                    memcpy(exifData_->data, section->data,
 
161
                           section->size);
 
162
                }
 
163
                break;
 
164
            }
 
165
 
 
166
            default: {
 
167
                break;
 
168
            }
 
169
 
 
170
            }
 
171
 
 
172
            if (found_SOSorEOI) {
 
173
                if (mode == ExifOnly)
 
174
                    jpegSections_.clear();
 
175
                return 0;
 
176
            }
 
177
 
 
178
        }
 
179
 
 
180
        qWarning("End of file without SOS or EOI");
 
181
        return -1;
 
182
 
 
183
    }
 
184
 
 
185
    qWarning("Not a jpeg file");
 
186
    return -1;
 
187
 
 
188
}
 
189
 
 
190
int ExifRestorer::writeFile(const QString& filename)
 
191
{
 
192
    std::ofstream outStream (filename.latin1(), ios::binary | ios::out);
 
193
 
 
194
    if (!outStream) {
 
195
        qWarning("Error in opening output file");
 
196
        return -1;
 
197
    }
 
198
 
 
199
    outStream.put(0xff);
 
200
    outStream.put(0xd8);
 
201
 
 
202
    for (unsigned int i=0; i<jpegSections_.count(); i++) {
 
203
        outStream.put(0xff);
 
204
        outStream.put(jpegSections_.at(i)->type);
 
205
        if (!outStream.write((char*)jpegSections_.at(i)->data,
 
206
                             jpegSections_.at(i)->size))
 
207
            return -1;
 
208
    }
 
209
 
 
210
    if (!outStream.write((char*)imageData_->data, imageData_->size)) {
 
211
        qWarning("Error in writing to file");
 
212
        return -1;
 
213
    }
 
214
 
 
215
    outStream.close();
 
216
 
 
217
    return 0;
 
218
}
 
219
 
 
220
void ExifRestorer::insertExifData(JpegSection *exifSection)
 
221
{
 
222
    QPtrList<JpegSection> newSections;
 
223
    newSections.setAutoDelete(false);
 
224
 
 
225
    // Check if the first section of jpegSections is a JFIF
 
226
    // If so, add this to newSections
 
227
    if (jpegSections_.at(0)->type == M_JFIF) {
 
228
        newSections.append(jpegSections_.at(0));
 
229
    }
 
230
 
 
231
 
 
232
    // Now add the new exif section
 
233
    JpegSection* newExifSection = new JpegSection;
 
234
    newExifSection->type = exifSection->type;
 
235
    newExifSection->size = exifSection->size;
 
236
    newExifSection->data = new unsigned char[exifSection->size];
 
237
    memcpy(newExifSection->data, exifSection->data,
 
238
           exifSection->size);
 
239
 
 
240
    newSections.append(newExifSection);
 
241
 
 
242
    // Check if image already has exif section. if so replace it
 
243
    for (JpegSection* section = jpegSections_.first(); section;
 
244
         section = jpegSections_.next()) {
 
245
        if (section->type == M_EXIF) {
 
246
            jpegSections_.remove(section);
 
247
        }
 
248
    }
 
249
 
 
250
 
 
251
    // Add the rest of the sections;
 
252
    for (unsigned int i=1; i<jpegSections_.count(); i++) {
 
253
        newSections.append(jpegSections_.at(i));
 
254
    }
 
255
 
 
256
    jpegSections_.setAutoDelete(false);
 
257
    jpegSections_.clear();
 
258
 
 
259
    for (unsigned int i=0; i<newSections.count(); i++) {
 
260
        jpegSections_.append(newSections.at(i));
 
261
    }
 
262
 
 
263
    jpegSections_.setAutoDelete(true);
 
264
}