#include #include #include #include #include #include #include const char* ORIENTATION_KEY = "Exif.Image.Orientation"; extern "C" unsigned int getExifOrientation(uint8_t* imgBytes, unsigned int size) { try { Exiv2::XmpParser::initialize(); ::atexit(Exiv2::XmpParser::terminate); Exiv2::enableBMFF(); Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(imgBytes, size); assert(image.get() != 0); image->readMetadata(); Exiv2::ExifData &exifData = image->exifData(); if (exifData.empty()) { return 9; } return (unsigned int) exifData[ORIENTATION_KEY].toLong(); } //catch (std::exception& e) { //catch (Exiv2::AnyError& e) { catch (Exiv2::Error& e) { std::cout << "Caught Exiv2 exception '" << e.what() << "'\n"; return 9; } } extern "C" void setExifOrientation(char* fileName, unsigned int orientation) { try { // Exiv init Exiv2::XmpParser::initialize(); ::atexit(Exiv2::XmpParser::terminate); Exiv2::enableBMFF(); // using blob works, except that exiv2 won't write back to the blob :( // std::unique_ptr image = Exiv2::ImageFactory::open(imgBytes, size); // So instead we load from the temp file std::unique_ptr image = Exiv2::ImageFactory::open(fileName); assert(image.get() != 0); image->readMetadata(); Exiv2::ExifData &exifData = image->exifData(); exifData[ORIENTATION_KEY] = orientation; // Save exif to image object & save image back to file image->setExifData(exifData); image->writeMetadata(); } catch (Exiv2::Error& e) { std::cout << "Caught Exiv2 exception '" << e.what() << "'\n"; } } /* extern "C" void setExifOrientation(uint8_t* imgBytes, unsigned int size, unsigned int orientation) { try { // Hack to work around Exiv2 seeming to refuse to write back to blob, but will write // back to a file. Create temp file -> operate on it -> copy back to blob, unlink file. // tmpFileName gets overwritten with the actual filename by mkstemp char tmpFileName[] = "/tmp/image-temp.XXXXXX"; int fd = mkstemp(tmpFileName); assert(fd != -1); write(fd, imgBytes, size); close(fd); // Exiv init Exiv2::XmpParser::initialize(); ::atexit(Exiv2::XmpParser::terminate); Exiv2::enableBMFF(); // using blob works, except that exiv2 won't write back to the blob :( // std::unique_ptr image = Exiv2::ImageFactory::open(imgBytes, size); // So instead we load from the temp file std::unique_ptr image = Exiv2::ImageFactory::open(tmpFileName); assert(image.get() != 0); image->readMetadata(); Exiv2::ExifData &exifData = image->exifData(); exifData[ORIENTATION_KEY] = orientation; // Save exif to image object & save image back to file image->setExifData(exifData); image->writeMetadata(); //TODO: fix problem of img file corruption caused by output being a different size // to the input buffer FILE *fileptr; char *buffer; long filelen; fileptr = fopen(tmpFileName, "rb"); fseek(fileptr, 0, SEEK_END); filelen = ftell(fileptr); rewind(fileptr); buffer = (char *)malloc(filelen * sizeof(char)); fread(buffer, filelen, 1, fileptr); fclose(fileptr); printf("new len: %ld old len: %d", filelen, size); // reopen temp file, copy result back into byte array fileptr = fopen(tmpFileName, "rb"); fread(imgBytes, size, 1, fileptr); fclose(fileptr); // unlink(tmpFileName); } catch (Exiv2::Error& e) { std::cout << "Caught Exiv2 exception '" << e.what() << "'\n"; } }*/