11
$\begingroup$

This post is related to this post, But somewhat different. Since Wizard focus on alpha channel, and didn't got an answer. So I made this post.

My system is Windows 10, and Mathematica 11.2

If I run

plot = Image[RandomReal[1., {6, 6}]]

I got

enter image description here

Then I texture this image on a square like this

Graphics[{Texture[plot], EdgeForm[],
  Append[Polygon @@ RegionBoundary[Rectangle[]], 
   VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]}]

I got

enter image description here

You can see it is already blurred

What is worse, if we generate a color image

plot = Image[RandomReal[1., {6, 6, 3}]]

enter image description here

and texture it.

Graphics[{Texture[plot], EdgeForm[],
  Append[Polygon @@ RegionBoundary[Rectangle[]], 
   VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]}]

I got

enter image description here

Which is a total mess.

The difference between my result and Wizard's result is that, even I don't set alpha channel, I already screw up the color image texture.

So why Texture always blur image? I check the doc, it seems that this blurring feature is not mentioned. Is it possible to make Texture clear especially for color image generated by Image?


update

Thanks to J.M. and kglr. They both suggest that it is a problem of low-res of image. But I have a counter example, which suggest that there is some subtle effect. Take a look at this, using ArrayPlot

plot = ArrayPlot[RandomReal[1., {6, 6}], ColorFunction -> "Rainbow", 
  Frame -> None]

enter image description here

then texture it with the same method,

Graphics[{Texture[plot], EdgeForm[],
  Append[Polygon @@ RegionBoundary[Rectangle[]], 
   VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]}]

you will got

enter image description here

You will notice there is still some blur, but much weaker. And the color is much much better than Image texture, but seems not as vivid as original plot.

If you test ImageDimensions@plot. Both ArrayPlot and Image generate 6x6 image. So at least, this example shows low-res may not be a real reason for poor texture of Image

$\endgroup$
  • $\begingroup$ try plot = Image[RandomReal[1., {6, 6}], ImageSize -> 500]? $\endgroup$ – kglr Mar 14 '18 at 2:54
  • 1
    $\begingroup$ This seems to be a problem when your images are low-res. At least for this simple case, try plotNew = ImageResize[plot, Scaled[50], Resampling -> "Nearest"]; Graphics[{Texture[plotNew], EdgeForm[], Polygon[{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]}] $\endgroup$ – J. M. will be back soon Mar 14 '18 at 2:54
  • 1
    $\begingroup$ Rasterize[plot ,RasterSize ->500, ImageResolution -> 300 ] also works in both v9 an v11. $\endgroup$ – kglr Mar 14 '18 at 3:12
  • 1
    $\begingroup$ Point 7 under "More Details" of the docs for Texture[]: "Texture[obj] is equivalent to Texture[Rasterize[obj]] and will rasterize obj at the size and resolution it would normally be displayed in a notebook." With that, try plot = Rasterize[ArrayPlot[RandomReal[1., {6, 6}], ColorFunction -> "Rainbow", Frame -> None]]; ImageDimensions[plot]. $\endgroup$ – J. M. will be back soon Mar 14 '18 at 4:48
  • 3
    $\begingroup$ The problem is one of texture filtering (scroll down to the "Texture Filtering" section on that page). Most graphics APIs allow one to choose between nearest neighbour (which is what you want) and bilinear filtering (which is what Mathematica does), but it seems Mathematica doesn't give you that choice. So you'll have to work around it, either by creating a high-resolution texture, or by creating lots of little squares and colouring them individually. $\endgroup$ – Rahul Mar 14 '18 at 6:35
7
$\begingroup$

Rahul is correct in his comment. To map a texture to an object, you use VertexTextureCoordinates to specify where the texture is glued to the object. The problem is, that those few points are not enough because you need a color for every single position inside your polygon.

When you know the coordinates of your polygon that are mapped to the texture corners, you can map each point inside the polygon to point of the texture. These calculated points will almost never lie on a perfect pixel and you will not have exactly as many points as you have image pixels.

The question is, how do you calculate the color at pixel position (2.34, 4.003)? You interpolate the pixels of your texture. As Rahul pointed out, bilinear interpolation is used. When we know this, we can recreate the artifact ourselves. Just take your image and create a larger one with linear resampling:

plot = Image[RandomReal[1., {6, 6, 3}]];
ImageResize[plot, 128, Resampling -> "Linear"]

Mathematica graphics

Since it seems we cannot set (I haven't looked carefully!) the interpolation aka "Texture Filtering" in Mathematica, one choice is to create a larger image by resampling linearly yourself and use a larger texture image:

plot = Image[RandomReal[1., {6, 6, 3}]];
tex = ImageResize[plot, 256, Resampling -> "Constant"];

Graphics[{Texture[tex], EdgeForm[], 
  Polygon[{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, 
   VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]
  }]

Mathematica graphics

This is not perfect, but way better.

$\endgroup$
  • $\begingroup$ Thank you so much, halirutan. Very clear : ) $\endgroup$ – matheorem Mar 14 '18 at 13:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.