mirror of
https://github.com/talgo-cloud/bimg.git
synced 2026-03-16 19:05:54 -07:00
add more exif data to metadata
This commit is contained in:
parent
9b82aecec1
commit
b38ffd41d1
6 changed files with 118 additions and 6 deletions
20
metadata.go
20
metadata.go
|
|
@ -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
|
||||||
|
|
|
||||||
BIN
testdata/test_exif.jpg
vendored
Normal file
BIN
testdata/test_exif.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 793 KiB |
BIN
testdata/test_exif_canon.jpg
vendored
Normal file
BIN
testdata/test_exif_canon.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.8 KiB |
23
vips.go
23
vips.go
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
43
vips.h
43
vips.h
|
|
@ -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) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
vips_exif_tag(VipsImage *image, const char *tag) {
|
||||||
|
const char *exif;
|
||||||
|
if (
|
||||||
|
vips_image_get_typeof(image, tag) != 0 &&
|
||||||
|
!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
|
int
|
||||||
vips_exif_orientation(VipsImage *image) {
|
vips_exif_orientation(VipsImage *image) {
|
||||||
int orientation = 0;
|
int orientation = 0;
|
||||||
const char *exif;
|
const char *exif = vips_exif_tag(image, EXIF_IFD0_ORIENTATION);
|
||||||
if (
|
if (strcmp(exif, "")) {
|
||||||
vips_image_get_typeof(image, EXIF_IFD0_ORIENTATION) != 0 &&
|
|
||||||
!vips_image_get_string(image, EXIF_IFD0_ORIENTATION, &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…
Add table
Add a link
Reference in a new issue