Writing bindings for the exiv2 library

There are thousands of libraries already written in C/C++ and used in practice, sometimes for decades. Therefore, it doesn't make sense to try to write everything from scratch. Of course, if you want to run your code in the browser, you have to rewrite it into Dart, but in cases where you're only interested in server-side scripting, you can reuse existing C/C++ code, wrap it with a small native extension, and use it in Dart.

In this example, we'll use exiv2, which is a library written in C++ that can read and modify the EXIF metadata from pictures. This is, for example, what camera vendor and model you used, the exposure time, and so on:

// main.cpp
// Header file is a part of exiv2 source code.
#include "exiv2.hpp"

void GetExifRecord(Dart_NativeArguments arguments) {
    Dart_EnterScope();
    
    const char *filename;
    const char *tag;
    Dart_StringToCString(
        Dart_GetNativeArgument(arguments, 0), &filename);
    Dart_StringToCString(
        Dart_GetNativeArgument(arguments, 1), &tag);

    Exiv2::Image::AutoPtr image =
        Exiv2::ImageFactory::open(filename);
    image->readMetadata();
    Exiv2::ExifData &exifData = image->exifData();
    Exiv2::ExifKey key = Exiv2::ExifKey(tag);
    Exiv2::ExifData::const_iterator pos = exifData.findKey(key);
    
    Dart_Handle result;
    
    if (pos == exifData.end()) { // not found
        result = Dart_Null();
    } else {
        result = Dart_NewStringFromCString(
            pos->value().toString().c_str());
    }
    
    Dart_SetReturnValue(arguments, result);
    Dart_ExitScope();
}

void GetAllExifRecords(Dart_NativeArguments args) {
    Dart_EnterScope();
    
    const char *fname;
    Dart_StringToCString(Dart_GetNativeArgument(args, 0), &fname);
        
    Exiv2::Image::AutoPtr image =
        Exiv2::ImageFactory::open(fname);
    image->readMetadata();
    Exiv2::ExifData &exifData = image->exifData();
    Exiv2::ExifData::const_iterator end = exifData.end();
    Exiv2::ExifData::const_iterator pointer = exifData.begin();
    
    Dart_Handle result = Dart_NewList(exifData.count());
    // Iterate all EXIF records.
    for (int j = 0; pointer != end; ++pointer, j++) {
        // Create 	 delimetered char*.
        std::stringstream fmt;
        fmt << pointer->key() << "	" << pointer->value();
        const char *record = fmt.str().c_str();
        Dart_ListSetAt(result, j,
            Dart_NewStringFromCString(record));
    }
    
    Dart_SetReturnValue(args, result);
    Dart_ExitScope();
}

We created two functions. The first one returns a specific EXIF record by its tag name. The second one creates a list of all tags and records delimited by the character. Right now, there's no easy way to create a Dart's Map object and set its key-value pairs in a native extension, so we'll process the List object later in Dart.

The rest of the C++ code is the same as in the previous examples. The Dart code just wraps all calls to the extension:

// lib/exiv2/exiv2.dart
import 'dart-ext:exiv2_wrapper';

List<String> _all(String filename) native "GetAllExifRecords";
String _get(String filename, String tag) native "GetExifRecord";

Map<String, String> all(String filename) {
  Map<String, String> map = {};
  _all(filename).forEach((String record) {
    List kv = record.split('	'),
    map[kv[0]] = kv[1];
  });
  return map;
}

String get(String filename, String tag) {
  return _get(filename, tag);
}

We wrapped calls to _all() with a function that converts Dart's List object into a Map object. Let's test our extension with the following code:

import 'package:Chapter_09_exiv2/exiv2/exiv2.dart' as exiv2;
import 'dart:io';

main() {
  String path = Platform.script.resolve('img.jpg').toFilePath();
  exiv2.all(path).forEach((String key, String value) {
    print("$key = $value");
  });
  print(exiv2.get(path, 'Exif.Photo.ExposureTime'));
}

The result looks something like this:

$ dart main.dart 
Exif.Image.Make = Canon
Exif.Image.Model = Canon EOS 550D
Exif.Image.Orientation = 1
...
Exif.Photo.WhiteBalance = 1
Exif.Photo.SceneCaptureType = 0
1/250

As of now (May 2015), the Dart package repository doesn't contain any EXIF manipulation library written in Dart.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.126.56