본문 바로가기

Dead Code/Flutter_Dart

[플러터] Sheets로 이미지 URL의 EXIF 정보 얻어내기

Sheets를 DB로 사용하는만큼, 데이터를 손쉽게 추가할 수 있는 장점이 있다.(아니, 이미지 원본이 함께 저장되는 DB에서는 더 쉽게 처리할 수 있을 것 같기는 하다.)

웹에 올려진 이미지에서 EXIF 정보를 얻어내는 후처리가 필요한 경우에 아주 요긴하게 사용할 수 있을 것 같은 느낌이 있었으나, APPSCRIPT부터 시작해서, 꽤 오래전에 봤었던 내용을 찬찬히 복기해 보고 있자니, 생각보다 꽤 오랜 시간이 걸렸다.

 

사진 앨범의 특정사진을 탭했을때, EXIF 정보가 같이 노출되길 바랬던 본 프로젝트에서 전제되어있는 컨디션은 아래와 같다. 

_원본 이미지가 특정 경로에 올라가 있다.

_특정열에 경로(URL) 정보가 들어가 있다. 물론 해당 경로상의 이미지는 EXIF 데이터를 가지고 있다.

_Sheets의 매크로로, EXIF 중 원하는 데이터를 해당 열에 추가한다.

정리가 된다면 아래 이미지처럼 될 것이다. 해당 내용은 flutter를 통해, 불러들어져서 이미지지 위에 표기될 예정이다.

 

 

 

플러터 상에서 이미지를 bytecode로 변환하여, 추출하는 방법이 있으나, 장당 10메가가 넘는 EXIF 데이터가 포함된 원본 이미지를 불러오는 것은 모바일에서는 상당한 부담이고, 그렇게 기다려야할만큼 매력이 있는 정보는 아니다.

 

그래서 그냥 Sheets에서 사진을 업데이트할때마다, 매크로로 돌려줄 생각이다. 함수를 쓴다면, 매번 데이터를 불러올텐데, 그 시간 또한 꽤 걸리므로, 이미 확정된 데이터를 업데이트해줄 필요는 없을 것이다. 매크로를 써서, 데이터 값이 이미 있으면 스킵하도록 했다.

 

APPSCRIPT 코드는 아래와 같다. 개발새발 노가다로 하다보니, 뭐 별수 없다. 맞는지 틀린지 잘 모르겠지만, 일단 대략적인 flow는 데이터가 있으면 스킵하고, 없으면, 이미지URL에서 이미지를 복사, 구글Drive에 저장하고, 원하는 EXIF 데이터를 추출한 다음 파일은 지우고, 해당 정보를 Sheets에 키인해준다.

 

function getExifDataFromUrl() {
  var app = SpreadsheetApp.getActiveSpreadsheet();
  var o_sht = app.getSheetByName("gal");

  for (let r = 1; r < o_sht.getLastRow() + 1; r++) {
    Logger.log(r);

    if (o_sht.getRange(r, 6).getValue() == "") {
      if (o_sht.getRange(r, 1).getValue() == "img") {
        var url = o_sht.getRange(r, 3).getValue();
        o_sht.getRange(r, 6).setValue(getExifData(url)[0]);
        o_sht.getRange(r, 7).setValue(getExifData(url)[1]);
        o_sht.getRange(r, 8).setValue(getExifData(url)[2]);
      } else {
        if (r >= 2) {
          o_sht.getRange(r, 6).setValue("-");
          o_sht.getRange(r, 7).setValue("-");
          o_sht.getRange(r, 8).setValue("-");
        }
      }
    }
  }
}

function getExifData(imageUrl) {
  var response = UrlFetchApp.fetch(imageUrl, {
    headers: { "Contents-Type": "img/jpeg" },
  });
  var fileBlob = response.getBlob();
  var res = Drive.Files.insert({ title: "temp" }, fileBlob);
  var meta = res.imageMediaMetadata;
  Drive.Files.remove(res.id);

  return [meta.cameraModel, meta.lens, meta.aperture];
}

 

생각보다, 잘 되서 석연치 않기는 하지만, 좀 오래 걸리긴 하는데, 음.. 뭘 걷어내야할지는 잘 모르겠다.

 

끝.