728x90
플러터에서 사진촬영 또는 사진 이미지에서 위치좌표를 추출하는 방법을 알아보자.
사진을 찍을 때 위치좌표값이 포함되어 저장되도록 하는 방법은 카메라에서 위치정보를 활성화시켜야 한다.
아이폰
설정 → 개인정보 보호 및 보안 → 위치서비스 → 카메라 → 앱을 사용하는 동안
안드로이드폰
카메라 앱 → 카메라 설정 → 위치태그 활성화
위와 같이 하면 기본적으로 사진을 찍으면 이미지에 위치정보가 포함된다.
하지만 구현하는 앱에서 카메라로 촬영해도 위치정보가 포함되지 않을 수도 있다.
이 경우에는 사진을 찍는 시점의 GPS 위치정보를 기준으로 위치정보를 수집해야 한다.
pubspec.yaml 파일
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
dio: ^5.4.0
retrofit: ^4.0.3
flutter_riverpod: ^2.4.9
json_annotation: ^4.8.1
freezed_annotation: ^2.4.1
permission_handler: ^11.2.0
flutter_secure_storage: ^9.0.0
image_picker: ^1.0.7
exif: ^3.3.0
geolocator: ^10.1.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
build_runner: ^2.4.8
json_serializable: ^6.7.1
freezed: ^2.4.6
retrofit_generator: ^8.0.6
|
앨범 및 사진촬영한 이미지를 앱 화면에 보여주는 예제 코드
import 'dart:io';
import 'package:exif/exif.dart';
import 'package:fileupload/presentation/view/file_upload_screen.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:image_picker/image_picker.dart';
class ImageViewScreen extends StatefulWidget {
const ImageViewScreen({super.key});
@override
State<ImageViewScreen> createState() => _ImageViewScreenState();
}
class _ImageViewScreenState extends State<ImageViewScreen> {
XFile? _image; //이미지 담을 변수 선언
double latitude = 0;
double longitude = 0;
bool isLocation = false;
@override
void initState() {
super.initState();
getLocationPermission();
}
Future<void> getLocationPermission() async {
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
}
}
Future<void> getImage(ImageSource imageSource) async {
var picker = ImagePicker();
var pickerImage = await picker.pickImage(source: imageSource);
// 이미지를 읽을 때마다 위치정보 좌표값 초기화 처리
latitude = 0;
longitude = 0;
if (pickerImage != null) {
var metadata = await readExifFromBytes(File(pickerImage.path).readAsBytesSync());
if (metadata.containsKey('GPS GPSLatitude')) {
print("location enabled");
isLocation = true;
getCurrentLocationFromexif(metadata);
} else {
isLocation = false;
print("location disabled");
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
latitude = position.latitude;
longitude = position.longitude;
} catch (e) {
print(e);
}
}
// 이미지를 출력하기 위해 상태 변경
setState(() {
_image = XFile(pickerImage.path);
});
}
}
Future<void> getCurrentLocationFromexif(var data) async {
if (data.containsKey('GPS GPSLongitude')) {
final gpsLatitude = data['GPS GPSLatitude'];
final latitudeSignal = data['GPS GPSLatitudeRef']!.printable;
List latitudeRation = gpsLatitude!.values.toList();
List latitudeValue = latitudeRation.map((item) {
return (item.numerator.toDouble() / item.denominator.toDouble());
}).toList();
latitude = latitudeValue[0] + (latitudeValue[1] / 60) +
(latitudeValue[2] / 3600);
if (latitudeSignal == 'S') latitude = -latitude;
print('latitude ::: ${latitude}');
final gpsLongitude = data['GPS GPSLongitude'];
final longitudeSignal = data['GPS GPSLongitude']!.printable;
List longitudeRation = gpsLongitude!.values.toList();
List longitudeValue = longitudeRation.map((item) {
return (item.numerator.toDouble() / item.denominator.toDouble());
}).toList();
longitude = longitudeValue[0] + (longitudeValue[1] / 60) +
(longitudeValue[2] / 3600);
if (longitudeSignal == 'W') longitude = -longitude;
print('longitude ::: ${longitude}');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildPhotoArea(),
if(latitude > 0) _buildLocation(),
],
),
floatingActionButton: Stack(
children: [
Align(
alignment: Alignment(
Alignment.bottomRight.x, Alignment.bottomRight.y - 0.4),
child: FloatingActionButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const FileUploadScreen(),
));
},
tooltip: 'back',
heroTag: UniqueKey(),
child: const Icon(Icons.arrow_back),
),
),
Align(
alignment: Alignment(
Alignment.bottomRight.x, Alignment.bottomRight.y - 0.2),
child: FloatingActionButton(
onPressed: () async {
getImage(ImageSource.camera);
},
tooltip: 'image',
heroTag: UniqueKey(),
child: const Icon(Icons.camera_alt),
),
),
Align(
alignment: Alignment.bottomRight,
child: FloatingActionButton(
onPressed: () async {
getImage(ImageSource.gallery);
},
tooltip: 'image',
heroTag: UniqueKey(),
child: const Icon(Icons.image),
),
),
],
),
);
}
Widget _buildPhotoArea() {
return _image != null
? Container(
width: 400,
height: 400,
child: Image.file(File(_image!.path)), //가져온 이미지 화면에 띄워주는 코드
)
: const Center(
child: Text("불러온 이미지가 없습니다."),
);
}
Widget _buildLocation() {
return Column(
children: [
Container(
child: Text('GPS Location ::: $isLocation'),
),
Container(
child: Text('위도: ${latitude} ,경도: ${longitude}'),
),
],
);
}
}
|
위 소스코드를 보다 정리한 모든 소스코드 파일은 GitHub 에 올려두었다.
https://github.com/jsk005/Flutter/tree/main/fileupload/2nd
728x90
'Flutter 앱 > 활용예제' 카테고리의 다른 글
Flutter phone call (플러터 전화걸기) (0) | 2024.02.22 |
---|---|
Flutter Image Upload(플러터 파일 서버 업로드) (2) | 2024.02.16 |
Flutter QR Code Scan (플러터 QR코드 스캔) (0) | 2024.02.08 |
flutter 현재 위치좌표 가져오기 (0) | 2024.02.01 |
flutter 네이버 지도 사용하기 (0) | 2024.01.30 |