- Home /
How to load a BMP file in binary?
This code works:
var image = transform.GetComponent<Image>();
var bits = Util.LoadBinary(BoardImage); // load off disk in binary
var tex = new Texture2D(2, 2); // size not used
tex.LoadImage(bits);
image.preserveAspect = true;
image.sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.zero);
But it only works for PNG and JPG, not for BMP. Unity Editor can load BMP, but it creates metadata. So it can be done, I just don't know how.
So the question is how to load a BMP file directly in binary using the API, not via the editor.
Answer by Bunny83 · Feb 05, 2017 at 05:51 AM
Besides what @Seyren said in his answer you can always load any format you want as long as you know how the format is specified and as long as it's not too complex / complicated.
This is both true for the BMP format. All you actually need is the wikipedia page of the BMP format. It explains the whole format.
Another option besides creating your own BMP loader is to search the net for a C# implementation of a BMP loader. If you don't mind setting your project to .NET 2.0 and importing the System.Drawing assembly, you could use the Bitmap class inside System.Drawing. Though it might not work on certain platforms and is quite large.
A bit of "googling" revealed this. Not sure what language that actually is, but the code is in C# and looks like a naive straight forward implementation of the wikipedia information ^^. It just extracts the image data as a byte array as well as the image resolution. It certainly is a start to implement a proper BMP --> Texture2D loader.
edit
Since the BMP format is rather simple i just went ahead and quickly wrote a BMPFile loader for Unity. It's hosted on my pastebin account as unlisted paste.
As i have written in the information header I have not tested it with all possible file versions. Also it doesn't support any of the compressed formats (yet). Though it can read alpha values if required. I couldn't test the 16 and 32 bit formats since MS Paint only supports up to 24 bit images. Paint .NET only supports 8 or 24bit. So i only tested the alpha read for indexed images. I actually changed the alpha value manually in the file with a hexeditor. I also tried to change the palette colors of a monochrome image. Funnily the windows image preview as well as my loader had no problem with a monochrome image (1bit) that has a custom palette (for example red and green). MS Paint itself doesn't seem to actually interpret the palette and force the image to a B&W image when loaded.
Usage example:
// at the top
using B83.Image.BMP;
// [...]
BMPLoader loader = new BMPLoader();
//loader.ForceAlphaReadWhenPossible = true; // can be uncomment to read alpha
//load the image data
BMPImage img = loader.LoadBMP("C:\\Data\\B1.bmp");
// Convert the Color32 array into a Texture2D
Texture2D tex = img.ToTexture2D();
If someone uses it and / or finds any bugs or problems, feel free to leave a comment. If you try to load an unsupported format it should print some error messages in the console.
For convenience the LoadBMP method has overloads that takes either a filepath as string, a data stream, a byte array or a BinaryReader.
But Unity already knows how to load B$$anonymous$$P files. I just want to know how.
No, "Unity" does not know how to load B$$anonymous$$Ps. You have to differentiate between Unity as engine and the Unity editor application. That's two completely different things. The Unity editor can load a lot formats but not the engine. This is true for any kind of "asset". For example at runtime the only audio formats you can load are "wav" and "ogg", no mp3 support. Likewise textures can only be loaded from either JPG or PNG files, nothing else. Also certain things can't be loaded at all like models / meshes as the engine has no parser / loader for any 3d format built into the engine. If you need that functionality, you have to add it yourself.
Just in case you haven't noticed, i quickly wrote a B$$anonymous$$P file loader. I've edited my answer.
@bunny83: I'm impressed you 'quickly wrote' such a large chunk of code. That looks useful.
However, you haven't convinced me it's needed. Once the file XXX.bmp.meta has been created (by the editor), a Unity app can load B$$anonymous$$P files just fine. There is code already in Unity somewhere to load B$$anonymous$$P files, and I would still like to know where it is and how to get it to do its thing.
No, it is not. Unity uses a proprietary asset format. All assets are imported into their asset database. It actually doesn't matter what format you put into your project, Unity will store it in a different format and might even rescale it (depending on the texture import settings). The meta file just contains the asset ID where Unity stored the asset inside the assetdatabase.
The actual asset data is stored in YourProject\Library\metadata\ ...
. There you will find a lot (x256) folders which actually represents the assetdatabase. When an asset got imported it's data will be converted into the internal format and stored there. In case the library is deleted, the Unity editor can simply recreate it from the original assets by simply reimport them. The meta file is important so then an asset get moved / or reimported Unity can recreate all cross-references between assets.
All built-in image loading functions (like WWW.LoadImageIntoTexture or Texture2D.LoadImage) can only load either PNG or JPG files. That's why we have AssetBundles. They basically represent a seperate / standalone version of the assetdatabase which can be loaded at runtime.
I work with Unity for over 6 years now. I know almost every bit about Unity which you can know from an "outside" perspective. I will now stop trying to "convince" you of anything, but i can tell you, you won't get any other answers than those 3 options you have right now:
Wait until Unity implements a B$$anonymous$$P loader into their engine
Use a supported format ( JPG or PNG )
Use a custom loader
The first option is not really an option unless you can wait about half a year up to infinity.
Btw: A lot of the code i've written is just type definition / constants. The "BitStreamReader" class i've written a long time ago, so it was just a copy&paste ^^. I basically had the wikipedia page open on one monitor and VS on the other. Haven't really checked the time, but it wasn't too long :). Also when i decide to implement something it's usually because i might need it for myself.
Thanks, that's the answer I was looking for. The B$$anonymous$$P loader is not part of the editor as such, nor is it available in the runtime. It's in code that runs whenever the editor starts up, even if you never touch the file in the editor. I would call that the asset pipeline, and I would suspect it's possible to build assets that include B$$anonymous$$P files (and probably many file types) by running a stand-alone build. But what you've told me is enough to solve my problem.
Uhm, i don't get how you come to this conclusion:
The B$$anonymous$$P loader is not part of the editor as such
The Unity editor application does have a B$$anonymous$$P loader as well as TIFF loader and many other formats. The editor uses it's loaders to import and convert those files into the assetdatabase of your project.
It's in code that runs whenever the editor starts up
That sentence even contradicts your first statement. If there's code running when the editor starts up, it has to be part of the editor. How could a program execute code that doesn't exist...
Yes, the editor imports new files when it loads up your project, however it also does so when you add files later or even when you change the files. Unity keeps track of the original asset file. When you edit / change that asset file outside of Unity, Unity will will detect the change and reimport the asset to update the assetdatabase when you switch back to the editor.
When you build a game, none of the original assets are included into the build, but only the imported / converted data in Unity's own proprietary asset format.
ps: If your question is solved, you might want to accept an answer.
Your answer is the separate B$$anonymous$$P loader and while that's handy, it doesn't answer the question. If you'd like to convert your comments into an actual answer to my question, I could accept it.
But your view of 'the Unity editor application' is not one I can agree with. The B$$anonymous$$P loader (as I have now discovered) is a function of the Asset Importer, which runs alongside the editor but can also be run separately. The Asset Importer can handle many file types, can be extended with custom loaders, and has its own extensive documentation. A good answer would point that out, perhaps with a link to the relevant documentation.
Wow, this is SO useful! Thank you - it worked like a charm! I can't believe how easy it was to implement! You even have an overload for the LoadB$$anonymous$$P function to take in a byte array - unbelievable. I didn't even need to tweak or debug anything, it just ran. Props to you, good sir! I tried to make a B$$anonymous$$P loader for something else in the past but had little luck, so I didn't know what I would do when I found myself in need of one now, but I'm so glad I found your comment! To the top with you! :D
:) Thanks. No problem. Though i quickly glanced over the code again an found a "little" problem ^^. B$$anonymous$$P files can have a negative height value. This indicates that the image starts at the top left ins$$anonymous$$d of the bottom left. So what's currently missing is the top-down-reversal when the height is negative. Though i guess such images are actually rare.
Actually i wanted to implement the run length encoded formats (RLE4 / RLE8) as well but haven't found the time to implement them. I also don't have any images in that format for testing ^^. Though the format seem to be pretty simple.
Cool - well it works great for me, just for a for-fun application I'm making. I wanted to read in all the miscellaneous pictures in my pictures folder into unity and make a collage of sorts, but 80% of my pictures are B$$anonymous$$Ps, and I wasn't about to convert all the files just for this one for-fun project. So this has been an awesome help :) I have only ran into one problem so far, but it wasn't an issue for me. When trying to read in one particular .bmp image, it threw the error, "Not a B$$anonymous$$P file". I checked and it most certainly was. But the image was one taken off an old camera years ago, so something with the format must've been wrong. I opened the picture in the paint program, copied everything, and pasted it in a new bmp file and saved it, deleting the original, and the error went away and it worked fine. And that's the only tiny issue I've had reading in hundreds of pictures. So I'm very happy with it :)
Just got around to trying this. The code compiles fine, with 3 warnings (shiftR/G/B not used at line 315). It loads B$$anonymous$$P files and returns textures. I loaded the textures into sprites using Sprite.Create(). Seems to run O$$anonymous$$, with no Unity errors.
On my collection of B$$anonymous$$Ps some are BI_RLE8 so no joy at all. The rest are BI_RGB 8-bit. They load and display; the colours look O$$anonymous$$, but the pixels are moved around. Hard to describe. Looks like it could be errors in the pixel location calculations. Happy to provide samples if you're interested.
Right now I'm not sure whether to give up, get coding or look elsewhere. But if you fixed any bugs already that might help.
Yes, those 3 lines are actually left over (copy&paste error -.-). Of course since they aren't used they can be removed from the "ReadIndexedImage" method. (edit I just realised that i actually had removed those 3 lines already but haven't updated my pastebin version -.-)
Yes, an example image would help. If you don't want to post the images in public you can write me a P$$anonymous$$ on the forum. Though you may want to post a quick comment here as i don't check my P$$anonymous$$s on a regular basis -.-
I just updated the pastebin version to my latest version i've found in my test project. It actually had RLE4 and RLE8 support already ^^. Not sure why i didn't update the file online.
Downloaded, tested, RLE works fine. Warnings gone. Good work. But the scrambled bitmaps are still scrambled. Two bitmaps attached. /storage/temp/101841-tictactoe.zip
Answer by Seyren · Feb 05, 2017 at 03:11 AM
If the API does not support it, you either have to wait until it does, or just go back to PNG or JPG, which in my opinion is the best option for a videogame.
BMP files are uncompressed, and will take a lot of space, and therefore, more time to load, which is not good.
I would choose in this case, between PNG and JPG, a PNG file, since it uses lossless compression, which means the image will not lose any data compared to the original, so you can freely switch to it, being the size the only difference between the two formats.
If your concern is, for example, that you have a lot of files in BMP and it's a pain to convert them to PNG, there is a lot of batch conversors you can find on google.
I know that this is not the solution you would want, but in my opinion BMP is not a good idea.
Not to mention PNG supports transparency.
Thank you for your answer, but this is what is known on Stack Overflow as an X-Y answer. I want to do X, but you told me to do Y ins$$anonymous$$d. I still want an answer for X.
I know everything you said, but I still want to load B$$anonymous$$P files (and I have a good reason, which is not relevant to the question.) Can you help or not?