mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-20 03:16:10 +00:00
Deleted unused libraries Qmeta and jhead
This commit is contained in:
parent
496b0bfe4a
commit
9e5063193b
291
src/fgt/filter_photosynth/Makefile
Normal file
291
src/fgt/filter_photosynth/Makefile
Normal file
@ -0,0 +1,291 @@
|
||||
#############################################################################
|
||||
# Makefile for building: libfilter_photosynth.dylib
|
||||
# Generated by qmake (2.01a) (Qt 4.7.0) on: Tue Nov 23 16:55:56 2010
|
||||
# Project: filter_photosynth.pro
|
||||
# Template: lib
|
||||
# Command: /usr/bin/qmake -spec /usr/local/Qt4.7/mkspecs/macx-g++ -o Makefile filter_photosynth.pro
|
||||
#############################################################################
|
||||
|
||||
####### Compiler, tools and options
|
||||
|
||||
CC = gcc
|
||||
CXX = g++-4.2
|
||||
DEFINES = -DQT_PLUGIN -DQT_SCRIPT_LIB -DQT_XMLPATTERNS_LIB -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED
|
||||
CFLAGS = -pipe -g -gdwarf-2 -Wall -W -fPIC $(DEFINES)
|
||||
CXXFLAGS = -pipe -g -gdwarf-2 -Wall -W -fPIC $(DEFINES)
|
||||
INCPATH = -I/usr/local/Qt4.7/mkspecs/macx-g++ -I. -I/Library/Frameworks/QtCore.framework/Versions/4/Headers -I/usr/include/QtCore -I/Library/Frameworks/QtNetwork.framework/Versions/4/Headers -I/usr/include/QtNetwork -I/Library/Frameworks/QtGui.framework/Versions/4/Headers -I/usr/include/QtGui -I/Library/Frameworks/QtOpenGL.framework/Versions/4/Headers -I/usr/include/QtOpenGL -I/Library/Frameworks/QtXml.framework/Versions/4/Headers -I/usr/include/QtXml -I/Library/Frameworks/QtXmlPatterns.framework/Versions/4/Headers -I/usr/include/QtXmlPatterns -I/Library/Frameworks/QtScript.framework/Versions/4/Headers -I/usr/include/QtScript -I/usr/include -I../.. -I../../../../vcglib -I../../external/glew-1.5.1/include -I../../external/qtsoap-2.7_1/src -I/System/Library/Frameworks/OpenGL.framework/Versions/A/Headers -I/System/Library/Frameworks/AGL.framework/Headers -I. -F/Library/Frameworks
|
||||
LINK = g++
|
||||
LFLAGS = -headerpad_max_install_names -single_module -dynamiclib
|
||||
LIBS = $(SUBLIBS) -F/Library/Frameworks -L/Library/Frameworks ../../common/libcommon.dylib -framework QtScript -L/tmp/qt-stuff-6474/source/qt-everywhere-opensource-src-4.7.0/lib -F/tmp/qt-stuff-6474/source/qt-everywhere-opensource-src-4.7.0/lib -framework QtXmlPatterns -framework QtXml -framework QtOpenGL -framework QtGui -framework QtNetwork -framework QtCore -framework OpenGL -framework AGL
|
||||
AR = ar cq
|
||||
RANLIB = ranlib -s
|
||||
QMAKE = /usr/bin/qmake
|
||||
TAR = tar -cf
|
||||
COMPRESS = gzip -9f
|
||||
COPY = cp -f
|
||||
SED = sed
|
||||
COPY_FILE = cp -f
|
||||
COPY_DIR = cp -f -R
|
||||
STRIP =
|
||||
INSTALL_FILE = $(COPY_FILE)
|
||||
INSTALL_DIR = $(COPY_DIR)
|
||||
INSTALL_PROGRAM = $(COPY_FILE)
|
||||
DEL_FILE = rm -f
|
||||
SYMLINK = ln -f -s
|
||||
DEL_DIR = rmdir
|
||||
MOVE = mv -f
|
||||
CHK_DIR_EXISTS= test -d
|
||||
MKDIR = mkdir -p
|
||||
export MACOSX_DEPLOYMENT_TARGET = 10.4
|
||||
|
||||
####### Output directory
|
||||
|
||||
OBJECTS_DIR = ./
|
||||
|
||||
####### Files
|
||||
|
||||
SOURCES = filter_photosynth.cpp \
|
||||
downloader.cpp \
|
||||
../../external/qtsoap-2.7_1/src/qtsoap.cpp moc_filter_photosynth.cpp \
|
||||
moc_synthData.cpp \
|
||||
moc_qtsoap.cpp
|
||||
OBJECTS = filter_photosynth.o \
|
||||
downloader.o \
|
||||
qtsoap.o \
|
||||
moc_filter_photosynth.o \
|
||||
moc_synthData.o \
|
||||
moc_qtsoap.o
|
||||
DIST = /usr/local/Qt4.7/mkspecs/common/unix.conf \
|
||||
/usr/local/Qt4.7/mkspecs/common/mac.conf \
|
||||
/usr/local/Qt4.7/mkspecs/common/mac-g++.conf \
|
||||
/usr/local/Qt4.7/mkspecs/qconfig.pri \
|
||||
/usr/local/Qt4.7/mkspecs/modules/qt_webkit_version.pri \
|
||||
/usr/local/Qt4.7/mkspecs/features/qt_functions.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/qt_config.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/exclusive_builds.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/default_pre.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/default_pre.prf \
|
||||
../../shared.pri \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/dwarf2.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/debug.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/default_post.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/default_post.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/objective_c.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/warn_on.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/qt.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/unix/opengl.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/unix/thread.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/moc.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/rez.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/sdk.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/resources.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/uic.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/yacc.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/lex.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/include_source_dir.prf \
|
||||
filter_photosynth.pro
|
||||
QMAKE_TARGET = filter_photosynth
|
||||
DESTDIR = ../../distrib/plugins/
|
||||
TARGET = libfilter_photosynth.dylib
|
||||
TARGETD = libfilter_photosynth.dylib
|
||||
|
||||
####### Custom Compiler Variables
|
||||
QMAKE_COMP_QMAKE_OBJECTIVE_CFLAGS = -pipe \
|
||||
-g \
|
||||
-gdwarf-2 \
|
||||
-Wall \
|
||||
-W
|
||||
|
||||
|
||||
first: all
|
||||
####### Implicit rules
|
||||
|
||||
.SUFFIXES: .o .c .cpp .cc .cxx .C
|
||||
|
||||
.cpp.o:
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
|
||||
|
||||
.cc.o:
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
|
||||
|
||||
.cxx.o:
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
|
||||
|
||||
.C.o:
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
|
||||
|
||||
####### Build rules
|
||||
|
||||
all: Makefile ../../distrib/plugins/$(TARGET)
|
||||
|
||||
../../distrib/plugins/$(TARGET): $(OBJECTS) $(SUBLIBS) $(OBJCOMP)
|
||||
@$(CHK_DIR_EXISTS) ../../distrib/plugins/ || $(MKDIR) ../../distrib/plugins/
|
||||
-$(DEL_FILE) $(TARGET)
|
||||
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) $(OBJCOMP)
|
||||
-$(MOVE) $(TARGET) ../../distrib/plugins/
|
||||
|
||||
|
||||
|
||||
Makefile: filter_photosynth.pro /usr/local/Qt4.7/mkspecs/macx-g++/qmake.conf /usr/local/Qt4.7/mkspecs/common/unix.conf \
|
||||
/usr/local/Qt4.7/mkspecs/common/mac.conf \
|
||||
/usr/local/Qt4.7/mkspecs/common/mac-g++.conf \
|
||||
/usr/local/Qt4.7/mkspecs/qconfig.pri \
|
||||
/usr/local/Qt4.7/mkspecs/modules/qt_webkit_version.pri \
|
||||
/usr/local/Qt4.7/mkspecs/features/qt_functions.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/qt_config.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/exclusive_builds.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/default_pre.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/default_pre.prf \
|
||||
../../shared.pri \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/dwarf2.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/debug.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/default_post.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/default_post.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/objective_c.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/warn_on.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/qt.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/unix/opengl.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/unix/thread.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/moc.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/rez.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/sdk.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/resources.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/uic.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/yacc.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/lex.prf \
|
||||
/usr/local/Qt4.7/mkspecs/features/include_source_dir.prf \
|
||||
/Library/Frameworks/QtScript.framework/QtScript.prl \
|
||||
/Library/Frameworks/QtCore.framework/QtCore.prl \
|
||||
/Library/Frameworks/QtXmlPatterns.framework/QtXmlPatterns.prl \
|
||||
/Library/Frameworks/QtNetwork.framework/QtNetwork.prl \
|
||||
/Library/Frameworks/QtXml.framework/QtXml.prl \
|
||||
/Library/Frameworks/QtOpenGL.framework/QtOpenGL.prl \
|
||||
/Library/Frameworks/QtGui.framework/QtGui.prl
|
||||
$(QMAKE) -spec /usr/local/Qt4.7/mkspecs/macx-g++ -o Makefile filter_photosynth.pro
|
||||
/usr/local/Qt4.7/mkspecs/common/unix.conf:
|
||||
/usr/local/Qt4.7/mkspecs/common/mac.conf:
|
||||
/usr/local/Qt4.7/mkspecs/common/mac-g++.conf:
|
||||
/usr/local/Qt4.7/mkspecs/qconfig.pri:
|
||||
/usr/local/Qt4.7/mkspecs/modules/qt_webkit_version.pri:
|
||||
/usr/local/Qt4.7/mkspecs/features/qt_functions.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/qt_config.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/exclusive_builds.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/default_pre.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/default_pre.prf:
|
||||
../../shared.pri:
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/dwarf2.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/debug.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/default_post.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/default_post.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/objective_c.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/warn_on.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/qt.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/unix/opengl.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/unix/thread.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/moc.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/rez.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/mac/sdk.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/resources.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/uic.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/yacc.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/lex.prf:
|
||||
/usr/local/Qt4.7/mkspecs/features/include_source_dir.prf:
|
||||
/Library/Frameworks/QtScript.framework/QtScript.prl:
|
||||
/Library/Frameworks/QtCore.framework/QtCore.prl:
|
||||
/Library/Frameworks/QtXmlPatterns.framework/QtXmlPatterns.prl:
|
||||
/Library/Frameworks/QtNetwork.framework/QtNetwork.prl:
|
||||
/Library/Frameworks/QtXml.framework/QtXml.prl:
|
||||
/Library/Frameworks/QtOpenGL.framework/QtOpenGL.prl:
|
||||
/Library/Frameworks/QtGui.framework/QtGui.prl:
|
||||
qmake: FORCE
|
||||
@$(QMAKE) -spec /usr/local/Qt4.7/mkspecs/macx-g++ -o Makefile filter_photosynth.pro
|
||||
|
||||
dist:
|
||||
@$(CHK_DIR_EXISTS) .tmp/filter_photosynth1.0.0 || $(MKDIR) .tmp/filter_photosynth1.0.0
|
||||
$(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/filter_photosynth1.0.0/ && $(COPY_FILE) --parents filter_photosynth.h synthData.h ../../external/qtsoap-2.7_1/src/qtsoap.h .tmp/filter_photosynth1.0.0/ && $(COPY_FILE) --parents filter_photosynth.cpp downloader.cpp ../../external/qtsoap-2.7_1/src/qtsoap.cpp .tmp/filter_photosynth1.0.0/ && (cd `dirname .tmp/filter_photosynth1.0.0` && $(TAR) filter_photosynth1.0.0.tar filter_photosynth1.0.0 && $(COMPRESS) filter_photosynth1.0.0.tar) && $(MOVE) `dirname .tmp/filter_photosynth1.0.0`/filter_photosynth1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/filter_photosynth1.0.0
|
||||
|
||||
|
||||
clean:compiler_clean
|
||||
-$(DEL_FILE) $(OBJECTS)
|
||||
-$(DEL_FILE) *~ core *.core
|
||||
|
||||
|
||||
####### Sub-libraries
|
||||
|
||||
distclean: clean
|
||||
-$(DEL_FILE) $(TARGET)
|
||||
-$(DEL_FILE) Makefile
|
||||
|
||||
|
||||
check: first
|
||||
|
||||
mocclean: compiler_moc_header_clean compiler_moc_source_clean
|
||||
|
||||
mocables: compiler_moc_header_make_all compiler_moc_source_make_all
|
||||
|
||||
compiler_objective_c_make_all:
|
||||
compiler_objective_c_clean:
|
||||
compiler_moc_header_make_all: moc_filter_photosynth.cpp moc_synthData.cpp moc_qtsoap.cpp
|
||||
compiler_moc_header_clean:
|
||||
-$(DEL_FILE) moc_filter_photosynth.cpp moc_synthData.cpp moc_qtsoap.cpp
|
||||
moc_filter_photosynth.cpp: synthData.h \
|
||||
filter_photosynth.h
|
||||
/Developer/Tools/Qt/moc $(DEFINES) $(INCPATH) -D__APPLE__ -D__GNUC__ filter_photosynth.h -o moc_filter_photosynth.cpp
|
||||
|
||||
moc_synthData.cpp: synthData.h
|
||||
/Developer/Tools/Qt/moc $(DEFINES) $(INCPATH) -D__APPLE__ -D__GNUC__ synthData.h -o moc_synthData.cpp
|
||||
|
||||
moc_qtsoap.cpp: ../../external/qtsoap-2.7_1/src/qtsoap.h
|
||||
/Developer/Tools/Qt/moc $(DEFINES) $(INCPATH) -D__APPLE__ -D__GNUC__ ../../external/qtsoap-2.7_1/src/qtsoap.h -o moc_qtsoap.cpp
|
||||
|
||||
compiler_rcc_make_all:
|
||||
compiler_rcc_clean:
|
||||
compiler_image_collection_make_all: qmake_image_collection.cpp
|
||||
compiler_image_collection_clean:
|
||||
-$(DEL_FILE) qmake_image_collection.cpp
|
||||
compiler_moc_source_make_all:
|
||||
compiler_moc_source_clean:
|
||||
compiler_rez_source_make_all:
|
||||
compiler_rez_source_clean:
|
||||
compiler_uic_make_all:
|
||||
compiler_uic_clean:
|
||||
compiler_yacc_decl_make_all:
|
||||
compiler_yacc_decl_clean:
|
||||
compiler_yacc_impl_make_all:
|
||||
compiler_yacc_impl_clean:
|
||||
compiler_lex_make_all:
|
||||
compiler_lex_clean:
|
||||
compiler_clean: compiler_moc_header_clean
|
||||
|
||||
####### Compile
|
||||
|
||||
filter_photosynth.o: filter_photosynth.cpp filter_photosynth.h \
|
||||
synthData.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o filter_photosynth.o filter_photosynth.cpp
|
||||
|
||||
downloader.o: downloader.cpp synthData.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o downloader.o downloader.cpp
|
||||
|
||||
qtsoap.o: ../../external/qtsoap-2.7_1/src/qtsoap.cpp ../../external/qtsoap-2.7_1/src/qtsoap.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o qtsoap.o ../../external/qtsoap-2.7_1/src/qtsoap.cpp
|
||||
|
||||
moc_filter_photosynth.o: moc_filter_photosynth.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_filter_photosynth.o moc_filter_photosynth.cpp
|
||||
|
||||
moc_synthData.o: moc_synthData.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_synthData.o moc_synthData.cpp
|
||||
|
||||
moc_qtsoap.o: moc_qtsoap.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_qtsoap.o moc_qtsoap.cpp
|
||||
|
||||
####### Install
|
||||
|
||||
install: FORCE
|
||||
|
||||
uninstall: FORCE
|
||||
|
||||
FORCE:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,217 +0,0 @@
|
||||
//--------------------------------------------------------------------------
|
||||
// Parsing of GPS info from exif header.
|
||||
//
|
||||
// Matthias Wandel, Dec 1999 - Dec 2002
|
||||
//--------------------------------------------------------------------------
|
||||
#include "jhead.h"
|
||||
|
||||
#define MAX_GPS_TAG 0x1e
|
||||
|
||||
|
||||
#define TAG_GPS_LAT_REF 1
|
||||
#define TAG_GPS_LAT 2
|
||||
#define TAG_GPS_LONG_REF 3
|
||||
#define TAG_GPS_LONG 4
|
||||
#define TAG_GPS_ALT_REF 5
|
||||
#define TAG_GPS_ALT 6
|
||||
|
||||
|
||||
static const char * GpsTags[MAX_GPS_TAG+1]= {
|
||||
"VersionID ",//0x00
|
||||
"LatitudeRef ",//0x01
|
||||
"Latitude ",//0x02
|
||||
"LongitudeRef ",//0x03
|
||||
"Longitude ",//0x04
|
||||
"AltitudeRef ",//0x05
|
||||
"Altitude ",//0x06
|
||||
"TimeStamp ",//0x07
|
||||
"Satellites ",//0x08
|
||||
"Status ",//0x09
|
||||
"MeasureMode ",//0x0A
|
||||
"DOP ",//0x0B
|
||||
"SpeedRef ",//0x0C
|
||||
"Speed ",//0x0D
|
||||
"TrackRef ",//0x0E
|
||||
"Track ",//0x0F
|
||||
"ImgDirectionRef ",//0x10
|
||||
"ImgDirection ",//0x11
|
||||
"MapDatum ",//0x12
|
||||
"DestLatitudeRef ",//0x13
|
||||
"DestLatitude ",//0x14
|
||||
"DestLongitudeRef",//0x15
|
||||
"DestLongitude ",//0x16
|
||||
"DestBearingRef ",//0x17
|
||||
"DestBearing ",//0x18
|
||||
"DestDistanceRef ",//0x19
|
||||
"DestDistance ",//0x1A
|
||||
"ProcessingMethod",//0x1B
|
||||
"AreaInformation ",//0x1C
|
||||
"DateStamp ",//0x1D
|
||||
"Differential ",//0x1E
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Process GPS info directory
|
||||
//--------------------------------------------------------------------------
|
||||
void ProcessGpsInfo(unsigned char * DirStart, int ByteCountUnused, unsigned char * OffsetBase, unsigned ExifLength)
|
||||
{
|
||||
int de;
|
||||
unsigned a;
|
||||
int NumDirEntries;
|
||||
|
||||
NumDirEntries = Get16u(DirStart);
|
||||
#define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
|
||||
|
||||
if (ShowTags){
|
||||
printf("(dir has %d entries)\n",NumDirEntries);
|
||||
}
|
||||
|
||||
ImageInfo.GpsInfoPresent = TRUE;
|
||||
strcpy(ImageInfo.GpsLat, "? ?");
|
||||
strcpy(ImageInfo.GpsLong, "? ?");
|
||||
ImageInfo.GpsAlt[0] = 0;
|
||||
|
||||
for (de=0;de<NumDirEntries;de++){
|
||||
unsigned Tag, Format, Components;
|
||||
unsigned char * ValuePtr;
|
||||
int ComponentSize;
|
||||
unsigned ByteCount;
|
||||
unsigned char * DirEntry;
|
||||
DirEntry = DIR_ENTRY_ADDR(DirStart, de);
|
||||
|
||||
if (DirEntry+12 > OffsetBase+ExifLength){
|
||||
ErrNonfatal("GPS info directory goes past end of exif",0,0);
|
||||
return;
|
||||
}
|
||||
|
||||
Tag = Get16u(DirEntry);
|
||||
Format = Get16u(DirEntry+2);
|
||||
Components = Get32u(DirEntry+4);
|
||||
|
||||
if ((Format-1) >= NUM_FORMATS) {
|
||||
// (-1) catches illegal zero case as unsigned underflows to positive large.
|
||||
ErrNonfatal("Illegal number format %d for Exif gps tag %04x", Format, Tag);
|
||||
continue;
|
||||
}
|
||||
|
||||
ComponentSize = BytesPerFormat[Format];
|
||||
ByteCount = Components * ComponentSize;
|
||||
|
||||
if (ByteCount > 4){
|
||||
unsigned OffsetVal;
|
||||
OffsetVal = Get32u(DirEntry+8);
|
||||
// If its bigger than 4 bytes, the dir entry contains an offset.
|
||||
if (OffsetVal+ByteCount > ExifLength){
|
||||
// Bogus pointer offset and / or bytecount value
|
||||
ErrNonfatal("Illegal value pointer for Exif gps tag %04x", Tag,0);
|
||||
continue;
|
||||
}
|
||||
ValuePtr = OffsetBase+OffsetVal;
|
||||
}else{
|
||||
// 4 bytes or less and value is in the dir entry itself
|
||||
ValuePtr = DirEntry+8;
|
||||
}
|
||||
|
||||
switch(Tag){
|
||||
char FmtString[21];
|
||||
char TempString[50];
|
||||
double Values[3];
|
||||
|
||||
case TAG_GPS_LAT_REF:
|
||||
ImageInfo.GpsLat[0] = ValuePtr[0];
|
||||
break;
|
||||
|
||||
case TAG_GPS_LONG_REF:
|
||||
ImageInfo.GpsLong[0] = ValuePtr[0];
|
||||
break;
|
||||
|
||||
case TAG_GPS_LAT:
|
||||
case TAG_GPS_LONG:
|
||||
if (Format != FMT_URATIONAL){
|
||||
ErrNonfatal("Inappropriate format (%d) for Exif GPS coordinates!", Format, 0);
|
||||
}
|
||||
strcpy(FmtString, "%0.0fd %0.0fm %0.0fs");
|
||||
for (a=0;a<3;a++){
|
||||
int den, digits;
|
||||
|
||||
den = Get32s(ValuePtr+4+a*ComponentSize);
|
||||
digits = 0;
|
||||
while (den > 1 && digits <= 6){
|
||||
den = den / 10;
|
||||
digits += 1;
|
||||
}
|
||||
if (digits > 6) digits = 6;
|
||||
FmtString[1+a*7] = (char)('2'+digits+(digits ? 1 : 0));
|
||||
FmtString[3+a*7] = (char)('0'+digits);
|
||||
|
||||
Values[a] = ConvertAnyFormat(ValuePtr+a*ComponentSize, Format);
|
||||
}
|
||||
|
||||
sprintf(TempString, FmtString, Values[0], Values[1], Values[2]);
|
||||
|
||||
if (Tag == TAG_GPS_LAT){
|
||||
strncpy(ImageInfo.GpsLat+2, TempString, 29);
|
||||
}else{
|
||||
strncpy(ImageInfo.GpsLong+2, TempString, 29);
|
||||
}
|
||||
break;
|
||||
|
||||
case TAG_GPS_ALT_REF:
|
||||
ImageInfo.GpsAlt[0] = (char)(ValuePtr[0] ? '-' : ' ');
|
||||
break;
|
||||
|
||||
case TAG_GPS_ALT:
|
||||
sprintf(ImageInfo.GpsAlt + 1, "%.2fm",
|
||||
ConvertAnyFormat(ValuePtr, Format));
|
||||
break;
|
||||
}
|
||||
|
||||
if (ShowTags){
|
||||
// Show tag value.
|
||||
if (Tag < MAX_GPS_TAG){
|
||||
printf(" GPS%s =", GpsTags[Tag]);
|
||||
}else{
|
||||
// Show unknown tag
|
||||
printf(" Illegal GPS tag %04x=", Tag);
|
||||
}
|
||||
|
||||
switch(Format){
|
||||
case FMT_UNDEFINED:
|
||||
// Undefined is typically an ascii string.
|
||||
|
||||
case FMT_STRING:
|
||||
// String arrays printed without function call (different from int arrays)
|
||||
{
|
||||
printf("\"");
|
||||
for (a=0;a<ByteCount;a++){
|
||||
int ZeroSkipped = 0;
|
||||
if (ValuePtr[a] >= 32){
|
||||
if (ZeroSkipped){
|
||||
printf("?");
|
||||
ZeroSkipped = 0;
|
||||
}
|
||||
putchar(ValuePtr[a]);
|
||||
}else{
|
||||
if (ValuePtr[a] == 0){
|
||||
ZeroSkipped = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\"\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Handle arrays of numbers later (will there ever be?)
|
||||
for (a=0;;){
|
||||
PrintFormatNumber(ValuePtr+a*ComponentSize, Format, ByteCount);
|
||||
if (++a >= Components) break;
|
||||
printf(", ");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,219 +0,0 @@
|
||||
//--------------------------------------------------------------------------
|
||||
// Process IPTC data and XMP data.
|
||||
//--------------------------------------------------------------------------
|
||||
#include "jhead.h"
|
||||
|
||||
// IPTC entry types known to Jhead (there's many more defined)
|
||||
#define IPTC_RECORD_VERSION 0x00
|
||||
#define IPTC_SUPLEMENTAL_CATEGORIES 0x14
|
||||
#define IPTC_KEYWORDS 0x19
|
||||
#define IPTC_CAPTION 0x78
|
||||
#define IPTC_AUTHOR 0x7A
|
||||
#define IPTC_HEADLINE 0x69
|
||||
#define IPTC_SPECIAL_INSTRUCTIONS 0x28
|
||||
#define IPTC_CATEGORY 0x0F
|
||||
#define IPTC_BYLINE 0x50
|
||||
#define IPTC_BYLINE_TITLE 0x55
|
||||
#define IPTC_CREDIT 0x6E
|
||||
#define IPTC_SOURCE 0x73
|
||||
#define IPTC_COPYRIGHT_NOTICE 0x74
|
||||
#define IPTC_OBJECT_NAME 0x05
|
||||
#define IPTC_CITY 0x5A
|
||||
#define IPTC_STATE 0x5F
|
||||
#define IPTC_COUNTRY 0x65
|
||||
#define IPTC_TRANSMISSION_REFERENCE 0x67
|
||||
#define IPTC_DATE 0x37
|
||||
#define IPTC_COPYRIGHT 0x0A
|
||||
#define IPTC_COUNTRY_CODE 0x64
|
||||
#define IPTC_REFERENCE_SERVICE 0x2D
|
||||
#define IPTC_TIME_CREATED 0x3C
|
||||
#define IPTC_SUB_LOCATION 0x5C
|
||||
#define IPTC_IMAGE_TYPE 0x82
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Process and display IPTC marker.
|
||||
//
|
||||
// IPTC block consists of:
|
||||
// - Marker: 1 byte (0xED)
|
||||
// - Block length: 2 bytes
|
||||
// - IPTC Signature: 14 bytes ("Photoshop 3.0\0")
|
||||
// - 8BIM Signature 4 bytes ("8BIM")
|
||||
// - IPTC Block start 2 bytes (0x04, 0x04)
|
||||
// - IPTC Header length 1 byte
|
||||
// - IPTC header Header is padded to even length, counting the length byte
|
||||
// - Length 4 bytes
|
||||
// - IPTC Data which consists of a number of entries, each of which has the following format:
|
||||
// - Signature 2 bytes (0x1C02)
|
||||
// - Entry type 1 byte (for defined entry types, see #defines above)
|
||||
// - entry length 2 bytes
|
||||
// - entry data 'entry length' bytes
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
void show_IPTC (unsigned char* Data, unsigned int itemlen)
|
||||
{
|
||||
const char IptcSig1[] = "Photoshop 3.0";
|
||||
const char IptcSig2[] = "8BIM";
|
||||
const char IptcSig3[] = {0x04, 0x04};
|
||||
|
||||
unsigned char * pos = Data + sizeof(short); // position data pointer after length field
|
||||
unsigned char * maxpos = Data+itemlen;
|
||||
unsigned char headerLen = 0;
|
||||
unsigned char dataLen = 0;
|
||||
|
||||
if (itemlen < 25) goto corrupt;
|
||||
|
||||
// Check IPTC signatures
|
||||
if (memcmp(pos, IptcSig1, sizeof(IptcSig1)-1) != 0) goto badsig;
|
||||
pos += sizeof(IptcSig1); // move data pointer to the next field
|
||||
|
||||
if (memcmp(pos, IptcSig2, sizeof(IptcSig2)-1) != 0) goto badsig;
|
||||
pos += sizeof(IptcSig2)-1; // move data pointer to the next field
|
||||
|
||||
|
||||
while (memcmp(pos, IptcSig3, sizeof(IptcSig3)) != 0) { // loop on valid Photoshop blocks
|
||||
|
||||
pos += sizeof(IptcSig3); // move data pointer to the Header Length
|
||||
// Skip header
|
||||
headerLen = *pos; // get header length and move data pointer to the next field
|
||||
pos += (headerLen & 0xfe) + 2; // move data pointer to the next field (Header is padded to even length, counting the length byte)
|
||||
|
||||
pos += 3; // move data pointer to length, assume only one byte, TODO: use all 4 bytes
|
||||
|
||||
dataLen = *pos++;
|
||||
pos += dataLen; // skip data section
|
||||
|
||||
if (memcmp(pos, IptcSig2, sizeof(IptcSig2) - 1) != 0) {
|
||||
badsig: if (ShowTags) {
|
||||
ErrNonfatal("IPTC type signature mismatch\n", 0, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
pos += sizeof(IptcSig2) - 1; // move data pointer to the next field
|
||||
}
|
||||
|
||||
pos += sizeof(IptcSig3); // move data pointer to the next field
|
||||
|
||||
if (pos >= maxpos) goto corrupt;
|
||||
|
||||
// IPTC section found
|
||||
|
||||
// Skip header
|
||||
headerLen = *pos++; // get header length and move data pointer to the next field
|
||||
pos += headerLen + 1 - (headerLen % 2); // move data pointer to the next field (Header is padded to even length, counting the length byte)
|
||||
|
||||
if (pos+4 >= maxpos) goto corrupt;
|
||||
|
||||
// Get length (from motorola format)
|
||||
//length = (*pos << 24) | (*(pos+1) << 16) | (*(pos+2) << 8) | *(pos+3);
|
||||
|
||||
pos += 4; // move data pointer to the next field
|
||||
|
||||
printf("======= IPTC data: =======\n");
|
||||
|
||||
// Now read IPTC data
|
||||
while (pos < (Data + itemlen-5)) {
|
||||
short signature;
|
||||
unsigned char type = 0;
|
||||
short length = 0;
|
||||
char * description = NULL;
|
||||
|
||||
if (pos+5 > maxpos) goto corrupt;
|
||||
|
||||
signature = (*pos << 8) + (*(pos+1));
|
||||
pos += 2;
|
||||
|
||||
if (signature != 0x1C01 && signature != 0x1c02) break;
|
||||
|
||||
type = *pos++;
|
||||
length = (*pos << 8) + (*(pos+1));
|
||||
pos += 2; // Skip tag length
|
||||
|
||||
if (pos+length > maxpos) goto corrupt;
|
||||
// Process tag here
|
||||
switch (type) {
|
||||
case IPTC_RECORD_VERSION:
|
||||
printf("Record vers. : %d\n", (*pos << 8) + (*(pos+1)));
|
||||
break;
|
||||
|
||||
case IPTC_SUPLEMENTAL_CATEGORIES: description = "SuplementalCategories"; break;
|
||||
case IPTC_KEYWORDS: description = "Keywords"; break;
|
||||
case IPTC_CAPTION: description = "Caption"; break;
|
||||
case IPTC_AUTHOR: description = "Author"; break;
|
||||
case IPTC_HEADLINE: description = "Headline"; break;
|
||||
case IPTC_SPECIAL_INSTRUCTIONS: description = "Spec. Instr."; break;
|
||||
case IPTC_CATEGORY: description = "Category"; break;
|
||||
case IPTC_BYLINE: description = "Byline"; break;
|
||||
case IPTC_BYLINE_TITLE: description = "Byline Title"; break;
|
||||
case IPTC_CREDIT: description = "Credit"; break;
|
||||
case IPTC_SOURCE: description = "Source"; break;
|
||||
case IPTC_COPYRIGHT_NOTICE: description = "(C)Notice"; break;
|
||||
case IPTC_OBJECT_NAME: description = "Object Name"; break;
|
||||
case IPTC_CITY: description = "City"; break;
|
||||
case IPTC_STATE: description = "State"; break;
|
||||
case IPTC_COUNTRY: description = "Country"; break;
|
||||
case IPTC_TRANSMISSION_REFERENCE: description = "OriginalTransmissionReference"; break;
|
||||
case IPTC_DATE: description = "DateCreated"; break;
|
||||
case IPTC_COPYRIGHT: description = "(C)Flag"; break;
|
||||
case IPTC_REFERENCE_SERVICE: description = "Country Code"; break;
|
||||
case IPTC_COUNTRY_CODE: description = "Ref. Service"; break;
|
||||
case IPTC_TIME_CREATED: description = "Time Created"; break;
|
||||
case IPTC_SUB_LOCATION: description = "Sub Location"; break;
|
||||
case IPTC_IMAGE_TYPE: description = "Image type"; break;
|
||||
|
||||
default:
|
||||
if (ShowTags){
|
||||
printf("Unrecognised IPTC tag: %d\n", type );
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (description != NULL) {
|
||||
char TempBuf[32];
|
||||
memset(TempBuf, 0, sizeof(TempBuf));
|
||||
memset(TempBuf, ' ', 14);
|
||||
memcpy(TempBuf, description, strlen(description));
|
||||
strcat(TempBuf, ":");
|
||||
printf("%s %*.*s\n", TempBuf, length, length, pos);
|
||||
}
|
||||
pos += length;
|
||||
}
|
||||
return;
|
||||
corrupt:
|
||||
ErrNonfatal("Pointer corruption in IPTC\n",0,0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Dump contents of XMP section
|
||||
//--------------------------------------------------------------------------
|
||||
void ShowXmp(Section_t XmpSection)
|
||||
{
|
||||
unsigned char * Data;
|
||||
char OutLine[101];
|
||||
int OutLineChars;
|
||||
int NonBlank;
|
||||
unsigned a;
|
||||
NonBlank = 0;
|
||||
Data = XmpSection.Data;
|
||||
OutLineChars = 0;
|
||||
|
||||
|
||||
for (a=0;a<XmpSection.Size;a++){
|
||||
if (Data[a] >= 32 && Data[a] < 128){
|
||||
OutLine[OutLineChars++] = Data[a];
|
||||
if (Data[a] != ' ') NonBlank |= 1;
|
||||
}else{
|
||||
if (Data[a] != '\n'){
|
||||
OutLine[OutLineChars++] = '?';
|
||||
}
|
||||
}
|
||||
if (Data[a] == '\n' || OutLineChars >= 100){
|
||||
OutLine[OutLineChars] = 0;
|
||||
if (NonBlank){
|
||||
puts(OutLine);
|
||||
}
|
||||
NonBlank = (NonBlank & 1) << 1;
|
||||
OutLineChars = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,133 +0,0 @@
|
||||
//--------------------------------------------------------------------------
|
||||
// Program to pull the information out of various types of EXIF digital
|
||||
// camera files and show it in a reasonably consistent way
|
||||
//
|
||||
// Version 2.90
|
||||
//
|
||||
// Compiling under Windows:
|
||||
// Make sure you have Microsoft's compiler on the path, then run make.bat
|
||||
//
|
||||
// Dec 1999 - Feb 2010
|
||||
//
|
||||
// by Matthias Wandel www.sentex.net/~mwandel
|
||||
//--------------------------------------------------------------------------
|
||||
#include "jhead.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define JHEAD_VERSION "2.90"
|
||||
|
||||
// This #define turns on features that are too very specific to
|
||||
// how I organize my photos. Best to ignore everything inside #ifdef MATTHIAS
|
||||
//#define MATTHIAS
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
static int FilesMatched;
|
||||
static int FileSequence;
|
||||
|
||||
static const char * CurrentFile;
|
||||
|
||||
static const char * progname; // program name for error messages
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Command line options flags
|
||||
static int TrimExif = FALSE; // Cut off exif beyond interesting data.
|
||||
static int RenameToDate = 0; // 1=rename, 2=rename all.
|
||||
#ifdef _WIN32
|
||||
static int RenameAssociatedFiles = FALSE;
|
||||
#endif
|
||||
static char * strftime_args = NULL; // Format for new file name.
|
||||
static int Exif2FileTime = FALSE;
|
||||
static int DoModify = FALSE;
|
||||
static int DoReadAction = FALSE;
|
||||
int ShowTags = FALSE; // Do not show raw by default.
|
||||
static int Quiet = FALSE; // Be quiet on success (like unix programs)
|
||||
int DumpExifMap = FALSE;
|
||||
static int ShowConcise = FALSE;
|
||||
static int CreateExifSection = FALSE;
|
||||
static char * ApplyCommand = NULL; // Apply this command to all images.
|
||||
static char * FilterModel = NULL;
|
||||
static int ExifOnly = FALSE;
|
||||
static int PortraitOnly = FALSE;
|
||||
static time_t ExifTimeAdjust = 0; // Timezone adjust
|
||||
static time_t ExifTimeSet = 0; // Set exif time to a value.
|
||||
static char DateSet[11];
|
||||
static unsigned DateSetChars = 0;
|
||||
static unsigned FileTimeToExif = FALSE;
|
||||
|
||||
static int DeleteComments = FALSE;
|
||||
static int DeleteExif = FALSE;
|
||||
static int DeleteIptc = FALSE;
|
||||
static int DeleteXmp = FALSE;
|
||||
static int DeleteUnknown = FALSE;
|
||||
static char * ThumbSaveName = NULL; // If not NULL, use this string to make up
|
||||
// the filename to store the thumbnail to.
|
||||
|
||||
static char * ThumbInsertName = NULL; // If not NULL, use this string to make up
|
||||
// the filename to retrieve the thumbnail from.
|
||||
|
||||
static int RegenThumbnail = FALSE;
|
||||
|
||||
static char * ExifXferScrFile = NULL;// Extract Exif header from this file, and
|
||||
// put it into the Jpegs processed.
|
||||
|
||||
static int EditComment = FALSE; // Invoke an editor for editing the comment
|
||||
static int SupressNonFatalErrors = FALSE; // Wether or not to pint warnings on recoverable errors
|
||||
|
||||
static char * CommentSavefileName = NULL; // Save comment to this file.
|
||||
static char * CommentInsertfileName = NULL; // Insert comment from this file.
|
||||
static char * CommentInsertLiteral = NULL; // Insert this comment (from command line)
|
||||
|
||||
static int AutoRotate = FALSE;
|
||||
static int ZeroRotateTagOnly = FALSE;
|
||||
|
||||
static int ShowFileInfo = TRUE; // Indicates to show standard file info
|
||||
// (file name, file size, file date)
|
||||
|
||||
|
||||
#ifdef MATTHIAS
|
||||
// This #ifdef to take out less than elegant stuff for editing
|
||||
// the comments in a JPEG. The programs rdjpgcom and wrjpgcom
|
||||
// included with Linux distributions do a better job.
|
||||
|
||||
static char * AddComment = NULL; // Add this tag.
|
||||
static char * RemComment = NULL; // Remove this tag
|
||||
static int AutoResize = FALSE;
|
||||
#endif // MATTHIAS
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Error exit handler
|
||||
//--------------------------------------------------------------------------
|
||||
void ErrFatal(char * msg)
|
||||
{
|
||||
fprintf(stderr,"\nError : %s\n", msg);
|
||||
if (CurrentFile) fprintf(stderr,"in file '%s'\n",CurrentFile);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Report non fatal errors. Now that microsoft.net modifies exif headers,
|
||||
// there's corrupted ones, and there could be more in the future.
|
||||
//--------------------------------------------------------------------------
|
||||
void ErrNonfatal(char * msg, int a1, int a2)
|
||||
{
|
||||
if (SupressNonFatalErrors) return;
|
||||
|
||||
fprintf(stderr,"\nNonfatal Error : ");
|
||||
if (CurrentFile) fprintf(stderr,"'%s' ",CurrentFile);
|
||||
fprintf(stderr, msg, a1, a2);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Set file time as exif time.
|
||||
//--------------------------------------------------------------------------
|
||||
void FileTimeAsString(char * TimeStr)
|
||||
{
|
||||
struct tm ts;
|
||||
ts = *localtime(&ImageInfo.FileDateTime);
|
||||
strftime(TimeStr, 20, "%Y:%m:%d %H:%M:%S", &ts);
|
||||
}
|
||||
@ -1,254 +0,0 @@
|
||||
//--------------------------------------------------------------------------
|
||||
// Include file for jhead program.
|
||||
//
|
||||
// This include file only defines stuff that goes across modules.
|
||||
// I like to keep the definitions for macros and structures as close to
|
||||
// where they get used as possible, so include files only get stuff that
|
||||
// gets used in more than one file.
|
||||
//--------------------------------------------------------------------------
|
||||
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <sys/utime.h>
|
||||
#else
|
||||
#include <utime.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define MAX_COMMENT_SIZE 2000
|
||||
|
||||
#ifdef _WIN32
|
||||
#define JHEAD_PATH_MAX _MAX_PATH
|
||||
#define SLASH '\\'
|
||||
#else
|
||||
#ifndef JHEAD_PATH_MAX
|
||||
#define JHEAD_PATH_MAX 1024
|
||||
#endif
|
||||
#define SLASH '/'
|
||||
#endif
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// This structure is used to store jpeg file sections in memory.
|
||||
typedef struct {
|
||||
uchar * Data;
|
||||
int Type;
|
||||
unsigned Size;
|
||||
}Section_t;
|
||||
|
||||
extern int ExifSectionIndex;
|
||||
|
||||
extern int DumpExifMap;
|
||||
|
||||
#define MAX_DATE_COPIES 10
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// This structure stores Exif header image elements in a simple manner
|
||||
// Used to store camera data as extracted from the various ways that it can be
|
||||
// stored in an exif header
|
||||
typedef struct {
|
||||
char FileName [JHEAD_PATH_MAX+1];
|
||||
time_t FileDateTime;
|
||||
|
||||
struct {
|
||||
// Info in the jfif header.
|
||||
// This info is not used much - jhead used to just replace it with default
|
||||
// values, and over 10 years, only two people pointed this out.
|
||||
char Present;
|
||||
char ResolutionUnits;
|
||||
short XDensity;
|
||||
short YDensity;
|
||||
}JfifHeader;
|
||||
|
||||
unsigned FileSize;
|
||||
char CameraMake [32];
|
||||
char CameraModel [40];
|
||||
char DateTime [20];
|
||||
int Height, Width;
|
||||
int Orientation;
|
||||
int IsColor;
|
||||
int Process;
|
||||
int FlashUsed;
|
||||
float FocalLength;
|
||||
float ExposureTime;
|
||||
float ApertureFNumber;
|
||||
float Distance;
|
||||
float CCDWidth;
|
||||
float ExposureBias;
|
||||
float DigitalZoomRatio;
|
||||
int FocalLength35mmEquiv; // Exif 2.2 tag - usually not present.
|
||||
int Whitebalance;
|
||||
int MeteringMode;
|
||||
int ExposureProgram;
|
||||
int ExposureMode;
|
||||
int ISOequivalent;
|
||||
int LightSource;
|
||||
int DistanceRange;
|
||||
|
||||
float xResolution;
|
||||
float yResolution;
|
||||
int ResolutionUnit;
|
||||
|
||||
char Comments[MAX_COMMENT_SIZE];
|
||||
int CommentWidthchars; // If nonzero, widechar comment, indicates number of chars.
|
||||
|
||||
unsigned ThumbnailOffset; // Exif offset to thumbnail
|
||||
unsigned ThumbnailSize; // Size of thumbnail.
|
||||
unsigned LargestExifOffset; // Last exif data referenced (to check if thumbnail is at end)
|
||||
|
||||
char ThumbnailAtEnd; // Exif header ends with the thumbnail
|
||||
// (we can only modify the thumbnail if its at the end)
|
||||
int ThumbnailSizeOffset;
|
||||
|
||||
int DateTimeOffsets[MAX_DATE_COPIES];
|
||||
int numDateTimeTags;
|
||||
|
||||
int GpsInfoPresent;
|
||||
char GpsLat[31];
|
||||
char GpsLong[31];
|
||||
char GpsAlt[20];
|
||||
}ImageInfo_t;
|
||||
|
||||
|
||||
|
||||
#define EXIT_FAILURE 1
|
||||
#define EXIT_SUCCESS 0
|
||||
|
||||
// jpgfile.c functions
|
||||
typedef enum {
|
||||
READ_METADATA = 1,
|
||||
READ_IMAGE = 2,
|
||||
READ_ALL = 3
|
||||
}ReadMode_t;
|
||||
|
||||
|
||||
// prototypes for jhead.c functions
|
||||
void ErrFatal(char * msg);
|
||||
void ErrNonfatal(char * msg, int a1, int a2);
|
||||
void FileTimeAsString(char * TimeStr);
|
||||
|
||||
// Prototypes for exif.c functions.
|
||||
int Exif2tm(struct tm * timeptr, char * ExifTime);
|
||||
void process_EXIF (unsigned char * CharBuf, unsigned int length);
|
||||
int RemoveThumbnail(unsigned char * ExifSection);
|
||||
void ShowImageInfo(int ShowFileInfo);
|
||||
void ShowConciseImageInfo(void);
|
||||
const char * ClearOrientation(void);
|
||||
void PrintFormatNumber(void * ValuePtr, int Format, int ByteCount);
|
||||
double ConvertAnyFormat(void * ValuePtr, int Format);
|
||||
int Get16u(void * Short);
|
||||
unsigned Get32u(void * Long);
|
||||
int Get32s(void * Long);
|
||||
void Put32u(void * Value, unsigned PutValue);
|
||||
void create_EXIF(void);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Exif format descriptor stuff
|
||||
extern const int BytesPerFormat[];
|
||||
#define NUM_FORMATS 12
|
||||
|
||||
#define FMT_BYTE 1
|
||||
#define FMT_STRING 2
|
||||
#define FMT_USHORT 3
|
||||
#define FMT_ULONG 4
|
||||
#define FMT_URATIONAL 5
|
||||
#define FMT_SBYTE 6
|
||||
#define FMT_UNDEFINED 7
|
||||
#define FMT_SSHORT 8
|
||||
#define FMT_SLONG 9
|
||||
#define FMT_SRATIONAL 10
|
||||
#define FMT_SINGLE 11
|
||||
#define FMT_DOUBLE 12
|
||||
|
||||
|
||||
// makernote.c prototypes
|
||||
extern void ProcessMakerNote(unsigned char * DirStart, int ByteCount,
|
||||
unsigned char * OffsetBase, unsigned ExifLength);
|
||||
|
||||
// gpsinfo.c prototypes
|
||||
void ProcessGpsInfo(unsigned char * ValuePtr, int ByteCount,
|
||||
unsigned char * OffsetBase, unsigned ExifLength);
|
||||
|
||||
// iptc.c prototpyes
|
||||
void show_IPTC (unsigned char * CharBuf, unsigned int length);
|
||||
void ShowXmp(Section_t XmpSection);
|
||||
|
||||
// Prototypes for myglob.c module
|
||||
#ifdef _WIN32
|
||||
void MyGlob(const char * Pattern , void (*FileFuncParm)(const char * FileName));
|
||||
void SlashToNative(char * Path);
|
||||
#endif
|
||||
|
||||
// Prototypes for paths.c module
|
||||
int EnsurePathExists(const char * FileName);
|
||||
void CatPath(char * BasePath, const char * FilePath);
|
||||
|
||||
// Prototypes from jpgfile.c
|
||||
int ReadJpegSections (FILE * infile, ReadMode_t ReadMode);
|
||||
void DiscardData(void);
|
||||
void DiscardAllButExif(void);
|
||||
int ReadJpegFile(const char * FileName, ReadMode_t ReadMode);
|
||||
int ReplaceThumbnail(const char * ThumbFileName);
|
||||
int SaveThumbnail(char * ThumbFileName);
|
||||
int RemoveSectionType(int SectionType);
|
||||
int RemoveUnknownSections(void);
|
||||
void WriteJpegFile(const char * FileName);
|
||||
Section_t * FindSection(int SectionType);
|
||||
Section_t * CreateSection(int SectionType, unsigned char * Data, int size);
|
||||
void ResetJpgfile(void);
|
||||
|
||||
|
||||
// Variables from jhead.c used by exif.c
|
||||
extern ImageInfo_t ImageInfo;
|
||||
extern int ShowTags;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// JPEG markers consist of one or more 0xFF bytes, followed by a marker
|
||||
// code byte (which is not an FF). Here are the marker codes of interest
|
||||
// in this program. (See jdmarker.c for a more complete list.)
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#define M_SOF0 0xC0 // Start Of Frame N
|
||||
#define M_SOF1 0xC1 // N indicates which compression process
|
||||
#define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use
|
||||
#define M_SOF3 0xC3
|
||||
#define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers
|
||||
#define M_SOF6 0xC6
|
||||
#define M_SOF7 0xC7
|
||||
#define M_SOF9 0xC9
|
||||
#define M_SOF10 0xCA
|
||||
#define M_SOF11 0xCB
|
||||
#define M_SOF13 0xCD
|
||||
#define M_SOF14 0xCE
|
||||
#define M_SOF15 0xCF
|
||||
#define M_SOI 0xD8 // Start Of Image (beginning of datastream)
|
||||
#define M_EOI 0xD9 // End Of Image (end of datastream)
|
||||
#define M_SOS 0xDA // Start Of Scan (begins compressed data)
|
||||
#define M_JFIF 0xE0 // Jfif marker
|
||||
#define M_EXIF 0xE1 // Exif marker. Also used for XMP data!
|
||||
#define M_XMP 0x10E1 // Not a real tag (same value in file as Exif!)
|
||||
#define M_COM 0xFE // COMment
|
||||
#define M_DQT 0xDB
|
||||
#define M_DHT 0xC4
|
||||
#define M_DRI 0xDD
|
||||
#define M_IPTC 0xED // IPTC marker
|
||||
@ -1,630 +0,0 @@
|
||||
//--------------------------------------------------------------------------
|
||||
// Program to pull the information out of various types of EXIF digital
|
||||
// camera files and show it in a reasonably consistent way
|
||||
//
|
||||
// This module handles basic Jpeg file handling
|
||||
//
|
||||
// Matthias Wandel
|
||||
//--------------------------------------------------------------------------
|
||||
#include "jhead.h"
|
||||
|
||||
// Storage for simplified info extracted from file.
|
||||
ImageInfo_t ImageInfo;
|
||||
|
||||
|
||||
static Section_t * Sections = NULL;
|
||||
static int SectionsAllocated;
|
||||
static int SectionsRead;
|
||||
static int HaveAll;
|
||||
|
||||
|
||||
|
||||
#define PSEUDO_IMAGE_MARKER 0x123; // Extra value.
|
||||
//--------------------------------------------------------------------------
|
||||
// Get 16 bits motorola order (always) for jpeg header stuff.
|
||||
//--------------------------------------------------------------------------
|
||||
static int Get16m(const void * Short)
|
||||
{
|
||||
return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1];
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Process a COM marker.
|
||||
// We want to print out the marker contents as legible text;
|
||||
// we must guard against random junk and varying newline representations.
|
||||
//--------------------------------------------------------------------------
|
||||
static void process_COM (const uchar * Data, int length)
|
||||
{
|
||||
int ch;
|
||||
char Comment[MAX_COMMENT_SIZE+1];
|
||||
int nch;
|
||||
int a;
|
||||
|
||||
nch = 0;
|
||||
|
||||
if (length > MAX_COMMENT_SIZE) length = MAX_COMMENT_SIZE; // Truncate if it won't fit in our structure.
|
||||
|
||||
for (a=2;a<length;a++){
|
||||
ch = Data[a];
|
||||
|
||||
if (ch == '\r' && Data[a+1] == '\n') continue; // Remove cr followed by lf.
|
||||
|
||||
if (ch >= 32 || ch == '\n' || ch == '\t'){
|
||||
Comment[nch++] = (char)ch;
|
||||
}else{
|
||||
Comment[nch++] = '?';
|
||||
}
|
||||
}
|
||||
|
||||
Comment[nch] = '\0'; // Null terminate
|
||||
|
||||
if (ShowTags){
|
||||
printf("COM marker comment: %s\n",Comment);
|
||||
}
|
||||
|
||||
strcpy(ImageInfo.Comments,Comment);
|
||||
ImageInfo.CommentWidthchars = 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Process a SOFn marker. This is useful for the image dimensions
|
||||
//--------------------------------------------------------------------------
|
||||
static void process_SOFn (const uchar * Data, int marker)
|
||||
{
|
||||
int data_precision, num_components;
|
||||
|
||||
data_precision = Data[2];
|
||||
ImageInfo.Height = Get16m(Data+3);
|
||||
ImageInfo.Width = Get16m(Data+5);
|
||||
num_components = Data[7];
|
||||
|
||||
if (num_components == 3){
|
||||
ImageInfo.IsColor = 1;
|
||||
}else{
|
||||
ImageInfo.IsColor = 0;
|
||||
}
|
||||
|
||||
ImageInfo.Process = marker;
|
||||
|
||||
if (ShowTags){
|
||||
printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",
|
||||
ImageInfo.Width, ImageInfo.Height, num_components, data_precision);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Check sections array to see if it needs to be increased in size.
|
||||
//--------------------------------------------------------------------------
|
||||
void CheckSectionsAllocated(void)
|
||||
{
|
||||
if (SectionsRead > SectionsAllocated){
|
||||
ErrFatal("allocation screwup");
|
||||
}
|
||||
if (SectionsRead >= SectionsAllocated){
|
||||
SectionsAllocated += SectionsAllocated/2;
|
||||
Sections = (Section_t *)realloc(Sections, sizeof(Section_t)*SectionsAllocated);
|
||||
if (Sections == NULL){
|
||||
ErrFatal("could not allocate data for entire image");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Parse the marker stream until SOS or EOI is seen;
|
||||
//--------------------------------------------------------------------------
|
||||
int ReadJpegSections (FILE * infile, ReadMode_t ReadMode)
|
||||
{
|
||||
int a;
|
||||
int HaveCom = FALSE;
|
||||
|
||||
a = fgetc(infile);
|
||||
|
||||
if (a != 0xff || fgetc(infile) != M_SOI){
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ImageInfo.JfifHeader.XDensity = ImageInfo.JfifHeader.YDensity = 300;
|
||||
ImageInfo.JfifHeader.ResolutionUnits = 1;
|
||||
|
||||
for(;;){
|
||||
int itemlen;
|
||||
int prev;
|
||||
int marker = 0;
|
||||
int ll,lh, got;
|
||||
uchar * Data;
|
||||
|
||||
CheckSectionsAllocated();
|
||||
|
||||
prev = 0;
|
||||
for (a=0;;a++){
|
||||
marker = fgetc(infile);
|
||||
if (marker != 0xff && prev == 0xff) break;
|
||||
prev = marker;
|
||||
}
|
||||
|
||||
if (a > 10){
|
||||
ErrNonfatal("Extraneous %d padding bytes before section %02X",a-1,marker);
|
||||
}
|
||||
|
||||
Sections[SectionsRead].Type = marker;
|
||||
|
||||
// Read the length of the section.
|
||||
lh = fgetc(infile);
|
||||
ll = fgetc(infile);
|
||||
|
||||
itemlen = (lh << 8) | ll;
|
||||
|
||||
if (itemlen < 2){
|
||||
ErrFatal("invalid marker");
|
||||
}
|
||||
|
||||
Sections[SectionsRead].Size = itemlen;
|
||||
|
||||
Data = (uchar *)malloc(itemlen);
|
||||
if (Data == NULL){
|
||||
ErrFatal("Could not allocate memory");
|
||||
}
|
||||
Sections[SectionsRead].Data = Data;
|
||||
|
||||
// Store first two pre-read bytes.
|
||||
Data[0] = (uchar)lh;
|
||||
Data[1] = (uchar)ll;
|
||||
|
||||
got = fread(Data+2, 1, itemlen-2, infile); // Read the whole section.
|
||||
if (got != itemlen-2){
|
||||
ErrFatal("Premature end of file?");
|
||||
}
|
||||
SectionsRead += 1;
|
||||
|
||||
switch(marker){
|
||||
|
||||
case M_SOS: // stop before hitting compressed data
|
||||
// If reading entire image is requested, read the rest of the data.
|
||||
if (ReadMode & READ_IMAGE){
|
||||
int cp, ep, size;
|
||||
// Determine how much file is left.
|
||||
cp = ftell(infile);
|
||||
fseek(infile, 0, SEEK_END);
|
||||
ep = ftell(infile);
|
||||
fseek(infile, cp, SEEK_SET);
|
||||
|
||||
size = ep-cp;
|
||||
Data = (uchar *)malloc(size);
|
||||
if (Data == NULL){
|
||||
ErrFatal("could not allocate data for entire image");
|
||||
}
|
||||
|
||||
got = fread(Data, 1, size, infile);
|
||||
if (got != size){
|
||||
ErrFatal("could not read the rest of the image");
|
||||
}
|
||||
|
||||
CheckSectionsAllocated();
|
||||
Sections[SectionsRead].Data = Data;
|
||||
Sections[SectionsRead].Size = size;
|
||||
Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER;
|
||||
SectionsRead ++;
|
||||
HaveAll = 1;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case M_EOI: // in case it's a tables-only JPEG stream
|
||||
fprintf(stderr,"No image in jpeg!\n");
|
||||
return FALSE;
|
||||
|
||||
case M_COM: // Comment section
|
||||
if (HaveCom || ((ReadMode & READ_METADATA) == 0)){
|
||||
// Discard this section.
|
||||
free(Sections[--SectionsRead].Data);
|
||||
}else{
|
||||
process_COM(Data, itemlen);
|
||||
HaveCom = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case M_JFIF:
|
||||
// Regular jpegs always have this tag, exif images have the exif
|
||||
// marker instead, althogh ACDsee will write images with both markers.
|
||||
// this program will re-create this marker on absence of exif marker.
|
||||
// hence no need to keep the copy from the file.
|
||||
if (memcmp(Data+2, "JFIF\0",5)){
|
||||
fprintf(stderr,"Header missing JFIF marker\n");
|
||||
}
|
||||
if (itemlen < 16){
|
||||
fprintf(stderr,"Jfif header too short\n");
|
||||
goto ignore;
|
||||
}
|
||||
|
||||
ImageInfo.JfifHeader.Present = TRUE;
|
||||
ImageInfo.JfifHeader.ResolutionUnits = Data[9];
|
||||
ImageInfo.JfifHeader.XDensity = (Data[10]<<8) | Data[11];
|
||||
ImageInfo.JfifHeader.YDensity = (Data[12]<<8) | Data[13];
|
||||
if (ShowTags){
|
||||
printf("JFIF SOI marker: Units: %d ",ImageInfo.JfifHeader.ResolutionUnits);
|
||||
switch(ImageInfo.JfifHeader.ResolutionUnits){
|
||||
case 0: printf("(aspect ratio)"); break;
|
||||
case 1: printf("(dots per inch)"); break;
|
||||
case 2: printf("(dots per cm)"); break;
|
||||
default: printf("(unknown)"); break;
|
||||
}
|
||||
printf(" X-density=%d Y-density=%d\n",ImageInfo.JfifHeader.XDensity, ImageInfo.JfifHeader.YDensity);
|
||||
|
||||
if (Data[14] || Data[15]){
|
||||
fprintf(stderr,"Ignoring jfif header thumbnail\n");
|
||||
}
|
||||
}
|
||||
|
||||
ignore:
|
||||
|
||||
free(Sections[--SectionsRead].Data);
|
||||
break;
|
||||
|
||||
case M_EXIF:
|
||||
// There can be different section using the same marker.
|
||||
if (ReadMode & READ_METADATA){
|
||||
if (memcmp(Data+2, "Exif", 4) == 0){
|
||||
process_EXIF(Data, itemlen);
|
||||
break;
|
||||
}else if (memcmp(Data+2, "http:", 5) == 0){
|
||||
Sections[SectionsRead-1].Type = M_XMP; // Change tag for internal purposes.
|
||||
if (ShowTags){
|
||||
printf("Image cotains XMP section, %d bytes long\n", itemlen);
|
||||
if (ShowTags){
|
||||
ShowXmp(Sections[SectionsRead-1]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Oterwise, discard this section.
|
||||
free(Sections[--SectionsRead].Data);
|
||||
break;
|
||||
|
||||
case M_IPTC:
|
||||
if (ReadMode & READ_METADATA){
|
||||
if (ShowTags){
|
||||
printf("Image cotains IPTC section, %d bytes long\n", itemlen);
|
||||
}
|
||||
// Note: We just store the IPTC section. Its relatively straightforward
|
||||
// and we don't act on any part of it, so just display it at parse time.
|
||||
}else{
|
||||
free(Sections[--SectionsRead].Data);
|
||||
}
|
||||
break;
|
||||
|
||||
case M_SOF0:
|
||||
case M_SOF1:
|
||||
case M_SOF2:
|
||||
case M_SOF3:
|
||||
case M_SOF5:
|
||||
case M_SOF6:
|
||||
case M_SOF7:
|
||||
case M_SOF9:
|
||||
case M_SOF10:
|
||||
case M_SOF11:
|
||||
case M_SOF13:
|
||||
case M_SOF14:
|
||||
case M_SOF15:
|
||||
process_SOFn(Data, marker);
|
||||
break;
|
||||
default:
|
||||
// Skip any other sections.
|
||||
if (ShowTags){
|
||||
printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Discard read data.
|
||||
//--------------------------------------------------------------------------
|
||||
void DiscardData(void)
|
||||
{
|
||||
int a;
|
||||
|
||||
for (a=0;a<SectionsRead;a++){
|
||||
free(Sections[a].Data);
|
||||
}
|
||||
|
||||
memset(&ImageInfo, 0, sizeof(ImageInfo));
|
||||
SectionsRead = 0;
|
||||
HaveAll = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Read image data.
|
||||
//--------------------------------------------------------------------------
|
||||
int ReadJpegFile(const char * FileName, ReadMode_t ReadMode)
|
||||
{
|
||||
FILE * infile;
|
||||
int ret;
|
||||
|
||||
infile = fopen(FileName, "rb"); // Unix ignores 'b', windows needs it.
|
||||
|
||||
if (infile == NULL) {
|
||||
fprintf(stderr, "can't open '%s'\n", FileName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
// Scan the JPEG headers.
|
||||
ret = ReadJpegSections(infile, ReadMode);
|
||||
if (!ret){
|
||||
fprintf(stderr,"Not JPEG: %s\n",FileName);
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
|
||||
if (ret == FALSE){
|
||||
DiscardData();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Discard everything but the exif and comment sections.
|
||||
//--------------------------------------------------------------------------
|
||||
void DiscardAllButExif(void)
|
||||
{
|
||||
Section_t ExifKeeper;
|
||||
Section_t CommentKeeper;
|
||||
Section_t IptcKeeper;
|
||||
Section_t XmpKeeper;
|
||||
int a;
|
||||
|
||||
memset(&ExifKeeper, 0, sizeof(ExifKeeper));
|
||||
memset(&CommentKeeper, 0, sizeof(CommentKeeper));
|
||||
memset(&IptcKeeper, 0, sizeof(IptcKeeper));
|
||||
memset(&XmpKeeper, 0, sizeof(IptcKeeper));
|
||||
|
||||
for (a=0;a<SectionsRead;a++){
|
||||
if (Sections[a].Type == M_EXIF && ExifKeeper.Type == 0){
|
||||
ExifKeeper = Sections[a];
|
||||
}else if (Sections[a].Type == M_XMP && XmpKeeper.Type == 0){
|
||||
XmpKeeper = Sections[a];
|
||||
}else if (Sections[a].Type == M_COM && CommentKeeper.Type == 0){
|
||||
CommentKeeper = Sections[a];
|
||||
}else if (Sections[a].Type == M_IPTC && IptcKeeper.Type == 0){
|
||||
IptcKeeper = Sections[a];
|
||||
}else{
|
||||
free(Sections[a].Data);
|
||||
}
|
||||
}
|
||||
SectionsRead = 0;
|
||||
if (ExifKeeper.Type){
|
||||
CheckSectionsAllocated();
|
||||
Sections[SectionsRead++] = ExifKeeper;
|
||||
}
|
||||
if (CommentKeeper.Type){
|
||||
CheckSectionsAllocated();
|
||||
Sections[SectionsRead++] = CommentKeeper;
|
||||
}
|
||||
if (IptcKeeper.Type){
|
||||
CheckSectionsAllocated();
|
||||
Sections[SectionsRead++] = IptcKeeper;
|
||||
}
|
||||
|
||||
if (XmpKeeper.Type){
|
||||
CheckSectionsAllocated();
|
||||
Sections[SectionsRead++] = XmpKeeper;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Write image data back to disk.
|
||||
//--------------------------------------------------------------------------
|
||||
void WriteJpegFile(const char * FileName)
|
||||
{
|
||||
FILE * outfile;
|
||||
int a;
|
||||
|
||||
if (!HaveAll){
|
||||
ErrFatal("Can't write back - didn't read all");
|
||||
}
|
||||
|
||||
outfile = fopen(FileName,"wb");
|
||||
if (outfile == NULL){
|
||||
ErrFatal("Could not open file for write");
|
||||
}
|
||||
|
||||
// Initial static jpeg marker.
|
||||
fputc(0xff,outfile);
|
||||
fputc(0xd8,outfile);
|
||||
|
||||
if (Sections[0].Type != M_EXIF && Sections[0].Type != M_JFIF){
|
||||
// The image must start with an exif or jfif marker. If we threw those away, create one.
|
||||
static uchar JfifHead[18] = {
|
||||
0xff, M_JFIF,
|
||||
0x00, 0x10, 'J' , 'F' , 'I' , 'F' , 0x00, 0x01,
|
||||
0x01, 0x01, 0x01, 0x2C, 0x01, 0x2C, 0x00, 0x00
|
||||
};
|
||||
|
||||
if (ImageInfo.ResolutionUnit == 2 || ImageInfo.ResolutionUnit == 3){
|
||||
// Use the exif resolution info to fill out the jfif header.
|
||||
// Usually, for exif images, there's no jfif header, so if wediscard
|
||||
// the exif header, use info from the exif header for the jfif header.
|
||||
|
||||
ImageInfo.JfifHeader.ResolutionUnits = (char)(ImageInfo.ResolutionUnit-1);
|
||||
// Jfif is 1 and 2, Exif is 2 and 3 for In and cm respecively
|
||||
ImageInfo.JfifHeader.XDensity = (int)ImageInfo.xResolution;
|
||||
ImageInfo.JfifHeader.YDensity = (int)ImageInfo.yResolution;
|
||||
}
|
||||
|
||||
JfifHead[11] = ImageInfo.JfifHeader.ResolutionUnits;
|
||||
JfifHead[12] = (uchar)(ImageInfo.JfifHeader.XDensity >> 8);
|
||||
JfifHead[13] = (uchar)ImageInfo.JfifHeader.XDensity;
|
||||
JfifHead[14] = (uchar)(ImageInfo.JfifHeader.YDensity >> 8);
|
||||
JfifHead[15] = (uchar)ImageInfo.JfifHeader.YDensity;
|
||||
|
||||
|
||||
fwrite(JfifHead, 18, 1, outfile);
|
||||
|
||||
// use the values from the exif data for the jfif header, if we have found values
|
||||
if (ImageInfo.ResolutionUnit != 0) {
|
||||
// JFIF.ResolutionUnit is {1,2}, EXIF.ResolutionUnit is {2,3}
|
||||
JfifHead[11] = (uchar)ImageInfo.ResolutionUnit - 1;
|
||||
}
|
||||
if (ImageInfo.xResolution > 0.0 && ImageInfo.yResolution > 0.0) {
|
||||
JfifHead[12] = (uchar)((int)ImageInfo.xResolution>>8);
|
||||
JfifHead[13] = (uchar)((int)ImageInfo.xResolution);
|
||||
|
||||
JfifHead[14] = (uchar)((int)ImageInfo.yResolution>>8);
|
||||
JfifHead[15] = (uchar)((int)ImageInfo.yResolution);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write all the misc sections
|
||||
for (a=0;a<SectionsRead-1;a++){
|
||||
fputc(0xff,outfile);
|
||||
fputc((unsigned char)Sections[a].Type, outfile);
|
||||
fwrite(Sections[a].Data, Sections[a].Size, 1, outfile);
|
||||
}
|
||||
|
||||
// Write the remaining image data.
|
||||
fwrite(Sections[a].Data, Sections[a].Size, 1, outfile);
|
||||
|
||||
fclose(outfile);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Check if image has exif header.
|
||||
//--------------------------------------------------------------------------
|
||||
Section_t * FindSection(int SectionType)
|
||||
{
|
||||
int a;
|
||||
|
||||
for (a=0;a<SectionsRead;a++){
|
||||
if (Sections[a].Type == SectionType){
|
||||
return &Sections[a];
|
||||
}
|
||||
}
|
||||
// Could not be found.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Remove a certain type of section.
|
||||
//--------------------------------------------------------------------------
|
||||
int RemoveSectionType(int SectionType)
|
||||
{
|
||||
int a;
|
||||
for (a=0;a<SectionsRead-1;a++){
|
||||
if (Sections[a].Type == SectionType){
|
||||
// Free up this section
|
||||
free (Sections[a].Data);
|
||||
// Move succeding sections back by one to close space in array.
|
||||
memmove(Sections+a, Sections+a+1, sizeof(Section_t) * (SectionsRead-a));
|
||||
SectionsRead -= 1;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Remove sectons not part of image and not exif or comment sections.
|
||||
//--------------------------------------------------------------------------
|
||||
int RemoveUnknownSections(void)
|
||||
{
|
||||
int a;
|
||||
int Modified = FALSE;
|
||||
for (a=0;a<SectionsRead-1;){
|
||||
switch(Sections[a].Type){
|
||||
case M_SOF0:
|
||||
case M_SOF1:
|
||||
case M_SOF2:
|
||||
case M_SOF3:
|
||||
case M_SOF5:
|
||||
case M_SOF6:
|
||||
case M_SOF7:
|
||||
case M_SOF9:
|
||||
case M_SOF10:
|
||||
case M_SOF11:
|
||||
case M_SOF13:
|
||||
case M_SOF14:
|
||||
case M_SOF15:
|
||||
case M_SOI:
|
||||
case M_EOI:
|
||||
case M_SOS:
|
||||
case M_JFIF:
|
||||
case M_EXIF:
|
||||
case M_XMP:
|
||||
case M_COM:
|
||||
case M_DQT:
|
||||
case M_DHT:
|
||||
case M_DRI:
|
||||
case M_IPTC:
|
||||
// keep.
|
||||
a++;
|
||||
break;
|
||||
default:
|
||||
// Unknown. Delete.
|
||||
free (Sections[a].Data);
|
||||
// Move succeding sections back by one to close space in array.
|
||||
memmove(Sections+a, Sections+a+1, sizeof(Section_t) * (SectionsRead-a));
|
||||
SectionsRead -= 1;
|
||||
Modified = TRUE;
|
||||
}
|
||||
}
|
||||
return Modified;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Add a section (assume it doesn't already exist) - used for
|
||||
// adding comment sections and exif sections
|
||||
//--------------------------------------------------------------------------
|
||||
Section_t * CreateSection(int SectionType, unsigned char * Data, int Size)
|
||||
{
|
||||
Section_t * NewSection;
|
||||
int a;
|
||||
int NewIndex;
|
||||
NewIndex = 2;
|
||||
|
||||
if (SectionType == M_EXIF) NewIndex = 0; // Exif alwas goes first!
|
||||
|
||||
// Insert it in third position - seems like a safe place to put
|
||||
// things like comments.
|
||||
|
||||
if (SectionsRead < NewIndex){
|
||||
ErrFatal("Too few sections!");
|
||||
}
|
||||
|
||||
CheckSectionsAllocated();
|
||||
for (a=SectionsRead;a>NewIndex;a--){
|
||||
Sections[a] = Sections[a-1];
|
||||
}
|
||||
SectionsRead += 1;
|
||||
|
||||
NewSection = Sections+NewIndex;
|
||||
|
||||
NewSection->Type = SectionType;
|
||||
NewSection->Size = Size;
|
||||
NewSection->Data = Data;
|
||||
|
||||
return NewSection;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Initialisation.
|
||||
//--------------------------------------------------------------------------
|
||||
void ResetJpgfile(void)
|
||||
{
|
||||
if (Sections == NULL){
|
||||
Sections = (Section_t *)malloc(sizeof(Section_t)*5);
|
||||
SectionsAllocated = 5;
|
||||
}
|
||||
|
||||
SectionsRead = 0;
|
||||
HaveAll = 0;
|
||||
}
|
||||
@ -1,191 +0,0 @@
|
||||
//--------------------------------------------------------------------------
|
||||
// Parse some maker specific onformation.
|
||||
// (Very limited right now - add maker specific stuff to this module)
|
||||
//--------------------------------------------------------------------------
|
||||
#include "jhead.h"
|
||||
|
||||
extern int MotorolaOrder;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Process exif format directory, as used by Cannon maker note
|
||||
//--------------------------------------------------------------------------
|
||||
void ProcessCanonMakerNoteDir(unsigned char * DirStart, unsigned char * OffsetBase,
|
||||
unsigned ExifLength)
|
||||
{
|
||||
int de;
|
||||
int a;
|
||||
int NumDirEntries;
|
||||
|
||||
NumDirEntries = Get16u(DirStart);
|
||||
#define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
|
||||
|
||||
{
|
||||
unsigned char * DirEnd;
|
||||
DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries);
|
||||
if (DirEnd > (OffsetBase+ExifLength)){
|
||||
ErrNonfatal("Illegally sized Exif makernote subdir (%d entries)",NumDirEntries,0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DumpExifMap){
|
||||
printf("Map: %05d-%05d: Directory (makernote)\n",(int)(DirStart-OffsetBase), (int)(DirEnd-OffsetBase));
|
||||
}
|
||||
}
|
||||
|
||||
if (ShowTags){
|
||||
printf("(dir has %d entries)\n",NumDirEntries);
|
||||
}
|
||||
|
||||
for (de=0;de<NumDirEntries;de++){
|
||||
int Tag, Format, Components;
|
||||
unsigned char * ValuePtr;
|
||||
int ByteCount;
|
||||
unsigned char * DirEntry;
|
||||
DirEntry = DIR_ENTRY_ADDR(DirStart, de);
|
||||
|
||||
Tag = Get16u(DirEntry);
|
||||
Format = Get16u(DirEntry+2);
|
||||
Components = Get32u(DirEntry+4);
|
||||
|
||||
if ((Format-1) >= NUM_FORMATS) {
|
||||
// (-1) catches illegal zero case as unsigned underflows to positive large.
|
||||
ErrNonfatal("Illegal Exif number format %d for maker tag %04x", Format, Tag);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((unsigned)Components > 0x10000){
|
||||
ErrNonfatal("Too many components (%d) for Exif maker tag %04x", Components, Tag);
|
||||
continue;
|
||||
}
|
||||
|
||||
ByteCount = Components * BytesPerFormat[Format];
|
||||
|
||||
if (ByteCount > 4){
|
||||
unsigned OffsetVal;
|
||||
OffsetVal = Get32u(DirEntry+8);
|
||||
// If its bigger than 4 bytes, the dir entry contains an offset.
|
||||
if (OffsetVal+ByteCount > ExifLength){
|
||||
// Bogus pointer offset and / or bytecount value
|
||||
ErrNonfatal("Illegal value pointer for Exif maker tag %04x", Tag,0);
|
||||
continue;
|
||||
}
|
||||
ValuePtr = OffsetBase+OffsetVal;
|
||||
|
||||
if (DumpExifMap){
|
||||
printf("Map: %05d-%05d: Data for makernote tag %04x\n",OffsetVal, OffsetVal+ByteCount, Tag);
|
||||
}
|
||||
}else{
|
||||
// 4 bytes or less and value is in the dir entry itself
|
||||
ValuePtr = DirEntry+8;
|
||||
}
|
||||
|
||||
if (ShowTags){
|
||||
// Show tag name
|
||||
printf(" Canon maker tag %04x Value = ", Tag);
|
||||
}
|
||||
|
||||
// Show tag value.
|
||||
switch(Format){
|
||||
|
||||
case FMT_UNDEFINED:
|
||||
// Undefined is typically an ascii string.
|
||||
|
||||
case FMT_STRING:
|
||||
// String arrays printed without function call (different from int arrays)
|
||||
if (ShowTags){
|
||||
printf("\"");
|
||||
for (a=0;a<ByteCount;a++){
|
||||
int ZeroSkipped = 0;
|
||||
if (ValuePtr[a] >= 32){
|
||||
if (ZeroSkipped){
|
||||
printf("?");
|
||||
ZeroSkipped = 0;
|
||||
}
|
||||
putchar(ValuePtr[a]);
|
||||
}else{
|
||||
if (ValuePtr[a] == 0){
|
||||
ZeroSkipped = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\"\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ShowTags){
|
||||
PrintFormatNumber(ValuePtr, Format, ByteCount);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
if (Tag == 1 && Components > 16){
|
||||
int IsoCode = Get16u(ValuePtr + 16*sizeof(unsigned short));
|
||||
if (IsoCode >= 16 && IsoCode <= 24){
|
||||
ImageInfo.ISOequivalent = 50 << (IsoCode-16);
|
||||
}
|
||||
}
|
||||
|
||||
if (Tag == 4 && Format == FMT_USHORT){
|
||||
if (Components > 7){
|
||||
int WhiteBalance = Get16u(ValuePtr + 7*sizeof(unsigned short));
|
||||
switch(WhiteBalance){
|
||||
// 0=Auto, 6=Custom
|
||||
case 1: ImageInfo.LightSource = 1; break; // Sunny
|
||||
case 2: ImageInfo.LightSource = 1; break; // Cloudy
|
||||
case 3: ImageInfo.LightSource = 3; break; // Thungsten
|
||||
case 4: ImageInfo.LightSource = 2; break; // Fourescent
|
||||
case 5: ImageInfo.LightSource = 4; break; // Flash
|
||||
}
|
||||
}
|
||||
if (Components > 19 && ImageInfo.Distance <= 0) {
|
||||
// Indicates the distance the autofocus camera is focused to.
|
||||
// Tends to be less accurate as distance increases.
|
||||
int temp_dist = Get16u(ValuePtr + 19*sizeof(unsigned short));
|
||||
if (temp_dist != 65535){
|
||||
ImageInfo.Distance = (float)temp_dist/100;
|
||||
}else{
|
||||
ImageInfo.Distance = -1 /* infinity */;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Show generic maker note - just hex bytes.
|
||||
//--------------------------------------------------------------------------
|
||||
void ShowMakerNoteGeneric(unsigned char * ValuePtr, int ByteCount)
|
||||
{
|
||||
int a;
|
||||
for (a=0;a<ByteCount;a++){
|
||||
if (a > 10){
|
||||
printf("...");
|
||||
break;
|
||||
}
|
||||
printf(" %02x",ValuePtr[a]);
|
||||
}
|
||||
printf(" (%d bytes)", ByteCount);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Process maker note - to the limited extent that its supported.
|
||||
//--------------------------------------------------------------------------
|
||||
void ProcessMakerNote(unsigned char * ValuePtr, int ByteCount,
|
||||
unsigned char * OffsetBase, unsigned ExifLength)
|
||||
{
|
||||
if (strstr(ImageInfo.CameraMake, "Canon")){
|
||||
// So it turns out that some canons cameras use big endian, others use little
|
||||
// endian in the main exif header. But the maker note is always little endian.
|
||||
static int MotorolaOrderSave;
|
||||
MotorolaOrderSave = MotorolaOrder;
|
||||
MotorolaOrder = 0; // Temporarily switch to little endian.
|
||||
ProcessCanonMakerNoteDir(ValuePtr, OffsetBase, ExifLength);
|
||||
MotorolaOrder = MotorolaOrderSave;
|
||||
}else{
|
||||
if (ShowTags){
|
||||
ShowMakerNoteGeneric(ValuePtr, ByteCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
73
src/fgt/filter_photosynth/moc_filter_photosynth.cpp
Normal file
73
src/fgt/filter_photosynth/moc_filter_photosynth.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'filter_photosynth.h'
|
||||
**
|
||||
** Created: Thu Nov 25 13:56:00 2010
|
||||
** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "filter_photosynth.h"
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'filter_photosynth.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 62
|
||||
#error "This file was generated using the moc from 4.7.0. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
static const uint qt_meta_data_FilterPhotosynthPlugin[] = {
|
||||
|
||||
// content:
|
||||
5, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
0, 0, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
static const char qt_meta_stringdata_FilterPhotosynthPlugin[] = {
|
||||
"FilterPhotosynthPlugin\0"
|
||||
};
|
||||
|
||||
const QMetaObject FilterPhotosynthPlugin::staticMetaObject = {
|
||||
{ &QObject::staticMetaObject, qt_meta_stringdata_FilterPhotosynthPlugin,
|
||||
qt_meta_data_FilterPhotosynthPlugin, 0 }
|
||||
};
|
||||
|
||||
#ifdef Q_NO_DATA_RELOCATION
|
||||
const QMetaObject &FilterPhotosynthPlugin::getStaticMetaObject() { return staticMetaObject; }
|
||||
#endif //Q_NO_DATA_RELOCATION
|
||||
|
||||
const QMetaObject *FilterPhotosynthPlugin::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *FilterPhotosynthPlugin::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return 0;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_FilterPhotosynthPlugin))
|
||||
return static_cast<void*>(const_cast< FilterPhotosynthPlugin*>(this));
|
||||
if (!strcmp(_clname, "MeshFilterInterface"))
|
||||
return static_cast< MeshFilterInterface*>(const_cast< FilterPhotosynthPlugin*>(this));
|
||||
if (!strcmp(_clname, "vcg.meshlab.MeshFilterInterface/1.0"))
|
||||
return static_cast< MeshFilterInterface*>(const_cast< FilterPhotosynthPlugin*>(this));
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int FilterPhotosynthPlugin::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QObject::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
return _id;
|
||||
}
|
||||
QT_END_MOC_NAMESPACE
|
||||
100
src/fgt/filter_photosynth/moc_qtsoap.cpp
Normal file
100
src/fgt/filter_photosynth/moc_qtsoap.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'qtsoap.h'
|
||||
**
|
||||
** Created: Thu Nov 25 13:31:30 2010
|
||||
** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../../external/qtsoap-2.7_1/src/qtsoap.h"
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'qtsoap.h' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 62
|
||||
#error "This file was generated using the moc from 4.7.0. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_MOC_NAMESPACE
|
||||
static const uint qt_meta_data_QtSoapHttpTransport[] = {
|
||||
|
||||
// content:
|
||||
5, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
3, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
0, // flags
|
||||
2, // signalCount
|
||||
|
||||
// signals: signature, parameters, type, tag, flags
|
||||
21, 20, 20, 20, 0x05,
|
||||
46, 37, 20, 20, 0x05,
|
||||
|
||||
// slots: signature, parameters, type, tag, flags
|
||||
81, 75, 20, 20, 0x08,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
static const char qt_meta_stringdata_QtSoapHttpTransport[] = {
|
||||
"QtSoapHttpTransport\0\0responseReady()\0"
|
||||
"response\0responseReady(QtSoapMessage)\0"
|
||||
"reply\0readResponse(QNetworkReply*)\0"
|
||||
};
|
||||
|
||||
const QMetaObject QtSoapHttpTransport::staticMetaObject = {
|
||||
{ &QObject::staticMetaObject, qt_meta_stringdata_QtSoapHttpTransport,
|
||||
qt_meta_data_QtSoapHttpTransport, 0 }
|
||||
};
|
||||
|
||||
#ifdef Q_NO_DATA_RELOCATION
|
||||
const QMetaObject &QtSoapHttpTransport::getStaticMetaObject() { return staticMetaObject; }
|
||||
#endif //Q_NO_DATA_RELOCATION
|
||||
|
||||
const QMetaObject *QtSoapHttpTransport::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *QtSoapHttpTransport::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return 0;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_QtSoapHttpTransport))
|
||||
return static_cast<void*>(const_cast< QtSoapHttpTransport*>(this));
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int QtSoapHttpTransport::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QObject::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
switch (_id) {
|
||||
case 0: responseReady(); break;
|
||||
case 1: responseReady((*reinterpret_cast< const QtSoapMessage(*)>(_a[1]))); break;
|
||||
case 2: readResponse((*reinterpret_cast< QNetworkReply*(*)>(_a[1]))); break;
|
||||
default: ;
|
||||
}
|
||||
_id -= 3;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
// SIGNAL 0
|
||||
void QtSoapHttpTransport::responseReady()
|
||||
{
|
||||
QMetaObject::activate(this, &staticMetaObject, 0, 0);
|
||||
}
|
||||
|
||||
// SIGNAL 1
|
||||
void QtSoapHttpTransport::responseReady(const QtSoapMessage & _t1)
|
||||
{
|
||||
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
|
||||
QMetaObject::activate(this, &staticMetaObject, 1, _a);
|
||||
}
|
||||
QT_END_MOC_NAMESPACE
|
||||
@ -1,38 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of Qitty.
|
||||
//
|
||||
// Qitty is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// Qitty is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Qitty. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// Qitty - a toolkit to enhance the Qt library.
|
||||
//
|
||||
// Defines utility functions for Qt's QByteArray class.
|
||||
|
||||
#ifndef QITTY_UTILS_BYTE_ARRAY_H_
|
||||
#define QITTY_UTILS_BYTE_ARRAY_H_
|
||||
|
||||
class QByteArray;
|
||||
|
||||
namespace qitty_utils {
|
||||
|
||||
bool EqualToInt(QByteArray byte_array, int value);
|
||||
QByteArray ReverseByteArray(QByteArray byte_array);
|
||||
int ToInt(QByteArray byte_array);
|
||||
|
||||
} // namespace qitty_utils
|
||||
|
||||
#endif // QITTY_UTILS_BYTE_ARRAY_H_
|
||||
@ -1,37 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of Qitty.
|
||||
//
|
||||
// Qitty is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// Qitty is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Qitty. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// Qitty - a toolkit to enhance the Qt library.
|
||||
//
|
||||
// Utility functions for image-related processing.
|
||||
|
||||
#ifndef QITTY_UTILS_IMAGE_H_
|
||||
#define QITTY_UTILS_IMAGE_H_
|
||||
|
||||
class QImage;
|
||||
class QString;
|
||||
|
||||
namespace qitty_utils {
|
||||
|
||||
QImage SacledImage(const QString &file_name, int length);
|
||||
|
||||
} // namespace qitty_utils
|
||||
|
||||
#endif // QITTY_UTILS_IMAGE_H_
|
||||
@ -1,78 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of Qitty.
|
||||
//
|
||||
// Qitty is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// Qitty is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Qitty. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// Qitty - a toolkit to enhance the Qt library.
|
||||
//
|
||||
// This file defines the LineEdit class which enhances the QLineEdit class.
|
||||
|
||||
#ifndef QITTY_WIDGETS_LINE_EDIT_H_
|
||||
#define QITTY_WIDGETS_LINE_EDIT_H_
|
||||
|
||||
#include <QLineEdit>
|
||||
|
||||
namespace qitty_widgets {
|
||||
|
||||
class LineEdit : public QLineEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LineEdit(QWidget *parent = NULL);
|
||||
LineEdit(const QString &contents, QWidget *parent = NULL);
|
||||
void SetHint(const QString &hint);
|
||||
// Accessor functions for properties.
|
||||
void set_clear_focus_when_return_pressed(bool b) {
|
||||
clear_focus_when_return_pressed_ = b;
|
||||
}
|
||||
bool is_modified() { return is_modified_; }
|
||||
|
||||
signals:
|
||||
// This signal is emitted whenever the focus is out.
|
||||
void FocusOut();
|
||||
|
||||
protected:
|
||||
void focusInEvent(QFocusEvent *event);
|
||||
void focusOutEvent(QFocusEvent *event);
|
||||
|
||||
private slots:
|
||||
void ClearFocusWhenReturnPressed();
|
||||
void SetModifiedToTrue();
|
||||
|
||||
private:
|
||||
void Init();
|
||||
// Accessor functions for properties.
|
||||
bool clear_focus_when_return_pressed() {
|
||||
return clear_focus_when_return_pressed_;
|
||||
}
|
||||
QString hint() { return hint_; }
|
||||
void set_hint(QString hint) { hint_ = hint; }
|
||||
void set_is_modified(bool is_modified) { is_modified_ = is_modified; }
|
||||
|
||||
// Whether to clear focus when the Return or Enter key is pressed.
|
||||
bool clear_focus_when_return_pressed_;
|
||||
// Whether the text is modified or not, this value is updated by the
|
||||
// textEdited() signal and the SetModifiedToTrue() slot.
|
||||
bool is_modified_;
|
||||
// The hint displayed as text if focus is out.
|
||||
QString hint_;
|
||||
};
|
||||
|
||||
} // namespace qitty_widgets
|
||||
|
||||
#endif // QITTY_WIDGETS_LINE_EDIT_H_
|
||||
@ -1,118 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of Qitty.
|
||||
//
|
||||
// Qitty is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// Qitty is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Qitty. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// Qitty - a toolkit to enhance the Qt library.
|
||||
//
|
||||
// This file defines the PlainTextEdit widget, which enhances the QPlainTextEdit
|
||||
// class.
|
||||
|
||||
#ifndef QITTY_WIDGETS_PLAIN_TEXT_EDIT_H_
|
||||
#define QITTY_WIDGETS_PLAIN_TEXT_EDIT_H_
|
||||
|
||||
#include <QPlainTextEdit>
|
||||
#include <QSize>
|
||||
|
||||
class QResizeEvent;
|
||||
|
||||
namespace qitty_widgets {
|
||||
|
||||
class PlainTextEdit : public QPlainTextEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Mode {
|
||||
kNormalMode = 0,
|
||||
// The height will be changed to adapt the text.
|
||||
kElasticMode,
|
||||
};
|
||||
|
||||
PlainTextEdit(Mode mode = kNormalMode, QWidget *parent = NULL);
|
||||
// Accessor functions for properties.
|
||||
void set_clear_focus_when_return_pressed(bool b) {
|
||||
clear_focus_when_return_pressed_ = b;
|
||||
}
|
||||
void set_mode(Mode mode) {
|
||||
mode_ = mode;
|
||||
emit ModeChanged(mode);
|
||||
}
|
||||
bool is_modified() { return is_modified_; }
|
||||
void set_minimum_line_number(int number) { minimum_line_number_ = number; }
|
||||
|
||||
signals:
|
||||
// This signal is emitted whenever the focus is out.
|
||||
void FocusOut();
|
||||
// This signal is emitted whenever the mode is changed.
|
||||
void ModeChanged(Mode mode);
|
||||
|
||||
protected:
|
||||
void focusInEvent(QFocusEvent *event);
|
||||
void focusOutEvent(QFocusEvent *event);
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
// Overwrites the wheelEvent() to deactivate the wheel.
|
||||
// void wheelEvent(QWheelEvent *event) {}
|
||||
|
||||
private slots:
|
||||
void RecoverCursorWidth();
|
||||
void UpdateAllSelected();
|
||||
void UpdateHeight();
|
||||
void UpdateModeState(Mode mode);
|
||||
void UpdateModified(bool changed);
|
||||
|
||||
private:
|
||||
void Init(Mode mode);
|
||||
void UpdateMinimumHeight();
|
||||
// Accessor functions for properties.
|
||||
bool all_selected() { return all_selected_; }
|
||||
void set_all_selected(bool b) { all_selected_ = b; }
|
||||
bool clear_focus_when_return_pressed() {
|
||||
return clear_focus_when_return_pressed_;
|
||||
}
|
||||
int initial_cursor_width() { return initial_cursor_width_; }
|
||||
void set_initial_cursor_width(int width) { initial_cursor_width_ = width; }
|
||||
void set_is_modified(bool b) { is_modified_ = b; }
|
||||
int minimum_height() { return minimum_height_; }
|
||||
void set_minimum_height(int height) { minimum_height_ = height; }
|
||||
int minimum_line_number() { return minimum_line_number_; }
|
||||
Mode mode() { return mode_; }
|
||||
|
||||
// Sets to true if full text is selected.
|
||||
bool all_selected_;
|
||||
// Whether to clear focus when the Return or Enter key is pressed.
|
||||
bool clear_focus_when_return_pressed_;
|
||||
// The initial width of the cursor of this widget.
|
||||
int initial_cursor_width_;
|
||||
// Whether the text is modified or not, this value is updated by the
|
||||
// modificationChanged() signal and the UpdateModified() slot.
|
||||
bool is_modified_;
|
||||
// The minimum height of this widget. The value will be calculated in the
|
||||
// UpdateMinimumHeight() function.
|
||||
int minimum_height_;
|
||||
// The minimum line number of this widget. This value is used to determine
|
||||
// the minimum height of this widget in the kElasticMode.
|
||||
int minimum_line_number_;
|
||||
// Current mode of the widget.
|
||||
Mode mode_;
|
||||
};
|
||||
|
||||
} // namespace qitty_widgets
|
||||
|
||||
#endif // QITTY_WIDGETS_PLAIN_TEXT_EDIT_H_
|
||||
@ -1,5 +0,0 @@
|
||||
#include "qitty/byte_array.h"
|
||||
#include "qitty/image.h"
|
||||
#include "qitty/line_edit.h"
|
||||
#include "qitty/plain_text_edit.h"
|
||||
#include "qitty/style_sheet.h"
|
||||
@ -1,35 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of Qitty.
|
||||
//
|
||||
// Qitty is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// Qitty is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Qitty. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// Qitty - a toolkit to enhance the Qt library.
|
||||
|
||||
#ifndef QITTY_UTILS_STYLE_SHEET_H_
|
||||
#define QITTY_UTILS_STYLE_SHEET_H_
|
||||
|
||||
class QString;
|
||||
class QWidget;
|
||||
|
||||
namespace qitty_utils {
|
||||
|
||||
void SetStyleSheet(QWidget *widget, const QString &path);
|
||||
|
||||
} // namespace qitty_utils
|
||||
|
||||
#endif // QITTY_UTILS_STYLE_SHEET_H_
|
||||
@ -1,213 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file defines the Exif class.
|
||||
|
||||
#ifndef QMETA_EXIF_H_
|
||||
#define QMETA_EXIF_H_
|
||||
|
||||
#include <QHash>
|
||||
|
||||
#include "qmeta/exif_data.h"
|
||||
#include "qmeta/identifiers.h"
|
||||
#include "qmeta/standard.h"
|
||||
|
||||
class QIODevice;
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
class TiffHeader;
|
||||
|
||||
class Exif : public Standard {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Tag {
|
||||
// Exif-specific IFD.
|
||||
kExifIfdPointer = 34665,
|
||||
kGpsInfoIfdPointer = 34853,
|
||||
kInteroperabilityIfdPointer = 40965,
|
||||
|
||||
// TIFF Rev. 6.0 attribute information used in Exif, represented in decimal.
|
||||
// Tags relating to image data structure.
|
||||
kImageWidth = 256, // Image width
|
||||
kImageLength = 257, // Image height
|
||||
kBitsPerSample = 258, // Number of bits per component
|
||||
kCompression = 259, // Compression scheme
|
||||
kPhotometricInterpretation = 262, // Pixel composition
|
||||
kOrientation = 274, // Orientation of image
|
||||
kSamplesPerPixel = 277, // Number of components
|
||||
kPlanarConfiguration = 284, // Image data arrangement
|
||||
kYCbCrSubSampling = 530, // Subsampling ratio of Y to C
|
||||
kYCbCrPositioning = 531, // Y and C positioning
|
||||
kXResolution = 282, // Image resolution in width direction
|
||||
kYResolution = 283, // Image resolution in height direction
|
||||
kResolutionUnit = 296, // Unit of X and Y resolution
|
||||
// Tags relating to recording offset.
|
||||
kStripOffsets = 273, // Image data location
|
||||
kRowsPerStrip = 278, // Number of rows per strip
|
||||
kStripByteCounts = 279, // Bytes per compressed strip
|
||||
kJPEGInterchangeFormat = 513, // Offset to JPEG SOI
|
||||
kJPEGInterchangeFormatLength = 514, // Bytes of JPEG data
|
||||
// Tags relating to image data characteristics.
|
||||
kTransferFunction = 301, // Transfer function
|
||||
kWhitePoint = 318, // White point chromaticity
|
||||
kPrimaryChromaticities = 319, // Chromaticities of primaries
|
||||
kYCbCrCoefficients = 529, // Color space transformation matrix coefficients
|
||||
kReferenceBlackWhite = 532, // Pair of black and white reference values
|
||||
// Other tags.
|
||||
kDateTime = 306, // File change date and time
|
||||
kImageDescription = 270, // Image title
|
||||
kMake = 271, // Image input equipment manufacturer
|
||||
kModel = 272, // Image input equipment model
|
||||
kSoftware = 305, // Software used
|
||||
kArtist = 315, // Person who created the image
|
||||
kCopyright = 33432, // Copyright holder
|
||||
|
||||
// The attribute information recorded in the Exif IFD.
|
||||
// Tags relating to version.
|
||||
kExifVersion = 36864, // Exif version
|
||||
kFlashpixVersion = 40960, // Supported Flashpix version
|
||||
// Tag relating to image data characteristics.
|
||||
kColorSpace = 40961, // Color space information
|
||||
// Tags relating to image configuration.
|
||||
kComponentsConfiguration = 37121, // Meaning of each component
|
||||
kCompressedBitsPerPixel = 37122, // Image compression mode
|
||||
kPixelXDimension = 40962, // Valid image width
|
||||
kPixelYDimension = 40963, // Valid image height
|
||||
// Tags relating to user information.
|
||||
kMakerNote = 37500, // Manufacturer notes
|
||||
kUserComment = 37510, // User comments
|
||||
// Tags relating to related file information.
|
||||
kRelatedSoundFile = 40964,
|
||||
// Tags relating to date and time.
|
||||
kDateTimeOriginal = 36867, // Date and time of original data generation
|
||||
kDateTimeDigitized = 36868, // Date and time of digital data generation
|
||||
kSubSecTime = 37520, // Date Time subseconds
|
||||
kSubSecTimeOriginal = 37521, // Date Time Original subseconds
|
||||
kSubSecTimeDigitized = 37522, // Date Time Digitized subseconds
|
||||
// Tags relating to picture-taking conditions.
|
||||
kExposureTime = 33434, // Exposure time
|
||||
kFNumber = 33437, // F number
|
||||
kExposureProgram = 34850, // Exposure program
|
||||
kSpectralSensitivity = 34852, // Spectral sensitivity
|
||||
kISOSpeedRatings = 34855, // ISO speed rating
|
||||
kOECF = 34856, // Optoelectric conversion factor
|
||||
kShutterSpeedValue = 37377, // Shutter speed
|
||||
kApertureValue = 37378, // Aperture
|
||||
kBrightnessValue = 37379, // Brightness
|
||||
kExposureBiasValue = 37380, // Exposure bias
|
||||
kMaxApertureValue = 37381, // Maximum lens aperture
|
||||
kSubjectDistance = 37382, // Subject distance
|
||||
kMeteringMode = 37383, // Metering mode
|
||||
kLightSource = 37384, // Light source
|
||||
kFlash = 37385, // Flash
|
||||
kFocalLength = 37386, //Lens focal length
|
||||
kSubjectArea = 37396, // Subject area
|
||||
kFlashEnergy = 41483, // Flash energy
|
||||
kSpatialFrequencyResponse = 41484, // Spatial frequency response
|
||||
kFocalPlaneXResolution = 41486, // Focal plane X resolution
|
||||
kFocalPlaneYResolution = 41487, // Focal plane Y resolution
|
||||
kFocalPlaneResolutionUnit = 41488, // Focal plane resolution unit
|
||||
kSubjectLocation = 41492, // Subject location
|
||||
kExposureIndex = 41493, // Exposure index
|
||||
kSensingMethod = 41495, // Sensing method
|
||||
kFileSource = 41728, // File source
|
||||
kSceneType = 41729, // Scene type
|
||||
kCFAPattern = 41730, // CFA pattern
|
||||
kCustomRendered = 41985, // Custom image processing
|
||||
kExposureMode = 41986, // Exposure mode
|
||||
kWhiteBalance = 41987, // White balance
|
||||
kDigitalZoomRatio = 41988, //Digital zoom ratio
|
||||
kFocalLengthIn35mmFilm = 41989, // Focal length in 35 mm film
|
||||
kSceneCaptureType = 41990, // Scene capture type
|
||||
kGainControl = 41991, // Gain control
|
||||
kContrast = 41992, // Contrast
|
||||
kSaturation = 41993, // Saturation
|
||||
kSharpness = 41994, // Sharpness
|
||||
kDeviceSettingDescription = 41995, // Device settings description
|
||||
kSubjectDistanceRange = 41996, // Subject distance range
|
||||
// Other tags.
|
||||
kImageUniqueID = 42016, // Unique image ID
|
||||
|
||||
// The attribute information recorded in the GPS Info IFD.
|
||||
kGPSVersionID = 0, // GPS tag version
|
||||
kGPSLatitudeRef = 1, // North or South Latitude
|
||||
kGPSLatitude = 2, // Latitude
|
||||
kGPSLongitudeRef = 3, // East or West Longitude
|
||||
kGPSLongitude = 4, // Longitude
|
||||
kGPSAltitudeRef = 5, // Altitude reference
|
||||
kGPSAltitude = 6, // Altitude
|
||||
kGPSTimeStamp = 7, // GPS time (atomic clock)
|
||||
kGPSSatellites = 8, // GPS satellites used for measurement
|
||||
kGPSStatus = 9, // GPS receiver status
|
||||
kGPSMeasureMode = 10, // GPS measurement mode
|
||||
kGPSDOP = 11, // Measurement precision
|
||||
kGPSSpeedRef = 12, // Speed unit
|
||||
kGPSSpeed = 13, // Speed of GPS receiver
|
||||
kGPSTrackRef = 14, // Reference for direction of movement
|
||||
kGPSTrack = 15, // Direction of movement
|
||||
kGPSImgDirectionRef = 16, // Reference for direction of image
|
||||
kGPSImgDirection = 17, // Direction of image
|
||||
kGPSMapDatum = 18, // Geodetic survey data used
|
||||
kGPSDestLatitudeRef = 19, // Reference for latitude of destination
|
||||
kGPSDestLatitude = 20, // Latitude of destination
|
||||
kGPSDestLongitudeRef = 21, // Reference for longitude of destination
|
||||
kGPSDestLongitude = 22, // Longitude of destination
|
||||
kGPSDestBearingRef = 23, // Reference for longitude of destination
|
||||
kGPSDestBearing = 24, // Bearing of destination
|
||||
kGPSDestDistanceRef = 25, // Reference for distance to destination
|
||||
kGPSDestDistance = 26, // Distance to destination
|
||||
kGPSProcessingMethod = 27, // Name of GPS processing method
|
||||
kGPSAreaInformation = 28, // Name of GPS area
|
||||
kGPSDateStamp = 29, // GPS date
|
||||
kGPSDifferential = 30, // GPS differential correction
|
||||
};
|
||||
|
||||
explicit Exif(QObject *parent = NULL);
|
||||
bool Init(QIODevice *file, TiffHeader *tiff_header);
|
||||
QByteArray Thumbnail();
|
||||
ExifData Value(Tag tag);
|
||||
|
||||
QHash<Tag, QString> tag_names() const { return tag_names_; }
|
||||
|
||||
private:
|
||||
void InitTagNames();
|
||||
void ReadIfds(int ifd_offset);
|
||||
|
||||
void set_tag_names(QHash<Tag, QString> names) { tag_names_ = names; }
|
||||
QHash<Tag, qint64> tag_offsets() const { return tag_offsets_; }
|
||||
void set_tag_offsets(QHash<Tag, qint64> offsets) { tag_offsets_ = offsets; }
|
||||
TiffHeader* tiff_header() const { return tiff_header_; }
|
||||
void set_tiff_header(TiffHeader *tiff_header) { tiff_header_ = tiff_header; }
|
||||
|
||||
// The tag names to read for human.
|
||||
QHash<Tag, QString> tag_names_;
|
||||
// Records offsets of tags used in Exif.
|
||||
QHash<Tag, qint64> tag_offsets_;
|
||||
// Tracks the TiffHeader object.
|
||||
TiffHeader *tiff_header_;
|
||||
};
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
#endif // QMETA_EXIF_H_
|
||||
@ -1,45 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file defines all classes for supported Types and specific tag data in
|
||||
// Exif. All classes should inherit from the ExifData class.
|
||||
|
||||
#ifndef QMETA_EXIF_DATA_H_
|
||||
#define QMETA_EXIF_DATA_H_
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
class ExifData : public QByteArray {
|
||||
public:
|
||||
ExifData(const QByteArray &other);
|
||||
double ToDouble();
|
||||
float ToFloat();
|
||||
int ToInt();
|
||||
QString ToString();
|
||||
uint ToUInt();
|
||||
};
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
#endif // QMETA_EXIF_DATA_H_
|
||||
@ -1,84 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file defines the File class which is the base class for all QMeta
|
||||
// supported file types.
|
||||
|
||||
#ifndef QMETA_FILE_H_
|
||||
#define QMETA_FILE_H_
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QIODevice;
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
class Exif;
|
||||
class Iptc;
|
||||
class Xmp;
|
||||
|
||||
class File : public QObject {
|
||||
public:
|
||||
explicit File(QByteArray *data);
|
||||
explicit File(QIODevice *file);
|
||||
explicit File(const QString &file_name);
|
||||
QByteArray Thumbnail();
|
||||
|
||||
Exif* exif() const { return exif_; }
|
||||
Iptc* iptc() const { return iptc_; }
|
||||
Xmp* xmp() const { return xmp_; }
|
||||
|
||||
protected:
|
||||
// Initializes the Exif object.
|
||||
virtual void InitExif() {};
|
||||
virtual void InitIptc() {};
|
||||
void InitMetadata();
|
||||
virtual void InitXmp() {};
|
||||
|
||||
void set_exif(Exif *exif) { exif_ = exif; }
|
||||
QIODevice* file() const { return file_; }
|
||||
void set_iptc(Iptc *iptc) { iptc_ = iptc; }
|
||||
void set_xmp(Xmp *xmp) { xmp_ = xmp; }
|
||||
|
||||
private:
|
||||
// Returns true if the tracked file is valid. This function should be
|
||||
// reimplemented in all subclasses to verify specific file types.
|
||||
virtual bool IsValid() { return false; }
|
||||
|
||||
void set_file(QIODevice *file) { file_ = file; }
|
||||
|
||||
// The corresponded Exif object of the tracked file. This property is set
|
||||
// if the tracked file supports the EXIF standard.
|
||||
Exif *exif_;
|
||||
// Tracks the current opened file.
|
||||
QIODevice *file_;
|
||||
// The corresponded Iptc object of the tracked file. This property is set
|
||||
// if the tracked file supports the IPTC standard.
|
||||
Iptc *iptc_;
|
||||
// The corresponded Xmp object of the tracked file. This property is set
|
||||
// if the tracked file supports the XMP standard.
|
||||
Xmp *xmp_;
|
||||
};
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
#endif // QMETA_FILE_H_
|
||||
@ -1,43 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file defines miscellaneous identifiers used throguh the QMeta library.
|
||||
|
||||
#ifndef QMETA_IDENTIFIERS_H_
|
||||
#define QMETA_IDENTIFIERS_H_
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
enum Endianness {
|
||||
kLittleEndians = 0,
|
||||
kBigEndians,
|
||||
};
|
||||
|
||||
enum FileType {
|
||||
kInvalidFileType = 0,
|
||||
kJpegFileType,
|
||||
kTiffFileType,
|
||||
};
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
#endif // QMETA_IDENTIFIERS_H_
|
||||
@ -1,59 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file defines the Image class, which has the ability to guess the file
|
||||
// type of the specified image data, and can be used as a normal file class
|
||||
// such as Jpeg, Tiff, etc.
|
||||
|
||||
#ifndef QMETA_IMAGE_H_
|
||||
#define QMETA_IMAGE_H_
|
||||
|
||||
#include "qmeta/exif.h"
|
||||
#include "qmeta/file.h"
|
||||
#include "qmeta/identifiers.h"
|
||||
#include "qmeta/iptc.h"
|
||||
#include "qmeta/jpeg.h"
|
||||
#include "qmeta/tiff.h"
|
||||
#include "qmeta/xmp.h"
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
class Image : public File {
|
||||
public:
|
||||
explicit Image(QByteArray *data);
|
||||
explicit Image(QIODevice *file);
|
||||
explicit Image(const QString &file_name);
|
||||
bool IsValid();
|
||||
|
||||
FileType file_type() const { return file_type_; }
|
||||
|
||||
private:
|
||||
void GuessType();
|
||||
template<class T> bool GuessType(FileType file_type);
|
||||
|
||||
void set_file_type(FileType file_type) { file_type_ = file_type; }
|
||||
FileType file_type_;
|
||||
};
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
#endif // QMETA_IMAGE_H_
|
||||
@ -1,130 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file defines the Iptc class.
|
||||
|
||||
#ifndef QMETA_IPTC_H_
|
||||
#define QMETA_IPTC_H_
|
||||
|
||||
#include <QHash>
|
||||
|
||||
#include "standard.h"
|
||||
|
||||
class QIODevice;
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
class Iptc : public Standard {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// Only contains the list of valid editorial IPTC tags (2:xx).
|
||||
enum Tag {
|
||||
kRecordVersion = 0,
|
||||
kObjectTypeReference = 3,
|
||||
kObjectAttributeReference = 4,
|
||||
kObjectName = 5,
|
||||
kEditStatus = 7,
|
||||
kEditorialUpdate = 8,
|
||||
kUrgency = 10,
|
||||
kSubjectReference = 12,
|
||||
kCategory = 15,
|
||||
kSupplementalCategory = 20,
|
||||
kFixtureIdentifier = 22,
|
||||
kKeywords = 25,
|
||||
kContentLocationCode = 26,
|
||||
kContentLocationName = 27,
|
||||
kReleaseDate = 30,
|
||||
kReleaseTime = 35,
|
||||
kExpirationDate = 37,
|
||||
kExpirationTime = 38,
|
||||
kSpecialInstructions = 40,
|
||||
kActionAdvised = 42,
|
||||
kReferenceService = 45,
|
||||
kReferenceDate = 47,
|
||||
kReferenceNumber = 50,
|
||||
kDateCreated = 55,
|
||||
kTimeCreated = 60,
|
||||
kDigitalCreationDate = 62,
|
||||
kDigitalCreationTime = 63,
|
||||
kOriginatingProgram = 65,
|
||||
kProgramVersion = 70,
|
||||
kObjectCycle = 75,
|
||||
kByLine = 80,
|
||||
kByLineTitle = 85,
|
||||
kCity = 90,
|
||||
kSubLocation = 92,
|
||||
kProvinceState = 95,
|
||||
kCountryPrimaryLocationCode = 100,
|
||||
kCountryPrimaryLocationName = 101,
|
||||
kOriginalTransmissionReference = 103,
|
||||
kHeadline = 105,
|
||||
kCredit = 110,
|
||||
kSource = 115,
|
||||
kCopyrightNotice = 116,
|
||||
kContact = 118,
|
||||
kCaptionAbstract = 120,
|
||||
kWriterEditor = 122,
|
||||
kRasterizedCaption = 125,
|
||||
kImageType = 130,
|
||||
kImageOrientation = 131,
|
||||
kLanguageIdentifier = 135,
|
||||
kAudioType = 150,
|
||||
kAudioSamplingRate = 151,
|
||||
kAudioSamplingResolution = 152,
|
||||
kAudioDuration = 153,
|
||||
kAudioOutcue = 154,
|
||||
kObjDataPreviewFileFormat = 200,
|
||||
kObjDataPreviewFileFormatVer = 201,
|
||||
kObjDataPreviewData = 202,
|
||||
};
|
||||
|
||||
explicit Iptc(QObject *parent = NULL);
|
||||
bool Init(QIODevice *file, const qint64 file_start_offset);
|
||||
QByteArray Value(Tag tag);
|
||||
QList<QByteArray> Values(Tag tag);
|
||||
|
||||
QHash<Tag, QString> tag_names() const { return tag_names_; }
|
||||
|
||||
private:
|
||||
void InitRepeatableTags();
|
||||
void InitTagNames();
|
||||
QByteArray ReadDataSet(int offset);
|
||||
bool ReadRecord();
|
||||
|
||||
QList<Tag> repeatable_tags() const { return repeatable_tags_; }
|
||||
void set_repeatable_tags(QList<Tag> tags) { repeatable_tags_ = tags; }
|
||||
void set_tag_names(QHash<Tag, QString> names) { tag_names_ = names; }
|
||||
QHash<Tag, qint64> tag_offsets() const { return tag_offsets_; }
|
||||
void set_tag_offsets(QHash<Tag, qint64> offsets) { tag_offsets_ = offsets; }
|
||||
|
||||
// Records the repeatable tags.
|
||||
QList<Tag> repeatable_tags_;
|
||||
// The tag names to read for human.
|
||||
QHash<Tag, QString> tag_names_;
|
||||
// Records offsets of tags used in IPTC.
|
||||
QHash<Tag, qint64> tag_offsets_;
|
||||
};
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
#endif // QMETA_IPTC_H_
|
||||
@ -1,49 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file defines the Jpeg class.
|
||||
|
||||
#ifndef QMETA_JPEG_
|
||||
#define QMETA_JPEG_
|
||||
|
||||
#include "qmeta/file.h"
|
||||
|
||||
class QString;
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
class Jpeg : public File {
|
||||
public:
|
||||
explicit Jpeg(QByteArray *data);
|
||||
explicit Jpeg(QIODevice *file);
|
||||
explicit Jpeg(const QString &file_name);
|
||||
bool IsValid();
|
||||
|
||||
private:
|
||||
void InitExif();
|
||||
void InitIptc();
|
||||
void InitXmp();
|
||||
};
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
#endif // QMETA_JPEG_
|
||||
@ -1,12 +0,0 @@
|
||||
#include "exif.h"
|
||||
#include "exif_data.h"
|
||||
#include "file.h"
|
||||
#include "identifiers.h"
|
||||
#include "image.h"
|
||||
#include "iptc.h"
|
||||
#include "jpeg.h"
|
||||
#include "standard.h"
|
||||
#include "tiff.h"
|
||||
#include "tiff_header.h"
|
||||
#include "xmp.h"
|
||||
#include "qmeta.h"
|
||||
@ -1,55 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file defines the Standard class, which is the base class for all
|
||||
// metadata standard classes such as Exif and Iptc.
|
||||
|
||||
#ifndef QMETA_STANDARD_H_
|
||||
#define QMETA_STANDARD_H_
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QIODevice;
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
class Standard : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Standard(QObject *parent = NULL);
|
||||
|
||||
protected:
|
||||
QIODevice* file() const { return file_; }
|
||||
void set_file(QIODevice *file) { file_ = file; }
|
||||
qint64 file_start_offset() const { return file_start_offset_; }
|
||||
void set_file_start_offset(qint64 offset) { file_start_offset_ = offset; }
|
||||
|
||||
// Tracks the file containing the metadata.
|
||||
QIODevice *file_;
|
||||
// The offset of the beginning of the metadata standard in the tracked file.
|
||||
qint64 file_start_offset_;
|
||||
};
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
#endif // QMETA_STANDARD_H_
|
||||
@ -1,58 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file defines the TIFF class.
|
||||
|
||||
#ifndef QMETA_TIFF_H_
|
||||
#define QMETA_TIFF_H_
|
||||
|
||||
#include "qmeta/file.h"
|
||||
|
||||
class QString;
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
class TiffHeader;
|
||||
|
||||
class Tiff : public File {
|
||||
public:
|
||||
explicit Tiff(QByteArray *data);
|
||||
explicit Tiff(QIODevice *file);
|
||||
explicit Tiff(const QString &file_name);
|
||||
void Init();
|
||||
bool IsValid();
|
||||
|
||||
private:
|
||||
void InitExif();
|
||||
void InitIptc();
|
||||
void InitXmp();
|
||||
|
||||
TiffHeader* tiff_header() const { return tiff_header_; }
|
||||
void set_tiff_header(TiffHeader *tiff_header) { tiff_header_ = tiff_header; }
|
||||
|
||||
// Tracks the TiffHeader object of the tracked file.
|
||||
TiffHeader *tiff_header_;
|
||||
};
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
#endif // QMETA_TIFF_H_
|
||||
@ -1,128 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file defines the TiffHeader class which is used for TIFF files and
|
||||
// Exif metadata embeded in JPEG files. Both the Tiff and the Jpeg classes
|
||||
// should instantiate the TiffHeader object and pass it to the corresponded
|
||||
// Exif object.
|
||||
|
||||
#ifndef QMETA_TIFF_HEADER_H_
|
||||
#define QMETA_TIFF_HEADER_H_
|
||||
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
|
||||
#include "qmeta/identifiers.h"
|
||||
|
||||
class QIODevice;
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
class TiffHeader : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// The value data types used in TIFF header.
|
||||
enum Type {
|
||||
// An 8-bit unsigned integer.
|
||||
kByteType = 1,
|
||||
// An 8-bit byte containing one 7-bit ASCII code. The final byte is
|
||||
// terminated with NULL.
|
||||
kAsciiType = 2,
|
||||
// A 16-bit (2-byte) unsigned integer.
|
||||
kShortType = 3,
|
||||
// A 32-bit (4-byte) unsigned integer.
|
||||
kLongType = 4,
|
||||
// Two LONGs. The first LONG is the numerator and the second LONG expresses
|
||||
// the denominator.
|
||||
kRationalType = 5,
|
||||
// An 8-bit signed integer.
|
||||
kSByte = 6,
|
||||
// An 8-bit byte that can take any value depending ont he field definition.
|
||||
kUndefinedType = 7,
|
||||
// A 16-bit signed integer.
|
||||
kSShort = 8,
|
||||
// A 32-bit (4-byte) signed integer (2's complement notation)
|
||||
kSLongType = 9,
|
||||
// Two SLONGs. The first SLONG is the numerator and the second SLONG is the
|
||||
// denominator.
|
||||
kSRationalType = 10,
|
||||
// A 4-byte IEEE floating point value.
|
||||
kFloat = 11,
|
||||
// An 8-byte IEEE floating point value.
|
||||
kDouble = 12,
|
||||
};
|
||||
|
||||
explicit TiffHeader(QObject *parent = NULL);
|
||||
bool HasNextIfdEntry();
|
||||
int IfdEntryTag(qint64 ifd_entry_offset);
|
||||
Type IfdEntryType(qint64 ifd_entry_offset);
|
||||
QByteArray IfdEntryValue(qint64 ifd_entry_offset);
|
||||
qint64 IfdEntryOffset(qint64 ifd_entry_offset);
|
||||
bool Init(QIODevice *file, qint64 file_start_offset);
|
||||
qint64 NextIfdEntryOffset();
|
||||
void ToFirstIfd();
|
||||
void ToIfd(qint64 offset);
|
||||
|
||||
qint64 current_ifd_offset() const { return current_ifd_offset_; }
|
||||
qint64 file_start_offset() const { return file_start_offset_; }
|
||||
|
||||
private:
|
||||
void InitTypeByteUnit();
|
||||
QByteArray ReadFromFile(const int max_size);
|
||||
|
||||
int current_entry_count() const { return current_entry_count_; }
|
||||
void set_current_entry_count(int count) { current_entry_count_ = count; }
|
||||
int current_entry_number() const { return current_entry_number_; }
|
||||
void set_current_entry_number(int number) { current_entry_number_ = number; }
|
||||
void set_current_ifd_offset(qint64 offset) { current_ifd_offset_ = offset; }
|
||||
Endianness endianness() const { return endianness_; }
|
||||
void set_endianness(Endianness endian) { endianness_ = endian; }
|
||||
QIODevice* file() const { return file_; }
|
||||
void set_file(QIODevice *file) { file_ = file; }
|
||||
void set_file_start_offset(qint64 offset) { file_start_offset_ = offset; }
|
||||
int first_ifd_offset() const { return first_ifd_offset_; }
|
||||
void set_first_ifd_offset(int offset) { first_ifd_offset_ = offset; }
|
||||
QHash<Type, int> type_byte_unit() const { return type_byte_unit_; }
|
||||
void set_type_byte_unit(QHash<Type, int> unit) { type_byte_unit_ = unit; }
|
||||
|
||||
// The count of directory entries of the current IFD.
|
||||
int current_entry_count_;
|
||||
// The number of current directory entry in the IFD.
|
||||
int current_entry_number_;
|
||||
// Tracks the beginning offset of current IFD.
|
||||
int current_ifd_offset_;
|
||||
// The byte order of the TIFF file.
|
||||
Endianness endianness_;
|
||||
// The tracked file.
|
||||
QIODevice *file_;
|
||||
// The beginning offset of the TIFF header in the tracked file.
|
||||
qint64 file_start_offset_;
|
||||
// The offset of the first IFD.
|
||||
int first_ifd_offset_;
|
||||
// The byte unit for each entry type.
|
||||
QHash<Type, int> type_byte_unit_;
|
||||
};
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
#endif // QMETA_TIFF_HEADER_H_
|
||||
@ -1,46 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file defines the Xmp class.
|
||||
|
||||
#ifndef QMETA_XMP_H_
|
||||
#define QMETA_XMP_H_
|
||||
|
||||
#include <QHash>
|
||||
|
||||
#include "qmeta/standard.h"
|
||||
|
||||
class QIODevice;
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
class Xmp : public Standard {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Xmp(QObject *parent = NULL);
|
||||
bool Init(QIODevice *file, qint64 file_start_offset);
|
||||
};
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
#endif // QMETA_XMP_H_
|
||||
@ -1,239 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file implements the detail of the Exif class.
|
||||
|
||||
#include "qmeta/exif.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <qitty/byte_array.h>
|
||||
|
||||
#include "qmeta/tiff_header.h"
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
Exif::Exif(QObject *parent) : Standard(parent) {
|
||||
InitTagNames();
|
||||
QHash<Tag, qint64> tag_offsets;
|
||||
set_tag_offsets(tag_offsets);
|
||||
}
|
||||
|
||||
// Initializes the Exif object.
|
||||
bool Exif::Init(QIODevice *file, TiffHeader *tiff_header) {
|
||||
set_file(file);
|
||||
set_tiff_header(tiff_header);
|
||||
tiff_header->ToFirstIfd();
|
||||
ReadIfds(tiff_header->current_ifd_offset());
|
||||
if (tag_offsets().count() == 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initializes tag names used in Exif.
|
||||
void Exif::InitTagNames() {
|
||||
QHash<Tag, QString> tag_names;
|
||||
// Exif-specific IFD.
|
||||
tag_names.insert(kExifIfdPointer, tr("Exif IFD Pointer"));
|
||||
tag_names.insert(kGpsInfoIfdPointer, tr("GPS Info IFD Pointer"));
|
||||
tag_names.insert(kInteroperabilityIfdPointer,
|
||||
tr("Interoperability IFD Pointer"));
|
||||
// TIFF Rev. 6.0 attribute information used in Exif.
|
||||
tag_names.insert(kImageWidth, tr("Image Width"));
|
||||
tag_names.insert(kImageLength, tr("Image Height"));
|
||||
tag_names.insert(kBitsPerSample, tr("Bits Per Sample"));
|
||||
tag_names.insert(kCompression, tr("Compression"));
|
||||
tag_names.insert(kPhotometricInterpretation,
|
||||
tr("Photometric Interpretation"));
|
||||
tag_names.insert(kOrientation, tr("Orientation"));
|
||||
tag_names.insert(kSamplesPerPixel, tr("Samples Per Pixel"));
|
||||
tag_names.insert(kPlanarConfiguration, tr("Planar Configuration"));
|
||||
tag_names.insert(kYCbCrSubSampling, tr("YCbCr Sub Sampling"));
|
||||
tag_names.insert(kYCbCrPositioning, tr("YCbCr Positioning"));
|
||||
tag_names.insert(kXResolution, tr("X-Resolution"));
|
||||
tag_names.insert(kYResolution, tr("Y-Resolution"));
|
||||
tag_names.insert(kResolutionUnit, tr("Resolution Unit"));
|
||||
tag_names.insert(kStripOffsets, tr("Strip Offsets"));
|
||||
tag_names.insert(kRowsPerStrip, tr("Rows Per Strip"));
|
||||
tag_names.insert(kStripByteCounts, tr("Strip Byte Counts"));
|
||||
tag_names.insert(kJPEGInterchangeFormat, tr("JPEG Interchange Format"));
|
||||
tag_names.insert(kJPEGInterchangeFormatLength,
|
||||
tr("JPEG Interchange Format Length"));
|
||||
tag_names.insert(kTransferFunction, tr("Transfer Function"));
|
||||
tag_names.insert(kWhitePoint, tr("White Point"));
|
||||
tag_names.insert(kPrimaryChromaticities, tr("Primary Chromaticities"));
|
||||
tag_names.insert(kYCbCrCoefficients, tr("YCbCr Coefficients"));
|
||||
tag_names.insert(kReferenceBlackWhite, tr("Reference Black White"));
|
||||
tag_names.insert(kDateTime, tr("Date Time"));
|
||||
tag_names.insert(kImageDescription, tr("Image Description"));
|
||||
tag_names.insert(kMake, tr("Make"));
|
||||
tag_names.insert(kModel, tr("Model"));
|
||||
tag_names.insert(kSoftware, tr("Software"));
|
||||
tag_names.insert(kArtist, tr("Artist"));
|
||||
tag_names.insert(kCopyright, tr("Copyright"));
|
||||
// The attribute information recorded in the Exif IFD.
|
||||
tag_names.insert(kExifVersion, tr("Exif Version"));
|
||||
tag_names.insert(kFlashpixVersion, tr("Flashpix Version"));
|
||||
tag_names.insert(kColorSpace, tr("Color Space"));
|
||||
tag_names.insert(kComponentsConfiguration, tr("Components Configuration"));
|
||||
tag_names.insert(kCompressedBitsPerPixel, tr("Compressed Bits Per Pixel"));
|
||||
tag_names.insert(kPixelXDimension, tr("Pixel X Dimension"));
|
||||
tag_names.insert(kPixelYDimension, tr("Pixel Y Dimension"));
|
||||
tag_names.insert(kMakerNote, tr("Maker Note"));
|
||||
tag_names.insert(kUserComment, tr("User Comment"));
|
||||
tag_names.insert(kRelatedSoundFile, tr("Related Sound File"));
|
||||
tag_names.insert(kDateTimeOriginal, tr("Date Time Original"));
|
||||
tag_names.insert(kDateTimeDigitized, tr("Date Time Digitized"));
|
||||
tag_names.insert(kSubSecTime, tr("Sub Sec Time"));
|
||||
tag_names.insert(kSubSecTimeOriginal, tr("Sub Sec Time Original"));
|
||||
tag_names.insert(kSubSecTimeDigitized, tr("Sub Sec Time Digitized"));
|
||||
tag_names.insert(kExposureTime, tr("Exposure Time"));
|
||||
tag_names.insert(kFNumber, tr("F Number"));
|
||||
tag_names.insert(kExposureProgram, tr("Exposure Program"));
|
||||
tag_names.insert(kSpectralSensitivity, tr("Spectral Sensitivity"));
|
||||
tag_names.insert(kISOSpeedRatings, tr("ISO Speed Rating"));
|
||||
tag_names.insert(kOECF, tr("Optoelectric conversion factor"));
|
||||
tag_names.insert(kShutterSpeedValue, tr("Shutter Speed"));
|
||||
tag_names.insert(kApertureValue, tr("Aperture Value"));
|
||||
tag_names.insert(kBrightnessValue, tr("Brightness"));
|
||||
tag_names.insert(kExposureBiasValue, tr("Exposure Bias"));
|
||||
tag_names.insert(kMaxApertureValue, tr("Maximum Lens Aperture"));
|
||||
tag_names.insert(kSubjectDistance, tr("Subject Distance"));
|
||||
tag_names.insert(kMeteringMode, tr("Metering Mode"));
|
||||
tag_names.insert(kLightSource, tr("Light Source"));
|
||||
tag_names.insert(kFlash, tr("Flash"));
|
||||
tag_names.insert(kFocalLength, tr("Focal Length"));
|
||||
tag_names.insert(kSubjectArea, tr("Subject Area"));
|
||||
tag_names.insert(kFlashEnergy, tr("Flash Energy"));
|
||||
tag_names.insert(kSpatialFrequencyResponse,
|
||||
tr("Spatial Frequency Response"));
|
||||
tag_names.insert(kFocalPlaneXResolution, tr("Focal Plane X Resolution"));
|
||||
tag_names.insert(kFocalPlaneYResolution, tr("Focal Plane Y Resolution"));
|
||||
tag_names.insert(kFocalPlaneResolutionUnit,
|
||||
tr("Focal Plane Resolution Unit"));
|
||||
tag_names.insert(kSubjectLocation, tr("Subject Location"));
|
||||
tag_names.insert(kExposureIndex, tr("Exposure Index"));
|
||||
tag_names.insert(kSensingMethod, tr("Sensing Method"));
|
||||
tag_names.insert(kFileSource, tr("File Source"));
|
||||
tag_names.insert(kSceneType, tr("Scene Type"));
|
||||
tag_names.insert(kCFAPattern, tr("CFA Pattern"));
|
||||
tag_names.insert(kCustomRendered, tr("Custom Rendered"));
|
||||
tag_names.insert(kExposureMode, tr("Exposure Mode"));
|
||||
tag_names.insert(kWhiteBalance, tr("White Balance"));
|
||||
tag_names.insert(kDigitalZoomRatio, tr("Digital Zoom Ratio"));
|
||||
tag_names.insert(kFocalLengthIn35mmFilm, tr("Focal Length In 35mm Film"));
|
||||
tag_names.insert(kSceneCaptureType, tr("Scene Capture Type"));
|
||||
tag_names.insert(kGainControl, tr("Gain Control"));
|
||||
tag_names.insert(kContrast, tr("Contrast"));
|
||||
tag_names.insert(kSaturation, tr("Saturation"));
|
||||
tag_names.insert(kSharpness, tr("Sharpness"));
|
||||
tag_names.insert(kDeviceSettingDescription,
|
||||
tr("Device Setting Description"));
|
||||
tag_names.insert(kSubjectDistanceRange, tr("Subject Distance Range"));
|
||||
tag_names.insert(kImageUniqueID, tr("Image Unique ID"));
|
||||
// The attribute information recorded in the GPS Info IFD.
|
||||
tag_names.insert(kGPSVersionID, tr("GPS Version ID"));
|
||||
tag_names.insert(kGPSLatitudeRef, tr("GPS Latitude Ref"));
|
||||
tag_names.insert(kGPSLatitude, tr("GPS Latitude"));
|
||||
tag_names.insert(kGPSLongitudeRef, tr("GPS Longitude Ref"));
|
||||
tag_names.insert(kGPSLongitude, tr("GPS Longitude"));
|
||||
tag_names.insert(kGPSAltitudeRef, tr("GPS Altitude Ref"));
|
||||
tag_names.insert(kGPSAltitude, tr("GPS Altitude"));
|
||||
tag_names.insert(kGPSTimeStamp, tr("GPS Time Stamp"));
|
||||
tag_names.insert(kGPSSatellites, tr("GPS Satellites"));
|
||||
tag_names.insert(kGPSStatus, tr("GPS Status"));
|
||||
tag_names.insert(kGPSMeasureMode, tr("GPS Measure Mode"));
|
||||
tag_names.insert(kGPSDOP, tr("GPS DOP"));
|
||||
tag_names.insert(kGPSSpeedRef, tr("GPS Speed Ref"));
|
||||
tag_names.insert(kGPSSpeed, tr("GPS Speed"));
|
||||
tag_names.insert(kGPSTrackRef, tr("GPS Track Ref"));
|
||||
tag_names.insert(kGPSTrack, tr("GPS Track"));
|
||||
tag_names.insert(kGPSImgDirectionRef, tr("GPS Img Direction Ref"));
|
||||
tag_names.insert(kGPSImgDirection, tr("GPS Img Direction"));
|
||||
tag_names.insert(kGPSMapDatum, tr("GPS Map Datum"));
|
||||
tag_names.insert(kGPSDestLatitudeRef, tr("GPS Dest Latitude Ref"));
|
||||
tag_names.insert(kGPSDestLatitude, tr("GPS Dest Latitude"));
|
||||
tag_names.insert(kGPSDestLongitudeRef, tr("GPS Dest Longitude Ref"));
|
||||
tag_names.insert(kGPSDestLongitude, tr("GPS Dest Longitude"));
|
||||
tag_names.insert(kGPSDestBearingRef, tr("GPS Dest Bearing Ref"));
|
||||
tag_names.insert(kGPSDestBearing, tr("GPS Dest Bearing"));
|
||||
tag_names.insert(kGPSDestDistanceRef, tr("GPS Dest Distance Ref"));
|
||||
tag_names.insert(kGPSDestDistance, tr("GPS Dest Distance"));
|
||||
tag_names.insert(kGPSProcessingMethod, tr("GPS Processing Method"));
|
||||
tag_names.insert(kGPSAreaInformation, tr("GPS Area Information"));
|
||||
tag_names.insert(kGPSDateStamp, tr("GPS Date Stamp"));
|
||||
tag_names.insert(kGPSDifferential, tr("GPS Differential"));
|
||||
set_tag_names(tag_names);
|
||||
}
|
||||
|
||||
// Reads all IFDs from the specified ifd_offset and saved
|
||||
void Exif::ReadIfds(int ifd_offset) {
|
||||
tiff_header()->ToIfd(ifd_offset);
|
||||
|
||||
QList<qint64> ifd_offsets;
|
||||
// Reads a sequence of 12-byte field entries.
|
||||
while (tiff_header()->HasNextIfdEntry()) {
|
||||
qint64 ifd_entry_offset = tiff_header()->NextIfdEntryOffset();
|
||||
Tag tag = static_cast<Tag>(tiff_header()->IfdEntryTag(ifd_entry_offset));
|
||||
|
||||
if (!tag_names().contains(tag))
|
||||
continue;
|
||||
|
||||
QHash<Tag, qint64> offsets = tag_offsets();
|
||||
offsets.insert(tag, ifd_entry_offset);
|
||||
set_tag_offsets(offsets);
|
||||
|
||||
if (tag == kExifIfdPointer || tag == kGpsInfoIfdPointer) {
|
||||
QByteArray entry_value = tiff_header()->IfdEntryValue(ifd_entry_offset);
|
||||
qint64 ifd_pointer_offset = entry_value.toHex().toUInt(NULL, 16) +
|
||||
tiff_header()->file_start_offset();
|
||||
ifd_offsets.append(ifd_pointer_offset);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < ifd_offsets.count(); ++i) {
|
||||
ReadIfds(ifd_offsets.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the byte data of the thumbnail saved in Exif.
|
||||
QByteArray Exif::Thumbnail() {
|
||||
QByteArray thumbnail;
|
||||
quint32 thumbnail_offset = Value(kJPEGInterchangeFormat).ToUInt();
|
||||
quint32 length = Value(kJPEGInterchangeFormatLength).ToUInt();
|
||||
if (thumbnail_offset && length) {
|
||||
thumbnail_offset += tiff_header()->file_start_offset();
|
||||
file()->seek(thumbnail_offset);
|
||||
thumbnail = file()->read(length);
|
||||
}
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
// Returns the value of the specified tag as a ExifData.
|
||||
ExifData Exif::Value(Tag tag) {
|
||||
QByteArray value;
|
||||
if (tag_offsets().contains(tag))
|
||||
value = tiff_header()->IfdEntryValue(tag_offsets().value(tag));
|
||||
ExifData exif_data(value);
|
||||
return exif_data;
|
||||
}
|
||||
|
||||
} // namespace qmeta
|
||||
@ -1,67 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file implements the details of all classes related to Exif data.
|
||||
|
||||
#include "qmeta/exif_data.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
ExifData::ExifData(const QByteArray &other) : QByteArray(other) {}
|
||||
|
||||
// Returns the byte array converted to double. This function works correctly
|
||||
// if the Type is RATIONAL and the Count is 1.
|
||||
double ExifData::ToDouble() {
|
||||
double numerator = static_cast<double>(mid(0,4).toHex().toUInt(NULL, 16));
|
||||
double denominator = static_cast<double>(mid(4).toHex().toUInt(NULL, 16));
|
||||
return numerator/ denominator;
|
||||
}
|
||||
|
||||
// Returns the byte array converted to float. This function works correctly
|
||||
// if the Type is SRATIONAL and the Count is 1.
|
||||
float ExifData::ToFloat() {
|
||||
float numerator = static_cast<float>(mid(0,4).toHex().toInt(NULL, 16));
|
||||
float denominator = static_cast<float>(mid(4).toHex().toInt(NULL, 16));
|
||||
return numerator/ denominator;
|
||||
}
|
||||
|
||||
// Returns the byte array converted to int in decimal. This function works
|
||||
// correctly if the Type is one of BYTE, SHORT, or SLONG and the Count is 1.
|
||||
int ExifData::ToInt() {
|
||||
return toHex().toInt(NULL, 16);
|
||||
}
|
||||
|
||||
// Returns the byte array converted to QString. This functions works correctly
|
||||
// if the Type is ASCII.
|
||||
QString ExifData::ToString() {
|
||||
return QString(data());
|
||||
}
|
||||
|
||||
// Returns the byte array converted to uint in decimal. This function works
|
||||
// correctly if the Type is BYTE, SHORT, or LONG and the Count is 1.
|
||||
uint ExifData::ToUInt() {
|
||||
return toHex().toUInt(NULL, 16);
|
||||
}
|
||||
|
||||
} // namespace qmeta
|
||||
@ -1,84 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file implements the detail of the File class.
|
||||
|
||||
#include "qmeta/file.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
#include "qmeta/exif.h"
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
// Constructs a file from the given QByteArray data.
|
||||
File::File(QByteArray *data) {
|
||||
set_exif(NULL);
|
||||
set_iptc(NULL);
|
||||
set_xmp(NULL);
|
||||
QBuffer *file = new QBuffer(data, this);
|
||||
if (file->open(QIODevice::ReadOnly))
|
||||
set_file(file);
|
||||
else
|
||||
set_file(NULL);
|
||||
}
|
||||
|
||||
// Constructs a file from the given QIODevice file.
|
||||
File::File(QIODevice *file) {
|
||||
set_exif(NULL);
|
||||
set_iptc(NULL);
|
||||
set_xmp(NULL);
|
||||
set_file(file);
|
||||
}
|
||||
|
||||
// Constructs a file and tries to load the file with the given file_name.
|
||||
File::File(const QString &file_name) {
|
||||
set_exif(NULL);
|
||||
set_iptc(NULL);
|
||||
set_xmp(NULL);
|
||||
QFile *file = new QFile(file_name, this);
|
||||
if (file->open(QIODevice::ReadOnly))
|
||||
set_file(file);
|
||||
else
|
||||
set_file(NULL);
|
||||
}
|
||||
|
||||
// Returns the thumbnail from supported metadata. Currently Exif is the only
|
||||
// supported metadata.
|
||||
QByteArray File::Thumbnail() {
|
||||
QByteArray thumbnail;
|
||||
if (exif())
|
||||
thumbnail = exif()->Thumbnail();
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
// Initializes metadata objects for the tracked file.
|
||||
void File::InitMetadata() {
|
||||
if (!IsValid())
|
||||
return;
|
||||
|
||||
InitExif();
|
||||
InitIptc();
|
||||
InitXmp();
|
||||
}
|
||||
|
||||
} // namespace qmeta
|
||||
@ -1,85 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file implements the detail of the Image class.
|
||||
|
||||
#include "qmeta/image.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
Image::Image(QByteArray *data) : File(data) {
|
||||
GuessType();
|
||||
}
|
||||
|
||||
Image::Image(QIODevice *file) : File(file) {
|
||||
GuessType();
|
||||
}
|
||||
|
||||
Image::Image(const QString &file_name) : File(file_name) {
|
||||
GuessType();
|
||||
}
|
||||
|
||||
// Guesses the file type of the tracked file. It calls the GuessType(FileType)
|
||||
// function for all file types it guesses. If there is no matched file type
|
||||
// or there is no tracked file object, sets the file type to kInvalidFileType.
|
||||
void Image::GuessType() {
|
||||
if (file()) {
|
||||
// Guess the file type as JPEG.
|
||||
if (GuessType<Jpeg>(kJpegFileType))
|
||||
return;
|
||||
// Guess the file type as Tiff.
|
||||
else if (GuessType<Tiff>(kTiffFileType))
|
||||
return;
|
||||
}
|
||||
set_file_type(kInvalidFileType);
|
||||
}
|
||||
|
||||
// Guesses the file type of the tracked file. Tries to creates a new image
|
||||
// object using the specified type T, if the image is valid, sets the specified
|
||||
// file_type to current file type and binds the image's metadata objects.
|
||||
// Returns true if the specified type T is correct.
|
||||
template<class T> bool Image::GuessType(FileType file_type) {
|
||||
T *image = new T(file());
|
||||
if (image->IsValid()) {
|
||||
image->setParent(this);
|
||||
set_file_type(file_type);
|
||||
set_exif(image->exif());
|
||||
set_iptc(image->iptc());
|
||||
set_xmp(image->xmp());
|
||||
return true;
|
||||
} else {
|
||||
delete image;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Reimplements the File::IsValid().
|
||||
bool Image::IsValid() {
|
||||
if (file_type() == kInvalidFileType)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,189 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file implements the detail of the Iptc class.
|
||||
|
||||
#include "qmeta/iptc.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
Iptc::Iptc(QObject *parent) : Standard(parent) {
|
||||
InitRepeatableTags();
|
||||
InitTagNames();
|
||||
}
|
||||
|
||||
// Initializes the IPTC object. Returns false if no valid tag is found.
|
||||
bool Iptc::Init(QIODevice *file, const qint64 file_start_offset) {
|
||||
set_file(file);
|
||||
set_file_start_offset(file_start_offset);
|
||||
return ReadRecord();
|
||||
}
|
||||
|
||||
// Adds all repeatable tags to the repeatable_tags_ property.
|
||||
void Iptc::InitRepeatableTags() {
|
||||
QList<Tag> repeatable_tags;
|
||||
repeatable_tags.append(kObjectAttributeReference);
|
||||
repeatable_tags.append(kSubjectReference);
|
||||
repeatable_tags.append(kSupplementalCategory);
|
||||
repeatable_tags.append(kKeywords);
|
||||
repeatable_tags.append(kContentLocationCode);
|
||||
repeatable_tags.append(kContentLocationName);
|
||||
repeatable_tags.append(kReferenceService);
|
||||
repeatable_tags.append(kReferenceDate);
|
||||
repeatable_tags.append(kReferenceNumber);
|
||||
repeatable_tags.append(kByLine);
|
||||
repeatable_tags.append(kByLineTitle);
|
||||
repeatable_tags.append(kContact);
|
||||
repeatable_tags.append(kWriterEditor);
|
||||
set_repeatable_tags(repeatable_tags);
|
||||
}
|
||||
|
||||
// Initializes tag names used in IPTC.
|
||||
void Iptc::InitTagNames() {
|
||||
QHash<Tag, QString> tag_names;
|
||||
tag_names.insert(kRecordVersion, tr("Record Version"));
|
||||
tag_names.insert(kObjectTypeReference, tr("Object Type Reference"));
|
||||
tag_names.insert(kObjectAttributeReference, tr("Object Attribute Reference"));
|
||||
tag_names.insert(kObjectName, tr("Object Name"));
|
||||
tag_names.insert(kEditStatus, tr("Edit Status"));
|
||||
tag_names.insert(kEditorialUpdate, tr("Editorial Update"));
|
||||
tag_names.insert(kUrgency, tr("Urgency"));
|
||||
tag_names.insert(kSubjectReference, tr("Subject Reference"));
|
||||
tag_names.insert(kCategory, tr("Category"));
|
||||
tag_names.insert(kSupplementalCategory, tr("Supplemental Category"));
|
||||
tag_names.insert(kFixtureIdentifier, tr("Fixture Identifier"));
|
||||
tag_names.insert(kKeywords, tr("Keywords"));
|
||||
tag_names.insert(kContentLocationCode, tr("Content Location Code"));
|
||||
tag_names.insert(kContentLocationName, tr("Content Location Name"));
|
||||
tag_names.insert(kReleaseDate, tr("Release Date"));
|
||||
tag_names.insert(kReleaseTime, tr("Release Time"));
|
||||
tag_names.insert(kExpirationDate, tr("Expiration Date"));
|
||||
tag_names.insert(kExpirationTime, tr("Expiration Time"));
|
||||
tag_names.insert(kSpecialInstructions, tr("Special Instructions"));
|
||||
tag_names.insert(kActionAdvised, tr("Action Advised"));
|
||||
tag_names.insert(kReferenceService, tr("Reference Service"));
|
||||
tag_names.insert(kReferenceDate, tr("Reference Date"));
|
||||
tag_names.insert(kReferenceNumber, tr("Reference Number"));
|
||||
tag_names.insert(kDateCreated, tr("Date Created"));
|
||||
tag_names.insert(kTimeCreated, tr("Time Created"));
|
||||
tag_names.insert(kDigitalCreationDate, tr("Digital Creation Date"));
|
||||
tag_names.insert(kDigitalCreationTime, tr("Digital Creation Time"));
|
||||
tag_names.insert(kOriginatingProgram, tr("Originating Program"));
|
||||
tag_names.insert(kProgramVersion, tr("Program Version"));
|
||||
tag_names.insert(kObjectCycle, tr("Object Cycle"));
|
||||
tag_names.insert(kByLine, tr("By Line"));
|
||||
tag_names.insert(kByLineTitle, tr("By Line Title"));
|
||||
tag_names.insert(kCity, tr("City"));
|
||||
tag_names.insert(kSubLocation, tr("Sub Location"));
|
||||
tag_names.insert(kProvinceState, tr("Province State"));
|
||||
tag_names.insert(kCountryPrimaryLocationCode,
|
||||
tr("Country Primary Location Code"));
|
||||
tag_names.insert(kCountryPrimaryLocationName,
|
||||
tr("Country Primary Location Name"));
|
||||
tag_names.insert(kOriginalTransmissionReference,
|
||||
tr("Original Transmission Reference"));
|
||||
tag_names.insert(kHeadline, tr("Headline"));
|
||||
tag_names.insert(kCredit, tr("Credit"));
|
||||
tag_names.insert(kSource, tr("Source"));
|
||||
tag_names.insert(kCopyrightNotice, tr("Copyright Notice"));
|
||||
tag_names.insert(kContact, tr("Contact"));
|
||||
tag_names.insert(kCaptionAbstract, tr("Caption Abstract"));
|
||||
tag_names.insert(kWriterEditor, tr("Writer Editor"));
|
||||
tag_names.insert(kRasterizedCaption, tr("Rasterized Caption"));
|
||||
tag_names.insert(kImageType, tr("Image Type"));
|
||||
tag_names.insert(kImageOrientation, tr("Image Orientation"));
|
||||
tag_names.insert(kLanguageIdentifier, tr("Language Identifier"));
|
||||
tag_names.insert(kAudioType, tr("Audio Type"));
|
||||
tag_names.insert(kAudioSamplingRate, tr("Audio Sampling Rate"));
|
||||
tag_names.insert(kAudioSamplingResolution, tr("Audio Sampling Resolution"));
|
||||
tag_names.insert(kAudioDuration, tr("Audio Duration"));
|
||||
tag_names.insert(kAudioOutcue, tr("Audio Outcue"));
|
||||
tag_names.insert(kObjDataPreviewFileFormat,
|
||||
tr("Object Data Preview File Format"));
|
||||
tag_names.insert(kObjDataPreviewFileFormatVer,
|
||||
tr("Object Data Preview File Format Version"));
|
||||
tag_names.insert(kObjDataPreviewData, tr("Object Data Preview Data"));
|
||||
set_tag_names(tag_names);
|
||||
}
|
||||
|
||||
// Reads the DataSet started from the specified offset.
|
||||
QByteArray Iptc::ReadDataSet(int offset) {
|
||||
QByteArray data;
|
||||
file()->seek(offset);
|
||||
Tag tag = static_cast<Tag>(file()->read(1).toHex().toInt(NULL, 16));
|
||||
if (!tag_names().contains(tag))
|
||||
return data;
|
||||
int size = file()->read(2).toHex().toInt(NULL, 16);
|
||||
data = file()->read(size);
|
||||
return data;
|
||||
}
|
||||
|
||||
// Reads the Record started from the specified offset. Also saves all found
|
||||
// tags and their offsets in the tag_offsets_ property. Returns false if
|
||||
// no tag is found.
|
||||
bool Iptc::ReadRecord() {
|
||||
file()->seek(file_start_offset());
|
||||
QHash<Tag, qint64> tag_offsets;
|
||||
while (file()->read(2).toHex() == "1c02") {
|
||||
qint64 tag_offset = file()->pos();
|
||||
Tag tag = static_cast<Tag>(file()->read(1).toHex().toInt(NULL, 16));
|
||||
QByteArray data = ReadDataSet(tag_offset);
|
||||
|
||||
if (repeatable_tags().contains(tag))
|
||||
tag_offsets.insertMulti(tag, tag_offset);
|
||||
else
|
||||
tag_offsets.insert(tag, tag_offset);
|
||||
}
|
||||
// Returns false if no valid tag is found.
|
||||
if (tag_offsets.count() == 0)
|
||||
return false;
|
||||
|
||||
set_tag_offsets(tag_offsets);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the value associated with the specified tag.
|
||||
QByteArray Iptc::Value(Tag tag) {
|
||||
QByteArray value;
|
||||
if (tag_offsets().contains(tag)) {
|
||||
int offset = tag_offsets().value(tag);
|
||||
value = ReadDataSet(offset);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// Returns a lit containing all the values associated with the specified tag.
|
||||
QList<QByteArray> Iptc::Values(Tag tag) {
|
||||
QList<QByteArray> values;
|
||||
QList<qint64> offsets = tag_offsets().values(tag);
|
||||
for (int i = 0; i < offsets.count(); ++i) {
|
||||
qint64 offset = offsets.at(i);
|
||||
QByteArray value = ReadDataSet(offset);
|
||||
values.append(value);
|
||||
}
|
||||
qSort(values);
|
||||
return values;
|
||||
}
|
||||
|
||||
} // namespace qmeta
|
||||
@ -1,181 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate file_types metadata based on Qt.
|
||||
//
|
||||
// This file implements the detail of the Jpeg class.
|
||||
|
||||
#include "qmeta/jpeg.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <qitty/byte_array.h>
|
||||
|
||||
#include "qmeta/exif.h"
|
||||
#include "qmeta/iptc.h"
|
||||
#include "qmeta/tiff_header.h"
|
||||
#include "qmeta/xmp.h"
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
Jpeg::Jpeg(QByteArray *data) : File(data) {
|
||||
InitMetadata();
|
||||
}
|
||||
|
||||
Jpeg::Jpeg(QIODevice *file) : File(file) {
|
||||
InitMetadata();
|
||||
}
|
||||
|
||||
Jpeg::Jpeg(const QString &file_name) : File(file_name) {
|
||||
InitMetadata();
|
||||
}
|
||||
|
||||
// Reimplements the File::IsValid().
|
||||
bool Jpeg::IsValid() {
|
||||
if (!file())
|
||||
return false;
|
||||
|
||||
// Checks the first 2 bytes if equals to the SOI marker.
|
||||
file()->seek(0);
|
||||
if (file()->read(2).toHex() != "ffd8")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reimplements the File::InitExif().
|
||||
void Jpeg::InitExif() {
|
||||
file()->seek(2);
|
||||
while (!file()->atEnd()) {
|
||||
// Finds APP1 marker.
|
||||
if (file()->read(1).toHex() != "ff")
|
||||
continue;
|
||||
if (file()->read(1).toHex() != "e1")
|
||||
continue;
|
||||
|
||||
// Retrieves the APP1 length. The length doesn't include the APP1 marker.
|
||||
file()->read(2).toHex().toInt(NULL, 16);
|
||||
|
||||
// Checks the Exif signature.
|
||||
if (QString(file()->read(6)) == "Exif")
|
||||
break;
|
||||
}
|
||||
if (file()->atEnd())
|
||||
return;
|
||||
|
||||
TiffHeader *tiff_header = new TiffHeader(this);
|
||||
if (tiff_header->Init(file(), file()->pos())) {
|
||||
// Creates the Exif object.
|
||||
Exif *exif = new Exif(this);
|
||||
if (exif->Init(file(), tiff_header))
|
||||
set_exif(exif);
|
||||
else
|
||||
delete exif;
|
||||
} else {
|
||||
delete tiff_header;
|
||||
}
|
||||
}
|
||||
|
||||
// Reimplements the File::InitIptc().
|
||||
void Jpeg::InitIptc() {
|
||||
// Finds the APP13 marker.
|
||||
file()->seek(2);
|
||||
while (!file()->atEnd()) {
|
||||
if (file()->read(1).toHex() != "ff")
|
||||
continue;
|
||||
if (file()->read(1).toHex() != "ed")
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
// Returns if there is not APP13 marker.
|
||||
if (file()->atEnd())
|
||||
return;
|
||||
|
||||
// Skips segment size marker.
|
||||
file()->read(2);
|
||||
|
||||
// Checks the Photoshop signature.
|
||||
if (QString(file()->read(14)) != "Photoshop 3.0")
|
||||
return;
|
||||
|
||||
bool found_iptc = false;
|
||||
// Interators the Image Resource Blocks to find IPTC data. If found, sets the
|
||||
// `found_iptc` to true and gets out of the loop.
|
||||
while (QString(file()->read(4)) == "8BIM") {
|
||||
int identifier = file()->read(2).toHex().toInt(NULL, 16);
|
||||
// Skips the variable name in Pascal string, padded to make the size even.
|
||||
// A null name consists of two bytes of 0.
|
||||
int name_length = file()->read(1).toHex().toInt(NULL, 16);
|
||||
if (name_length == 0)
|
||||
file()->read(1);
|
||||
else if (name_length % 2 == 1)
|
||||
file()->read(name_length);
|
||||
else
|
||||
file()->read(name_length + 1);
|
||||
// Determines the actual size of resource data that follows.
|
||||
int data_length = file()->read(4).toHex().toInt(NULL, 16);
|
||||
// Determines if the current block is used to record the IPTC data.
|
||||
// If true, the identifier should be 1028 in decimal.
|
||||
if (identifier == 1028) {
|
||||
found_iptc = true;
|
||||
break;
|
||||
} else {
|
||||
file()->read(data_length);
|
||||
}
|
||||
}
|
||||
// Returns if there is no IPTC data.
|
||||
if (!found_iptc)
|
||||
return;
|
||||
|
||||
// Creates the Iptc object.
|
||||
Iptc *iptc = new Iptc(this);
|
||||
if (iptc->Init(file(), file()->pos()))
|
||||
set_iptc(iptc);
|
||||
else
|
||||
delete iptc;
|
||||
}
|
||||
|
||||
// Reimplements the File::InitXmp().
|
||||
void Jpeg::InitXmp() {
|
||||
file()->seek(2);
|
||||
while (!file()->atEnd()) {
|
||||
// Finds APP1 marker.
|
||||
if (file()->read(1).toHex() != "ff")
|
||||
continue;
|
||||
if (file()->read(1).toHex() != "e1")
|
||||
continue;
|
||||
|
||||
// Retrieves the APP1 length. The length doesn't include the APP1 marker.
|
||||
file()->read(2).toHex().toInt(NULL, 16);
|
||||
|
||||
// Checks the XMP signature.
|
||||
if (QString(file()->read(29)) == "http://ns.adobe.com/xap/1.0/")
|
||||
break;
|
||||
}
|
||||
if (file()->atEnd())
|
||||
return;
|
||||
|
||||
Xmp *xmp = new Xmp(this);
|
||||
if (xmp->Init(file(), file()->pos()))
|
||||
set_xmp(xmp);
|
||||
else
|
||||
delete xmp;
|
||||
}
|
||||
|
||||
} // namespace qmeta
|
||||
@ -1,33 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file implements the detail of the Standard class.
|
||||
|
||||
#include "qmeta/standard.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
Standard::Standard(QObject *parent) : QObject(parent) {}
|
||||
|
||||
} // namespace qmeta
|
||||
@ -1,138 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file implements the detail of the TIFF class.
|
||||
|
||||
#include "qmeta/tiff.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <qitty/byte_array.h>
|
||||
|
||||
#include "qmeta/exif.h"
|
||||
#include "qmeta/iptc.h"
|
||||
#include "qmeta/tiff_header.h"
|
||||
#include "qmeta/xmp.h"
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
Tiff::Tiff(QByteArray *data) : File(data) {
|
||||
Init();
|
||||
}
|
||||
|
||||
Tiff::Tiff(QIODevice *file) : File(file) {
|
||||
Init();
|
||||
}
|
||||
|
||||
Tiff::Tiff(const QString &file_name) : File(file_name) {
|
||||
Init();
|
||||
}
|
||||
|
||||
// Initializes the Tiff object.
|
||||
void Tiff::Init() {
|
||||
if (!file())
|
||||
return;
|
||||
|
||||
TiffHeader *tiff_header = new TiffHeader(this);
|
||||
if (tiff_header->Init(file(), 0))
|
||||
set_tiff_header(tiff_header);
|
||||
else
|
||||
set_tiff_header(NULL);
|
||||
|
||||
InitMetadata();
|
||||
}
|
||||
|
||||
// Reimplements the File::IsValid().
|
||||
bool Tiff::IsValid() {
|
||||
if (!file())
|
||||
return false;
|
||||
|
||||
if (tiff_header())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reimplements the File::InitExif().
|
||||
void Tiff::InitExif() {
|
||||
if (tiff_header()) {
|
||||
// Creates the Exif object.
|
||||
Exif *exif = new Exif(this);
|
||||
if (exif->Init(file(), tiff_header()))
|
||||
set_exif(exif);
|
||||
else
|
||||
delete exif;
|
||||
}
|
||||
}
|
||||
|
||||
// Reimplements the File::InitIptc().
|
||||
void Tiff::InitIptc() {
|
||||
tiff_header()->ToFirstIfd();
|
||||
// Creates a variable used to save the offset of the IPTC data. This value
|
||||
// will be overwritten if the IPTC data is found.
|
||||
qint64 iptc_offset = -1;
|
||||
// Finds the IPTC data from the TIFF header. IPTC offset is recorded in
|
||||
// the "IPTC dataset" tag, and represented as 33723 in decimal.
|
||||
while (tiff_header()->HasNextIfdEntry()) {
|
||||
qint64 ifd_entry_offset = tiff_header()->NextIfdEntryOffset();
|
||||
int tag = tiff_header()->IfdEntryTag(ifd_entry_offset);
|
||||
if (tag == 33723) {
|
||||
iptc_offset = tiff_header()->IfdEntryOffset(ifd_entry_offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iptc_offset != -1) {
|
||||
// Creates the Iptc object.
|
||||
Iptc *iptc = new Iptc(this);
|
||||
if (iptc->Init(file(), iptc_offset))
|
||||
set_iptc(iptc);
|
||||
else
|
||||
delete iptc;
|
||||
}
|
||||
}
|
||||
|
||||
// Reimplements the File::InitXmp().
|
||||
void Tiff::InitXmp() {
|
||||
tiff_header()->ToFirstIfd();
|
||||
// Creates a variable used to save the offset of the XMP packet. This value
|
||||
// will be overwritten if the XMP packet is found.
|
||||
qint64 xmp_offset = -1;
|
||||
// Finds the XMP packet from the TIFF header. XMP offset is recorded in
|
||||
// the "XMP packet" tag, and represented as 700 in decimal.
|
||||
while (tiff_header()->HasNextIfdEntry()) {
|
||||
qint64 ifd_entry_offset = tiff_header()->NextIfdEntryOffset();
|
||||
int tag = tiff_header()->IfdEntryTag(ifd_entry_offset);
|
||||
if (tag == 700) {
|
||||
xmp_offset = tiff_header()->IfdEntryOffset(ifd_entry_offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (xmp_offset != -1) {
|
||||
// Creates the Xmp object.
|
||||
Xmp *xmp = new Xmp(this);
|
||||
if (xmp->Init(file(), xmp_offset))
|
||||
set_xmp(xmp);
|
||||
else
|
||||
delete xmp;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace qmeta
|
||||
@ -1,207 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file implements the detail of the TiffHeader class.
|
||||
|
||||
#include "qmeta/tiff_header.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <qitty/byte_array.h>
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
TiffHeader::TiffHeader(QObject *parent) : QObject(parent) {
|
||||
InitTypeByteUnit();
|
||||
}
|
||||
|
||||
// Returns true if next IFD entry exists.
|
||||
bool TiffHeader::HasNextIfdEntry() {
|
||||
if (current_entry_number() < current_entry_count())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the Tag of the entry at the specified entry_offset in decimal.
|
||||
int TiffHeader::IfdEntryTag(qint64 ifd_entry_offset) {
|
||||
file()->seek(ifd_entry_offset);
|
||||
return ReadFromFile(2).toHex().toInt(NULL, 16);
|
||||
}
|
||||
|
||||
// Returns the Type of the entry at the specified entry_offset.
|
||||
TiffHeader::Type TiffHeader::IfdEntryType(qint64 ifd_entry_offset) {
|
||||
file()->seek(ifd_entry_offset + 2);
|
||||
return static_cast<Type>(ReadFromFile(2).toHex().toInt(NULL, 16));
|
||||
}
|
||||
|
||||
// Returns the value of the entry at the specified entry_offset. Note that
|
||||
// the returned value is always in the big-endian byte order.
|
||||
QByteArray TiffHeader::IfdEntryValue(qint64 ifd_entry_offset) {
|
||||
Type type = IfdEntryType(ifd_entry_offset);
|
||||
int count = ReadFromFile(4).toHex().toInt(NULL, 16);
|
||||
// Retrieves the byte unit of the specified type.
|
||||
int current_type_byte_unit = type_byte_unit().value(type);
|
||||
// Calculates the number of bytes used for the entry value.
|
||||
int value_byte_count = current_type_byte_unit * count;
|
||||
// Jumps to the offset containing the entry value if the byte count > 4.
|
||||
if (value_byte_count > 4) {
|
||||
qint64 offset = ReadFromFile(4).toHex().toInt(NULL, 16) +
|
||||
file_start_offset();
|
||||
file()->seek(offset);
|
||||
}
|
||||
|
||||
QByteArray value;
|
||||
if (current_type_byte_unit == 1) {
|
||||
value = file()->read(value_byte_count);
|
||||
} else {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
// If the specified type is RATIONAL or SRATIONAL, read 4 bytes twice
|
||||
// for double LONG or double SLONG, respectively.
|
||||
if (current_type_byte_unit == 8) {
|
||||
value.append(ReadFromFile(4));
|
||||
value.append(ReadFromFile(4));
|
||||
} else {
|
||||
value.append(ReadFromFile(current_type_byte_unit));
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// Returns the value offset for the IFD entry at the specified ifd_entry_offset.
|
||||
// Returns -1 if the if the value is not an offset.
|
||||
qint64 TiffHeader::IfdEntryOffset(qint64 ifd_entry_offset) {
|
||||
Type type = IfdEntryType(ifd_entry_offset);
|
||||
int count = ReadFromFile(4).toHex().toInt(NULL, 16);
|
||||
// Retrieves the byte unit of the specified type.
|
||||
int current_type_byte_unit = type_byte_unit().value(type);
|
||||
// Calculates the number of bytes used for the entry value.
|
||||
int value_byte_count = current_type_byte_unit * count;
|
||||
// Jumps to the offset containing the entry value if the byte count > 4.
|
||||
if (value_byte_count > 4) {
|
||||
qint64 offset = ReadFromFile(4).toHex().toInt(NULL, 16) +
|
||||
file_start_offset();
|
||||
return offset;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Initializes the TiffHeader object. Returns true if successful.
|
||||
bool TiffHeader::Init(QIODevice *file, qint64 file_start_offset) {
|
||||
set_file(file);
|
||||
|
||||
file->seek(file_start_offset);
|
||||
// Determines the byte order in the specified file.
|
||||
QByteArray byte_order = file->read(2);
|
||||
if (byte_order == "II")
|
||||
set_endianness(kLittleEndians);
|
||||
else if (byte_order == "MM")
|
||||
set_endianness(kBigEndians);
|
||||
else
|
||||
return false;
|
||||
|
||||
// Further identifies whether the specified file has a valid TIFF header.
|
||||
// Reads the next two bytes which should have the value of 42 in decimal.
|
||||
if (ReadFromFile(2).toHex().toInt(NULL, 16) != 42)
|
||||
return false;
|
||||
|
||||
// Reads the next four bytes to determine the offset of the first IFD.
|
||||
int first_ifd_offset = ReadFromFile(4).toHex().toInt(NULL, 16);
|
||||
// Sets the offset to the current position if the read value equals to 8.
|
||||
// The reason is for JPEG files, if the TIFF header is followed immediately
|
||||
// by the first IFD, it is written as 00000008 in hexidecimal.
|
||||
if (first_ifd_offset == 8)
|
||||
first_ifd_offset = file->pos();
|
||||
|
||||
// Sets properties.
|
||||
set_file_start_offset(file_start_offset);
|
||||
set_first_ifd_offset(first_ifd_offset);
|
||||
// Jumps to the first IFD by default.
|
||||
ToFirstIfd();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initializes the type_byte_unit_ property.
|
||||
void TiffHeader::InitTypeByteUnit() {
|
||||
QHash<Type, int> type_byte_unit;
|
||||
type_byte_unit.insert(kByteType, 1);
|
||||
type_byte_unit.insert(kAsciiType, 1);
|
||||
type_byte_unit.insert(kShortType, 2);
|
||||
type_byte_unit.insert(kLongType, 4);
|
||||
type_byte_unit.insert(kRationalType, 8);
|
||||
type_byte_unit.insert(kSByte, 1);
|
||||
type_byte_unit.insert(kUndefinedType, 1);
|
||||
type_byte_unit.insert(kSShort, 2);
|
||||
type_byte_unit.insert(kSLongType, 4);
|
||||
type_byte_unit.insert(kSRationalType, 8);
|
||||
type_byte_unit.insert(kFloat, 4);
|
||||
type_byte_unit.insert(kDouble, 8);
|
||||
set_type_byte_unit(type_byte_unit);
|
||||
}
|
||||
|
||||
// Returns the offset of the next IFD entry and increases the entry offset.
|
||||
// Returns -1 if there is no further IFD entry.
|
||||
qint64 TiffHeader::NextIfdEntryOffset() {
|
||||
if (current_entry_number() == current_entry_count())
|
||||
return -1;
|
||||
|
||||
qint64 entry_offset = current_ifd_offset() + 2 + current_entry_number() * 12;
|
||||
// Increases the current entry number by 1.
|
||||
set_current_entry_number(current_entry_number() + 1);
|
||||
// If already reaches the end of the current IFD. Jumps to the next IFD if
|
||||
// available.
|
||||
if (current_entry_number() == current_entry_count()) {
|
||||
file()->seek(current_ifd_offset() + 2 + current_entry_count() * 12);
|
||||
qint64 next_ifd_offset = ReadFromFile(4).toHex().toInt(NULL, 16);
|
||||
if (next_ifd_offset != 0)
|
||||
ToIfd(next_ifd_offset + file_start_offset());
|
||||
}
|
||||
return entry_offset;
|
||||
}
|
||||
|
||||
// Reads at most max_size bytes from the tracked file object, and returns the
|
||||
// data read as a QByteArray in big-endian byte order.
|
||||
QByteArray TiffHeader::ReadFromFile(const int max_size) {
|
||||
QByteArray data = file()->read(max_size);
|
||||
if (endianness() == kLittleEndians)
|
||||
data = qitty_utils::ReverseByteArray(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
// Jumps to the offset of the first IFD and sets the current_entry_number_ and
|
||||
// the entry_count_ properties.
|
||||
void TiffHeader::ToFirstIfd() {
|
||||
ToIfd(first_ifd_offset());
|
||||
}
|
||||
|
||||
// Jumps to the IFD at specified offset and sets the current_entry_number_ and
|
||||
// the entry_count_ properties. The specified offset must point to the beginning
|
||||
// of a valid IFD.
|
||||
void TiffHeader::ToIfd(qint64 offset) {
|
||||
file()->seek(offset);
|
||||
set_current_ifd_offset(offset);
|
||||
set_current_entry_count(ReadFromFile(2).toHex().toInt(NULL, 16));
|
||||
set_current_entry_number(0);
|
||||
}
|
||||
|
||||
} // namespace qmeta
|
||||
@ -1,41 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of Qitty.
|
||||
//
|
||||
// Qitty is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// Qitty is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Qitty. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// Qitty - a toolkit to enhance the Qt library.
|
||||
//
|
||||
// Implements utility functions for Qt's QByteArray class.
|
||||
|
||||
#include "qitty/byte_array.h"
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
namespace qitty_utils {
|
||||
|
||||
// Reverses the order of data in the specified byte_array.
|
||||
QByteArray ReverseByteArray(QByteArray byte_array) {
|
||||
QByteArray reversed_byte_array;
|
||||
while (byte_array.count()) {
|
||||
reversed_byte_array.append(byte_array.right(1).at(0));
|
||||
byte_array.chop(1);
|
||||
}
|
||||
return reversed_byte_array;
|
||||
}
|
||||
|
||||
} // namespace qitty_utils
|
||||
@ -1,56 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of Qitty.
|
||||
//
|
||||
// Qitty is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// Qitty is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Qitty. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// Qitty - a toolkit to enhance the Qt library.
|
||||
|
||||
#include "qitty/image.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QImageReader>
|
||||
#include <QString>
|
||||
|
||||
namespace qitty_utils {
|
||||
|
||||
// Returns an image with the given length and tries to load the image from the
|
||||
// file with the given file_name.
|
||||
QImage SacledImage(const QString &file_name, int length) {
|
||||
QImageReader image_reader(file_name);
|
||||
if (!image_reader.canRead()) {
|
||||
QImage image;
|
||||
return image;
|
||||
}
|
||||
|
||||
int image_width = image_reader.size().width();
|
||||
int image_height = image_reader.size().height();
|
||||
if (image_width > image_height) {
|
||||
image_height = static_cast<double>(length) / image_width * image_height;
|
||||
image_width = length;
|
||||
} else if (image_width < image_height) {
|
||||
image_width = static_cast<double>(length) / image_height * image_width;
|
||||
image_height = length;
|
||||
} else {
|
||||
image_width = length;
|
||||
image_height = length;
|
||||
}
|
||||
image_reader.setScaledSize(QSize(image_width, image_height));
|
||||
return image_reader.read();
|
||||
}
|
||||
|
||||
} // namespace qitty_utils
|
||||
@ -1,40 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of Qitty.
|
||||
//
|
||||
// Qitty is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// Qitty is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Qitty. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// Qitty - a toolkit to enhance the Qt library.
|
||||
|
||||
#include "qitty/style_sheet.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QIODevice>
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
|
||||
namespace qitty_utils {
|
||||
|
||||
// Sets the style sheet of the specified widget from the specified file path.
|
||||
void SetStyleSheet(QWidget *widget, const QString &path) {
|
||||
QFile file(path);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
widget->setStyleSheet(QString(file.readAll().constData()));
|
||||
file.close();
|
||||
}
|
||||
|
||||
} // namespace qitty_utils
|
||||
@ -1,95 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of Qitty.
|
||||
//
|
||||
// Qitty is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// Qitty is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Qitty. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// Qitty - a toolkit to enhance the Qt library.
|
||||
//
|
||||
// This file implements the detail of the LineEdit class.
|
||||
|
||||
#include "qitty/line_edit.h"
|
||||
|
||||
#include <QtGui>
|
||||
|
||||
namespace qitty_widgets {
|
||||
|
||||
// Constructs a line edit with no text.
|
||||
LineEdit::LineEdit(QWidget *parent) : QLineEdit(parent) {
|
||||
Init();
|
||||
}
|
||||
|
||||
// Constructs a line edit containing the text `contents`.
|
||||
LineEdit::LineEdit(const QString &contents, QWidget *parent) :
|
||||
QLineEdit(contents, parent) {
|
||||
Init();
|
||||
}
|
||||
|
||||
// Clears focus if the clear_focus_when_return_pressed_ property is set to true.
|
||||
void LineEdit::ClearFocusWhenReturnPressed() {
|
||||
if (clear_focus_when_return_pressed())
|
||||
clearFocus();
|
||||
}
|
||||
|
||||
// Reimplements the QLineEdit::focusInEvent() function.
|
||||
void LineEdit::focusInEvent(QFocusEvent *event) {
|
||||
// Clears the text if the hint is set.
|
||||
if (!hint().isNull())
|
||||
setText("");
|
||||
|
||||
QLineEdit::focusInEvent(event);
|
||||
}
|
||||
|
||||
// Reimplements the QLineEdit::focusOutEvent() function.
|
||||
void LineEdit::focusOutEvent(QFocusEvent *event) {
|
||||
// Emits the FocusOut() signal.
|
||||
emit FocusOut();
|
||||
|
||||
// Sets the text to the hint if the hint is set.
|
||||
if (!hint().isNull())
|
||||
setText(hint());
|
||||
|
||||
QLineEdit::focusOutEvent(event);
|
||||
}
|
||||
|
||||
// Initializes the LineEdit object. This function should be called in all
|
||||
// constructors.
|
||||
void LineEdit::Init() {
|
||||
set_clear_focus_when_return_pressed(false);
|
||||
set_is_modified(false);
|
||||
// Updates the is_modified_ property using the modificationChanged() signal.
|
||||
connect(this, SIGNAL(textEdited(const QString)),
|
||||
this, SLOT(SetModifiedToTrue()));
|
||||
// Clears focus when the Return or the Enter key pressed if the
|
||||
// clear_focus_when_return_pressed_ is set to true.
|
||||
connect(this, SIGNAL(returnPressed()),
|
||||
this, SLOT(ClearFocusWhenReturnPressed()));
|
||||
}
|
||||
|
||||
// Sets the hint, also sets the text if the widget doesn't have focus.
|
||||
void LineEdit::SetHint(const QString &hint) {
|
||||
set_hint(hint);
|
||||
if (!hasFocus())
|
||||
setText(hint);
|
||||
}
|
||||
|
||||
// [slot] Sets the is_modified_ property to true.
|
||||
void LineEdit::SetModifiedToTrue() {
|
||||
set_is_modified(true);
|
||||
}
|
||||
|
||||
} // namespace qitty_widgets
|
||||
@ -1,203 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of Qitty.
|
||||
//
|
||||
// Qitty is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// Qitty is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Qitty. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// Qitty - a toolkit to enhance the Qt library.
|
||||
//
|
||||
// This file implements the detail of the PlainTextEdit class.
|
||||
|
||||
#include "qitty/plain_text_edit.h"
|
||||
|
||||
#include <QtGui>
|
||||
|
||||
#include "qitty/style_sheet.h"
|
||||
|
||||
namespace qitty_widgets {
|
||||
|
||||
// Constructs an PlainTextEdit with `mode` and `parent`.
|
||||
PlainTextEdit::PlainTextEdit(Mode mode, QWidget *parent) :
|
||||
QPlainTextEdit(parent) {
|
||||
Init(mode);
|
||||
}
|
||||
|
||||
// Reimplements the QPlainTextEdit::focusInEvent() function.
|
||||
void PlainTextEdit::focusInEvent(QFocusEvent *event) {
|
||||
// Clears the cursor. The width of the cursor will be recovered in the
|
||||
// keyPressEvent() and the mousePressEvent() functions.
|
||||
setCursorWidth(0);
|
||||
|
||||
// Selects all text. This step is trying to simulates the effect of the
|
||||
// QLineEdit widget whenever the focus moves in to the widget by the Tab key.
|
||||
selectAll();
|
||||
|
||||
QPlainTextEdit::focusInEvent(event);
|
||||
}
|
||||
|
||||
// Reimplements the QPlainTextEdit::focusOutEvent() function.
|
||||
void PlainTextEdit::focusOutEvent(QFocusEvent *event) {
|
||||
// Clears the selection.
|
||||
QTextCursor text_cursor = textCursor();
|
||||
text_cursor.clearSelection();
|
||||
setTextCursor(text_cursor);
|
||||
|
||||
// Emits the FocusOut() signal.
|
||||
emit FocusOut();
|
||||
|
||||
QPlainTextEdit::focusOutEvent(event);
|
||||
}
|
||||
|
||||
// Initializes the PlainTextEdit object. This function should be called
|
||||
// in all constructors.
|
||||
void PlainTextEdit::Init(Mode mode) {
|
||||
setObjectName("plain_text_edit");
|
||||
qitty_utils::SetStyleSheet(this, ":/qitty/css/plain_text_edit.css");
|
||||
// Initializes properties.
|
||||
set_all_selected(false);
|
||||
set_clear_focus_when_return_pressed(false);
|
||||
set_initial_cursor_width(cursorWidth());
|
||||
set_minimum_line_number(3);
|
||||
// Updates the state of the all_selected_ property whenever selection changed.
|
||||
connect(this, SIGNAL(selectionChanged()), this, SLOT(UpdateAllSelected()));
|
||||
// Updates the is_modified_ property using the modificationChanged() signal.
|
||||
connect(this, SIGNAL(modificationChanged(bool)),
|
||||
this, SLOT(UpdateModified(bool)));
|
||||
// Updates the state whenever the mode is changed and keeps the specified
|
||||
// `mode`
|
||||
connect(this, SIGNAL(ModeChanged(Mode)), this, SLOT(UpdateModeState(Mode)));
|
||||
set_mode(mode);
|
||||
}
|
||||
|
||||
// Reimplements the QPlainTextEdit::keyPressEvent() function.
|
||||
void PlainTextEdit::keyPressEvent(QKeyEvent *event) {
|
||||
// Clears focus if the clear_focus_when_return_pressed_ property is set to
|
||||
// true and the Return or the Enter key is pressed.
|
||||
if (clear_focus_when_return_pressed() &&
|
||||
(event->key() == 16777220 || event->key() == 16777221)) {
|
||||
clearFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Recovers the width of the cursor. This step is needed because the cursor
|
||||
// is cleared in the focusInEvent() function.
|
||||
RecoverCursorWidth();
|
||||
|
||||
// If full text is selected, moves the cursor to the start if left or up
|
||||
// arrows are pressed, moves to the end if right or bottom arrows are pressed.
|
||||
if (all_selected()) {
|
||||
if (event->key() == 16777234 || event->key() == 16777235)
|
||||
moveCursor(QTextCursor::Start);
|
||||
else if (event->key() == 16777236 || event->key() == 16777237)
|
||||
moveCursor(QTextCursor::End);
|
||||
}
|
||||
|
||||
QPlainTextEdit::keyPressEvent(event);
|
||||
}
|
||||
|
||||
// Reimplements the QPlainTextEdit::mousePressEvent() function.
|
||||
void PlainTextEdit::mousePressEvent(QMouseEvent *event) {
|
||||
// Recovers the width of the cursor. This step is needed because the cursor
|
||||
// is cleared in the focusInEvent() function.
|
||||
RecoverCursorWidth();
|
||||
|
||||
// Clears the selection if full text is selected.
|
||||
if (all_selected()) {
|
||||
QTextCursor text_cursor = textCursor();
|
||||
text_cursor.clearSelection();
|
||||
setTextCursor(text_cursor);
|
||||
}
|
||||
|
||||
QPlainTextEdit::mousePressEvent(event);
|
||||
}
|
||||
|
||||
// Sets the width of the cursor back to the orignal one.
|
||||
void PlainTextEdit::RecoverCursorWidth() {
|
||||
setCursorWidth(initial_cursor_width());
|
||||
}
|
||||
|
||||
// Reimplements the QPlainTextEdit::resizeEvent() function.
|
||||
void PlainTextEdit::resizeEvent(QResizeEvent *event) {
|
||||
QPlainTextEdit::resizeEvent(event);
|
||||
|
||||
// Updates the minimum_height_ property and the hieght of this widget if
|
||||
// this widget is in the kElasticMode.
|
||||
if (mode() == kElasticMode) {
|
||||
UpdateMinimumHeight();
|
||||
UpdateHeight();
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the all_selected_ property to true if full text is selected.
|
||||
void PlainTextEdit::UpdateAllSelected() {
|
||||
QTextCursor text_cursor = textCursor();
|
||||
if (text_cursor.selectedText() == toPlainText())
|
||||
set_all_selected(true);
|
||||
else
|
||||
set_all_selected(false);
|
||||
}
|
||||
|
||||
// Calculates the proper height according to the plain text. If the height is
|
||||
// shorter than the minimum height, sets the height to the minimum height.
|
||||
// Note that this function is used only in the kElasticMode.
|
||||
void PlainTextEdit::UpdateHeight() {
|
||||
// Calculates the proper height according to current plain text.
|
||||
QFontMetrics font_metrics = fontMetrics();
|
||||
QRect bounding_rect = font_metrics.boundingRect(0, 0, width() - 6, 0,
|
||||
Qt::TextWordWrap,
|
||||
toPlainText());
|
||||
// Determines the actual height by comparing with the minimum height.
|
||||
int height = minimum_height();
|
||||
if (bounding_rect.height() > height)
|
||||
height = bounding_rect.height();
|
||||
// Sets the height of this widget. Adds 6 for padding.
|
||||
setFixedHeight(height + 6);
|
||||
}
|
||||
|
||||
// Calculates the minimum height according to the minimum line number.
|
||||
// Note that this function is used only in the kElasticMode.
|
||||
void PlainTextEdit::UpdateMinimumHeight() {
|
||||
// Creates an empty text to contain minimum lines.
|
||||
QString text;
|
||||
for (int i = 1; i < minimum_line_number(); ++i)
|
||||
text.append(QChar::LineSeparator);
|
||||
// Calculates the height according to the text.
|
||||
QFontMetrics font_metrics = fontMetrics();
|
||||
QRect bounding_rect = font_metrics.boundingRect(0, 0, width(), 0,
|
||||
Qt::TextWordWrap, text);
|
||||
set_minimum_height(bounding_rect.height());
|
||||
}
|
||||
|
||||
// [slot] Updates the state according to the specified `mode`.
|
||||
void PlainTextEdit::UpdateModeState(Mode mode) {
|
||||
if (mode == kElasticMode) {
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setTabChangesFocus(true);
|
||||
// // Updates the height of this widget whenever text changed.
|
||||
connect(this, SIGNAL(textChanged()), this, SLOT(UpdateHeight()));
|
||||
} else {
|
||||
disconnect(this, SIGNAL(textChanged()), this, SLOT(UpdateHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
// [slot] Updates the is_modified_ property by the specified `changed`.
|
||||
void PlainTextEdit::UpdateModified(bool changed) {
|
||||
set_is_modified(changed);
|
||||
}
|
||||
|
||||
} // namespace qitty_widgets
|
||||
@ -1,77 +0,0 @@
|
||||
// Copyright 2010, Ollix
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of QMeta.
|
||||
//
|
||||
// QMeta is free software: you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or any later version.
|
||||
//
|
||||
// QMeta is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with QMeta. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// ---
|
||||
// Author: olliwang@ollix.com (Olli Wang)
|
||||
//
|
||||
// QMeta - a library to manipulate image metadata based on Qt.
|
||||
//
|
||||
// This file implements the detail of the Xmp class.
|
||||
|
||||
#include "qmeta/xmp.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
namespace qmeta {
|
||||
|
||||
Xmp::Xmp(QObject *parent) : Standard(parent) {}
|
||||
|
||||
// Initializes the Xmp object. Returns true if successful.
|
||||
bool Xmp::Init(QIODevice *file, qint64 file_start_offset) {
|
||||
set_file(file);
|
||||
set_file_start_offset(file_start_offset);
|
||||
|
||||
// Checks if wrapper exists. Return false if the header is invalid, or if
|
||||
// the header is valid but the valid trailer is not found.
|
||||
file->seek(file_start_offset);
|
||||
if (QString(file->read(17)) == "<?xpacket begin=\"" &&
|
||||
// Checks the Unicode "zero width non-breaking space charater" (U+FEFF)
|
||||
// used as a byte-order marker.
|
||||
file->read(3).toHex() == "efbbbf" &&
|
||||
// Checks the rest part of the wrapper header.
|
||||
file->read(31) == "\" id=\"W5M0MpCehiHzreSzNTczkc9d\"") {
|
||||
// Makes sure the closing notation of the wrapper header exists.
|
||||
// Note that header attributes other than "begin" and "id" are not
|
||||
// supported currently.
|
||||
bool header_is_valid = false;
|
||||
while (!file->atEnd()) {
|
||||
if (QString(file->read(1)) == "?" && QString(file->read(1)) == ">") {
|
||||
header_is_valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Returns false if the wrapper header is invalid.
|
||||
if (!header_is_valid)
|
||||
return false;
|
||||
// Found wrapper header, now checks if the wrapper trailer exists.
|
||||
bool found_trailer = false;
|
||||
while (!file->atEnd()) {
|
||||
if (QString(file->read(1)) == "<" && QString(file->read(1)) == "?" &&
|
||||
QString(file->read(17)) == "xpacket end=\"w\"?>") {
|
||||
found_trailer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found_trailer)
|
||||
return false;
|
||||
// Found wrapper trailer. Now we can make sure the XMP wrapper is valid.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace qmeta
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user