Files
SRCC/convert_icon.rb
T

210 lines
5.3 KiB
Ruby
Raw Normal View History

2026-06-22 11:33:18 +08:00
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# 将PNG转换为systray可用的 []byte 格式
# 支持输出: Go byte slice 或 ICO 格式
require 'base64'
require 'optparse'
options = {
size: 32,
output_format: 'go', # 'go' | 'ico' | 'png'
input: 'image.png',
output: nil
}
OptionParser.new do |opts|
opts.banner = "用法: ruby convert_icon.rb [选项]"
opts.on("-s", "--size SIZE", Integer, "图标尺寸 (默认: 32)") { |s| options[:size] = s }
opts.on("-f", "--format FORMAT", ["go", "ico", "png"], "输出格式: go/ico/png (默认: go)") { |f| options[:output_format] = f }
opts.on("-i", "--input FILE", "输入PNG文件路径 (默认: image.png)") { |i| options[:input] = i }
opts.on("-o", "--output FILE", "输出文件路径") { |o| options[:output] = o }
opts.on("-h", "--help", "显示帮助") { puts opts; exit }
end.parse!
# 检查依赖
def check_mini_magick
begin
require 'mini_magick'
true
rescue LoadError
false
end
end
def check_chunky_png
begin
require 'chunky_png'
true
rescue LoadError
false
end
end
# 使用mini_magick (ImageMagick) 调整图片大小
def resize_with_magick(input_path, output_path, size)
image = MiniMagick::Image.open(input_path)
image.resize "#{size}x#{size}"
image.write(output_path)
output_path
end
# 使用chunky_png (纯Ruby) 调整图片大小 - 简单最近邻插值
def resize_with_chunky_png(input_path, output_path, size)
require 'chunky_png'
source = ChunkyPNG::Image.from_file(input_path)
# 计算缩放比例
scale_x = source.width.to_f / size
scale_y = source.height.to_f / size
# 创建新图片
resized = ChunkyPNG::Image.new(size, size)
size.times do |y|
size.times do |x|
src_x = (x * scale_x).to_i
src_y = (y * scale_y).to_i
src_x = [src_x, source.width - 1].min
src_y = [src_y, source.height - 1].min
resized[x, y] = source[src_x, src_y]
end
end
resized.save(output_path)
output_path
end
# 将图片转换为ICO格式 (多分辨率)
def convert_to_ico(input_path, output_path, sizes = [16, 32, 48, 64])
require 'mini_magick'
images = []
sizes.each do |size|
img = MiniMagick::Image.open(input_path)
img.resize "#{size}x#{size}"
img.format 'png'
temp_file = "temp_icon_#{size}.png"
img.write(temp_file)
images << temp_file
end
# 使用ImageMagick合并为ICO
MiniMagick::Tool::Convert.new do |convert|
images.each { |img| convert << img }
convert << output_path
end
# 清理临时文件
images.each { |f| File.delete(f) if File.exist?(f) }
output_path
end
# 生成Go []byte 格式
def generate_go_bytes(file_path, var_name = "iconData")
bytes = File.binread(file_path).bytes
lines = []
lines << "var #{var_name} = []byte{"
bytes.each_slice(12) do |slice|
hex_values = slice.map { |b| "0x%02X" % b }
lines << " " + hex_values.join(", ") + ","
end
lines << "}"
lines.join("\n")
end
# 生成 base64 内嵌格式 (另一种Go方案)
def generate_go_base64(file_path, var_name = "iconData")
data = File.binread(file_path)
base64_str = Base64.strict_encode64(data)
<<~GO
var #{var_name}Base64 = `#{base64_str}`
// 使:
// import "encoding/base64"
// iconData, _ := base64.StdEncoding.DecodeString(#{var_name}Base64)
GO
end
# 主逻辑
puts "转换 systray 图标..."
puts "输入文件: #{options[:input]}"
puts "目标尺寸: #{options[:size]}x#{options[:size]}"
unless File.exist?(options[:input])
puts "错误: 找不到输入文件 #{options[:input]}"
exit 1
end
# 选择处理方式
if check_mini_magick
puts "使用 ImageMagick (mini_magick)..."
elsif check_chunky_png
puts "使用纯 Ruby (chunky_png)..."
else
puts "需要安装依赖. 请选择以下方式之一:"
puts " 1. gem install mini_magick (推荐, 需要安装ImageMagick)"
puts " 2. gem install chunky_png (纯Ruby, 无需ImageMagick)"
exit 1
end
begin
if options[:output_format] == 'ico'
# 生成ICO文件
output = options[:output] || "icon.ico"
if check_mini_magick
convert_to_ico(options[:input], output)
else
puts "生成ICO需要ImageMagick, 请先安装: gem install mini_magick"
exit 1
end
puts "已生成ICO文件: #{output}"
elsif options[:output_format] == 'png'
# 生成PNG文件
output = options[:output] || "icon_#{options[:size]}.png"
if check_mini_magick
resize_with_magick(options[:input], output, options[:size])
else
resize_with_chunky_png(options[:input], output, options[:size])
end
puts "已生成PNG文件: #{output}"
else # go
# 生成Go代码
temp_file = "temp_icon_#{options[:size]}.png"
if check_mini_magick
resize_with_magick(options[:input], temp_file, options[:size])
else
resize_with_chunky_png(options[:input], temp_file, options[:size])
end
go_code = generate_go_bytes(temp_file, "iconData")
if options[:output]
File.write(options[:output], go_code)
puts "已生成Go代码文件: #{options[:output]}"
else
puts "\n=== 复制以下代码到你的Go文件 ===\n"
puts go_code
puts "\n=================================\n"
end
File.delete(temp_file) if File.exist?(temp_file)
end
puts "完成!"
rescue => e
puts "错误: #{e.message}"
puts e.backtrace.first(5).join("\n")
exit 1
end