• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Java BLP IIO Plugins

Status
Not open for further replies.

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Finally got around to finishing my Java IIO ImageReader and ImageWriter plugin for BLP files.

One can check out the source on GitHub.

This is by far the most compatible BLP0/1 reader and writer for Java one can get at the moment.

Both ImageReader and ImageWriter exist. As this is a plugin all one needs is to place the JAR file somewhere in the path and it will automatically be used by the standard Image IO API. Outside of some implementation specific features the ImageReader can be used without needing to link to any of the implementation classes.

Performance is pretty reasonable from rough tests performed. It can read every mipmap level of every image in Warcraft III in less than a minute.

With a JAR of the plugin placed anywhere along the Java path one can read a BufferedImage from a BLP file as simply as...
Code:
File blpFile = new File(...);
BufferedImage img = ImageIO.read(blpFile);
Reading of mipmap levels from appropriate BLP files is also supported...
Code:
ImageReader reader = ImageIO.getImageReadersByFormatName("blp").next();
File blpFile = new File(...);
ImageInputStream iis = ImageIO.createImageInputStream(blpFile)
reader.setInput(iis, true, true);
final int imageNum = reader.getNumImages(true);
for (int i = 0; i < imageNum; i += 1) {
    BufferedImage img = reader.read(i);
}
It supports both BLP0 (Warcraft III Reign of Chaos beta) and BLP1 (all release versions of Warcraft III). BLP0 files have to be read from either a File or Path due requiring accompanying files.
Code:
ImageReader reader = ImageIO.getImageReadersByFormatName("blp").next();
File blp0File = new File(...);
reader.setInput(blp0File, true, true);
BufferedImage img = reader.read(0);
Like wise one can write images using it. It will automatically generate mipmaps by default. All one has to do to write a usable BLP version 1 file is...
Code:
BufferedImage img = ...;
File blpFile = new File(...);
ImageIO.write(img, "blp", blpFile);
 
Last edited:

Deleted member 219079

D

Deleted member 219079

BLP format is interesting. Is there something concrete written on the subject, extending upon this? (Edit: Talking about the section "11) "war3mapMap.blp" the minimap image")
Nothing I can say about the code, I'd never rely on end user installing runtime environment just to run my app (yeah I hate managed C++!)
 
Last edited by a moderator:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
extending upon this?
No because that declaration of the BLP format is out right wrong. Specifically it does not cover mipmaps, alpha bits and correct indexed color logic.

I wrote an article about BLP in this forum a while ago. It is not complete and has some inaccuracies, especially regarding BLP2 as I cannot test that, but it is a lot more accurate than any other specification out there.
Nothing I can say about the code, I'd never rely on end user installing runtime environment just to run my app (yeah I hate managed C++!)
Java is a standard runtime environment that most computers, especially OEM ones, comes with.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Finally finished writing the BLP ImageWriter. The plugin can now both read and write BLP files.

I have only tested the writer with JPEG content BLP files at the moment. In theory it should support direct content (indexed color model) however I have not tested that so there may be errors.

JPEG content shared header production does not seem ideal. Where as Blizzard gets a 624 byte shared header, I am getting only a 76 byte shared header. I do not know if that is because of shared bloat in Blizzard's, or if I am not sharing common structures in mine. Looking at mipmap data block sizes I am inclined to believe that up to 100 bytes could be saved per mipmap level in JPEG content with better header sharing algorithm. However an at most 1kb saving per file is not much, especially since the files are often hundreds of kilobytes in a map limit of 128 Megabytes.

By default the writer will automatically create mipmaps. These are generated using an area averaging algorithm from the full scale image which appears to produce visually good results, at least for JPEG content. For indexed color direct content better results might be obtainable by using dithering, which I am not sure how to implement at the moment.

I discovered that JPEG content shared header has a maximum size. I assume this to be 624 bytes (0x270) as that is what all Blizzard shared headers use. I tried a value of 1024 (0x400) and noticed symptoms of buffer overrun on occasion when loading the BLP file.
 
Status
Not open for further replies.
Top