Determine if a texture2D has alpha

Hello community

Unfortunately, now texture2D hasn’t any properties how get internal data buffer or just property like texture2D.HasAlpha(). I have only one solution: get ImageSource’s path and load image to Buffer second time and check alpha byte to byte, but its pain.

Regards

Won’t the Texture2D.Format property tell you what you need to know? Or am I misunderstanding your question? https://www.fusetools.com/docs/uno/graphics/texture2d/format

The problem is Texture2D.Format return Unknown for JPG source and RGBA8888 for PNG even if it hasn’t alpha channel

I wrote very simple method for checking images with alpha. But this is not right way to get of this. By the way, if png hasn’t alpha texture2D.Format return Unknown as well

bool HasAlpha(FileSource file) {
  // check only png files
  if (String.Compare(Uno.IO.Path.GetExtension(file.Name), ".png") == 0) {
      byte[] data = file.ReadAllBytes();
      if (data != null) {
          byte[] pngSign = new byte[]{ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };

          for (int i = 0; i < pngSign.Length; ++i) {
              if (pngSign[i] != data[i]) {
                  return false; // invalid file format
              }
          }

          byte colorType = data[25];
          if (colorType == 0x4 || colorType == 0x6) {
              return true;
          }
      }
  }

  return false;
}

Ah, I did indeed misunderstand your post. :slight_smile:

The problem is Texture2D.Format return Unknown for JPG source and RGBA8888 for PNG even if it hasn’t alpha channel

This is actually expected behavior for PNG. We convert all images to have an alpha channel as a texture.

I don’t know what your app does or how this alpha channel check fits into it, but if I was looking to do something like this (and most likely, I wouldn’t, because between you and me I’m not even a developer :), I’d do it as a pre-processing step on the files themselves before they enter texture memory, especially if you have many of them or expect unknown/external files to enter the pipeline.

As for the alpha channel issue with PNGs, it’s entirely possible for a PNG to have an alpha channel but still have opaque pixes, so if you’re looking to programmatically check if an image has “see-through parts”, that’s actually a much harder task than just checking for the existence of an alpha channel.

Does it mean that you use GL_BGRA for format and GL_UNSIGNED_INT_8_8_8_8_REV for internal format type? It’s the best practice for minimize upload time from host memory to gpu, and in this reason it makes sense, but GL_UNSIGNED_INT_8_8_8_8_REV use for perfect alignment in gpu memory and not always contain real alpha data, so while you decode png file it will be perfect to determine and set some boolean value for alpha channel before upload to gpu.

In my app I need some preprocessing with image alpha, but I cant’t access to pixels data or decoded buffer in host memory. For expamle Unity has GetPixels method for that: https://docs.unity3d.com/ScriptReference/Texture2D.GetPixels.html

The TextureLoader in Fuse decides what format is the most appropriate when it loads the JPG/PNG. Could you explain your use case in some more detail? Since you want the Unity equivalent of GetPixels, does that mean you can’t do the processing you mention in a shader? Maybe you should load the images to a bitmap and then upload as a texture.

Vegard Strand Lende wrote:

The TextureLoader in Fuse decides what format is the most appropriate when it loads the JPG/PNG. Could you explain your use case in some more detail? Since you want the Unity equivalent of GetPixels, does that mean you can’t do the processing you mention in a shader? Maybe you should load the images to a bitmap and then upload as a texture.

FuseJS/ImageTools has getBufferFromImage(image) for js but not for Uno, however for every js-method Uno’s has some equivalent:

FuseJS/ImageTools:

- crop(image, options);
- getImageFromBase64(base64);
- resize(image, options);

Uno:

- Crop(Image, int, int, int, int, bool);
- ImageFromBase64(string) : Future<Image>;
- Resize(Image, int, int, ResizeMode, bool) : Future<Image>;

I would like to be equvalent Uno’s API for getBufferFromImage(image). For what? well, for example: reading alpha channel for trimming images, for compute signed distance field, for compute dominant color from rgb-channels and make adaptive backgrounds (http://briangonzalez.github.io/jquery.adaptive-backgrounds.js), and there are many, many other cases when it is useful

PS This Bitmap class looks very promising but how work with it?

You can get the image as a buffer by doing something like this new Uno.Buffer(Uno.IO.File.ReadAllBytes(image.Path));. But then you would need to put that through an image loader to get to the bitmap data. I think I would go down the Foreign code route to get this how I wanted it and not rely on what is in the Uno api.