Trying to load an image that's a server side redirect.

I’m trying to load an image with the following url…

https://graph.facebook.com/1/picture

…the above url does a server side redirect which provides the following image link…

http://static.ak.fbcdn.net/rsrc.php/zo/r/UlIqmHJn-SK.gif

when I use the following code to for the actual image it works fine, however I only know what the server side redirect url is… is there a way for Unity to understand that it’s being redirected to another url?

WWW www = new WWW("http://static.ak.fbcdn.net/rsrc.php/zo/r/UlIqmHJn-SK.gif"); // what works
WWW www = new WWW("https://graph.facebook.com/1/picture"); // <- this is what I need to work

Merry Christmas :slight_smile:

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

public class prefetching : MonoBehaviour {

    WWW w;
    string _data = String.Empty;
    string err = String.Empty;

	void Start () {
        StartCoroutine(loadInfo());
	}
	
    IEnumerator loadInfo()
    {
        try
        {
            w = new WWW("https://graph.facebook.com/1/picture");
        }
        catch (Exception ex)
        {
            err += ex.ToString() + "\n";
        }
        yield return w;
        foreach (KeyValuePair<string,string> i in w.responseHeaders)
        {
            _data += "Key : " + i.Key + "   Value: " + i.Value + "\n";
        }
        _data += "Size : " + w.size.ToString() + "\n";
        _data += "Data : " + w.data.ToString() + "\n";
        byte[] b = w.bytes;
        _data += "Byte info: " + b.ToString() + "\n";
     
        Debug.Log(_data);
    }
}

Now it is really simple, and I will leave it up to you to figure this part out, simply get the “location” value from the key pair and use it for a new fetch :slight_smile:

I’ve been tinkering with the code you provided. I’m not getting past the yield return w; The images I’m getting are from Facebook and I also checked on the WWW class and saw the following…

Note: The security sandbox present in web-player builds prevents you from accessing content not hosted the server where the webplayer is hosted.

Is there a way to get Facebook friend images into Unity at all?

Doing some testing with deployed package now, the sandbox doesn’t seem to be a problem for me, but I do get different results from the key, I have an idea, not sure if I can do what I am thinking yet, but if I can, I will post the package for you to try or at the very least, the code.

Ok, one snag:
Texture2D.LoadImage.html

That will only handle JPG and PNG files, the file you are trying to grab is a GIF, trying to find a way to load in a GIF by byte array at the moment, time for lunch.

Edit: 12/17/2010 13:07pm :slight_smile:
Since Unity texture loader is looking for the PNG or JPG and then we are talking about grabbing avatars from Facebook (or any other system for that matter), the thought crossed my mind, on the server you are hosting your game, why not create a form that you can use to translate other image times to PNG or JPG? So thinking this through, Unity in its little sandbox can in fact send POST and GET type commands, ok, so where do we sit? We have a URL that will actually return the BYTEs of our image, the header of that is our image type with the contents containing the image data. Well, in theory we should be able to accomplish the following, create either a php script or asp script or even asp.net script (slowest of the bunch) that has a web form that you can post to, giving it the URL that we know we want (not the final URL), then that script goes out and retrieves the byte array of the image, so far so good, now that byte array then is converted via your code on that web form from a GIF to JPG or PNG, this results in another set of bytes that is valid for Unity to understand.

With me so far? Good… Now, on that final round type, we give Unity the converted image bytes OR to streamline this even more, create a MySQL database and a table in it that holds the images, first, you have a query that looks to see if the requested URL already exists on the table, if it does, then return the image to Unity, if it does not, go out, get the image, convert the image, store the JPG or PNG in your database and return that to Unity, so you are prefetching and caching the image to avoid the trip to Facebook… Still working out the issues since to do this mechanically, you need to use System.Drawing.DLL and no DLL’s can be pushed out within Unity’s sandbox, so you have to dance a little dance.

I haven’t tested this completely, but I believe any valid Facebook profile image is returned as a JPG. You’re using the ID of 1, which does not exist so it’s returning a default GIF.

Try this link, you’ll see what I mean.

http://graph.facebook.com/100001340211556/picture

Loading images should work just fine. Just be sure you’re testing with valid Facebook IDs.

Thanks, that makes sense, I was wondering why they used GIF format, let me play with that new link you just gave.

Also, only the supported formats work for Unity, so GIF / BMP and other non-supported formats will not work with this code.

Edit: sweet my code works locally, let me publish it out and test.
Although I just threw the image onto a cube, it is upside down, but this uses the code in this thread:
(NOTE: I was playing with bytes to gank the header and convert from GIF to PNG, so that code is useless here)
http://jbwgames.com/unity/prefetch/webplayer.html

using UnityEngine;
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;

public class prefetching : MonoBehaviour
{
    WWW w;
    string _data = String.Empty;
    string err = String.Empty;
    Texture2D tex;
    public GameObject obj;
    void Start()
    {
        tex = new Texture2D(50, 50);
        StartCoroutine(loadInfo());
    }

    void OnGUI()
    {
        GUI.TextArea(new Rect(0, 10, 400, 400), _data);
        GUI.TextArea(new Rect(410, 10, 500, 400), err);
    }

    IEnumerator loadInfo()
    {
        try
        {
            w = new WWW("http://graph.facebook.com/100001340211556/picture");
        }
        catch (Exception ex)
        {
            err += ex.ToString() + "\n";
        }
        yield return w;
        foreach (KeyValuePair<string, string> i in w.responseHeaders)
        {
            _data += "Key : " + i.Key + "   Value: " + i.Value + "\n";
        }
        _data += "Size : " + w.size.ToString() + "\n";
        _data += "Data : " + w.data.ToString() + "\n";

        //int byteheader = 0;
        //byte[] b = w.bytes;
        //byte[] c = new byte[b.Length - byteheader];
        //int k = 0;
        //for (int i = byteheader; i < b.Length; i++)
        //{
        //    c[k] = b[i];
        //    k++;
        //}
        //_data += "Byte info: " + b.Length.ToString() + "\n";
        //_data += "\n" + c.Length.ToString();
        tex.LoadImage(w.bytes);
        //byte[] enc = tex.EncodeToPNG();
        //tex.LoadImage(enc);
        obj.renderer.material.mainTexture = tex;
    }
}

I should clarify that ID 1 does actually exist, it’s just private to us. If you don’t have permission to see a user’s picture or they haven’t uploaded a picture, that GIF image will be returned.

You could save a JPG version of it in your Unity project and if you ever come across that GIF, use your JPG instead.

If the ID doesn’t exist then you’ll get a JSON response like this:

{
“error”: {
“type”: “OAuthException”,
“message”: “(#803) Some of the aliases you requested do not exist: 666666666666666666666666666”
}
}

Not sure that it matters for the purpose of the OP since the pull is based on an image that can’t be converted and that is all that Unity is aware of, it doesn’t get the JSON response, not from what I am seeing, it simply gets the default image (gif), however, that said, it still can be handled in the same way you are describing, if the image is of an unknown format (not jpg / png) then throw in the default canvas man image. A simple code block to handle that would be as follows: (although you probably want to do it with checking valid jpg or png not invalid) Edit: switched out for looking for only valid image types

using UnityEngine;
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;

public class prefetching : MonoBehaviour
{
    WWW w;
    string _data = String.Empty;
    string err = String.Empty;
    Texture2D tex;
    public GameObject obj;
    bool isValid = false;
    void Start()
    {
        tex = new Texture2D(50, 50);
        StartCoroutine(loadInfo());
    }

    void OnGUI()
    {
        GUI.TextArea(new Rect(0, 10, 400, 400), _data);
        GUI.TextArea(new Rect(410, 10, 500, 400), err);
    }

    IEnumerator loadInfo()
    {
        try
        {
            // Example of a Valid item
            w = new WWW("http://graph.facebook.com/100001340211556/picture");
            // Example of an Invalid item
            //w = new WWW("http://graph.facebook.com/1/picture");
        }
        catch (Exception ex)
        {
            err += ex.ToString() + "\n";
        }
        yield return w;
        foreach (KeyValuePair<string, string> i in w.responseHeaders)
        {
            if (i.Key.Trim() == "CONTENT-TYPE"  (i.Value.Trim() == "image/png" | i.Value.Trim() == "image/jpeg"))
            {
                _data += "Key: " + i.Key + "   Value: " + i.Value + "\n";
                isValid = true;
                break;
            }
            else
            {
                // invalid, we need a jpg or png
                _data += "Key: " + i.Key + "   Value: " + i.Value + "\n";
                isValid = false;
            }            
        }
        _data += "\nValid Image: " + isValid.ToString();
        if (isValid)
        {
            tex.LoadImage(w.bytes);
            obj.renderer.material.mainTexture = tex;
        }
        else
        {
            // load some good default JPG
        }
    }
}