How do I get the texture coordinates of an image clicked on?

So I have an Image component using the new UI.

And I have a Pointer Down event on it which calls a function. Now I need to get the exact color of the pixel that the user clicked on?

Is there a specific way of doing this for the new UI?

BTW it is for my colour picker:

1924330--124273--colorpicker.png

1 Like

No worries. I did it using

Texture2D tex = colorpad.sprite.texture;
       
        Rect r=colorpad.rectTransform.rect;
        Vector2 localPoint;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(colorpad.rectTransform,Input.mousePosition,Camera.main,out localPoint);
       
        int px = Mathf.Clamp (0,(int)(((localPoint.x-r.x)*tex.width)/r.width),tex.width);
        int py = Mathf.Clamp (0,(int)(((localPoint.y-r.y)*tex.height)/r.height),tex.height);
       
        Color32 col=tex.GetPixel (px,py);
5 Likes

Umm stupid question what is colorPad? I’m guessing just by the fact that you’ve used .sprite that it is a Image. I have a bad feeling about this as once the texture gets packed im thinking the .GetPixel won’t work. This is due to the atlas not being read/write enabled. For that one image you might want to consider using a RawImage

Nah, it seems to work fine. I just enabled read/write on the image.

I guess it doesn’t try to pack sprites that have read/write set. Anyway, you might want to use Texture2D.GetPixelBilinear() here (probably not much difference though except for simpler code). :slight_smile:

I talked with the dev who did the sprite packer and he informed me he didnt take into consideration the whole read/write thing. Its just a FYI if it works great, if it suddenly breaks you know why

Thanks. Well it seems to work for now. I always test it just to make sure! Not sure how it would break if I set the image to ARGB32 non-compressed. TBH I don’t really know what sprite packing means! It’s just an image component. Thanks for the warning!:slight_smile:

if the texture (sprite) gets a packing tag the sprite packing will pick that up and merge the textures together thus reducing draw calls as all textures are now in a atlas.

Sorry to bring this thread back up but I’m trying to use the code yoonitee posted above to get the colour from a texture. I’m getting really screwy numbers for the variable localPoint, it varies from (-200,-700) to (10,-500) the zero on the X axis shows up when my mouse is off the Unity window hovering on my desktop. I use Unityscript and my code is below, can anyone help? I’ve only started using the new UI system so maybe theres a toggle somewhere ri need to hit.

import UnityEngine.UI;

var tex : Texture2D;
var rectTransform : RectTransform;

function Update ()
{   
    var localPoint : Vector2;
    var r = rectTransform.rect;
   
    RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, Input.mousePosition, Camera.main, localPoint);
   
    var px : int = Mathf.Clamp (0,(((localPoint.x-r.x)*tex.width)/r.width),tex.width);
    var py : int = Mathf.Clamp (0,(((localPoint.y-r.y)*tex.height)/r.height),tex.height);
    var col : Color32 = tex.GetPixel (px,py);
    Debug.Log("local " + localPoint);
    Debug.Log(col);
}

The answer was to read the documentation properly, replacing Camera.main with null worked perfectly

It depends on what setting you have for the camera for your canvas.

I really am confused by the above code.
Mathf.Clamp(0, min, max) ? How does this work? Value should be passed right?

Clamp(0,a,b) = a if 0<a
= 0 if a<0<b
= b if a>b

1 Like

it will also return
= b if a<b<0 which shouldn’t happen ever since your talking about widths of images/textures

Just to explain Clamp. It basically makes sure a variable (in this case the static number 0) is between the min (a), and the maximum (b). You normally use it like this Math.Clampf(myVar, 0, 10) this will return my var if its between 0 and 10… or it will return 0, or 10 if myVar is too small or too big.

However in this case your giving it a number 0 and passing in to variables a,b. a = minimum number and b = maximum number. if a > b then the minimum is always bigger than than maximum so it will return that. Using Math.Clamp this way is just a fancy way of doing this:
Math.Max(0,Math.Max(a,b)); // get the max of a,b then make sure its bigger than 0
And I might humbly suggest this is more readable :slight_smile:

1 Like

At both the above explanations, thank you… that clears it up :slight_smile:
I have used Mathf.clamp(var, min, max) till now and hence was wondering how this is gonna work.

As far as i can see, Mathf.clamp(0, a, b) is same as Mathf.clamp(a, 0, b) ? right?

It works exactly the same except in the case where a > b.
Mathf.clamp (0,a,b) return a when a >b : This case says give me a number thats 0, except the min it can be is a, and the maximum b.

Mathf.clamp (a,0, b) returns b when a > b This says give me the number a, except the min it can be is 0, and maximum is b.

Had to set the third parameter to null:

RectTransformUtility.ScreenPointToLocalPointInRectangle(Image.rectTransform, Input.mousePosition, null, out localPoint);

This is why:

The cam parameter should be the camera associated with the screen point. For a RectTransform in a Canvas set to Screen Space - Overlay mode, the cam parameter should be null.

You are my hero, man!!! <3<3<3