using UnityEngine; using UnityEngine.UI; using ZXing; using ZXing.QrCode; using ZXing.Common; using ZXing.Rendering; using ZXing.QrCode.Internal; namespace Kill.UI.Components { /// /// 二维码生成器 /// 支持生成用户ID等文本的二维码图片 /// public class QRCodeGenerator : MonoBehaviour { [Header("显示组件")] public RawImage qrCodeImage; // 显示二维码的RawImage public int textureSize = 256; // 二维码图片尺寸(像素) [Header("二维码样式")] public Color foregroundColor = Color.black; // 前景色(二维码颜色) public Color backgroundColor = Color.white; // 背景色 public int margin = 2; // 边距 // 当前生成的纹理 private Texture2D currentTexture; // void Start() // { // Generate("123123"); // } /// /// 生成二维码 /// /// 二维码内容(如用户ID) public void Generate(string content) { if (string.IsNullOrEmpty(content)) { Debug.LogWarning("[QRCodeGenerator] 内容为空,无法生成二维码"); return; } // 生成二维码纹理 Texture2D texture = GenerateQRCodeTexture(content, textureSize, textureSize); if (texture != null) { // 清理旧纹理 if (currentTexture != null) { Destroy(currentTexture); } currentTexture = texture; // 显示二维码 if (qrCodeImage != null) { qrCodeImage.texture = currentTexture; qrCodeImage.SetNativeSize(); // 可以在这里调整显示大小 float scale = Mathf.Min( qrCodeImage.rectTransform.rect.width / textureSize, qrCodeImage.rectTransform.rect.height / textureSize ); qrCodeImage.rectTransform.sizeDelta = new Vector2(textureSize * scale, textureSize * scale); } Debug.Log($"[QRCodeGenerator] 二维码生成成功: {content}"); } } /// /// 生成用户ID二维码 /// /// 用户ID public void GenerateUserQRCode(string userId) { // 可以添加前缀标识这是用户ID string content = $"USER:{userId}"; Generate(content); } /// /// 生成设备分享二维码 /// /// 设备ID /// 用户ID public void GenerateDeviceShareQRCode(string deviceId, string userId) { // 格式: DEVICE:设备ID:用户ID string content = $"DEVICE:{deviceId}:{userId}"; Generate(content); } /// /// 生成二维码纹理 /// private Texture2D GenerateQRCodeTexture(string content, int width, int height) { try { // 配置二维码参数 var options = new QrCodeEncodingOptions { Width = width, Height = height, Margin = margin, CharacterSet = "UTF-8", ErrorCorrection = ErrorCorrectionLevel.M // 中等容错率 }; // 创建写入器 var writer = new BarcodeWriter { Format = BarcodeFormat.QR_CODE, Options = options, Renderer = new ZXingRender() }; // 生成二维码 Texture2D texture = writer.Write(content); // 应用颜色 ApplyColors(texture, foregroundColor, backgroundColor); return texture; } catch (System.Exception ex) { Debug.LogError($"[QRCodeGenerator] 生成二维码失败: {ex.Message}"); return null; } } /// /// 应用自定义颜色到二维码 /// private void ApplyColors(Texture2D texture, Color foreground, Color background) { Color32[] pixels = texture.GetPixels32(); for (int i = 0; i < pixels.Length; i++) { // 黑色像素变前景色,白色像素变背景色 if (pixels[i].r < 128) { pixels[i] = foreground; } else { pixels[i] = background; } } texture.SetPixels32(pixels); texture.Apply(); } /// /// 保存二维码到相册(移动端) /// public void SaveToGallery(string filename = "QRCode") { if (currentTexture == null) { Debug.LogWarning("[QRCodeGenerator] 没有可保存的二维码"); return; } // 将纹理转为PNG字节 byte[] bytes = currentTexture.EncodeToPNG(); // 保存到相册 #if UNITY_ANDROID string path = $"/storage/emulated/0/DCIM/{filename}.png"; System.IO.File.WriteAllBytes(path, bytes); // 刷新相册 using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { using (AndroidJavaObject currentActivity = unityPlayer.GetStatic("currentActivity")) { using (AndroidJavaObject mediaScanner = new AndroidJavaObject("android.media.MediaScannerConnection")) { mediaScanner.CallStatic("scanFile", currentActivity, new string[] { path }, null, null); } } } #elif UNITY_IOS // iOS 使用原生插件保存 // NativeGallery.SaveImageToGallery(currentTexture, "QRCode", filename); #else string path = System.IO.Path.Combine(Application.persistentDataPath, $"{filename}.png"); System.IO.File.WriteAllBytes(path, bytes); Debug.Log($"[QRCodeGenerator] 二维码已保存到: {path}"); #endif ToastUI.Show("二维码已保存到相册"); } /// /// 获取当前二维码纹理 /// public Texture2D GetCurrentTexture() { return currentTexture; } /// /// 清除二维码 /// public void Clear() { if (currentTexture != null) { Destroy(currentTexture); currentTexture = null; } if (qrCodeImage != null) { qrCodeImage.texture = null; } } private void OnDestroy() { Clear(); } } /// /// ZXing 纹理渲染器 /// public class ZXingRender : IBarcodeRenderer { public Texture2D Render(BitMatrix matrix, BarcodeFormat format, string content) { return Render(matrix, format, content, null); } public Texture2D Render(BitMatrix matrix, BarcodeFormat format, string content, EncodingOptions options) { int width = matrix.Width; int height = matrix.Height; Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false); Color32[] pixels = new Color32[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { pixels[y * width + x] = matrix[x, y] ? Color.black : Color.white; } } texture.SetPixels32(pixels); texture.Apply(); texture.filterMode = FilterMode.Point; // 保持像素清晰 return texture; } } }