Skip to content

Commit

Permalink
Merge pull request #8 from rtio/rtio/add-strip-exif-key
Browse files Browse the repository at this point in the history
Add strip key option
  • Loading branch information
antonsergeyev authored Mar 2, 2023
2 parents 33c2dd0 + a3dce42 commit 162de2f
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 0 deletions.
4 changes: 4 additions & 0 deletions exif.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,7 @@ func makeExifDatumIterator(data *ExifData, cIter *C.Exiv2ExifDatumIterator) *Exi

return datum
}

func (i *Image) ExifStripKey(key string) error {
return i.StripKey(EXIF, key)
}
34 changes: 34 additions & 0 deletions exiv.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ type MetadataProvider interface {
GetString(key string) (string, error)
}

type MetadataFormat int

const (
EXIF MetadataFormat = iota
IPTC
XMP
)

var ErrMetadataKeyNotFound = errors.New("key not found")

func (e *Error) Error() string {
Expand Down Expand Up @@ -224,3 +232,29 @@ func (i *Image) SetMetadataShort(format, key, value string) error {

return nil
}

func (i *Image) StripKey(f MetadataFormat, key string) error {
ckey := C.CString(key)
defer C.free(unsafe.Pointer(ckey))

var cErr *C.Exiv2Error

switch f {
case EXIF:
C.exiv2_exif_strip_key(i.img, ckey, &cErr)
case IPTC:
C.exiv2_iptc_strip_key(i.img, ckey, &cErr)
case XMP:
C.exiv2_xmp_strip_key(i.img, ckey, &cErr)
default:
return errors.New("invalid metadata format")
}

if cErr != nil {
err := makeError(cErr)
C.exiv2_error_free(cErr)
return err
}

return nil
}
58 changes: 58 additions & 0 deletions exiv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,64 @@ func Test_GetBytes_Goroutine(t *testing.T) {
t.Logf("Allocated bytes after test: %+v\n", memStats.HeapAlloc)
}

func TestExifStripKey(t *testing.T) {
img, err := goexiv.Open("testdata/pixel.jpg")
require.NoError(t, err)

err = img.SetExifString("Exif.Photo.UserComment", "123")
require.NoError(t, err)

err = img.ExifStripKey("Exif.Photo.UserComment")
require.NoError(t, err)

err = img.ReadMetadata()
require.NoError(t, err)

data := img.GetExifData()

_, err = data.GetString("Exif.Photo.UserComment")
require.Error(t, err)
}

func TestIptcStripKey(t *testing.T) {
img, err := goexiv.Open("testdata/pixel.jpg")
require.NoError(t, err)

err = img.SetIptcString("Iptc.Application2.Caption", "123")
require.NoError(t, err)

err = img.IptcStripKey("Iptc.Application2.Caption")
require.NoError(t, err)

err = img.ReadMetadata()
require.NoError(t, err)

data := img.GetIptcData()

_, err = data.GetString("Iptc.Application2.Caption")
require.Error(t, err)
}

func TestXmpStripKey(t *testing.T) {
t.Skip("XMP SetXmpString and GetString is not implemented yet")
//img, err := goexiv.Open("testdata/pixel.jpg")
//require.NoError(t, err)
//
//err = img.SetXmpString("Xmp.dc.description", "123")
//require.NoError(t, err)
//
//err = img.XmpStripKey("Xmp.dc.description")
//require.NoError(t, err)
//
//err = img.ReadMetadata()
//require.NoError(t, err)
//
//data := img.GetXmpData()
//
//_, err = data.GetString("Xmp.dc.description")
//require.Error(t, err)
}

func BenchmarkImage_GetBytes_KeepAlive(b *testing.B) {
bytes, err := ioutil.ReadFile("testdata/stripped_pixel.jpg")
require.NoError(b, err)
Expand Down
60 changes: 60 additions & 0 deletions helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,66 @@ Exiv2ExifDatum* exiv2_exif_datum_iterator_next(Exiv2ExifDatumIterator *iter)
return iter->next();
}

void
exiv2_exif_strip_key(Exiv2Image *img, char *key, Exiv2Error **error)
{
Exiv2::ExifData exifData = img->image->exifData();

try {
Exiv2::ExifData::iterator pos = exifData.findKey(Exiv2::ExifKey(key));
if (pos == exifData.end()) {
return;
}
exifData.erase(pos);
img->image->setExifData(exifData);
img->image->writeMetadata();
} catch (Exiv2::Error &e) {
if (error) {
*error = new Exiv2Error(e);
}
}
}

void
exiv2_iptc_strip_key(Exiv2Image *img, char *key, Exiv2Error **error)
{
Exiv2::IptcData iptcData = img->image->iptcData();

try {
Exiv2::IptcData::iterator pos = iptcData.findKey(Exiv2::IptcKey(key));
if (pos == iptcData.end()) {
return;
}
iptcData.erase(pos);
img->image->setIptcData(iptcData);
img->image->writeMetadata();
} catch (Exiv2::Error &e) {
if (error) {
*error = new Exiv2Error(e);
}
}
}

void
exiv2_xmp_strip_key(Exiv2Image *img, char *key, Exiv2Error **error)
{
Exiv2::XmpData xmpData = img->image->xmpData();

try {
Exiv2::XmpData::iterator pos = xmpData.findKey(Exiv2::XmpKey(key));
if (pos == xmpData.end()) {
return;
}
xmpData.erase(pos);
img->image->setXmpData(xmpData);
img->image->writeMetadata();
} catch (Exiv2::Error &e) {
if (error) {
*error = new Exiv2Error(e);
}
}
}

DEFINE_FREE_FUNCTION(exiv2_exif_data, Exiv2ExifData*);

const char* exiv2_exif_datum_key(const Exiv2ExifDatum *datum)
Expand Down
4 changes: 4 additions & 0 deletions helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ Exiv2ExifDatumIterator* exiv2_exif_data_iterator(const Exiv2ExifData *data);
int exiv2_exif_data_iterator_has_next(const Exiv2ExifDatumIterator *iter);
Exiv2ExifDatum* exiv2_exif_datum_iterator_next(Exiv2ExifDatumIterator *iter);

void exiv2_exif_strip_key(Exiv2Image *img, char *key, Exiv2Error **error);
void exiv2_iptc_strip_key(Exiv2Image *img, char *key, Exiv2Error **error);
void exiv2_xmp_strip_key(Exiv2Image *img, char *key, Exiv2Error **error);

const unsigned char* exiv2_image_icc_profile(Exiv2Image *img);
long exiv2_image_icc_profile_size(Exiv2Image *img);

Expand Down
4 changes: 4 additions & 0 deletions iptc.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,7 @@ func makeIptcDatumIterator(data *IptcData, cIter *C.Exiv2IptcDatumIterator) *Ipt

return datum
}

func (i *Image) IptcStripKey(key string) error {
return i.StripKey(IPTC, key)
}
4 changes: 4 additions & 0 deletions xmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,7 @@ func (d *XmpDatum) String() string {

return C.GoString(cstr)
}

func (i *Image) XmpStripKey(key string) error {
return i.StripKey(XMP, key)
}

0 comments on commit 162de2f

Please sign in to comment.