Powershell快速转换生成指定尺寸的Kindle屏保图

01 前言

周末无事,想到手头还有一泡面盖儿(Kindle Paperwhite 3),正好玩一玩。一顿操作猛如虎,成功越狱,过程略,可参考 这里。终于可以换上自己喜欢的屏保图了,图片有了,怎么快速转成指定的尺寸和格式就成了新的问题。有PS大法(参考 这里),N年不用PS了不说,还得注意图片大小,觉得麻烦,也可以网上搜一搜,不过萝卜青菜各有所爱。于是动手写了一个脚本实现批量转换(不想写界面-_-//),支持自动缩放(不管图片尺寸够不够,原图居中,不够的地方就留黑),支持自动重命名,支持转为灰度图(并增加15点对比度),默认竖屏,这不就舒服了嘛,记录一下。

02 正文

在win 10,64位开发,powershell 脚本如下:


<#
批量将图片处理为kindle屏保图片功能:1、将图片按比例缩放,适合指定屏幕大小(不拉伸),转为24位图2、转为灰度图,并设置15点对比度3、按格式批量重命名by hokison 2022-05-16 20:47#>function Set-Pic
{[CmdletBinding()]Param([Parameter(Mandatory=$true,Position=0)][string]$imgPath,[Parameter(Mandatory=$true,Position=1)][ValidateSet('KPW3ANDUP', 'KPW1AND2','KO2', 'K7ANDOTHER')][string]$devType,[Parameter(Mandatory=$true,Position=2)][string]$outPath,[switch]$toGray)Begin{if(-not (Test-Path -LiteralPath $imgPath -PathType Leaf)){Write-Host ('找不到图片路径:'+$imgPath)return}#不存在则创建if(-not (Test-Path -Path $outPath)){mkdir $outPath -ErrorAction Stop | Out-Null}#默认是KPW3ANDUP或以上的屏幕尺寸$size = @(1448,1072)if($devType -eq 'KPW1AND2'){$size = @(1024,758)}elseif($devType -eq 'KO2'){$size = @(1680,1264)}elseif($devType -eq 'K7ANDOTHER'){$size = @(800,600)}#一般高比宽大(竖屏),所以换位置[int]$fixWidth = $size[1][int]$fixHeight = $size[0]Write-Verbose ('待输出尺寸大小(px),宽:'+ $fixWidth + ',高:' + $fixHeight)#加载库[void][reflection.assembly]::Load('System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')}Process{[System.Drawing.Image]$img = [System.Drawing.Image]::FromFile($imgPath)Write-Verbose ('原图尺寸大小(px),宽:'+ $img.Width + ',高:' + $img.Height)#计算缩放比例[float]$nPercentW = $fixWidth / $img.Width[float]$nPercentH = $fixHeight / $img.Height#取小的缩放比例[float]$nPercent = $nPercentW;if($nPercentH -lt $nPercentW){$nPercent = $nPercentH}Write-Verbose ('缩放比例:'+ $nPercent)#缩放后的宽高[int]$newWidth = $img.Width * $nPercent[int]$newHeight = $img.Height * $nPercentWrite-Verbose ('缩放后尺寸大小(px),宽:'+ $newWidth + ',高:' + $newHeight)#引用c#代码处理$code = @'/// <summary>/// 图像设置灰度/// </summary>/// <param name='curBitmpap'>原始图</param>/// <returns></returns>public static System.Drawing.Bitmap MakeGrayscale(System.Drawing.Bitmap curBitmpap){if (curBitmpap != null){//位图矩形System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, curBitmpap.Width, curBitmpap.Height);//以可读写的方式锁定全部位图像素System.Drawing.Imaging.BitmapData bmpData = curBitmpap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmpap.PixelFormat);//得到首地址IntPtr ptr = bmpData.Scan0;//定义被锁定的数组大小,由位图数据与未用空间组成的int bytes = bmpData.Stride * bmpData.Height;//定义位图数组byte[] rgbValues = new byte[bytes];//复制被锁定的位图像素值到该数组内System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);//灰度化double colorTemp = 0;for (int i = 0; i < bmpData.Height; i++){//只处理每行中是图像像素的数据,舍弃未用空间for (int j = 0; j < bmpData.Width * 3; j += 3){//利用公式计算灰度值colorTemp = rgbValues[i * bmpData.Stride + j + 2] * 0.299 + rgbValues[i * bmpData.Stride + j + 1] * 0.587 + rgbValues[i * bmpData.Stride + j] * 0.114;//R=G=BrgbValues[i * bmpData.Stride + j] = rgbValues[i * bmpData.Stride + j + 1] = rgbValues[i * bmpData.Stride + j + 2] = (byte)colorTemp;}}//把数组复制回位图System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);//解锁位图像素curBitmpap.UnlockBits(bmpData);}return curBitmpap;}/// <summary>/// 图像对比度调整/// </summary>/// <param name='b'>原始图</param>/// <param name='degree'>对比度[-100, 100]</param>/// <returns></returns>public static System.Drawing.Bitmap KiContrast(System.Drawing.Bitmap b, int degree){if (b == null){return null;}if (degree < -100) degree = -100;if (degree > 100) degree = 100;try{double pixel = 0;double contrast = (100.0 + degree) / 100.0;contrast *= contrast;int width = b.Width;int height = b.Height;System.Drawing.Imaging.BitmapData data = b.LockBits(new System.Drawing.Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.ReadWrite, b.PixelFormat);unsafe{byte* p = (byte*)data.Scan0;int offset = data.Stride - width * 3;for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){// 处理指定位置像素的对比度for (int i = 0; i < 3; i++){pixel = ((p[i] / 255.0 - 0.5) * contrast + 0.5) * 255;if (pixel < 0) pixel = 0;if (pixel > 255) pixel = 255;p[i] = (byte)pixel;} p += 3;} p += offset;} }b.UnlockBits(data);return b;}catch{return null;}}'@#自定义编译参数[System.CodeDom.Compiler.CompilerParameters]$cp = [System.CodeDom.Compiler.CompilerParameters]::new()[void]$cp.ReferencedAssemblies.Add('System.Drawing.dll')#如果含有unsafe代码要设置一下$cp.CompilerOptions = '/unsafe'#ReferencedAssemblies 与 CompilerParameters参数不能同时使用$type = Add-Type -MemberDefinition $code -Name myapi -PassThru -CompilerParameters $cp #如果宽相等,但是高小于固定的#或者高相等,但是宽小于固定的#则直接输出调整比例后的图片if(($newWidth -eq $fixWidth -and $newHeight -lt $fixHeight) -or ($newHeight -eq $fixHeight -and $newWidth -lt $fixWidth)){#24位[System.Drawing.Bitmap]$newPic = [System.Drawing.Bitmap]::new($fixWidth,$fixHeight,[System.Drawing.Imaging.PixelFormat]::Format24bppRgb)[System.Drawing.Graphics]$gs = [System.Drawing.Graphics]::FromImage($newPic)$gs.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic#设置图片,居中#距离上边$toTop = ($fixHeight - $newHeight) / 2#距离左边$toLeft = ($fixWidth - $newWidth) / 2#图片$gs.DrawImage($img,$toLeft,$toTop,$newWidth,$newHeight)$gs.Dispose()#时间戳加个随机数,避免处理快而覆盖了$ts = (Get-Date -Format 'yyyyMMdd_HHmmss_') + (Get-Random -Minimum 1 -Maximum 30000)$outFile = Join-Path -Path $outPath -ChildPath ($ts+'.png')#如果已存在则先删掉原文件if(Test-Path -Path $outFile){Remove-Item -Path $outFile -Force | Out-Null    }if($toGray){#增加15点对比度$type::KiContrast($type::MakeGrayscale($newPic),15).Save($outFile,[System.Drawing.Imaging.ImageFormat]::Png)}else{$newPic.Save($outFile,[System.Drawing.Imaging.ImageFormat]::Png)}}}End{Write-Verbose '处理完成...'}
}function Rename-Pic{[CmdletBinding()]Param([Parameter(Mandatory=$true,Position=0)][string]$imgPath)Begin{}Process{$index = 0$files = dir -Path $imgPath -Filter '*.png'foreach($file in $files){Rename-Item -Path $file.FullName -NewName (Join-Path -Path $file.DirectoryName -ChildPath ( 'bg_ss'+('{0:d2}' -f $index) +'.png') ) | Out-Null$index++}}End{}
}$ver = $PSVersionTable.PSVersion.Major
if($ver -lt 5){Write-Host ('PowerShell版本过低【'+$ver+'】,请升级~')exit
}$handlePicBtn = [System.Management.Automation.Host.ChoiceDescription]::new('&1 处理图片','仅处理图片')
$renamePicOnlyBtn = [System.Management.Automation.Host.ChoiceDescription]::new('&2 批量重命名','仅重命名')
$exitBtn = [System.Management.Automation.Host.ChoiceDescription]::new('&0 退出','退出程序')
$answerOfAction = $Host.UI.PromptForChoice('功能选择', '请选择:', [System.Management.Automation.Host.ChoiceDescription[]]@($handlePicBtn, $renamePicOnlyBtn,$exitBtn), 0)if($answerOfAction -eq 0){#各个选择$KPW3ANDUPBtn = [System.Management.Automation.Host.ChoiceDescription]::new('&1 KPW3ANDUP(1448 * 1072)','Kindle Paperwhite 3 and up/Kindle Voyage')$KPW1AND2Btn = [System.Management.Automation.Host.ChoiceDescription]::new('&2 KPW1AND2(1024 * 758)','Kindle Paperwhite 1/2')$KO2Btn = [System.Management.Automation.Host.ChoiceDescription]::new('&3 KO2(1680 * 1264)','Kindle Oasis 2(KO2)')$K7ANDOTHERBtn = [System.Management.Automation.Host.ChoiceDescription]::new('&4 K7ANDOTHER(800 * 600)','Kindle 7/8/Other')$answerOfSize = $Host.UI.PromptForChoice('要转为哪种类型屏幕大小(默认竖屏)?', '请选择:', [System.Management.Automation.Host.ChoiceDescription[]]@($KPW3ANDUPBtn, $KPW1AND2Btn,$KO2Btn,$K7ANDOTHERBtn, $exitBtn), 0)[string]$devType = ''switch ($answerOfSize){0 { $devType = 'KPW3ANDUP' }1 { $devType = 'KPW1AND2' }2 { $devType = 'KO2' }3 { $devType = 'K7ANDOTHER' }default {}}if($devType.Length -lt 1){Write-Host ('未选择类型~')exit}$toGrayBtn = [System.Management.Automation.Host.ChoiceDescription]::new('&1 置灰','设置成灰度图,且增加15点对比度')$notToGrayBtn = [System.Management.Automation.Host.ChoiceDescription]::new('&2 不处理','不处理,按原图')$answerOfGray = $Host.UI.PromptForChoice('是否转灰度图?', '请选择:', [System.Management.Automation.Host.ChoiceDescription[]]@($toGrayBtn, $notToGrayBtn), 0)$toGray = $falseswitch ($answerOfGray){0 { $toGray = $true }default {}}#批量处理$imgPath = $Host.UI.Prompt('','请输入要处理的图片所在文件全路径(如D:\pic,自动查找子目录,仅支持JPG/PNG格式)',[System.Management.Automation.Host.FieldDescription]::new('path'))if(-not $imgPath.path){Write-Host ('路径不能为空~')exit}if(-not (Test-Path -Path $imgPath.path.Trim() -PathType Container -ErrorAction Stop)){Write-Host ('【'+$imgPath.path+'】图片路径不存在~')exit}$savePath = $Host.UI.Prompt('','请输入处理后输出路径(如D:\out,不存在则自动创建)',[System.Management.Automation.Host.FieldDescription]::new('path'))if((-not $savePath.path) -or (-not $savePath.path.Trim()) -or (-not (Test-Path -Path ([System.IO.Path]::GetFullPath($savePath.path.Trim())) -IsValid))){Write-Host ('无效的输出路径~')exit}$outPath = [System.IO.Path]::GetFullPath($savePath.path.Trim())#不存在则创建目录if(-not (Test-Path -Path $outPath)){mkdir $outPath.path.Trim() -ErrorAction Stop | Out-Null}#所有图片$imgefiles = dir -Path (Join-Path -Path $imgPath.path.Trim() -ChildPath '*') -Include @('*.jpg','*.png') -Recurseif(-not ($imgefiles -and $imgefiles.Length -gt 0)){Write-Host ('该路径无JPG或PNG图片文件,请检查~')exit}#限制数量不应过大if($imgefiles.Length -gt 1000){Write-Host ('该路径图片文件过多【'+$imgefiles.Length+'】,请限制在1000以内~')exit}Write-Host ''Write-Host '-------------------【本次执行概要】-------------------'Write-Host ('图片源路径:'+$imgPath.path.Trim())Write-Host ('是否置灰:'+$toGray)Write-Host ('输出路径:'+$outPath)Write-Host ('即将处理图片数量:'+$imgefiles.Length)Write-Host '------------------------------------------------------'#是否继续$continueBtn = [System.Management.Automation.Host.ChoiceDescription]::new('&1 继续','继续运行')$answerOfContinue = $Host.UI.PromptForChoice('是否继续?', '请选择:', [System.Management.Automation.Host.ChoiceDescription[]]@($continueBtn, $exitBtn), 0)if($answerOfContinue -ne 0){Write-Host '结束....'exit}$index = 0foreach($img in $imgefiles){Write-Host ('总共:'+$imgefiles.Length+',当前:'+($index + 1)+',余:'+($imgefiles.Length - $index - 1 ))if($toGray){Set-Pic -imgPath $img.FullName -devType $devType -outPath $outPath -toGray | Out-Null}else{Set-Pic -imgPath $img.FullName -devType $devType -outPath $outPath | Out-Null}$index++}Write-Host '处理完成....'$answerOfRename = $Host.UI.PromptForChoice('是否自动按格式重命名(bg_ss_00.png,bg_ss_01.png...)?', '请选择:', [System.Management.Automation.Host.ChoiceDescription[]]@($continueBtn, $exitBtn), 0)if($answerOfRename -eq 0){Rename-Pic -imgPath $outPathWrite-Host '重命名完成...'}
}
elseif($answerOfAction -eq 1){$fPath = $Host.UI.Prompt('','请输入要处理路径(如D:\out)',[System.Management.Automation.Host.FieldDescription]::new('path'))#Write-Host ($savePath.path)if((-not $fPath.path) -or (-not $fPath.path.Trim()) -or (-not (Test-Path -Path ([System.IO.Path]::GetFullPath($fPath.path.Trim()))))){Write-Host ('无效的路径~')exit}$path = ([System.IO.Path]::GetFullPath($fPath.path.Trim()))Rename-Pic -imgPath $pathWrite-Host ('【'+$path+'】下所有PNG图片重命名成功~')
}Write-Host ('感谢使用,Bye~.'+(Get-Date -Format 'yyyy-MM-dd HH:mm:ss'))

使用:
方式1:代码另存为.ps1,右键,“使用Powershell运行”即可。如不能运行,参考此处解决。
方式2:见后文。
说明:
1.运行程序后,前三个选择可直接按回车键,第四个需要输入图片所在的全路径(支持子文件夹),第五个输入处理后保存图片的路径,确认无误后,直接按回车键继续执行。处理完成后,可自行选择是否重命名图片,按回车键则执行,否则结束运行
2.如果非中文操作系统,可能提示会乱码
3.低于win10系统可能运行异常
4.喜欢折腾的可根据需要自行调整

稍微解释一下各步骤:
1、功能选择
【1】处理图片——直接处理图片
【2】批量重命名——只给图片重命名
2、屏幕大小选择(选择对应kindle型号)
【1】KPW3ANDUP——Kindle Paperwhite 3 及更高、Kindle Voyage
【2】KPW1AND2——Kindle Paperwhite 1或2
【3】KO2——Kindle Oasis 2
【4】K7ANDOTHER——Kindle 7或8,其他
3、是否转为灰度图
【1】置灰——转为灰度图,且增加15点对比度
【2】不处理——原图是彩色就是彩色
4、要处理的图片所在文件全路径(递归查找所有子文件夹下的图片)
5、输出路径(如果不存在会自动创建)
6、是否确认继续执行
7、是否自动重命名
【1】继续——给生成的图片重命名
【2】退出——结束

运行过程:

转换效果(上方是转换后的):

虽然不想写成界面的,但是肯定也有不喜欢折腾的,还是稍微封装成.exe文件,可以直接双击运行(不过运行起来后还是黑窗口),下载链接: 提取码: 6xks。

03 后记

如果有些图片转灰度图,且增加了15点对比度后,会变的比较丑,可以自行修改此行代码中的15:

$type::KiContrast($type::MakeGrayscale($newPic),15).Save($outFile,[System.Drawing.Imaging.ImageFormat]::Png)

多试几次就好了。
有其他想法的小伙伴可以交流交流~

Powershell快速生成指定尺寸的Kindle屏保图相关推荐

  1. C# 中使用 ThoughtWorks.QRCode.dll 生成指定尺寸和边框宽度的二维码

    本文介绍在 C# 中使用 ThoughtWorks.QRCode.dll 生成指定尺寸和边框宽度的二维码.网上文章大多只是简单介绍内置参数的设置,根据我的使用目的,增加了自定义目标二维码图片尺寸和白边 ...

  2. 用Python批量生成指定尺寸的缩略图!比Ps好用!

    基本环境 版本:Python3.6 系统:Windows 相关模块: 1 import requests as req 2 from PIL import Image 3 from io import ...

  3. python编码尺寸_基于Python批量生成指定尺寸缩略图代码实例

    这篇文章主要介绍了基于Python批量生成指定尺寸缩略图代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 最近我们商城上架的应用越来越丰富了. ...

  4. kindle 屏保_送你一台免费Kindle,年度羊毛不要错过

    最近出门旅行限制比较多,今天橡树君想分享一个适合宅在家的活动-咪咕kindle0元购. 活动期间通过指定渠道购买咪咕&Kindle联名版机器,连续打卡100天返还购机款,橡树君再三确认了一下, ...

  5. cad调了比例因子没反应_CAD制图初学入门技巧:将CAD图形缩放为指定尺寸

    在使用浩辰CAD软件绘制图纸的过程中,很多CAD制图初学入门者由于对CAD软件的各种复杂功能不够了解,所以会出现比较多的问题,很多初学者会在网上找一下图纸联系,其中就会遇到CAD图形缩放的问题,如何将 ...

  6. 〖Kindle Paperwhite〗升级、越狱、换屏保教程

    个人不建议在Kindle PaperWhite上安装多看,一则不是原生系统.费电:二则系统来回切换着麻烦. 这里我给出优化Kindle PaperWhite阅读体验的方法,只需要4步左右即可,但是如果 ...

  7. kpw4换壁纸_Kindle Paperwhite 原生系统如何更换屏保图片?

    展开全部 除非启动"特惠"功能,Kindle 的默认屏保是无法通过设置更e69da5e887aa323131333532363134313032313635333133336630 ...

  8. 如何在Kobo电子书阅读器中添加自定义屏保

    If you're not particularly impressed with the screensaver system on your Kobo Ebook reader you can c ...

  9. Excel如何快速批量生成指定性别的随机姓名

    在工作中我们可能要生成指定性别的随机姓名,比如生成男性的姓名或者女性的姓名.下面就给大家分享一种快速方法.(下图为完成操作过程) 1.如下图,我们要快速批量生成男生姓名和女生姓名. 2.点击DIY工具 ...

最新文章

  1. Coursera课程Python for everyone:chapter8
  2. ASP.NET aspx页面中 写C#脚本; ASP.NET 指令(%@%);
  3. halcon read_ocr_trainf 从文件中读取训练字符并转换为图像
  4. oracle自动备份定时任务,Oracle数据库定时自动备份批处理代码(Windows)
  5. P1866 编号 python
  6. 27.产品经理需要具备的数据分析能力
  7. linux添加nginx启动脚本_linux环境开机自启动nginx
  8. 深入理解计算机系统第四版_《深入理解计算机系统》读书笔记 —— 第一章 计算机系统漫游...
  9. 红包随机算法微信群红包随机算法
  10. 数据结构 第一章 绪论
  11. BP神经网络预测(人口)程序(matlab)
  12. 计算机应用结课PPT,计算机应用说课.ppt
  13. android检测cup温度工具,Android如何实现获取手机CPU的温度?
  14. java-面向对象高阶
  15. python 读取文件报错:UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xb5 in position 0: invalid start
  16. (云服务器+JQuery+JS+BootStrap+Navicat+AJAX+JavaScript)第一个前端小项目【面试】
  17. 如何判断两个日期在一周内
  18. 常用到的Eclipse快捷键
  19. 智能家居DIY创意之智能灯泡
  20. 《金钱永不眠》书中的精髓:中国资本市场从无到有,是踩着石头过河,小步试错,快速迭代的持续发展过程

热门文章

  1. springboot包装controller返回值
  2. 从苏宁电器到卡巴斯基第23篇:难忘的三年硕士时光 I
  3. Android闹钟使用
  4. 一个谷歌浏览器主页插件的诞生
  5. 最新年龄划分标准出台,对照过后惊呆了
  6. 在vue项目中引入element,并改变主题色
  7. 表 ‘dbo.XXX’ 没有标识属性。无法执行 SET 操作 错误解决办法
  8. w3c易语言教程,易语言基础教程之简单的人机交互
  9. sql中单引号里面单引号怎么处理
  10. 凯叔讲故事:20,000,000用户的增长策略+埋点设计