吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 15944|回复: 324
收起左侧

[原创工具] 任意文件转PNG

    [复制链接]
头像被屏蔽
tgguan 发表于 2024-5-28 13:44
提示: 作者被禁止或删除 内容自动屏蔽

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

刺心 发表于 2024-5-31 17:13
我来优化一下代码吧。把内存流替换为文件流
[C#] 纯文本查看 复制代码
using System;
using System.Drawing;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Linq;

namespace file2jpg
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // 按钮1点击事件,选择文件并转换为图片
        private void button1_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog1 = new OpenFileDialog())
            {
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    string inputFilePath = openFileDialog1.FileName;
                    ConvertFileToImage(inputFilePath);
                }
            }
        }

        // 将文件转换为图片
        private void ConvertFileToImage(string inputFilePath)
        {
            string outputImagePath = Path.Combine(Path.GetDirectoryName(inputFilePath), "output.png");
            byte[] fileBytes = File.ReadAllBytes(inputFilePath);
            int totalPixels = (fileBytes.Length * 8 + 23) / 24; // 计算所需的总像素数
            int width = (int)Math.Ceiling(Math.Sqrt(totalPixels)); // 计算图片宽度
            int height = (int)Math.Ceiling((double)totalPixels / width); // 计算图片高度

            using (Bitmap bitmap = new Bitmap(width, height))
            {
                int byteIndex = 0;
                int bitOffset = 0;

                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        if (byteIndex >= fileBytes.Length)
                        {
                            bitmap.SetPixel(x, y, Color.Black); // 如果文件读取完毕,设置像素为黑色
                            continue;
                        }

                        int r = GetNextByte(fileBytes, ref byteIndex, ref bitOffset);
                        int g = GetNextByte(fileBytes, ref byteIndex, ref bitOffset);
                        int b = GetNextByte(fileBytes, ref byteIndex, ref bitOffset);

                        Color color = Color.FromArgb(r, g, b);
                        bitmap.SetPixel(x, y, color); // 设置像素颜色
                    }
                }

                bitmap.Save(outputImagePath, System.Drawing.Imaging.ImageFormat.Png); // 保存图片
            }

            MessageBox.Show("图片已保存为 " + outputImagePath);
        }

        // 获取下一个字节
        private int GetNextByte(byte[] bytes, ref int byteIndex, ref int bitOffset)
        {
            int value = 0;
            for (int i = 0; i < 8; i++)
            {
                if (byteIndex >= bytes.Length)
                    break;

                int bit = (bytes[byteIndex] >> (7 - bitOffset)) & 1;
                value = (value << 1) | bit;

                bitOffset++;
                if (bitOffset == 8)
                {
                    bitOffset = 0;
                    byteIndex++;
                }
            }
            return value;
        }

        // 按钮2点击事件,选择图片并恢复为文件
        private void button2_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog2 = new OpenFileDialog())
            {
                openFileDialog2.Filter = "PNG Image|*.png";
                if (openFileDialog2.ShowDialog() == DialogResult.OK)
                {
                    string pngFilePath = openFileDialog2.FileName;
                    RestoreImageToFile(pngFilePath);
                }
            }
        }

        // 从图片恢复文件
        private void RestoreImageToFile(string pngFilePath)
        {
            string outputDirectory = Path.GetDirectoryName(pngFilePath);
            string outputFilePath = Path.Combine(outputDirectory, "restored_file");

            using (Bitmap bitmap = new Bitmap(pngFilePath))
            {
                int width = bitmap.Width;
                int height = bitmap.Height;

                using (MemoryStream memoryStream = new MemoryStream())
                {
                    for (int y = 0; y < height; y++)
                    {
                        for (int x = 0; x < width; x++)
                        {
                            Color color = bitmap.GetPixel(x, y);
                            memoryStream.WriteByte(color.R);
                            memoryStream.WriteByte(color.G);
                            memoryStream.WriteByte(color.B);
                        }
                    }

                    byte[] fileBytes = memoryStream.ToArray();

                    int index = Array.IndexOf(fileBytes, (byte)'5');
                    if (index != -1 && index <= fileBytes.Length - 4 && fileBytes[index + 1] == (byte)'2' && fileBytes[index + 2] == (byte)'P' && fileBytes[index + 3] == (byte)'J')
                    {
                        string fileNameWithExtension = System.Text.Encoding.Default.GetString(fileBytes, index, fileBytes.Length - index);
                        string originalFileName = fileNameWithExtension.Substring(0, fileNameWithExtension.Length - 4);
                        string originalExtension = Path.GetExtension(originalFileName);

                        originalFileName = originalFileName.Substring(0, originalFileName.Length - originalExtension.Length);
                        string restoredFilePath = Path.Combine(outputDirectory, originalFileName + originalExtension);

                        int count = 1;
                        while (File.Exists(restoredFilePath))
                        {
                            restoredFilePath = Path.Combine(outputDirectory, $"{originalFileName} ({count++}){originalExtension}");
                        }

                        File.WriteAllBytes(restoredFilePath, fileBytes.Take(index).ToArray());
                        MessageBox.Show("文件已恢复为 " + restoredFilePath);
                    }
                    else
                    {
                        File.WriteAllBytes(outputFilePath, fileBytes);
                        MessageBox.Show("未找到加密文件名,文件已恢复为 " + outputFilePath);
                    }
                }
            }
        }
    }
}

免费评分

参与人数 5吾爱币 +5 热心值 +5 收起 理由
JC182 + 1 + 1 谢谢@Thanks!
skun92 + 1 + 1 热心回复!
内瑟斯 + 1 + 1 热心回复!
tgguan + 1 + 1 热心回复!
lccccccc + 1 + 1 我很赞同!

查看全部评分

kongk856 发表于 2024-6-1 03:02
tgguan 发表于 2024-5-29 18:18
没做内存优化,能支持多大文件,取决于你的空余内存。程序会把整个文件加载到内存里。

主要是下面这个语句的int变量溢出了了,不然理论上应该是支持6G左右的文件加密。
int totalPixels = (fileBytes.Length * 8 + 23) / 24;

int 最大值 2147483647,fileBytes.Length * 8的这两个int值相乘的时候如果大于2147483647,就会变成负值,即文件大于256MB就会溢出。
改成下面这样,理论上就能支持6g左右的文件,如果把totalPixels也改成long类型,还能更大。
int totalPixels = ((long)fileBytes.Length * 8 + 23) / 24;
但是后续代码中用了Bitmap方法限制了width,height只能用int,所以文件大小还是有限制的。不过这嘛大的文件搞起来太慢了,也比较少。大文件还是用普通的伪装快一点。
头像被屏蔽
 楼主| tgguan 发表于 2024-5-28 13:44
头像被屏蔽
 楼主| tgguan 发表于 2024-5-28 13:49
提示: 作者被禁止或删除 内容自动屏蔽
zch11230 发表于 2024-5-28 14:17
挺不错的创意,但为啥加了水印还能还原?
ThemanRonin 发表于 2024-5-28 14:14
还挺酷

刺心 发表于 2024-6-6 16:20
劉某人 发表于 2024-6-3 10:18
大锅,可以帮忙打下包么,没用过C#,搞整了一下各种问题解决不了

楼主更新了。你直接用塔最新的即可
china-ray 发表于 2024-5-28 15:19
如果不记得原来的文件类型,如何知道原有的文件类型哪?
头像被屏蔽
 楼主| tgguan 发表于 2024-5-30 12:23
提示: 作者被禁止或删除 内容自动屏蔽
gdfs59310 发表于 2024-5-28 13:46
什么应用场景?
42328669425 发表于 2024-5-28 13:50
感谢分享。
nizsm123 发表于 2024-5-28 13:53
问问是图片格式的转为PNG能查看不?
头像被屏蔽
 楼主| tgguan 发表于 2024-5-28 13:59
提示: 作者被禁止或删除 内容自动屏蔽
lizooo 发表于 2024-5-28 14:04
功夫?熊猫?厉害,居然加了水印依然能够还原!
mt808a 发表于 2024-5-28 14:12
谢谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-20 12:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表