Flutterのランチャーアイコンを単一?のイメージから生成する
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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