Event Sourcing - complex aggregate design

I have following code specification sample that is modelling image inside Photoshop.

Image is given with PhotoshopImage. Every image has Layers which is an object that holds all layers that an image is made of and in my case it contains only two layers - first is solid layer (instance of DefaultLayer) and second one is transparent layer (instance of NotifiableLayer). Whenever DefaultLayer is updated, we have also to update NotifiableLayer that is listening to changes on DefaultLayer (that is below), so that it can update itself (like when you update some black pixel on layer below, then transparent layer with 50% opacity that is on top of that lower layer will show that pixel in gray color).

Implementation of this is given as:

public class ES2 {
    public static void main(String[] args) {
        PhotoshopImage image = new PhotoshopImage();

        //draw ine black pixel at position 1,1 in layer 1 (top transparent layer)
        DrawOneBlackPixelCommand command1 = new DrawOneBlackPixelCommand(1,1,new Coordinates(1,1));
        image.drawOneBlackPixel(command1);

        //draw one black pixel at position 0,0 in layer 0 (bottom solid layer)
        //this command will also affect transparent layer 1 via callback
        DrawOneBlackPixelCommand command2 = new DrawOneBlackPixelCommand(1,0,new Coordinates(0,0));
        image.drawOneBlackPixel(command2);

        int[][] imagePixels = image.getImagePixels();

        //[2, 0]
        //[0, 1]
        System.out.println(Arrays.toString(imagePixels[0]));
        System.out.println(Arrays.toString(imagePixels[1]));
    }
}

record DrawOneBlackPixelCommand(
    int imageId,
    int layerType,
    Coordinates pixelCoordinates
){}
record Coordinates(int x, int y){}

class PhotoshopImage{
    Integer imageId = 1;
    String imageName = "someName";
    LocalDateTime dateTime = LocalDateTime.now();
    Layers layers;

    PhotoshopImage(){
        layers = new Layers();
    }

    void drawOneBlackPixel(DrawOneBlackPixelCommand command){
        if(LocalDateTime.now().isBefore(dateTime)){
            throw new DrawingPixelTimeExpiredException();
        }
        layers.drawOneBlackPixel(command.layerType(), command.pixelCoordinates());
    }

    int[][] getImagePixels(){
        return layers.getVisibleLayerPixels();
    }

    class DrawingPixelTimeExpiredException extends RuntimeException{}
}

class Layers{
    Set<NotifiableLayer> notifiableLayerObservers = new HashSet<>();
    NavigableMap<Integer, Layer> layers = new TreeMap<>();

    Layers(){
        DefaultLayer solid = new DefaultLayer();
        NotifiableLayer transparent = new NotifiableLayer();
        layers.put(0, solid);
        layers.put(1, transparent);
        notifiableLayerObservers.add(transparent);
    }

    void drawOneBlackPixel(int layerType, Coordinates pixelCoordinates){
        if(!layers.containsKey(layerType)){
            throw new LayerDoesNotExistException();
        }
        Layer change = layers.get(layerType);
        change.drawOneBlackPixel(pixelCoordinates);
        notifiableLayerObservers.forEach(l -> l.notifyLayer(change, pixelCoordinates));
    }

    public int[][] getVisibleLayerPixels() {
        return layers.lastEntry().getValue().getLayerPixels();
    }

    class LayerDoesNotExistException extends RuntimeException{}
}

interface Layer{
    void drawOneBlackPixel(Coordinates coordinates);
    int[][] getLayerPixels();
}

class DefaultLayer implements Layer{
    int[][] pixels = new int[][]{{0,0},{0,0}};

    @Override
    public void drawOneBlackPixel(Coordinates c) {
        pixels[c.x()][c.y()] = 1;
    }

    @Override
    public int[][] getLayerPixels() {
        return pixels;
    }
}

class NotifiableLayer implements Layer{
    int[][] pixels = new int[][]{{0,0},{0,0}};

    void notifyLayer(Layer changed, Coordinates c){
        //if it is not this layer, then it is layer below (solid layer)
        if(changed!=this){
            int pixelInLayerBelow = changed.getLayerPixels()[c.x()][c.y()];
            syncPixelWithLayerBelow(pixelInLayerBelow, c);
        }
    }

    private void syncPixelWithLayerBelow(int pixelBelow, Coordinates c){
        pixels[c.x()][c.y()] = pixelBelow + 1;
    }

    @Override
    public void drawOneBlackPixel(Coordinates c) {
        pixels[c.x()][c.y()] = 1;
    }

    @Override
    public int[][] getLayerPixels() {
        return pixels;
    }
}

Now, this is implemented as mutable state objects (that is - it is not using event sourcing). Whatever manual about event sourcing that I read, it is based only on some super-simple examples.

In my case - I do not know how to create events OneBlackPixelDrawnEvent - that should be result of these 2 operations in the code, and how to apply those events - should it be applied in PhotoshopImage, or should each layer be in charge of updating part of its state? How to forward those events from PhotoshopImage aggregate to Layers and further down?