load .png/.jpg from .txt-file

hey guys,
was looking for a solution to save some pictures inaccessible for the user. My first idea was to save them into a locked zipfile, don’t know if it is that easy but think so, BUT i was interested in the idea to save a picture as .txt and open it next time from that .txt-file. E.g. I got a picture and instead of saving it as .png or .jpg, just save it as .txt and…maybe delete the “‰PNG” in the first line so that the user has a .txt-file with some funny looking symbols like "IHDR ¾ ¸«: sRGB ®Îé gAMA ±üa pHYs Ã" and when the program needs to load it again, just add the “‰PNG” and open it as a picture.
think that’s not the easiest way and… hell yes, not the recommended way… to save …saved…pictures but it could be nice to know if it is possible.
anyone some ideas how to do that? or if it IS possible?

A file contains data. The file extension doesn’t do any changes to the data that’s inside the file. The extension is just part of the filename and helps the operating system to pick a program which should be used to open/edit/play the file. You don’t need an extension at all.

It seems you just want to “encrypt” the file. The easiest way is to “xor” the data with some key. That’s a very simple encryption.

btw: a [png file][1] starts with this hex sequence: 89 50 4E 47

Depending on the text encoding that your text editor uses 89 might represent totally different characters. Texteditors can’t view binary files in the most cases. If you open any binary file in a texteditor and just re-save it, it would probably be broken because binary can contain a lot non-printable characters.

If you want to encrypt any kind of file you have to:

  • get the file as byte array
  • apply an encryption method on each byte
  • write the byte array to a file.

The nice this with xor is that it you’re doing the same thing again it reverts to the original.

//C#
void SimpleEncrypt(byte[] aData, byte aKey)
{
    for(int i = 0; i < aData.Length; i++)
    {
        aData _= aData *^ aKey;*_

}
}
So if you use this function on any data it will become unreadable. If you use it once more (with the same key) on the encrypted data it will be decrypted. A lot encryption systems work like that but with a changing key for each byte and the strength of an algorithm lies in the key generation. A bit more complex is the use of a pseudo random generator and use the key as seed. If this approach is used you should make sure that the random generator does never change. So don’t use Unity’s or System’s Random class since it’s implementation can be changed in the future.
Final note:
The SimpleEncrypt function above uses a single byte as key, so there are 255 possible keys (0 should not be used since it wouldn’t change anything). This is an 8bit encryption which can be figured out quite fast is you know what you’re doing. However most people wouldn’t :wink:
edit
A quite nice and simple pseudo random generator is the one that’s used in the [Pascal][2] core libraries.
// C#
public class PRandom
{
private float m_Seed;
public PRandom(uint aSeed)
{
m_Seed = aSeed;
}

public uint Next(uint aRange)
{
m_Seed = m_Seed * 0x08088405 + 1;
return m_Seed % aRange;
}
}
The uint sequence doesn’t repeat until 4294967295 iterations. So it iterates through the whole uint range but in a pseudo-random way, you only pick a start value as key
So the encryption method could be written like this:
//C#
void Encrypt(byte[] aData, uint aKey)
{
PRandom rnd = new PRandom(aKey);
for(int i = 0; i < aData.Length; i++)
{
aData = aData ^ (byte)rnd.Next(256);
}
}
ps: I haven’t tested this code since i converted it from Pascal to C# but it used to work pretty well :wink:
[1]: PNG - Wikipedia
[2]: Pascal (programming language) - Wikipedia

Thanks for answering.
Well yes I know, that the extension doesn’t do any changed to the data, but I thought when I have the data of a png as txt-file and delete a constant of it like the first line it would be simple to save it unreadable for a casual-user.

But ok didn’t know that it may be broken. I’m still a newbie, hope I got that: I can get the byte-array in unity with the WWW.class right? When I have that byte-array i just encrypt it with your example-method and save it as .png again?

Even if it won’t work this way: If I have a encrypted byte-array, when I decrypted it, how can I display it? I’m a bit confused, can I “load” that byte-array into a texture2d?

Edit:

Ok nothing is working,
I played around with your code and some png’s about 5 hours and I really can’t get it to work. Your SimpleEncrypt code works (I added a (byte) cast) but I can’t get a “working” byte array from a png. I tried to load my test.png with something like that:

public static byte[] loadPngBytes(string path, string filename) {
		byte[] bytes;
		
		string pathPrefix = @"file://";
		string fileSuffix = @".png";
		
		path = pathPrefix + path;
		if(!path.EndsWith(@"\")) path = path + @"\";
		if(!filename.EndsWith(fileSuffix)) filename = filename + fileSuffix;
		
		string fullFilename = path + filename;
		
		WWW www = new WWW(fullFilename);
		
		bytes = www.bytes;
		
		return bytes;
	}
  • the first part of it till www = new WWW(…) works but bytes = www.bytes works not i think

I tried:

byte[] bytesOfPic = loadPngBytes(path, filename);

Texture2D myPic = new Texture2D(150, 150);

myPic.LoadImage(bytesOfPic);

but it doesn’t work (I can’t display it).

So I tried another way to get bytes of a picture with one of my working(!) methods to load the file into a Texture2D and then get the bytes of THAT:

public static Texture2D loadPng(string path, string filename, int width, int height) {
		Texture2D returnPic = new Texture2D(width, height, TextureFormat.ARGB32, true);
		pathPrefix = @"file://";
		fileSuffix = @".png";
		
		path = pathPrefix + path;
		if(!path.EndsWith(@"\")) path = path + @"\";
		if(!filename.EndsWith(fileSuffix)) filename = filename + fileSuffix;
		
		fullFilename = path + filename;
		
		WWW www = new WWW(fullFilename);
		
		www.LoadImageIntoTexture(returnPic);
		
		return returnPic;
	}

and:

Texture2D myPic = loadPng(path, filename, 150, 150);

byte[] bytesOfPic = myPic.EncodeToPNG();


Texture2D myPicToDisplay = new Texture2D(150, 150);

myPicToDisplay.LoadImage(bytesOfPic);

and I can’t display it again.

I can’t try to encrypt it cause I can’t even get working byte arrays of a picture… what the heck do I get from WWW.bytes and Texture2D.EncodeToPNG() ?!?

Really need some Help here, I can’t get it -.-

EDIT AGAIN:

got it solved…it was just a mistake by myself, the code I wrote with the code you wrote works…I just placed the

Texture2D myPic = new Texture2D(150, 150);

above the start() instead of IN the start() … such a dumb mistake :slight_smile:

so thanks again for your help

SOLVED!