CSharpImageLibrary icon indicating copy to clipboard operation
CSharpImageLibrary copied to clipboard

Width or Height equal or under 4 pixels

Open OriDevTeam opened this issue 8 years ago • 14 comments

Hello,

When i try to save an image using the lib, where is there an image with less than 4 pixel sized in width or height, there is a divison error on the DDSGeneral.cs script at line 342: Error: An exception of type 'System.DivideByZeroException' occurred in CSharpImageLibrary.dll Additional information: Attempted to divide by zero.

After a simple check to avoid less or equal 4 pixels width/height image saving where the image size is 111:20, another error appears on the DDS_Enconders.cs script at the line 37:

Error: An exception of type 'System.IndexOutOfRangeException' occurred in CSharpImageLibrary.dll Additional information: Index was outside the bounds of the array.

Here is a chunk of the code used:

` Rectangle rect = Rectangle.FromLTRB(left, top, right, bottom);

        if (rect.Width <= 0 || rect.Height <= 0)
            return;

        if (rect.Width <= 4 || rect.Height <= 4)
            return;

        try
        {

            bmp = bmp.Clone(rect, bmp.PixelFormat);

            using (var stream = new MemoryStream())
            {
                bmp.Save(stream, ImageFormat.Png);
                ImageEngineImage img = new ImageEngineImage(stream.ToArray());
                img.Save(path + @"\" + subImage.name + "." + extension, ImageEngineFormat.DDS_DXT3, MipHandling.KeepExisting, 0, 0, false);
            }
        }
        catch (Exception e)
        {
            LogManager.Instance.MsgError("Could not save image " + path + @"\" + subImage.name + "." + extension
                + "\nError: " + e.Message);
        }`

Best Regards

OriDevTeam avatar Jan 27 '17 01:01 OriDevTeam

I haven't properly figured out how to deal with images smaller than 4x4 for DDS', so that's why that doesn't work, although it should catch that exception. I'll track it down.

I'll take a look at the second one too.

KFreon avatar Jan 27 '17 03:01 KFreon

Is there any alternative for this type of situation? Im in kind of an urge to have this working properly to finish some important stuff.

Best Regards.

OriDevTeam avatar Jan 29 '17 18:01 OriDevTeam

Apologies, I got a bit distracted. I did some quick testing with the latest build on my end and didn't get any errors, so it might be fixed. Can you link me the image you're using so I can test with it?

KFreon avatar Jan 29 '17 21:01 KFreon

I verified that i had the last version (4.0.2) and then tried to do it on VS2015, when i debugged it, it didn't gave any error but the amount of sub images that it converted was not the same as the sub image property files, for some odd reason

Here you have the whole project and the resources to test it on resource folder https://github.com/OriDevTeam/SubImage-Manager

Best Regards,

OriDevTeam avatar Jan 29 '17 23:01 OriDevTeam

I've just uploaded a new version, so see how that one goes. BUT it's API is a little different, just so you're aware. Hope it fixes the problem :)

If it does, let me know and I'll close this issue.

EDIT: I'm not sure how you're using this, so my testing was to load that "windows.dds" image and re-save it. If that's not what's causing the bug, also let me know so I can test properly.

KFreon avatar Jan 30 '17 03:01 KFreon

The first problem persists, but now the error is popped up directly with exception and the second problem did not really disappear but it has changed, now instead of giving the error it gave, it doesn't give any error but when i check if the image is correct, it isn't, it just converts to a 1x1 sized image with a black pixel.

http://i.imgur.com/uxGvANU.png

Best Regards.

OriDevTeam avatar Feb 02 '17 00:02 OriDevTeam

Images with a dimension less than 4 aren't supported right now, don't know if/when I'll get to it. DXTn DDS' dimensions must be powers of 2, so that 111x20 will be resized to something like 128x16 on saving.

Some notes though, mipmaps below with a dimension < 4 will be black (for the top reason) and non powers of 2 will be resized to suit. I'm not sure why you're doing what you're doing, but perhaps it's better to pre-cut up that image in Photoshop or GIMP and save them using DirectXTex or the nVidia tools.

This tool is really just for rapid viewing and converting of most formats. It evidently won't be as good as the super fancy tools written by professionals.

EDIT: Here's one that fixes some bugs I found while testing with those image sizes.

KFreon avatar Feb 02 '17 00:02 KFreon

Well the reason of existance of that tool im making is to remove that system, it was used in a game as a way of consuming less IO requests, since HD reading was slower at the time(2006), now we are in 2017 and that kind of system is worthless, so the tool objective is to remove it completly.

It is completly worthless doing that on a real image editing app like gimp or so, because they cant obviously read the sub files, that contain the information that says exactly where is the image located inside an image that contains all images for certain thing.

Probably ill just convert to PNG instead and convert to DDS manually tho, later i will test the fix you gave.

Best Regards.

OriDevTeam avatar Feb 02 '17 08:02 OriDevTeam

Sorry I can't be of more help, but the little eccentricities of DDS are time consuming to implement and, in my mind, don't affect things (who uses 4x4 mips for anything?)

KFreon avatar Feb 02 '17 09:02 KFreon

After testing the version that you gave on your edited anwser, i set mipmap handling to KeepExisting, there is no problem if i can't have them, all gucci but,

When i convert all the images, they all convert without any exception but when i check them on GIMP or any other editor, they are not really correct as they should, heres a example below:

PNG Output: http://i.imgur.com/SaeRoW9.png DDS Output: http://i.imgur.com/yqCdVUM.png

The size decreases and so the quality, seems like the image is being shrunk(?) And i also noticed that in some images the size stays the same but the quality comes out badly or significantly different. Best Regards.

OriDevTeam avatar Feb 03 '17 08:02 OriDevTeam

Yeah that's the thing I mentioned above, where DDS's can't handle dimensions that aren't powers of 2. Far as I know, nothing can be done about that for DDS'.

KFreon avatar Feb 03 '17 12:02 KFreon

One day I'll get to figuring out how to make this work. To reiterate, the issue is that the dimensions must be divisible by 4, and while the initial dimensions of your image are, the mipmaps aren't.

KFreon avatar Jun 16 '17 02:06 KFreon

@KFreon I think i found the problem, after some tests with an graphic image professional, we tried for a few moments to understand why this was happening, and the result was that 1 millimeter is equal to 4 pixels, if you divide by 4 by 1 you get a 0,25, a decimal number, so thats why the division by 0 occurs since you define int in the code, we also tried in Photoshop and in the image he increased to 4 pixels more, so that the image stays with 8 pixels, that results in 2 millimeters and it just worked fine!

So maybe if you change the variable type to decimal(double, float if possible) probably it will work.

OriDevTeam avatar Feb 15 '18 20:02 OriDevTeam

Sorry about the lack of work on this. I've not had time to do anything but work.

The heart of the issue is that the compression algorithm works on 4x4 blocks regardless of the size of image. It'll chop up larger images into 4x4 bits and compress each bit separately. For a dimension smaller than 4, it needs to be padded with 0's (I think). I just haven't gotten around to figuring out how to go about doing that.

KFreon avatar Feb 17 '18 08:02 KFreon