Fix profile image squish and rotate isusse
This commit is contained in:
@@ -14,7 +14,6 @@ import javafx.scene.image.Image;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.ImagePattern;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.stage.Stage;
|
||||
import org.example.petshopdesktop.api.endpoints.ChatApi;
|
||||
@@ -31,6 +30,8 @@ import java.io.ByteArrayInputStream;
|
||||
|
||||
public class MainLayoutController {
|
||||
|
||||
private int avatarExifOrientation = 1;
|
||||
|
||||
private static final String NAV_BASE_STYLE = "-fx-background-color: transparent; " +
|
||||
"-fx-text-fill: #cbd5e1; " +
|
||||
"-fx-background-radius: 10; " +
|
||||
@@ -331,9 +332,11 @@ public class MainLayoutController {
|
||||
|
||||
try {
|
||||
byte[] imageBytes = AuthApi.getInstance().getMyAvatarFile();
|
||||
Image image = new Image(new ByteArrayInputStream(imageBytes), 52, 52, true, true);
|
||||
avatarExifOrientation = readExifOrientation(imageBytes);
|
||||
Image image = new Image(new ByteArrayInputStream(imageBytes), 200, 200, true, true);
|
||||
return image.isError() ? null : image;
|
||||
} catch (Exception e) {
|
||||
avatarExifOrientation = 1;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -342,19 +345,31 @@ public class MainLayoutController {
|
||||
Circle border = new Circle(29);
|
||||
border.setFill(Color.web("#dbe4ee"));
|
||||
|
||||
Circle circle = new Circle(26);
|
||||
Label initials = new Label(initials(displayName));
|
||||
initials.setStyle("-fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 16px;");
|
||||
|
||||
if (avatarImage != null) {
|
||||
circle.setFill(new ImagePattern(avatarImage));
|
||||
initials.setVisible(false);
|
||||
} else {
|
||||
circle.setFill(Color.web("#4ECDC4"));
|
||||
initials.setVisible(true);
|
||||
}
|
||||
double imgW = avatarImage.getWidth();
|
||||
double imgH = avatarImage.getHeight();
|
||||
double cropSize = Math.min(imgW, imgH);
|
||||
double cropX = (imgW - cropSize) / 2;
|
||||
double cropY = (imgH - cropSize) / 2;
|
||||
|
||||
avatarPreview.getChildren().setAll(border, circle, initials);
|
||||
javafx.scene.image.ImageView imageView = new javafx.scene.image.ImageView(avatarImage);
|
||||
imageView.setViewport(new javafx.geometry.Rectangle2D(cropX, cropY, cropSize, cropSize));
|
||||
imageView.setFitWidth(52);
|
||||
imageView.setFitHeight(52);
|
||||
imageView.setPreserveRatio(false);
|
||||
imageView.setRotate(exifOrientationToAngle(avatarExifOrientation));
|
||||
|
||||
Circle clip = new Circle(26, 26, 26);
|
||||
imageView.setClip(clip);
|
||||
|
||||
avatarPreview.getChildren().setAll(border, imageView);
|
||||
} else {
|
||||
Circle circle = new Circle(26);
|
||||
circle.setFill(Color.web("#4ECDC4"));
|
||||
Label initials = new Label(initials(displayName));
|
||||
initials.setStyle("-fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 16px;");
|
||||
avatarPreview.getChildren().setAll(border, circle, initials);
|
||||
}
|
||||
}
|
||||
|
||||
private String initials(String displayName) {
|
||||
@@ -495,4 +510,56 @@ public class MainLayoutController {
|
||||
}
|
||||
}
|
||||
|
||||
private double exifOrientationToAngle(int orientation) {
|
||||
return switch (orientation) {
|
||||
case 3 -> 180;
|
||||
case 6 -> 90;
|
||||
case 8 -> -90;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
private int readExifOrientation(byte[] data) {
|
||||
try {
|
||||
if (data.length < 2 || (data[0] & 0xFF) != 0xFF || (data[1] & 0xFF) != 0xD8) return 1;
|
||||
int offset = 2;
|
||||
while (offset + 4 < data.length) {
|
||||
if ((data[offset] & 0xFF) != 0xFF) break;
|
||||
int marker = data[offset + 1] & 0xFF;
|
||||
int segLen = ((data[offset + 2] & 0xFF) << 8) | (data[offset + 3] & 0xFF);
|
||||
if (marker == 0xE1 && offset + 9 < data.length
|
||||
&& data[offset + 4] == 'E' && data[offset + 5] == 'x'
|
||||
&& data[offset + 6] == 'i' && data[offset + 7] == 'f'
|
||||
&& data[offset + 8] == 0 && data[offset + 9] == 0) {
|
||||
int tiff = offset + 10;
|
||||
boolean le = data[tiff] == 'I';
|
||||
int ifdOffset = readInt(data, tiff + 4, le);
|
||||
int ifd = tiff + ifdOffset;
|
||||
int entries = readShort(data, ifd, le);
|
||||
for (int i = 0; i < entries; i++) {
|
||||
int e = ifd + 2 + i * 12;
|
||||
if (e + 9 < data.length && readShort(data, e, le) == 0x0112) {
|
||||
return readShort(data, e + 8, le);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (marker == 0xDA) break;
|
||||
offset += 2 + segLen;
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
return 1;
|
||||
}
|
||||
|
||||
private int readShort(byte[] data, int offset, boolean le) {
|
||||
return le
|
||||
? (data[offset] & 0xFF) | ((data[offset + 1] & 0xFF) << 8)
|
||||
: ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
|
||||
}
|
||||
|
||||
private int readInt(byte[] data, int offset, boolean le) {
|
||||
return le
|
||||
? (data[offset] & 0xFF) | ((data[offset + 1] & 0xFF) << 8) | ((data[offset + 2] & 0xFF) << 16) | ((data[offset + 3] & 0xFF) << 24)
|
||||
: ((data[offset] & 0xFF) << 24) | ((data[offset + 1] & 0xFF) << 16) | ((data[offset + 2] & 0xFF) << 8) | (data[offset + 3] & 0xFF);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user