210 lines
5.3 KiB
Ruby
210 lines
5.3 KiB
Ruby
#!/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
|