add isometric head renderer
Some checks failed
Deploy App / docker (ubuntu-latest, 2.44.0, 17, 3.8.5) (push) Failing after 30s

This commit is contained in:
Lee
2024-04-11 03:08:17 +01:00
parent 557c0facb7
commit 8e5adf337a
13 changed files with 284 additions and 70 deletions

View File

@ -0,0 +1,66 @@
package cc.fascinated.service.skin.impl;
import cc.fascinated.common.ImageUtils;
import cc.fascinated.model.player.Skin;
import cc.fascinated.service.skin.SkinPartParser;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
@Getter @Log4j2
public class FlatParser extends SkinPartParser {
/**
* The x and y position of the part.
*/
private final int x, y;
/**
* The width and height of the part.
*/
private final int widthAndHeight;
/**
* Constructs a new {@link FlatParser}.
*
* @param x the x position of the part
* @param y the y position of the part
* @param widthAndHeight the width and height of the part
*/
public FlatParser(int x, int y, int widthAndHeight) {
this.x = x;
this.y = y;
this.widthAndHeight = widthAndHeight;
}
@Override
public byte[] getPart(Skin skin, String partName, boolean renderOverlay, int size) {
double scale = (double) size / this.widthAndHeight;
log.info("Getting {} part bytes for {} with size {} and scale {}", partName, skin.getUrl(), size, scale);
try {
BufferedImage outputImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = outputImage.createGraphics();
graphics.setTransform(AffineTransform.getScaleInstance(scale, scale));
graphics.drawImage(this.getSkinPart(skin, this.x, this.y, this.widthAndHeight, this.widthAndHeight, 1), 0, 0, null);
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
ImageIO.write(outputImage, "png", outputStream);
// Cleanup
outputStream.flush();
graphics.dispose();
log.info("Successfully got {} part bytes for {}", partName, skin.getUrl());
return outputStream.toByteArray();
}
} catch (Exception ex) {
log.error("Failed to get {} part bytes for {}", partName, skin.getUrl(), ex);
return null;
}
}
}

View File

@ -0,0 +1,102 @@
package cc.fascinated.service.skin.impl;
import cc.fascinated.common.ImageUtils;
import cc.fascinated.model.player.Skin;
import cc.fascinated.service.skin.SkinPartParser;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
@Getter @Log4j2
public class IsometricHeadParser extends SkinPartParser {
private static final double SKEW_A = 26d / 45d; // 0.57777777
private static final double SKEW_B = SKEW_A * 2d; // 1.15555555
@Override
public byte[] getPart(Skin skin, String partName, boolean renderOverlay, int size) {
double scale = (size / 8d) / 2.5;
log.info("Getting {} part bytes for {} with size {} and scale {}", partName, skin.getUrl(), size, scale);
try {
final BufferedImage outputImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
// Get all the required head parts
final BufferedImage headTop = ImageUtils.resize(this.getSkinPart(skin, 8, 0, 8, 8, 1), scale);
final BufferedImage headFront = ImageUtils.resize(this.getSkinPart(skin, 8, 8, 8, 8, 1), scale);
final BufferedImage headRight = ImageUtils.resize(this.getSkinPart(skin, 0, 8, 8, 8, 1), scale);
if (renderOverlay) {
// Draw the overlay on top of the gathered skin parts
// Top overlay
Graphics2D g = headTop.createGraphics();
g.drawImage(this.getSkinPart(skin, 40, 0, 8, 8, 1), 0, 0, null);
g.dispose();
// Front overlay
g = headFront.createGraphics();
g.drawImage(this.getSkinPart(skin, 16, 8, 8, 8, 1), 0, 0, null);
g.dispose();
// Right side overlay
g = headRight.createGraphics();
g.drawImage(this.getSkinPart(skin, 32, 8, 8, 8, 1), 0, 0, null);
g.dispose();
}
// Declare pos
double x;
double y;
double z;
// Declare offsets
final double z_offset = scale * 3.5d;
final double x_offset = scale * 2d;
// Create graphics
final Graphics2D outGraphics = outputImage.createGraphics();
// head top
x = x_offset;
y = -0.5;
z = z_offset;
outGraphics.setTransform(new AffineTransform(1d, -SKEW_A, 1, SKEW_A, 0, 0));
outGraphics.drawImage(headTop, (int) (y - z), (int) (x + z), headTop.getWidth(), headTop.getHeight() + 1, null);
// head front
x = x_offset + 8 * scale;
y = 0;
z = z_offset - 0.5;
outGraphics.setTransform(new AffineTransform(1d, -SKEW_A, 0d, SKEW_B, 0d, SKEW_A));
outGraphics.drawImage(headFront, (int) (y + x), (int) (x + z), headFront.getWidth(), headFront.getHeight(), null);
// head right
x = x_offset;
y = 0;
z = z_offset;
outGraphics.setTransform(new AffineTransform(1d, SKEW_A, 0d, SKEW_B, 0d, 0d));
outGraphics.drawImage(headRight, (int) (x + y + 1), (int) (z - y - 0.5), headRight.getWidth(), headRight.getHeight() + 1, null);
// Cleanup and return
outGraphics.dispose();
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
ImageIO.write(outputImage, "png", outputStream);
// Cleanup
outputStream.flush();
outGraphics.dispose();
log.info("Successfully got {} part bytes for {}", partName, skin.getUrl());
return outputStream.toByteArray();
}
} catch (Exception ex) {
log.error("Failed to get {} part bytes for {}", partName, skin.getUrl(), ex);
return null;
}
}
}