Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Common: add some new properties to IImage #21

Open
Krakean opened this issue Mar 24, 2018 · 12 comments
Open

Common: add some new properties to IImage #21

Krakean opened this issue Mar 24, 2018 · 12 comments

Comments

@Krakean
Copy link

Krakean commented Mar 24, 2018

@nickbabcock
Hi! Can you please add listed below fields to IImage? They are mostly for DDS (since they available in dds header)

  1. int bitsPerPixel - amount of bits per pixel for a surface data (can be applied for TGA too, may be?)
  2. int MipMapCount - number of mip-map levels for a mip-mapped texture
  3. bool IsCubeMap - whether DDS resource is a cubemap
  4. bool IsVolumeTexture - whether DDS is a volume texture
  5. bool IsBC - whether the DDS contains block-compressed surface data (kinda important flag, that indicates that a user have to use another Gfx API's function to send texture to GPU)
  6. bool IsDX10 - whether this file data came from a DX10 DDS file, also they support texture arrays. This is not a flag that you read directly from dds header, but a flag that you can set if you successfully read DX10 DDS header structure in dds file, so it can indicate that this DDS is a DX10 dds.
  7. bool HasAlpha - whether the DDS contains alpha data
  8. Depth - either depth of a volume texture in pixels or amount of faces in a cubemap
  9. List<...?> Textures - file is guaranteed to contain at least one texture (if loaded/parsed successfully?); if it is a texture array / texture with mipmaps, there will be more than one.
  10. FormatD3D9 - http://msdn.microsoft.com/en-us/library/windows/desktop/bb172558%28v=vs.85%29.aspx
  11. FormatD3D10 - DDS: support for DXGI_FORMAT-like enumerations #22

Last two also very important, because depends on them, textures load path could be a bit different (at least, it needed to setup pixel format correctly).

@Krakean
Copy link
Author

Krakean commented Mar 24, 2018

bitsPerPixels

May be this code will help you:
...
public static int GetBitsPerPixel(DxgiFormat format)
{
switch (format) {
case DxgiFormat.R1_UNorm:
return 1;

            case DxgiFormat.BC1_Typeless:
            case DxgiFormat.BC1_UNorm:
            case DxgiFormat.BC1_UNorm_SRGB:
            case DxgiFormat.BC4_SNorm:
            case DxgiFormat.BC4_Typeless:
            case DxgiFormat.BC4_UNorm:
                return 4;

            case DxgiFormat.A8_UNorm:
            case DxgiFormat.R8_SInt:
            case DxgiFormat.R8_SNorm:
            case DxgiFormat.R8_Typeless:
            case DxgiFormat.R8_UInt:
            case DxgiFormat.R8_UNorm:
            case DxgiFormat.P8:
            case DxgiFormat.AI44:
            case DxgiFormat.IA44:
            case DxgiFormat.BC2_Typeless:
            case DxgiFormat.BC2_UNorm:
            case DxgiFormat.BC2_UNorm_SRGB:
            case DxgiFormat.BC3_Typeless:
            case DxgiFormat.BC3_UNorm:
            case DxgiFormat.BC3_UNorm_SRGB:
            case DxgiFormat.BC5_SNorm:
            case DxgiFormat.BC5_Typeless:
            case DxgiFormat.BC5_UNorm:
            case DxgiFormat.BC6H_SF16:
            case DxgiFormat.BC6H_Typeless:
            case DxgiFormat.BC6H_UF16:
            case DxgiFormat.BC7_Typeless:
            case DxgiFormat.BC7_UNorm:
            case DxgiFormat.BC7_UNorm_SRGB:
                return 8;

            case DxgiFormat.A8P8:
            case DxgiFormat.AYUV:
            case DxgiFormat.Y210:
            case DxgiFormat.Y216:
            case DxgiFormat.Y410:
            case DxgiFormat.Y416:
            case DxgiFormat.YUY2:
            case DxgiFormat.NV11:
            case DxgiFormat.NV12:
            case DxgiFormat.P010:
            case DxgiFormat.P016:
            case DxgiFormat.Opaque_420:
            case DxgiFormat.B4G4R4A4_UNorm:
            case DxgiFormat.B5G5R5A1_UNorm:
            case DxgiFormat.B5G6R5_UNorm:
            case DxgiFormat.D16_UNorm:
            case DxgiFormat.G8R8_G8B8_UNorm:
            case DxgiFormat.R8G8_B8G8_UNorm:
            case DxgiFormat.R8G8_SInt:
            case DxgiFormat.R8G8_SNorm:
            case DxgiFormat.R8G8_Typeless:
            case DxgiFormat.R8G8_UInt:
            case DxgiFormat.R8G8_UNorm:
            case DxgiFormat.R16_Float:
            case DxgiFormat.R16_SInt:
            case DxgiFormat.R16_SNorm:
            case DxgiFormat.R16_Typeless:
            case DxgiFormat.R16_UInt:
            case DxgiFormat.R16_UNorm:
                return 16;

            case DxgiFormat.R8G8B8A8_SInt:
            case DxgiFormat.R8G8B8A8_SNorm:
            case DxgiFormat.R8G8B8A8_Typeless:
            case DxgiFormat.R8G8B8A8_UInt:
            case DxgiFormat.R8G8B8A8_UNorm:
            case DxgiFormat.R8G8B8A8_UNorm_SRGB:
            case DxgiFormat.B8G8R8A8_Typeless:
            case DxgiFormat.B8G8R8A8_UNorm:
            case DxgiFormat.B8G8R8A8_UNorm_SRGB:
            case DxgiFormat.B8G8R8X8_Typeless:
            case DxgiFormat.B8G8R8X8_UNorm:
            case DxgiFormat.B8G8R8X8_UNorm_SRGB:
            case DxgiFormat.R24_UNorm_X8_Typeless:
            case DxgiFormat.X24_Typeless_G8_UInt:
            case DxgiFormat.R24G8_Typeless:
            case DxgiFormat.D24_UNorm_S8_UInt:
            case DxgiFormat.D32_Float:
            case DxgiFormat.R9G9B9E5_SHAREDEXP:
            case DxgiFormat.R10G10B10A2_Typeless:
            case DxgiFormat.R10G10B10A2_UNorm:
            case DxgiFormat.R10G10B10A2_UInt:
            case DxgiFormat.R11G11B10_Float:
            case DxgiFormat.R16G16_Typeless:
            case DxgiFormat.R16G16_Float:
            case DxgiFormat.R16G16_SInt:
            case DxgiFormat.R16G16_UInt:
            case DxgiFormat.R16G16_SNorm:
            case DxgiFormat.R16G16_UNorm:
            case DxgiFormat.R32_Float:
            case DxgiFormat.R32_SInt:
            case DxgiFormat.R32_Typeless:
            case DxgiFormat.R32_UInt:
            case DxgiFormat.R10G10B10_XR_BIAS_A2_UNorm:
                return 32;

            case DxgiFormat.R16G16B16A16_Typeless:
            case DxgiFormat.R16G16B16A16_UNorm:
            case DxgiFormat.R16G16B16A16_UInt:
            case DxgiFormat.R16G16B16A16_SInt:
            case DxgiFormat.R16G16B16A16_Float:
            case DxgiFormat.R16G16B16A16_SNorm:
                return 48;

            case DxgiFormat.R32G32_Typeless:
            case DxgiFormat.R32G32_Float:
            case DxgiFormat.R32G32_SInt:
            case DxgiFormat.R32G32_UInt:
            case DxgiFormat.R32G8X24_Typeless:
            case DxgiFormat.D32_Float_S8X24_UInt:
            case DxgiFormat.R32_Float_X8X24_Typeless:
            case DxgiFormat.X32_Typeless_G8X24_UInt:
                return 64;

            case DxgiFormat.R32G32B32_Typeless:
            case DxgiFormat.R32G32B32_SInt:
            case DxgiFormat.R32G32B32_Float:
            case DxgiFormat.R32G32B32_UInt:
                return 96;

            case DxgiFormat.R32G32B32A32_Typeless:
            case DxgiFormat.R32G32B32A32_UInt:
            case DxgiFormat.R32G32B32A32_SInt:
            case DxgiFormat.R32G32B32A32_Float:
                return 128;

            case DxgiFormat.Unknown:
                return 0;

            default:
                throw new ArgumentException($"Can't get bpp for unknown format '{format}'", nameof(format));
        }
    }

...

@nickbabcock
Copy link
Owner

Yeah a lot of those properties are good, but all the properties that are DDS specific (isBC, isDX10, etc) should require users to cast to Dds

@Krakean
Copy link
Author

Krakean commented Mar 25, 2018

@nickbabcock whatever you choose. But, may be, you can just add something like IDDSImage? Which will contain dds-specific image info fields. Plus something like "imageType" to IImage to quickly understand what type of image (dds, tga) we working with

@Krakean
Copy link
Author

Krakean commented Mar 29, 2018

@nickbabcock
Hi Nick, sorry for bothering you, just curious, any progress on #21 or #22 ?

@nickbabcock
Copy link
Owner

It's no bother. I've been giving some other projects of mine some love over Pfim, at the moment. Hopefully you can progress further in your projects with the current state of Pfim, as being a one-man open source library, distractions happen. So I can't give estimates when things will be done, but do know that I have Pfim on my priority list 😄

@Krakean
Copy link
Author

Krakean commented Mar 30, 2018

@nickbabcock

Hopefully you can progress further in your projects with the current state of Pfim

Yes, currently I using mostly DXT3/5 textures, but would like to use HDR cubemaps in May which I would like to keep in BC6H format. :)

So I can't give estimates when things will be done, but do know that I have Pfim on my priority list 😄

Oh, okay, well, hope that you get back to Pfim as soon as possible :)

@Krakean
Copy link
Author

Krakean commented Apr 14, 2018

@nickbabcock no progress, yet? :-\

@nickbabcock
Copy link
Owner

Small progress, but bills are first 😅

@nickbabcock
Copy link
Owner

I was working on displaying R16G16 images and had a couple thoughts.

  • Currently there is no decoding of non-BC encoded DDS images in Pfim. This means that Data was a byte array of a pixel depth of 32 bits with 16 bits for red, 16 bits for green.
  • I do not know of a platform that natively displays these images (R16G16), so I started questioning the use of storing data in this format.
  • I don't want to explode the ImageFormat enum to include all the dds image types especially if Pfim comes to support more images formats. I'd prefer to have basic 8, 16, 24, 32, 64 bit depth formats + an "other" category
  • The "other" category would signify to the caller that additional information (eg. R16G16_UNORM) is exposed by casting to the correct image type and that some form of conversion is necessary. This conversion (ie. R16G16 to RGBA32) can be baked into Pfim. eg. image.NormalizeToPixelDepth() would do this conversion
  • I specifically mention R16G16 to RGBA32 as then data doesn't need to be resized, so one might hope for good performance.
  • I can imagine users finding the "other" + image.NormalizeToPixelDepth() not ergonomic enough and Pfim should just normalize without asking.
  • I can also see some of the "other" category formats being supported by a certain platform so the normalization is unwarranted.
  • I also feel like assuming that R16G16 should be converted to RGBA32 (which is a lossy conversion) may not be ideal for some and may prefer the loseless conversion to RGBA64, thus image.NormalizeToPixelDepth() should accept a parameter for the desired output format (or no format for the default fastest conversion).
  • Then I started thinking about the two extremes: no decoding (ie, so BC decoding can happen on GPU) and on the other side you have ImageSharp where you dictate of format you want. Pfim sits in the middle with decoding BC and run length encoded images but not the others.
  • Maybe there is a way for Pfim to cater to all use cases like (optionally) decode BC and (optionally) convert to a specific format or the one that has the same bit depth but is more widely supported.

I'm currently mulling over these thoughts and didn't know if you wanted to weigh in on any of my ramblings

@Krakean
Copy link
Author

Krakean commented Apr 20, 2018

I do not know of a platform that natively displays these images (R16G16), so I started questioning the use of storing data in this format.

Well, if neither Unity or UE4 can display these DDS, then dont spend time on it too I suppose :)

I'd prefer to have basic 8, 16, 24, 32, 64 bit depth formats + an "other" category

Seems fine enough to me

I can imagine users finding the "other" + image.NormalizeToPixelDepth() not ergonomic enough and Pfim should just normalize without asking.

What if you will add some kind of flag to control this behaviour, but defaulted it to 'true' (like, do automatic normalize by default)?
Or least have an ability to know that image need normalization.

thus image.NormalizeToPixelDepth() should accept a parameter for the desired output format (or no format for the default fastest conversion).

Agree.

no decoding (ie, so BC decoding can happen on GPU)

It would be good addition (as an option, I suppose) to have an ability to feed gpu with texture data asap.

and on the other side you have ImageSharp where you dictate of format you want

Well, in my case I decided to avoid ImageSharp because it doesn't support dds, plus it a bit fat for texture purposes in my opinion. If to speak in game context, Tga/Dds is more than fine enough for textures, and some png library can be added by user (not into pfim) as screenshot format for example. So in my case, Pfim will be just more than enough :)

Maybe there is a way for Pfim to cater to all use cases like (optionally) decode BC and (optionally) convert to a specific format or the one that has the same bit depth but is more widely supported.

Would be good to have such features.

I'm currently mulling over these thoughts and didn't know if you wanted to weigh in on any of my ramblings

Thanks for sharing!

Also, curious, but may be @feliwir might want to add his few cents, since he was interesting in loading dds without uncompressing it.

@feliwir
Copy link

feliwir commented Apr 20, 2018

Having access to the compressed picture data would be very useful indeed!

@nickbabcock
Copy link
Owner

Excellent, thanks for the feedback. I'm working on the ability to parse with a configuration object that will dictate if decompression and format conversion will take place.

eg:

public enum TargetFormat
{
    // ... snip
    Rgb24,
    Rgba32,
    Native,
    NearestNeighbor
}

Supplying Native won't perform any conversion and NearestNeighbor would only convert relatively esoteric formats like R16G16 to Rgba32.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants