FM/Assets/Scripts/Runtime/Test/ImageConverter.cs

166 lines
5.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using UnityEngine;
using System.IO;
using BitMiracle.LibTiff.Classic;
public class ImageConverter : MonoBehaviour
{
public string pngPath;
public string tiffPath;
[ContextMenu("PngToTiff")]
void PNG()
{
PngToTiff(pngPath, tiffPath);
}
[ContextMenu("TiffToPng")]
void TIFF()
{
TiffToPng(tiffPath, pngPath);
}
// 检查纹理是否包含透明通道
private static bool HasTransparency(Texture2D tex)
{
Color32[] pixels = tex.GetPixels32();
for (int i = 0; i < pixels.Length; i++)
{
if (pixels[i].a < 255)
return true;
}
return false;
}
// PNG 转 TIFF (完整支持透明通道)
public static void PngToTiff(string pngPath, string tiffPath, int compression = 5)
{
// 加载PNG文件
byte[] pngBytes = File.ReadAllBytes(pngPath);
Texture2D sourceTex = new Texture2D(2, 2, TextureFormat.RGBA32, false);
sourceTex.LoadImage(pngBytes);
// 检查是否包含透明通道
bool hasAlpha = HasTransparency(sourceTex);
int channels = hasAlpha ? 4 : 3;
// 准备TIFF图像数据
byte[] tiffData = new byte[sourceTex.width * sourceTex.height * channels];
int pixelIndex = 0;
// 垂直翻转并处理像素数据Unity是左下原点TIFF是左上原点
for (int y = sourceTex.height - 1; y >= 0; y--)
{
for (int x = 0; x < sourceTex.width; x++)
{
Color32 pixel = sourceTex.GetPixel(x, y);
tiffData[pixelIndex++] = pixel.r;
tiffData[pixelIndex++] = pixel.g;
tiffData[pixelIndex++] = pixel.b;
if (hasAlpha)
{
tiffData[pixelIndex++] = pixel.a;
}
}
}
// 创建TIFF文件
using (Tiff tiff = Tiff.Open(tiffPath, "w"))
{
// 设置基本参数
tiff.SetField(TiffTag.IMAGEWIDTH, sourceTex.width);
tiff.SetField(TiffTag.IMAGELENGTH, sourceTex.height);
tiff.SetField(TiffTag.SAMPLESPERPIXEL, channels);
tiff.SetField(TiffTag.BITSPERSAMPLE, 8);
tiff.SetField(TiffTag.ROWSPERSTRIP, sourceTex.height);
tiff.SetField(TiffTag.ORIENTATION, Orientation.TOPLEFT);
tiff.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
// 设置光度解释RGB或带Alpha的RGB
tiff.SetField(TiffTag.PHOTOMETRIC, hasAlpha ? Photometric.RGB : Photometric.MINISBLACK);
// 设置Alpha通道信息
if (hasAlpha)
{
ushort[] extrasamples = { (ushort)ExtraSample.UNASSALPHA };
tiff.SetField(TiffTag.EXTRASAMPLES, extrasamples.Length, extrasamples);
}
// 设置压缩
if (compression > 0)
{
tiff.SetField(TiffTag.COMPRESSION, Compression.ADOBE_DEFLATE);
tiff.SetField(TiffTag.ZIPQUALITY, compression);
}
else
{
tiff.SetField(TiffTag.COMPRESSION, Compression.NONE);
}
// 写入图像数据
tiff.WriteEncodedStrip(0, tiffData, tiffData.Length);
}
}
// TIFF 转 PNG (支持透明通道)
public static void TiffToPng(string tiffPath, string pngPath, bool preserveAlpha = true)
{
using (Tiff tiff = Tiff.Open(tiffPath, "r"))
{
int width = tiff.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
int height = tiff.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
int channels = tiff.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToInt();
// 检查是否有额外通道如Alpha
FieldValue[] extraSamples = tiff.GetField(TiffTag.EXTRASAMPLES);
bool hasAlpha = extraSamples != null && extraSamples.Length > 0 &&
extraSamples[0].ToInt() == (int)ExtraSample.UNASSALPHA;
// 读取图像数据
byte[] buffer = new byte[width * height * channels];
for (int i = 0; i < height; i++)
{
tiff.ReadScanline(buffer, i * width * channels, i, 0);
}
// 创建Texture2D
TextureFormat format = preserveAlpha && (channels == 4 || hasAlpha)
? TextureFormat.RGBA32
: TextureFormat.RGB24;
Texture2D tex = new Texture2D(width, height, format, false);
// 填充像素 (垂直翻转)
Color32[] colors = new Color32[width * height];
for (int y = 0; y < height; y++)
{
int flippedY = height - 1 - y;
for (int x = 0; x < width; x++)
{
int bufferIndex = (y * width + x) * channels;
int colorIndex = flippedY * width + x;
byte r = buffer[bufferIndex];
byte g = buffer[bufferIndex + 1];
byte b = buffer[bufferIndex + 2];
byte a = (byte)255;
// 处理Alpha通道
if (preserveAlpha && (channels == 4 || hasAlpha))
{
a = channels == 4 ? buffer[bufferIndex + 3] : (hasAlpha ? buffer[bufferIndex + 3] : (byte)255);
}
colors[colorIndex] = new Color32(r, g, b, a);
}
}
tex.SetPixels32(colors);
tex.Apply();
// 保存为PNG
File.WriteAllBytes(pngPath, tex.EncodeToPNG());
}
}
}