# Trying to get multiple images out of a single image

Discussion in 'Spigot Plugin Development' started by jusjus112, Oct 5, 2019.

1. ### jusjus112

I've been stuck at something recently. What I want to do is to get multiple sub-images out of 1 big image.

So take this example. I have a frame of 128x128 pixels where all the images need to be in. I'm putting all the bufferedImages inside a list and scaling all those images to 128x128.

The image you see on that link is showing that I need 4 sub-images from that image, so at the end, I have 4 images which are 128x128 but 4 times. Or if you have an image with 128x384 it will give 3 sub-images going from top to bottom.

I know there is a function called

Code (Java):
BufferedImage.getSubimage(int x, int y, int w, int h);
But the problem is that I can't figure out what math I need to implement. What I tried is if the height or width is higher than 200 then divide it by 2 but that never worked for me.

A popular plugin had this method for that, which I thought to be pretty neat. (Might need some work, this was coded back in the days with 1.12, but the calculations should still apply.)

3. ### patri9ck

Here is a part of the documentation.
• x - the X coordinate of the upper-left corner of the specified rectangular region
• y - the Y coordinate of the upper-left corner of the specified rectangular region
• w - the width of the specified rectangular region
• h - the height of the specified rectangular region
With that knowledge, it is actually quite easy. Here is how you can get the bottom-right part.
Code (Java):
BufferedImage bufferedImage = /* Your image... */

int width = bufferedImage.getWidth() / 2;
int height = bufferedImage.getHeight() / 2;
You have to divide the height and width by 2 since every image is going to have half the width and half the height of the original image. Your are going to need these values as you can see in the documentation.

Now you have to get the X and Y coordinates of the upper-left corner. In this case it is the center of the original picture. And you can calculate the X and Y coordinates of the center in a rectangle like this:

X = width / 2;
Y = height / 2;

That means you can get your image that way:
Code (Java):
BufferedImage bottomRightPart = bufferedImage.getSubImage(width, height, width, height);
The only difference between getting the different parts of the image is calculating the upper-left corner. I hope this helps to get an idea.

#3
Last edited: Oct 5, 2019
4. ### jusjus112

Alright first of all thanks for helping me the correct way.
Currently, I'm able to extract multiple images out of 1 image. So if you have a dimension of 256x256 it will give you 4 images which is correct.
But right now I got another problem which I don't know if it is a bug or a wrong usage of the function getSubImage.

This is my the function I wrote:

Code (Java):
private void cut(@Nonnull final BufferedImage image) {
final int originalWidth = image.getWidth();
final int originalHeight = image.getHeight();

int rows = (int) Math.ceil(originalWidth / WIDTH);
int lines = (int) Math.ceil(originalHeight / HEIGHT);

int x = (int) Math.ceil(originalWidth/rows);
int y = (int) Math.ceil(originalHeight/lines);
int xCount = 0, yCount = 0;

for(int i = 0;i<lines;i++){
if (originalHeight > yCount){
for(int line=0;line<rows;line++){
if (xCount > originalWidth){
break;
}
BufferedImage subImage = image.getSubimage(xCount, yCount, x, y);
xCount += x;
}
}
xCount = 0;
yCount += y;
}
}
Together with this function how I built the image:

Code (Java):
@SuppressWarnings("deprecation")
public List<ItemStack> build() {
List<ItemStack> items = new ArrayList<>();

for(BufferedImage img : this.images) {
MapView map = Bukkit.createMap(Bukkit.getWorlds().get(0));
ItemStack item = new ItemStack(isOnePointFourteen ? Material.MAP : Material.valueOf("MAP"));

map.setScale(MapView.Scale.FAR);
map.getRenderers().forEach(map::removeRenderer);
@Override
public void render(MapView mapView, MapCanvas mapCanvas, Player player) {
if (rendered && renderOnce) {
return;
}

if (player != null && player.isOnline()) {
if (img != null) {
mapCanvas.drawImage(0, 0, resize(img, 128, 128));
}

if (!texts.isEmpty()) {
texts.forEach(text -> mapCanvas.drawText(text.getX(), text.getY(), text.getFont(), text.getMessage()));
}

if (cursors.size() > 0) {
mapCanvas.setCursors(cursors);
}

rendered = true;
}
}
});

if (isOnePointFourteen) {
MapMeta mapMeta = (MapMeta) item.getItemMeta();
mapMeta.setMapView(map);
mapMeta.setScaling(true);
item.setItemMeta(mapMeta);
} else {
item.setDurability(getMapId(map));
}