summaryrefslogtreecommitdiff
path: root/libopie2/opiemm/opieexif.cpp
Unidiff
Diffstat (limited to 'libopie2/opiemm/opieexif.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiemm/opieexif.cpp8
1 files changed, 6 insertions, 2 deletions
diff --git a/libopie2/opiemm/opieexif.cpp b/libopie2/opiemm/opieexif.cpp
index de49937..653216c 100644
--- a/libopie2/opiemm/opieexif.cpp
+++ b/libopie2/opiemm/opieexif.cpp
@@ -160,97 +160,97 @@ int ExifData::ReadJpegSections (QFile & infile, ReadMode_t ReadMode)
160 160
161 if (a >= 6){ 161 if (a >= 6){
162 162
163 owarn << "too many padding bytes" << oendl; 163 owarn << "too many padding bytes" << oendl;
164 return false; 164 return false;
165 165
166 } 166 }
167 } 167 }
168 168
169 if (marker == 0xff){ 169 if (marker == 0xff){
170 // 0xff is legal padding, but if we get that many, something's wrong. 170 // 0xff is legal padding, but if we get that many, something's wrong.
171 return false; 171 return false;
172 } 172 }
173 173
174 Sections[SectionsRead].Type = marker; 174 Sections[SectionsRead].Type = marker;
175 175
176 // Read the length of the section. 176 // Read the length of the section.
177 lh = (uchar) infile.getch(); 177 lh = (uchar) infile.getch();
178 ll = (uchar) infile.getch(); 178 ll = (uchar) infile.getch();
179 179
180 itemlen = (lh << 8) | ll; 180 itemlen = (lh << 8) | ll;
181 181
182 if (itemlen < 2) { 182 if (itemlen < 2) {
183 return false;; 183 return false;;
184 } 184 }
185 185
186 Sections[SectionsRead].Size = itemlen; 186 Sections[SectionsRead].Size = itemlen;
187 187
188 Data = (uchar *)malloc(itemlen+1); // Add 1 to allow sticking a 0 at the end. 188 Data = (uchar *)malloc(itemlen+1); // Add 1 to allow sticking a 0 at the end.
189 Sections[SectionsRead].Data = Data; 189 Sections[SectionsRead].Data = Data;
190 190
191 // Store first two pre-read bytes. 191 // Store first two pre-read bytes.
192 Data[0] = (uchar)lh; 192 Data[0] = (uchar)lh;
193 Data[1] = (uchar)ll; 193 Data[1] = (uchar)ll;
194 194
195 got = infile.readBlock((char*)Data+2, itemlen-2); // Read the whole section. 195 got = infile.readBlock((char*)Data+2, itemlen-2); // Read the whole section.
196 if (( unsigned ) got != itemlen-2){ 196 if (( unsigned ) got != itemlen-2){
197 return false; 197 return false;
198 } 198 }
199 SectionsRead++; 199 SectionsRead++;
200 200
201 switch(marker){ 201 switch(marker){
202 202
203 case M_SOS: // stop before hitting compressed data 203 case M_SOS: // stop before hitting compressed data
204 // If reading entire image is requested, read the rest of the data. 204 // If reading entire image is requested, read the rest of the data.
205 if (ReadMode & READ_IMAGE){ 205 if (ReadMode & READ_IMAGE){
206 unsigned long size; 206 unsigned long size;
207 207
208 size = QMAX( 0ul, infile.size()-infile.at() ); 208 size = infile.size()-infile.at();
209 Data = (uchar *)malloc(size); 209 Data = (uchar *)malloc(size);
210 if (Data == NULL){ 210 if (Data == NULL){
211 return false; 211 return false;
212 } 212 }
213 213
214 got = infile.readBlock((char*)Data, size); 214 got = infile.readBlock((char*)Data, size);
215 if (( unsigned ) got != size){ 215 if (( unsigned ) got != size){
216 return false; 216 return false;
217 } 217 }
218 218
219 Sections[SectionsRead].Data = Data; 219 Sections[SectionsRead].Data = Data;
220 Sections[SectionsRead].Size = size; 220 Sections[SectionsRead].Size = size;
221 Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER; 221 Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER;
222 SectionsRead ++; 222 SectionsRead ++;
223 //HaveAll = 1; 223 //HaveAll = 1;
224 } 224 }
225 return true; 225 return true;
226 226
227 case M_EOI: // in case it's a tables-only JPEG stream 227 case M_EOI: // in case it's a tables-only JPEG stream
228 owarn << "No image in jpeg!" << oendl; 228 owarn << "No image in jpeg!" << oendl;
229 return false; 229 return false;
230 230
231 case M_COM: // Comment section 231 case M_COM: // Comment section
232 // pieczy 2002-02-12 232 // pieczy 2002-02-12
233 // now the User comment goes to UserComment 233 // now the User comment goes to UserComment
234 // so we can store a Comment section also in READ_EXIF mode 234 // so we can store a Comment section also in READ_EXIF mode
235 process_COM(Data, itemlen); 235 process_COM(Data, itemlen);
236 break; 236 break;
237 237
238 case M_JFIF: 238 case M_JFIF:
239 // Regular jpegs always have this tag, exif images have the exif 239 // Regular jpegs always have this tag, exif images have the exif
240 // marker instead, althogh ACDsee will write images with both markers. 240 // marker instead, althogh ACDsee will write images with both markers.
241 // this program will re-create this marker on absence of exif marker. 241 // this program will re-create this marker on absence of exif marker.
242 // hence no need to keep the copy from the file. 242 // hence no need to keep the copy from the file.
243 free(Sections[--SectionsRead].Data); 243 free(Sections[--SectionsRead].Data);
244 break; 244 break;
245 245
246 case M_EXIF: 246 case M_EXIF:
247 // Seen files from some 'U-lead' software with Vivitar scanner 247 // Seen files from some 'U-lead' software with Vivitar scanner
248 // that uses marker 31 for non exif stuff. Thus make sure 248 // that uses marker 31 for non exif stuff. Thus make sure
249 // it says 'Exif' in the section before treating it as exif. 249 // it says 'Exif' in the section before treating it as exif.
250 if ((ReadMode & READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){ 250 if ((ReadMode & READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){
251 process_EXIF((uchar *)Data, itemlen); 251 process_EXIF((uchar *)Data, itemlen);
252 }else{ 252 }else{
253 // Discard this section. 253 // Discard this section.
254 free(Sections[--SectionsRead].Data); 254 free(Sections[--SectionsRead].Data);
255 } 255 }
256 break; 256 break;
@@ -764,97 +764,101 @@ int ExifData::Exif2tm(struct ::tm * timeptr, char * ExifTime)
764 764
765 if (a == 6){ 765 if (a == 6){
766 timeptr->tm_isdst = -1; 766 timeptr->tm_isdst = -1;
767 timeptr->tm_mon -= 1; // Adjust for unix zero-based months 767 timeptr->tm_mon -= 1; // Adjust for unix zero-based months
768 timeptr->tm_year -= 1900; // Adjust for year starting at 1900 768 timeptr->tm_year -= 1900; // Adjust for year starting at 1900
769 return true; // worked. 769 return true; // worked.
770 } 770 }
771 771
772 return false; // Wasn't in Exif date format. 772 return false; // Wasn't in Exif date format.
773} 773}
774 774
775//-------------------------------------------------------------------------- 775//--------------------------------------------------------------------------
776// Contructor for initialising 776// Contructor for initialising
777//-------------------------------------------------------------------------- 777//--------------------------------------------------------------------------
778ExifData::ExifData() 778ExifData::ExifData()
779{ 779{
780 ExifData::Whitebalance = -1; 780 ExifData::Whitebalance = -1;
781 ExifData::MeteringMode = -1; 781 ExifData::MeteringMode = -1;
782 ExifData::FlashUsed = -1; 782 ExifData::FlashUsed = -1;
783 Orientation = 0; 783 Orientation = 0;
784 Height = 0; 784 Height = 0;
785 Width = 0; 785 Width = 0;
786 IsColor = 0; 786 IsColor = 0;
787 Process = 0; 787 Process = 0;
788 FocalLength = 0; 788 FocalLength = 0;
789 ExposureTime = 0; 789 ExposureTime = 0;
790 ApertureFNumber = 0; 790 ApertureFNumber = 0;
791 Distance = 0; 791 Distance = 0;
792 CCDWidth = 0; 792 CCDWidth = 0;
793 ExposureBias = 0; 793 ExposureBias = 0;
794 ExposureProgram = 0; 794 ExposureProgram = 0;
795 ISOequivalent = 0; 795 ISOequivalent = 0;
796 CompressionLevel = 0; 796 CompressionLevel = 0;
797 MotorolaOrder = 0; 797 MotorolaOrder = 0;
798} 798}
799 799
800ExifData::~ExifData() 800ExifData::~ExifData()
801{ 801{
802} 802}
803 803
804//-------------------------------------------------------------------------- 804//--------------------------------------------------------------------------
805// process a EXIF jpeg file 805// process a EXIF jpeg file
806//-------------------------------------------------------------------------- 806//--------------------------------------------------------------------------
807bool ExifData::scan(const QString & path) 807bool ExifData::scan(const QString & path)
808{ 808{
809 int ret; 809 int ret;
810 810
811 QFile f(path); 811 QFile f(path);
812 f.open(IO_ReadOnly); 812 if ( !f.open(IO_ReadOnly) ) {
813 owarn << "Unable to open file " << f.name() << " readonly" << oendl;
814 DiscardData();
815 return false;
816 }
813 817
814 // Scan the JPEG headers. 818 // Scan the JPEG headers.
815 ret = ReadJpegSections(f, READ_EXIF); 819 ret = ReadJpegSections(f, READ_EXIF);
816 820
817 if (ret == false){ 821 if (ret == false){
818 owarn << "Not JPEG file!" << oendl; 822 owarn << "Not JPEG file!" << oendl;
819 DiscardData(); 823 DiscardData();
820 f.close(); 824 f.close();
821 return false; 825 return false;
822 } 826 }
823 f.close(); 827 f.close();
824 DiscardData(); 828 DiscardData();
825 829
826 //now make the strings clean, 830 //now make the strings clean,
827 // for exmaple my Casio is a "QV-4000 " 831 // for exmaple my Casio is a "QV-4000 "
828 CameraMake = CameraMake.stripWhiteSpace(); 832 CameraMake = CameraMake.stripWhiteSpace();
829 CameraModel = CameraModel.stripWhiteSpace(); 833 CameraModel = CameraModel.stripWhiteSpace();
830 UserComment = UserComment.stripWhiteSpace(); 834 UserComment = UserComment.stripWhiteSpace();
831 Comment = Comment.stripWhiteSpace(); 835 Comment = Comment.stripWhiteSpace();
832 return true; 836 return true;
833} 837}
834 838
835//-------------------------------------------------------------------------- 839//--------------------------------------------------------------------------
836// Does the embedded thumbnail match the jpeg image? 840// Does the embedded thumbnail match the jpeg image?
837//-------------------------------------------------------------------------- 841//--------------------------------------------------------------------------
838#ifndef JPEG_TOL 842#ifndef JPEG_TOL
839#define JPEG_TOL 0.02 843#define JPEG_TOL 0.02
840#endif 844#endif
841bool ExifData::isThumbnailSane() { 845bool ExifData::isThumbnailSane() {
842 if (Thumbnail.isNull()) return false; 846 if (Thumbnail.isNull()) return false;
843 847
844 // check whether thumbnail dimensions match the image 848 // check whether thumbnail dimensions match the image
845 // not foolproof, but catches some altered images (jpegtran -rotate) 849 // not foolproof, but catches some altered images (jpegtran -rotate)
846 if (ExifImageLength != 0 && ExifImageLength != Height) return false; 850 if (ExifImageLength != 0 && ExifImageLength != Height) return false;
847 if (ExifImageWidth != 0 && ExifImageWidth != Width) return false; 851 if (ExifImageWidth != 0 && ExifImageWidth != Width) return false;
848 if (Thumbnail.width() == 0 || Thumbnail.height() == 0) return false; 852 if (Thumbnail.width() == 0 || Thumbnail.height() == 0) return false;
849 if (Height == 0 || Width == 0) return false; 853 if (Height == 0 || Width == 0) return false;
850 double d = (double)Height/Width*Thumbnail.width()/Thumbnail.height(); 854 double d = (double)Height/Width*Thumbnail.width()/Thumbnail.height();
851 return (1-JPEG_TOL < d) && (d < 1+JPEG_TOL); 855 return (1-JPEG_TOL < d) && (d < 1+JPEG_TOL);
852} 856}
853 857
854 858
855 859
856static QImage flip_image( const QImage& img ); 860static QImage flip_image( const QImage& img );
857static QImage rotate_90( const QImage& img ); 861static QImage rotate_90( const QImage& img );
858static QImage rotate_180( const QImage& ); 862static QImage rotate_180( const QImage& );
859static QImage rotate_270( const QImage& ); 863static QImage rotate_270( const QImage& );
860 864