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()); } } }