mojira.dev
MC-159269

NativeImage#copyImageData not copying correctly

After doing some testing I can confirm this is a bug in Vanilla minecraft.

When using NativeImage.copyImageData() it will not copy correctly if the target image is larger than the original.

For example, this code right here:

private static void testNativeImg() {
        //Generate two instances of NativeImage, one larger than the other
        final NativeImage imgOld = new NativeImage(64, 64, true);
        final NativeImage imgNew = new NativeImage(128, 128, true);
                        
        //Filling imgOld with red        
        imgOld.fillAreaRGBA(0, 0, 64, 64, 255 | -16777216);
        
        //Filling imgNew with blue
        imgNew.fillAreaRGBA(0, 0, 128, 128, 16711680 | -16777216);
        
        //Copying imgOld to imgNew. This should make a 64x64 square of pixels on imgNew
        imgNew.copyImageData(imgOld);        
          
        //Lets write the result the file system
        try {
            imgOld.write(new File("img" + System.currentTimeMillis() / 1000 + ".png"));
            imgNew.write(new File("imgNew" + System.currentTimeMillis() / 1000 + ".png"));
        } catch (IOException e) { 
            e.printStackTrace();
        }
        
        //Close imgOld and imgNew
        imgOld.close();
        imgNew.close();
    }

Using Mojang mappings

import java.io.File;
import java.io.IOException;

import com.mojang.blaze3d.platform.NativeImage;

public class NativeImageTest {
    public static void main(String[] args) throws IOException {
        try (
            NativeImage imgOld = new NativeImage(64, 64, true);
            NativeImage imgNew = new NativeImage(128, 128, true);
        ) {
            //Filling imgOld with red        
            imgOld.fillRect(0, 0, 64, 64, 255 | -16777216);
            
            //Filling imgNew with blue
            imgNew.fillRect(0, 0, 128, 128, 16711680 | -16777216);
            
            //Copying imgOld to imgNew. This should make a 64x64 square of pixels on imgNew
            imgNew.copyFrom(imgOld);        
              
            //Lets write the result the file system
            imgOld.writeToFile(new File("img" + System.currentTimeMillis() / 1000 + ".png"));
            imgNew.writeToFile(new File("imgNew" + System.currentTimeMillis() / 1000 + ".png"));
        }
    }
}

Will create the 2 images below

Cause

The bytes value passed to MemoryUtil.memCopy is Math.min(this.getWidth(), nativeImage.getWidth()). The multiplication with format.components() is missing.

Linked issues

Attachments

Comments 3

Can you provide context where this is being used within the game? (I'm assuming screenshots)

I noticed this issue when using an unofficial modding api to create mods. However, as confirmed by the Unofficial API they do not edit any local code in this method. Therefore, it's an issue in the core code of Minecraft. Even though it might not affect current gameplay.

Can confirm in 1.19.3 and 23w04a

James Harrison

(Unassigned)

Confirmed

(Unassigned)

1.14.4, 1.15 Pre-release 6, 1.19.3, 23w04a, 1.19.4 Pre-release 1

Retrieved