Combining Several Images into a Single Image

I have created a program which combines several textures into a single texture.

The first part of the program loads each of the image files (256X256) and gets their imageData by drawing them into a HTML canvas (also 256X256), and extracting the imageData.

The second part creates an image that is a 3X3 (768X768) grid. It does this by takes the inageData extracted above and saving it to one of 9 locations on a larger HTML canvas (768X768). The program then extracts the imageData for the combined image (768X768) and uses that imageData in THREE.DataTexture to create a new image. (I have another version that outputs a 512X512 grid, which is done by initially loading the textures into a smaller canvas (171X171).)

Here is a program (regular and module version) which shows the results. The entire code is posted on jsfiddle (but for some reason does not work there).

I was having a problem getting the larger program to work. I was not sure if this had something to do with the various canvas operations. However, it now appears that the cause of the problem was that some textures were taking too long to load. I solved that by using a custom loading manager that allows initialization to proceed only after the files were loaded.

Because this issue has been resolved and had a fairly simple solution, I have deleted the extensive discussion regarding this issue.

Here are possible reasons for the code not working:

The JSFiddle console logs one error:

which comes, as it seems, from line 61 of your code:

Your JSFiddle also marks two lines of code with warnings (hover over yellow dots to see more:

I’d like to see your code working on JSFiddle, that’s why I’m pointing this out to you.

1 Like

Yes, line 61 was the problem.
I had initially displayed the results using objects, but later realized that I could do so with the meshes alone. But, when making the change, I forgot to remove the references to the old objects.
Here is the working fiddle.

Since writing this fiddle, I have tried some interesting variations, including one that uses the original 512x512 images to create both the large and small images. If that would be of interest, I can post that code to JSFiddle as well.

Here is my program that uses this technique.

The ground consists of two nested sets of squares (27X27). The nearer squares are 2k meters textured with a random mix of 7 random textures. The larger and more distant squares are 3X as large. To make a seamless transition between the two, I needed to match the pattern of the smaller squares in the larger squares. I wanted to avoid using 9 different faces in those larger squares with 9 different textures since that would presumably not be any faster than having 9 separate squares. The alternative was to do what I have done here and create a single texture for each large square. This is done once at the beginning, so there no hit to frame rate - which is 60 fps.

As modified, the program now uses only 1 canvas and 1 set of 7 515X512 textures.

1 Like

Thanks for sharing this :+1: :clap: :beer:

I’m surprised, how many random variations can be produced with just 9 individual textures. It’s virtually impossible to recognise any repeating pattern in your artificial earth surface. Very well done and my sincere congrats!

On a technical note:
this kind of texturing works well on

  • Firefox 98.0.2 (64bit)
  • Opera 65.0
  • Chrome 100.0.4896.60

It does not work on

  • Safari 13.1.3, where it looks like this:

This is the top snippet from the Safari JavaScript console (the last three lines keep repeating):

1 Like

Actually, it’s only 7 textures and I did a little tweaking of the random index generator to specify that adjacent squares could not have the same textures.

Your results on Safari are a bit odd since I tested it on my i-phone 13, which uses Safari, and it worked fine. I have even made the buttons smaller so that they don’t take up so much of the screen. What kind of device was your Safari on?

Regarding the errors: yes, I was getting that “stats is not a function” notification for a little while too. I am not sure what is happening since I have used the same method for other programs and did not get an error message. It does not appear to affect the program and goes away after awhile.

The last two error messages appear to relate to my use of mip-maps. The textures are a power of two (512), which is required for mip-maps. The use of mip-maps is not required for the program. The first working version that I posted did not have mip-maps and some of the farmland was was creating “moire” patterns because on the parallel lines on some of the farmland. The switch to mip-maps solved that problem. To enable mip-maps, I used the same approach as on this JSFiddle.

Thanks for testing this out! My goal is to create a (free) package of subroutines that can be used by programmers who want to create a basic flight simulation.

Yes, I can confirm that it runs well on an iPhone13 Pro Max and iOS 15.3.
The observed failure was/is on an iMac 5K and macOS Catalina (10.15.7)


I will double-check my stats commands to see if I have left something out. At worst, this can be removed because or disabled because it is not essential to the program. (I also have a flag in the program which I can change to turn it off.)

I will put some console.logs in my program to confirm that the textures are, indeed, 512X512. And I will check to see if there have been updates regarding implementation of mip-maps when using DataTexture. Odd that only one type of machine should have problems. It seems that Macs have problems with graphics programs. Perhaps their graphics card is not that great. Speaking of which, I should also try running it on my old MS Surface, which often has problems with graphics.

And I will post the latest version of my graphics “combiner” to JSFiddle.

The next step in the evolution of this gridmap will be to see what happens when I load a simple aircraft model since my current version will probably force the program to wait until all of the textures and models are loaded. That is not necessarily bad, but I want to make sure that there are no problems.

Once models are loadable, I can show how to add hills and high-resolution airfields to the environment by using objects - such as you might design in Blender. (I would also like to add a transparent layer of high cirrus clouds - but I am no artist and have had a hard time finding a good transparent texture I can use. Perhaps, I need to step outside sometime and take a picture of the sky above my house.)


  1. Stats appears to be fixed. The program doesn’t allow things to run until initialization is complete. The stats update was outside that loop. I moved it inside the loop and it seems to be working fine.
  2. JSFiddle example using latest code. This uses a single canvas and a single data source. It creates the small images, saves their imageData and later uses the imageData to combine them into a large 9X9 image. This version includes the 3 mipmap instructions and works fine. No errors.

The final version seems to be working fine. Here are a couple of demos:

  1. Here is the textured grid with a few improvements, such as cloud cover and a mountain.
  2. Here is the same setup with a small model aircraft. Still at 60 fps.