Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

[SOLVED] Default image using WWW class.

Discussion in 'iOS and tvOS' started by corey.stpierre, Jan 6, 2009.

  1. corey.stpierre

    corey.stpierre

    Joined:
    Nov 18, 2008
    Posts:
    79
    Hello Unity community.
    I hope everyone had a great new year. I have a slight issue using the www class. Right now I am able to grab an image from a url (using the code from the docs) and I can set it to a texture perfectly fine. However my issue is that I want to change the default image that appears if the www object receives an error (for whatever reason). Right now the image is a red question mark on a white background. Has anyone figured out a way to change this default image? I really would like it to display a custom image that one of the artists has put together. Thanks a lot! I can't wait to show everyone the game we have been working on.

    ~Corey~
     
  2. HiggyB

    HiggyB

    Unity Product Evangelist

    Joined:
    Dec 8, 2006
    Posts:
    6,183
    Should be easy:

    1. Include error image in your project/build.
    2. Initiate WWW operation.
    3. When WWW completes check for success or failure, if success use WWW.texture, if not use default texture you included in your build.


    Are you attempting the above or something different?
     
  3. corey.stpierre

    corey.stpierre

    Joined:
    Nov 18, 2008
    Posts:
    79
    Thanks for the quick response. We are attempting to do the above as we speak. Will respond back when we have have success.

    ~Corey~
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,400
    Unfortunately that process doesn't really work--if you have a valid URL but it points to data that Unity can't use for a texture, it won't return an error, but gives you that question mark instead. The only solution I found was to check for an 8x8 texture (which is the size of the question mark). Of course, that's kind of hack-ish, and it also doesn't work very well if you actually want a valid 8x8 texture, but at least it's unlikely you'd be using textures that small.

    --Eric
     
  5. corey.stpierre

    corey.stpierre

    Joined:
    Nov 18, 2008
    Posts:
    79
    I was about to post some bad news until I read Eric5h5's post. I was running into the same issue that Eric5h5 explained above. Using Eric5h5's approach works great for me. I will use this for now until I have some more time to peer into it. Thanks to the both of you for all of your help.

    ~Corey~
     
  6. HiggyB

    HiggyB

    Unity Product Evangelist

    Joined:
    Dec 8, 2006
    Posts:
    6,183
    I'm not sure what sort of URL(s) folks are using but if you're accessing image files directly then you can preemptively check the URL and make sure it's a JPG or PNG file. It gets a bit tougher if you're calling some other file that returns image data (like a PHP script) though, in which case Eric's suggestion seems spot on.
     
  7. Yann

    Yann

    Joined:
    Oct 20, 2007
    Posts:
    432
    Eric, if you were a girl I would send you several 8 x 8 pixel images of a red heart !

    I'm presently working on a project that includes realtime video in, and your brilliant workaround has put a happy end to a long, long head-scratching session... :D
     
    mksindia likes this.
  8. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552

    Trying to understand that workaround Eric. Are you fetching an 8x8 from the same server as the larger desired texture, or are you digging it out of your local project?

    Existing code:
    Code (csharp):
    1.  
    2. var url = "http://images.earthcam.com/ec_metros/ourcams/fridays.jpg";
    3. var tempMaterial: Material;
    4. var isReady=false;
    5. function Start () {
    6.  
    7.     renderer.material.mainTexture = new Texture2D(4, 4, TextureFormat.RGB565, false);
    8.     tempMaterial.mainTexture = new Texture2D(4, 4, TextureFormat.RGB565, false);
    9.    
    10.     while(true) {
    11.        
    12.         // Start a download of the given URL
    13.         var www = new WWW(url);
    14.  
    15.         // wait until the download is done and then some
    16.         yield www;
    17.  
    18.           if([URL="http://www.error/"]www.error[/URL])
    19.     {
    20.           print([URL="http://www.error%29/;"]www.error);[/URL]
    21.           www  = null;
    22.     }
    23.     else if([URL="http://www.isdone/"]www.isDone[/URL])
    24.     {
    25.           renderer.material.mainTexture = [URL="http://www.texture/;"]www.texture;[/URL]
    26.           www  = null;
    27.     }  
    28.     else
    29.     {
    30.           Debug.Log("Couldnt load resource");
    31.           www  = null;
    32.     }
    33.    
    34.    
    35.  
    36.     }
    37. }
    Thanks for any advice.
    AaronC
     
  9. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,400
    I'm not getting an 8x8 texture from anywhere. The point is that if the texture is that size, then it failed.

    --Eric
     
  10. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552
    So your saying "If Texture is horrible little red question mark (8px by 8px) -then (put in a replacement texture or something)"?

    I'd love to just rip the guts out of unity and replace that with a more respectable plain black square or something. Anyone know where to look?

    Cheers
    Aaron
     
  11. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    I've checked the resources in the app bundle (on a Mac) and I can't find the question mark image as an image file. This implies either that I haven't looked hard enough or that the question mark is more deeply embedded in the app and therefore not replaceable. It would be worth starting a feature request for this (I don't think you want a bug report since it's an intentional, but often annoying feature rather than a mistake).
     
  12. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,400
    I'm saying that if you get an 8x8 texture, then the download failed. (Probably...there might be cases where you actually wanted to download a legit 8x8 texture, which is why this is a work-around and not a complete solution.)

    --Eric
     
  13. Deleted User

    Deleted User

    Guest

    Checking 8x8 worked for me - good call!
     
  14. Xtro

    Xtro

    Joined:
    Apr 17, 2013
    Posts:
    551
    I implemented my code according to this post. It worked fine on Unity Editor. When I tested it on mobile (Android, possibly iOS too) my application exploded!!

    It was very painful to track down the problem but the thing I found is very annoying.

    Unity WWW class returns a non-null 8x8 texture(red question mark) on Windows but it returns null on mobile. God damn null. I am not against null return values but how can Unity WWW class behave differently on mobile? The error text may be different on different platforms but WWW.texture can't shouldn't mustn't!
     
  15. Shredsauce

    Shredsauce

    Joined:
    Apr 4, 2016
    Posts:
    37
    Here's what I do. This checks if the image is 8x8. If it is an 8x8 image, it tests each pixel. It has the disadvantage of having to initialize a Color array each time you want to validate an 8x8 texture. And you have to loop through and test all 64 pixels of the question mark texture if it is the question mark. But it works. Returns false if the texture is null or that little red question mark, and true for anything else.

    Code (CSharp):
    1.     /// <summary>
    2.     /// Validate a Texture2D. returns false if it's that little red question mark
    3.     /// </summary>
    4.     /// <param name="tex">Texture to validate.</param>
    5.     public static bool Valid (this Texture2D tex) {
    6.         if (tex == null)
    7.             return false;
    8.        
    9.         // Valid if not 8x8 texture
    10.         if (tex.width != 8 || tex.height != 8) {
    11.             return true;
    12.         }
    13.  
    14.         Color[,] colors = new Color[8, 8] {
    15.             {Color.white, Color.white, Color.white, Color.white, Color.white, Color.white, Color.white, Color.white},
    16.             {Color.white, Color.white, Color.white, Color.white, Color.white, Color.red,   Color.red,   Color.white},
    17.             {Color.white, Color.white, Color.white, Color.white, Color.white, Color.red,   Color.red,   Color.red  },
    18.             {Color.red,   Color.red,   Color.white, Color.red,   Color.white, Color.white, Color.white, Color.red  },
    19.             {Color.red,   Color.red,   Color.white, Color.red,   Color.red,   Color.white, Color.white, Color.red  },
    20.             {Color.white, Color.white, Color.white, Color.white, Color.red,   Color.red,   Color.red,   Color.red  },
    21.             {Color.white, Color.white, Color.white, Color.white, Color.white, Color.red,   Color.red,   Color.white},
    22.             {Color.white, Color.white, Color.white, Color.white, Color.white, Color.white, Color.white, Color.white}
    23.         };
    24.  
    25.         // Compare textures
    26.         for (int y = 0; y < 8; y++) {
    27.             for (int x = 0; x < 8; x++) {
    28.                 if (colors[x, y] != tex.GetPixel(x, y)) {
    29.                     return true;
    30.                 }
    31.             }
    32.         }
    33.  
    34.         // Texture is the red question mark, not valid
    35.         return false;
    36.     }
     
    Dalton-Lima likes this.
  16. NTG-Sera

    NTG-Sera

    Joined:
    Sep 13, 2019
    Posts:
    7
    Code (CSharp):
    1. public static Texture2D CreateReadable( this Texture2D texture )
    2. {
    3.     Texture2D output = new Texture2D( texture.width, texture.height );
    4.  
    5.     RenderTexture _renderTemp = RenderTexture.GetTemporary( texture.width, texture.height, 0, RenderTextureFormat.ARGB32 );
    6.  
    7.     Graphics.Blit( texture, _renderTemp );
    8.  
    9.     RenderTexture _renderActive = RenderTexture.active;
    10.  
    11.     RenderTexture.active = _renderTemp;
    12.  
    13.     output.ReadPixels( new Rect( 0, 0, texture.width, texture.height ), 0, 0 );
    14.  
    15.     RenderTexture.active = _renderActive;
    16.  
    17.     RenderTexture.ReleaseTemporary( _renderTemp );
    18.     _renderTemp = null;
    19.  
    20.     output.Apply();
    21.  
    22.     return output;
    23. }
    24.  
    25. private static bool[] invalidImageMask = new bool[]
    26. {
    27.     false, false, false, true, true, false, false, false,
    28.     false, false, false, true, true, false, false, false,
    29.     false, false, false, false, false, false, false, false,
    30.     false, false, false, true, true, false, false, false,
    31.     false, false, false, false, true, true, false, false,
    32.     false, true, true, false, false, true, true, false,
    33.     false, true, true, false, false, true, true, false,
    34.     false, false, true, true, true, true, false, false
    35. };
    36.  
    37. public static bool ValidateLoadedTexture( ref Texture2D texture, bool readLockedImages = false )
    38. {
    39.     if( texture.width == 8 && texture.height == 8 )
    40.     {
    41.         Texture2D evaluateTexture = texture;
    42.  
    43.         if( !evaluateTexture.isReadable )
    44.         {
    45.             if( !readLockedImages )
    46.                 return false;
    47.  
    48.             evaluateTexture = evaluateTexture.CreateReadable();
    49.         }
    50.  
    51.         Color32[] pixels = evaluateTexture.GetPixels32();
    52.         for( int i = 0, iC = pixels.Length; i < iC; i++ )
    53.         {
    54.             Color32 pixel = pixels[ i ];
    55.             if( invalidImageMask[ i ] != ( ( pixel.r == 255 ) && ( pixel.g == 0 ) && ( pixel.b == 0 ) ) )
    56.                 return true;
    57.         }
    58.  
    59.         return false;
    60.     }
    61.  
    62.     return true;
    63. }
    Sorry to necro the post, here's a more efficient version of Shredsauce's evaluation.
    Additionally I've included support to optionally validate non-readwrite textures by blitting a new one.
     
    Shredsauce likes this.