Skip to content

Instantly share code, notes, and snippets.

@take4blue
Created February 23, 2022 01:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save take4blue/5d2f0176665548ac51e28f38837c1d98 to your computer and use it in GitHub Desktop.
Save take4blue/5d2f0176665548ac51e28f38837c1d98 to your computer and use it in GitHub Desktop.
Flutterのランチャーアイコンを単一?のイメージから生成する
# Flutter専用のアイコン画像作成コマンド
# 変換元ファイルや変換先ファイルなどすべて固定
# 変換元
# assets/icons/base.png 1536x1536ファイル android/web/Windows用の元ファイル
# assets/icons/windows.png 1536x1536ファイル windows用ファイル(このファイルがなければbase.pngから作成する)
# assets/icons/ios.png 1536x1536ファイル iOS用の元ファイル
# 変換先
# Android(フォルダがある場合に変換する)
# android\app\src\main\res\mipmap-hdpi\ic_launcher.png 72x72
# android\app\src\main\res\mipmap-mdpi\ic_launcher.png 48x48
# android\app\src\main\res\mipmap-xhdpi\ic_launcher.png 96x96
# android\app\src\main\res\mipmap-xxhdpi\ic_launcher.png 144x144
# android\app\src\main\res\mipmap-xxxhdpi\ic_launcher.png 192x192
# iOS(フォルダがある場合に変換する)
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-20x20@1x.png 20x20
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-20x20@2x.png 40x40
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-20x20@3x.png 60x60
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-29x29@1x.png 29x29
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-29x29@2x.png 58x58
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-29x29@3x.png 87x87
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-40x40@1x.png 40x40
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-40x40@2x.png 80x80
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-40x40@3x.png 120x120
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-60x60@2x.png 120x120
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-60x60@3x.png 180x180
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-76x76@1x.png 76x76
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-76x76@2x.png 152x152
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-83.5x83.5@2x.png 167x167
# ios\Runner\Assets.xcassets\AppIcon.appiconset\Icon-App-1024x1024@1x.png 1024x1024
# Windows(フォルダがある場合に変換する)
# windows\runner\resources\app_icon.ico 256x256
# Web(フォルダがある場合に変換する)
# web\favicon.png 16x16
# web\icons\Icon-192.png 192x192
# web\icons\Icon-512.png 512x512
# web\icons\Icon-maskable-192.png 192x192
# web\icons\Icon-maskable-512.png 512x512
# 変換方法
# Android
# 変換元をサイズ変更する
# iOS
# 変換元をサイズ変更する
# Windows
# 変換元をサイズ変更しico形式で保存する
# Web
# favicon.png, Icon-192.png, Icon-512.pngは透明部分を白に塗りつぶし、サイズを変更する
# Icon-maskable-192.png, Icon-maskable-512.pngは指定サイズ*80%に縮小してから指定サイズのImageの中心に貼り付けた物にする
Add-Type -AssemblyName System.Drawing, System.IO
# 画像の単純リサイズ
function Resize($fromBmp, $width, $targetFolder, $files) {
$toBmp = New-Object Drawing.Bitmap($width, $width)
$graphics = [Drawing.Graphics]::FromImage($toBmp)
$graphics.DrawImage($fromBmp, 0, 0, $toBmp.Width, $toBmp.Height)
foreach ($file in $files) {
$targetFile = $targetfolder + "\\" + $file
if (Test-Path $targetFile) {
Remove-Item $targetFile
}
$toBmp.Save($targetFile, [Drawing.Imaging.ImageFormat]::Png)
}
}
function WakuDelete($fromBmp)
{
$toBmp = New-Object Drawing.Bitmap($fromBmp.Width, $fromBmp.Height)
$graphics = [Drawing.Graphics]::FromImage($toBmp)
$rect = New-Object Drawing.Rectangle 1, 1, ($fromBmp.Width - 2), ($fromBmp.Height - 2)
$graphics.DrawImage($fromBmp, $rect, 1, 1, ($fromBmp.Width - 2), ($fromBmp.Height - 2), [Drawing.GraphicsUnit]::Pixel)
return $toBmp
}
# 1ドットの枠付き画像のリサイズ
function ResizeWaku($fromBmp, $width, $targetFolder, $files) {
$target = WakuDelete $fromBmp
$toBmp = New-Object Drawing.Bitmap($width, $width)
$graphics = [Drawing.Graphics]::FromImage($toBmp)
$rect = New-Object Drawing.Rectangle 0, 0, $width, $width
$graphics.DrawImage($target, $rect, 1, 1, ($fromBmp.Width - 2), ($fromBmp.Height - 2), [Drawing.GraphicsUnit]::Pixel)
foreach ($file in $files) {
$targetFile = $targetfolder + "\\" + $file
if (Test-Path $targetFile) {
Remove-Item $targetFile
}
$toBmp.Save($targetFile, [Drawing.Imaging.ImageFormat]::Png)
}
}
# 1ドットの枠付き画像のリサイズ
# かつWEB用特殊コピー
function ResizeWeb($fromBmp, $width, $targetFolder, $files)
{
if ($files.Length -le 2) {
$target = WakuDelete $fromBmp
$toBmp = New-Object Drawing.Bitmap($width, $width)
$graphics = [Drawing.Graphics]::FromImage($toBmp)
$graphics.Clear([Drawing.Color]::White)
$rect = New-Object Drawing.Rectangle 0, 0, $width, $width
$graphics.DrawImage($target, $rect, 1, 1, ($fromBmp.Width - 2), ($fromBmp.Height - 2), [Drawing.GraphicsUnit]::Pixel)
$targetFile = $targetfolder + "\\" + $files[0]
if (Test-Path $targetFile) {
Remove-Item $targetFile
}
$toBmp.Save($targetFile, [Drawing.Imaging.ImageFormat]::Png)
}
if ($files.Length -eq 2) {
$target = WakuDelete $fromBmp
$toBmp = New-Object Drawing.Bitmap($width, $width)
$graphics = [Drawing.Graphics]::FromImage($toBmp)
$graphics.Clear([Drawing.Color]::White)
$wWidth = $width / 10
$rect = New-Object Drawing.Rectangle $wWidth, $wWidth, ($width - $wWidth * 2), ($width - $wWidth * 2)
$graphics.DrawImage($target, $rect, 1, 1, ($fromBmp.Width - 2), ($fromBmp.Height - 2), [Drawing.GraphicsUnit]::Pixel)
$targetFile = $targetfolder + "\\" + $files[1]
if (Test-Path $targetFile) {
Remove-Item $targetFile
}
$toBmp.Save($targetFile, [Drawing.Imaging.ImageFormat]::Png)
}
}
function CreateIOSFile($baseFolder)
{
$baseFile = $baseFolder + "\\assets\\icons\\ios.png"
$targetFolder = $baseFolder + "\\ios\\Runner\\Assets.xcassets\\AppIcon.appiconset"
if ((Test-Path $baseFile) -and (Test-Path $targetFolder)) {
$fromBmp = [Drawing.Image]::FromFile($baseFile)
Resize $fromBmp 20 $targetFolder @("Icon-App-20x20@1x.png")
Resize $fromBmp 40 $targetFolder @("Icon-App-20x20@2x.png", "Icon-App-40x40@1x.png")
Resize $fromBmp 60 $targetFolder @("Icon-App-20x20@3x.png")
Resize $fromBmp 29 $targetFolder @("Icon-App-29x29@1x.png")
Resize $fromBmp 58 $targetFolder @("Icon-App-29x29@2x.png")
Resize $fromBmp 87 $targetFolder @("Icon-App-29x29@3x.png")
Resize $fromBmp 80 $targetFolder @("Icon-App-40x40@2x.png")
Resize $fromBmp 120 $targetFolder @("Icon-App-40x40@3x.png", "Icon-App-60x60@2x.png")
Resize $fromBmp 180 $targetFolder @("Icon-App-60x60@3x.png")
Resize $fromBmp 76 $targetFolder @("Icon-App-76x76@1x.png")
Resize $fromBmp 72 $targetFolder @("Icon-App-76x76@2x.png")
Resize $fromBmp 167 $targetFolder @("Icon-App-83.5x83.5@2x.png")
Resize $fromBmp 1024 $targetFolder @("Icon-App-1024x1024@1x.png")
$fromBmp.Dispose()
}
}
function CreateAndroidFile($baseFolder)
{
$baseFile = $baseFolder + "\\assets\\icons\\base.png"
$targetFolder = $baseFolder + "\\android\\app\\src\\main\\res"
if ((Test-Path $baseFile) -and (Test-Path $targetFolder)) {
$fromBmp = [Drawing.Image]::FromFile($baseFile)
ResizeWaku $fromBmp 72 $targetFolder @("mipmap-hdpi\\ic_launcher.png")
ResizeWaku $fromBmp 48 $targetFolder @("mipmap-mdpi\\ic_launcher.png")
ResizeWaku $fromBmp 96 $targetFolder @("mipmap-xhdpi\\ic_launcher.png")
ResizeWaku $fromBmp 144 $targetFolder @("mipmap-xxhdpi\\ic_launcher.png")
ResizeWaku $fromBmp 192 $targetFolder @("mipmap-xxxhdpi\\ic_launcher.png")
$fromBmp.Dispose()
}
}
function SaveAsIcon($bitmap, $filename)
{
$fs = new-object IO.FileStream $filename, 'Create'
# ICO header
$fs.WriteByte(0)
$fs.WriteByte(0)
$fs.WriteByte(1)
$fs.WriteByte(0)
$fs.WriteByte(1)
$fs.WriteByte(0)
# Image size
$fs.WriteByte([byte]($bitmap.Width -band 0xFF))
$fs.WriteByte([byte]($bitmap.Height -band 0xFF))
# Palette
$fs.WriteByte(0)
# Reserved
$fs.WriteByte(0)
# Number of color planes
$fs.WriteByte(0)
$fs.WriteByte(0)
# Bits per pixel
$fs.WriteByte(32)
$fs.WriteByte(0)
# Data size, will be written after the data
$fs.WriteByte(0)
$fs.WriteByte(0)
$fs.WriteByte(0)
$fs.WriteByte(0)
# Offset to image data, fixed at 22
$fs.WriteByte(22)
$fs.WriteByte(0)
$fs.WriteByte(0)
$fs.WriteByte(0)
# Writing actual data
$bitmap.Save($fs, [Drawing.Imaging.ImageFormat]::Png)
# Getting data length (file length minus header)
$Len = $fs.Length - 22;
# Write it in the correct place
$null = $fs.Seek(14, [IO.SeekOrigin]::Begin)
$fs.WriteByte([byte]($len -band 0xFF))
$fs.WriteByte([byte]($len -shr 8))
$fs.Close();
}
function CreateWindowsFile($baseFolder)
{
$baseFile = $baseFolder + "\\assets\\icons\\windows.png"
if (-not (Test-Path $baseFile)) {
$baseFile = $baseFolder + "\\assets\\icons\\base.png"
}
$targetFolder = $baseFolder + "\\windows\\runner\\resources"
if ((Test-Path $baseFile) -and (Test-Path $targetFolder)) {
$fromBmp = [Drawing.Image]::FromFile($baseFile)
$target = WakuDelete $fromBmp
$toBmp = New-Object Drawing.Bitmap(256, 256)
$rect = New-Object Drawing.Rectangle 0, 0, 256, 256
$graphics = [Drawing.Graphics]::FromImage($toBmp)
$graphics.DrawImage($target, $rect, 1, 1, ($fromBmp.Width - 2), ($fromBmp.Height - 2), [Drawing.GraphicsUnit]::Pixel)
$targetFile = $targetfolder + "\\app_icon.ico"
if (Test-Path $targetFile) {
Remove-Item $targetFile
}
SaveAsIcon $toBmp $targetFile
$fromBmp.Dispose()
}
}
function CreateWebFile($baseFolder)
{
$baseFile = $baseFolder + "\\assets\\icons\\base.png"
$targetFolder = $baseFolder + "\\web"
if ((Test-Path $baseFile) -and (Test-Path $targetFolder)) {
$fromBmp = [Drawing.Image]::FromFile($baseFile)
ResizeWeb $fromBmp 16 $targetFolder @("favicon.png")
$targetFolder = $baseFolder + "\\web\\icons"
ResizeWeb $fromBmp 192 $targetFolder @("Icon-192.png", "Icon-maskable-192.png")
ResizeWeb $fromBmp 512 $targetFolder @("Icon-512.png", "Icon-maskable-512.png")
$fromBmp.Dispose()
}
}
if ($args.Length -eq 1) {
CreateWebFile($args[0])
CreateWindowsFile($args[0])
CreateIOSFile($args[0])
CreateAndroidFile($args[0])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment