์ด๋ฒ ๊ธ์์๋ GIF์ ์ด๋ฏธ์ง๋ฅผ ์ถ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์ดํด๋ณด๋๋ก ํ๊ฒ ๋ค.
GIF๋ ์ฌ๋ฌ์ฅ์ ์ด๋ฏธ์ง๋ฅผ ํ๋์ ์ด๋ฏธ์ง๋ก ์ ํํ๋ฉด์ ๋ ธ์ถ๋๋ ์ด๋ฏธ์ง๋ฅผ ์๋ฏธํ๋๋ฐ, ์ ํ๋ ์ด๋ฏธ์ง ๊ณต๊ฐ์ ๋ ๋ง์ ์ปจํ ์ธ ๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ์ ํ๋ ๊ฒฝ์ฐ์ ๋ง์ด ์ฌ์ฉํ๊ฒ ๋๋ค.
Flutter์์๋ GIF์ด๋ฏธ์ง๋ ์ผ๋ฐ .jpg, .png ์ด๋ฏธ์ง์ ๋์ผํ๊ฒ Image ์์ ฏ์ ์ฌ์ฉํด์ ๋ ธ์ถ ์ํฌ ์ ์๋ค.
GIF๋ฅผ ๋ ธ์ถ์ํค๋ ๋ฐฉ๋ฒ์ ๋ณ๋๋ก ์ฒ๋ฆฌํด ์ค ๊ฒ์ด ์์ด ๋จ์ํ๊ฒ ์์ ์ด ๊ฐ๋ฅํ๋ฐ, ๋ง์ผ GIF ์ด๋ฏธ์ง ์ค ํน์ ์ด๋ฏธ์ง๋ง์ ๋ ธ์ถ ํ๊ฑฐ๋ ์ ๊ฑฐ ํ๊ธฐ ์ํด์๋ ์ฝ๋๊ฐ ๋ณต์กํด ์ง๊ธฐ ์์ํ๋ค.
๋ฌผ๋ก ์ฌ๋ฌ ํจํค์ง๋ค์ด ์์ง๋ง, ํจํค์ง ์ง์์ด ์ํํ ์์ค์ ์๋์ฌ์ ๊ฒฐ๊ตญ ์ง์ ์ ์ดํด์ ์ฌ์ฉํ๋ ํธ์ด ์ ์ง ๋ณด์ ๋ฐ ๊ด๋ฆฌํ๊ธฐ ์์ํ๋ค๊ณ ์๊ฐํ๋ค.
๋จผ์ GIF๋ฅผ ๊ฐ๋จํ๊ฒ ๋ณด์ฌ์ฃผ๋๋ก ํ์.
6๊ฐ์ ์ด๋ฏธ์ง์ GIF๋ฅผ ์ค๋นํด์ Flutter์์ ๋ ธ์ถ์์ผ ๋ณด๋๋ก ํ๊ฒ ๋ค.
GIF ์ด๋ฏธ์ง๋ฅผ ๋ ธ์ถ์ํค๋ ๋ฐฉ๋ฒ์ ๊ฐ๋จํ๊ฒ ์ผ๋ฐ ์ด๋ฏธ์ง์ ๋์ผํ๊ฒ ์ฌ์ฉํ๋ฉด ๋๋ค.
Image.network(
"https://velog.velcdn.com/images/tygerhwang/post/b3952b7b-a9e8-4c61-b692-76c96c3d4d9f/image.gif",
),
GIF Image | Flutter |
---|---|
์์ ๋ก ์ฌ์ฉํ GIF ์ด๋ฏธ์ง๋ ์ด 6์ฅ์ ์ด๋ฏธ์ง๋ก ๋ง๋ค์ด ์ก๋ค.
์ด๋ฒ์ Flutter์์ ํ๋์ GIF ์ด๋ฏธ์ง์ ์๋ ์ฌ๋ฌ ์ด๋ฏธ์ง๋ค์ ๊ฐ๋ณ์ ์ผ๋ก ์ถ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด๋๋ก ํ๊ฒ ๋ค.
GIF ์ด๋ฏธ์ง๋ฅผ ์ถ์ถํ๋ ํจํค์ง๋ ๋ง์ง๋ง ์ฌ๊ธฐ์๋ ํจํค์ง๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ถ์ถํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์์ ์ด๋ค.
์ฐ์ GIF ์ด๋ฏธ์ง๋ ๋คํธ์ํฌ ์์ ์ ์ฅ๋ ์ด๋ฏธ์ง์ด๊ธฐ ๋๋ฌธ์, GIF์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ฐ๊ธฐ ์ํ http ํจํค์ง๊ฐ ํ์ํ๊ณ , ๋ค์ด ๋ฐ์ ์ด๋ฏธ์ง๋ฅผ ๋ก์ปฌ ๋ฐ์ดํฐ๋ก ์ ์ฅํ๊ธฐ ์ํ ์ ์ฅ์ ๊ฒฝ๋ก๋ฅผ ๊ฐ์ ธ์ค๋ path_provider ํจํค์ง๋ ํ์ํ๋ค.
dependencies:
http: ^1.2.0
path_provider: ^2.1.3
์ด์ GIF ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ฐ์ ๋ฐ์ดํธ ๋ฐฐ์ด์ ๋์ฝ๋ฉํ๊ณ , Codec ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด ๊ฐ ํ๋ ์ ๋ณ๋ก PNG ํ์ผ๋ก ์ ํํ์ฌ ์ฌ์ฉํ๋ฉด ๋๋ค.
๋จผ์ GIF ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ฐ์ ๋ฐ์ดํธ ๋ฐฐ์ด๋ก ๊ฐ์ ธ์ค๋๋ก ํ์.
import 'package:http/http.dart' as http;
Future<void> _extractFrameAsPng() async {
final http.Response response = await http.get(Uri.parse(url));
final Uint8List gifBytes = response.bodyBytes;
}
๋ฐ์ดํธ ๋ฐฐ์ด์ dart:ui ํจํค์ง๋ฅผ ์ฌ์ฉํด Codec ๊ฐ์ฒด๋ฅผ ์์ฑํด ์ฃผ๋๋ก ํ์.
Codec ๊ฐ์ฒด๋ ์ ๋๋ฉ์ด์ ์ด๋ฏธ์ง๋ฅผ ๋์ฝ๋ฉํ๊ณ ํ๋ ์๋ณ๋ก ์ฒ๋ฆฌํด ์ค ์ ์๋ ๊ฐ์ฒด์ด๋ค.
import 'dart:ui' as ui;
Future<void> _extractFrameAsPng() async {
final ui.Codec codec = await ui.instantiateImageCodec(gifBytes);
final int frameCount = codec.frameCount;
}
Codec ๊ฐ์ฒด์ ํ๋ ์ ๊ฐฏ์๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๊ธฐ ๋๋ฌธ์, ๊ฐ์๋งํผ ํ๋ ์์ ์์ฐจ์ ์ผ๋ก PNG ํ์ผ๋ก ๋ณํํด์ฃผ๋ฉด ๋๋ค.
์ ์ฅ์ ํ๊ธฐ ์ํด์๋ ์ ์ฅ ๊ฒฝ๋ก๋ฅผ ์์์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ ํ ๋ฆฌ๋ฅผ ๊ฐ์ ธ์ File ๋ฐ์ดํฐ๋ก ์ ์ฅ์ ํด์ฃผ๋ฉด ๋๋ค.
Future<void> _extractFrameAsPng() async {
final directory = await getApplicationDocumentsDirectory();
for (int i = 0; i < frameCount; i++) {
final ui.FrameInfo frameInfo = await codec.getNextFrame();
final ui.Image frame = frameInfo.image;
final ByteData? byteData =
await frame.toByteData(format: ui.ImageByteFormat.png);
if (byteData != null) {
final Uint8List pngBytes = byteData.buffer.asUint8List();
final File file = File("${directory.path}/frame_$i.png");
await file.writeAsBytes(pngBytes);
}
}
}
์ด์ ๊ฒฐ๊ณผ๋ฅผ ์ดํด๋ณด์. ์ ์์ ์ผ๋ก GIF ์ด๋ฏธ์ง ์์๋ค์ ์ถ์ถํ์๋ค.
์ ์ฒด ์ฝ๋์ด๋ค.
Future<void> _extractFrameAsPng() async {
final http.Response response = await http.get(Uri.parse(url));
final Uint8List gifBytes = response.bodyBytes;
final ui.Codec codec = await ui.instantiateImageCodec(gifBytes);
final int frameCount = codec.frameCount;
final directory = await getApplicationDocumentsDirectory();
for (int i = 0; i < frameCount; i++) {
final ui.FrameInfo frameInfo = await codec.getNextFrame();
final ui.Image frame = frameInfo.image;
final ByteData? byteData =
await frame.toByteData(format: ui.ImageByteFormat.png);
if (byteData != null) {
final Uint8List pngBytes = byteData.buffer.asUint8List();
final File file = File("${directory.path}/frame_$i.png");
await file.writeAsBytes(pngBytes);
images.add(file);
}
}
}
๊ฐ๋ณ๊ฒ GIF์ ์ด๋ฏธ์ง๋ฅผ ์ถ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์ดํด ๋ณด์๋ค.
Flutter์์ GIF๋ฅผ ์์ฑํ๊ณ ์ ์ดํ๋ ํจํค์ง๋ ์์ฃผ ์ฌ์ฉ๋๊ณ ์์ด์ ๋ณ๋๋ก ๋ค๋ฃจ์ง๋ ์๊ณ , ์ถ์ถํ๋ ๋ฐฉ๋ฒ๋ง ๋ค๋ค๋ณด์๋ค.
์ถ์ถํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ค ์์ฒญ ๋ค์ํ ๋ฐฉ๋ฒ๋ค์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์, ํธํ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค.