/// <summary> /// 以Unity方式壓上浮水印 /// </summary> /// <param name="pngData"></param> /// <param name="token"></param> /// <returns></returns> internal static byte[] MakeWatermarkPic(byte[] pngData, string token, bool zip) { Texture2D png = new Texture2D(1, 1); _ = ImageConversion.LoadImage(png, pngData); Texture2D watermark; if (zip) { watermark = ImageHelper.LoadDllResourceToTexture2D($"SaveLoadCompression.Resources.zip_watermark.png"); } else { watermark = ImageHelper.LoadDllResourceToTexture2D($"SaveLoadCompression.Resources.unzip_watermark.png"); } float scaleTimes = new PngCompression.PngCompression().GetScaleTimes(token); watermark = watermark.Scale(Convert.ToInt32(png.width * scaleTimes), Convert.ToInt32(png.width * scaleTimes)); png = png.OverwriteTexture( watermark, 0, png.height - watermark.height ); Extension.Logger.LogDebug($"Add Watermark: zip"); return(png.EncodeToPNG()); }
public static void Save(string path, string token) { //這裡用cleanedPath作"_compressed"字串清理 string cleanedPath = path; while (cleanedPath.Contains("_compressed")) { cleanedPath = cleanedPath.Replace("_compressed", ""); } string compressedPath = cleanedPath; if (!SaveLoadCompression.DeleteTheOri.Value) { compressedPath = cleanedPath.Substring(0, cleanedPath.Length - 4) + "_compressed.png"; } //Update Cache string decompressCacheDirName = SaveLoadCompression.CacheDirectory.CreateSubdirectory("Decompressed").FullName; if (!SaveLoadCompression.Enable.Value || !SaveLoadCompression.Notice.Value) { //Clear cache and out File.Delete(Path.Combine(decompressCacheDirName, Path.GetFileName(path))); File.Delete(Path.Combine(decompressCacheDirName, Path.GetFileName(cleanedPath))); File.Delete(Path.Combine(decompressCacheDirName, Path.GetFileName(compressedPath))); return; } File.Copy(path, Path.Combine(decompressCacheDirName, Path.GetFileName(compressedPath)), true); if (cleanedPath != path) { File.Copy(path, cleanedPath, true); Logger.LogDebug($"Clean Path: {cleanedPath}"); } byte[] pngData = MakeWatermarkPic(ImageHelper.LoadPngBytes(path), token, true); byte[] unzipPngData = MakeWatermarkPic(ImageHelper.LoadPngBytes(path), token, false); //New Thread, No Freeze Thread newThread = new Thread(saveThread); newThread.Start(); void saveThread() { Logger.LogInfo("Start Compress"); long newSize = 0; long originalSize = 0; float startTime = Time.time; string TempPath = Path.Combine(SaveLoadCompression.CacheDirectory.CreateSubdirectory("Compressed").FullName, Path.GetFileName(path)); SaveLoadCompression.Progress = ""; try { originalSize = new FileInfo(path).Length; newSize = new PngCompression.PngCompression().Save( path, TempPath, token: token, pngData: pngData, compressProgress: (decimal progress) => SaveLoadCompression.Progress = $"Compressing: {progress:p2}", doComapre: !SaveLoadCompression.SkipSaveCheck.Value, compareProgress: (decimal progress) => SaveLoadCompression.Progress = $"Comparing: {progress:p2}"); //複製或刪除檔案 if (newSize > 0) { LogLevel logLevel = SaveLoadCompression.DisplayMessage.Value ? (LogLevel.Message | LogLevel.Info) : LogLevel.Info; Logger.LogInfo($"Compression test SUCCESS"); Logger.Log(logLevel, $"Compression finish in {Time.time - startTime:n2} seconds"); Logger.Log(logLevel, $"Size compress from {originalSize} bytes to {newSize} bytes"); Logger.Log(logLevel, $"Compress ratio: {Convert.ToDecimal(originalSize) / newSize:n3}/1, which means it is now {Convert.ToDecimal(newSize) / originalSize:p3} big."); //寫入壓縮結果 File.Copy(TempPath, compressedPath, true); Logger.LogDebug($"Write to: {compressedPath}"); //如果壓縮路徑未覆寫,將原始圖檔加上unzip浮水印 if (cleanedPath != compressedPath) { ChangePNG(cleanedPath, unzipPngData); Logger.LogDebug($"Overwrite unzip watermark: {cleanedPath}"); } //如果原始路徑和上二存檔都不相同,刪除之 //因為File.Delete()不是立即執行完畢,不能有「砍掉以後立即在同位置寫入」的操作,所以是這個邏輯順序 //如果相同的話,上方就已經覆寫了;不同的話此處再做刪除 if (path != compressedPath && path != cleanedPath) { File.Delete(path); Logger.LogDebug($"Delete Original File: {path}"); } } else { Logger.LogError($"Compression FAILED"); } } catch (Exception e) { if (e is IOException && newSize > 0) { //覆寫時遇到讀取重整會IOException: Sharing violation on path,這在Compress太快時會發生 //Retry try { if (File.Exists(TempPath)) { if (SaveLoadCompression.DeleteTheOri.Value) { File.Copy(TempPath, path, true); } } } catch (Exception) { //Copy to a new name if failed twice File.Copy(TempPath, path.Substring(0, path.Length - 4) + "_compressed2.png"); Logger.LogError("Overwrite was FAILED twice. Fallback to use the '_compressed2' path."); } } else { Logger.Log(LogLevel.Error | LogLevel.Message, $"An unknown error occurred. If your files are lost, please find them at %TEMP%/{SaveLoadCompression.GUID}"); throw; } } finally { SaveLoadCompression.Progress = ""; if (File.Exists(TempPath)) { File.Delete(TempPath); } } } }