add more exif data to metadata

master
fredrsf 5 years ago
parent 9b82aecec1
commit b38ffd41d1

@ -22,6 +22,15 @@ type ImageMetadata struct {
Space string Space string
Colourspace string Colourspace string
Size ImageSize Size ImageSize
EXIF EXIF
}
type EXIF struct {
Make string
Model string
Orientation int
Software string
Datetime string
} }
// Size returns the image size by width and height pixels. // Size returns the image size by width and height pixels.
@ -63,14 +72,23 @@ func Metadata(buf []byte) (ImageMetadata, error) {
Height: int(image.Ysize), Height: int(image.Ysize),
} }
orientation := vipsExifOrientation(image)
metadata := ImageMetadata{ metadata := ImageMetadata{
Size: size, Size: size,
Channels: int(image.Bands), Channels: int(image.Bands),
Orientation: vipsExifOrientation(image), Orientation: orientation,
Alpha: vipsHasAlpha(image), Alpha: vipsHasAlpha(image),
Profile: vipsHasProfile(image), Profile: vipsHasProfile(image),
Space: vipsSpace(image), Space: vipsSpace(image),
Type: ImageTypeName(imageType), Type: ImageTypeName(imageType),
EXIF: EXIF{
Make: vipsExifMake(image),
Model: vipsExifModel(image),
Orientation: orientation,
Software: vipsExifSoftware(image),
Datetime: vipsExifDatetime(image),
},
} }
return metadata, nil return metadata, nil

@ -89,6 +89,44 @@ func TestImageInterpretation(t *testing.T) {
} }
} }
func TestEXIF(t *testing.T) {
files := []struct {
name string
make string
model string
orientation int
software string
datetime string
}{
{"test.jpg", "", "", 0, "", ""},
{"exif/Landscape_1.jpg", "", "", 1, "", ""},
{"test_exif.jpg", "Jolla", "Jolla", 1, "", "2014:09:21 16:00:56"},
{"test_exif_canon.jpg", "Canon", "Canon EOS 40D", 1, "GIMP 2.4.5", "2008:07:31 10:38:11"},
}
for _, file := range files {
metadata, err := Metadata(readFile(file.name))
if err != nil {
t.Fatalf("Cannot read the image: %s -> %s", file.name, err)
}
if metadata.EXIF.Make != file.make {
t.Fatalf("Unexpected image exif make: %s != %s", metadata.EXIF.Make, file.make)
}
if metadata.EXIF.Model != file.model {
t.Fatalf("Unexpected image exif model: %s != %s", metadata.EXIF.Model, file.model)
}
if metadata.EXIF.Orientation != file.orientation {
t.Fatalf("Unexpected image exif orientation: %d != %d", metadata.EXIF.Orientation, file.orientation)
}
if metadata.EXIF.Software != file.software {
t.Fatalf("Unexpected image exif software: %s != %s", metadata.EXIF.Software, file.software)
}
if metadata.EXIF.Datetime != file.datetime {
t.Fatalf("Unexpected image exif datetime: %s != %s", metadata.EXIF.Datetime, file.datetime)
}
}
}
func TestColourspaceIsSupported(t *testing.T) { func TestColourspaceIsSupported(t *testing.T) {
files := []struct { files := []struct {
name string name string

Binary file not shown.

After

Width:  |  Height:  |  Size: 793 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

@ -215,10 +215,33 @@ func VipsIsTypeSupportedSave(t ImageType) bool {
return false return false
} }
func vipsExifMake(image *C.VipsImage) string {
return vipsExifShort(C.GoString(C.vips_exif_make(image)))
}
func vipsExifModel(image *C.VipsImage) string {
return vipsExifShort(C.GoString(C.vips_exif_model(image)))
}
func vipsExifOrientation(image *C.VipsImage) int { func vipsExifOrientation(image *C.VipsImage) int {
return int(C.vips_exif_orientation(image)) return int(C.vips_exif_orientation(image))
} }
func vipsExifSoftware(image *C.VipsImage) string {
return vipsExifShort(C.GoString(C.vips_exif_software(image)))
}
func vipsExifDatetime(image *C.VipsImage) string {
return vipsExifShort(C.GoString(C.vips_exif_datetime(image)))
}
func vipsExifShort(s string) string {
if strings.Contains(s, " (") {
return s[:strings.Index(s, "(")-1]
}
return s
}
func vipsHasAlpha(image *C.VipsImage) bool { func vipsHasAlpha(image *C.VipsImage) bool {
return int(C.has_alpha_channel(image)) > 0 return int(C.has_alpha_channel(image)) > 0
} }

@ -18,7 +18,11 @@
#define VIPS_ANGLE_D270 VIPS_ANGLE_270 #define VIPS_ANGLE_D270 VIPS_ANGLE_270
#endif #endif
#define EXIF_IFD0_MAKE "exif-ifd0-Make"
#define EXIF_IFD0_MODEL "exif-ifd0-Model"
#define EXIF_IFD0_ORIENTATION "exif-ifd0-Orientation" #define EXIF_IFD0_ORIENTATION "exif-ifd0-Orientation"
#define EXIF_IFD0_SOFTWARE "exif-ifd0-Software"
#define EXIF_IFD0_DATETIME "exif-ifd0-DateTime"
#define INT_TO_GBOOLEAN(bool) (bool > 0 ? TRUE : FALSE) #define INT_TO_GBOOLEAN(bool) (bool > 0 ? TRUE : FALSE)
@ -218,19 +222,48 @@ vips_rotate_bridge(VipsImage *in, VipsImage **out, int angle) {
} }
} }
int const char *
vips_exif_orientation(VipsImage *image) { vips_exif_tag(VipsImage *image, const char *tag) {
int orientation = 0;
const char *exif; const char *exif;
if ( if (
vips_image_get_typeof(image, EXIF_IFD0_ORIENTATION) != 0 && vips_image_get_typeof(image, tag) != 0 &&
!vips_image_get_string(image, EXIF_IFD0_ORIENTATION, &exif) !vips_image_get_string(image, tag, &exif)
) { ) {
return &exif[0];
}
return "";
}
const char *
vips_exif_make(VipsImage *image) {
return vips_exif_tag(image, EXIF_IFD0_MAKE);
}
const char *
vips_exif_model(VipsImage *image) {
return vips_exif_tag(image, EXIF_IFD0_MODEL);
}
int
vips_exif_orientation(VipsImage *image) {
int orientation = 0;
const char *exif = vips_exif_tag(image, EXIF_IFD0_ORIENTATION);
if (strcmp(exif, "")) {
orientation = atoi(&exif[0]); orientation = atoi(&exif[0]);
} }
return orientation; return orientation;
} }
const char *
vips_exif_software(VipsImage *image) {
return vips_exif_tag(image, EXIF_IFD0_SOFTWARE);
}
const char *
vips_exif_datetime(VipsImage *image) {
return vips_exif_tag(image, EXIF_IFD0_DATETIME);
}
int int
interpolator_window_size(char const *name) { interpolator_window_size(char const *name) {
VipsInterpolate *interpolator = vips_interpolate_new(name); VipsInterpolate *interpolator = vips_interpolate_new(name);

Loading…
Cancel
Save