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.input.MouseEvent;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.scene.paint.ImagePattern;
|
|
||||||
import javafx.scene.shape.Circle;
|
import javafx.scene.shape.Circle;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import org.example.petshopdesktop.api.endpoints.ChatApi;
|
import org.example.petshopdesktop.api.endpoints.ChatApi;
|
||||||
@@ -31,6 +30,8 @@ import java.io.ByteArrayInputStream;
|
|||||||
|
|
||||||
public class MainLayoutController {
|
public class MainLayoutController {
|
||||||
|
|
||||||
|
private int avatarExifOrientation = 1;
|
||||||
|
|
||||||
private static final String NAV_BASE_STYLE = "-fx-background-color: transparent; " +
|
private static final String NAV_BASE_STYLE = "-fx-background-color: transparent; " +
|
||||||
"-fx-text-fill: #cbd5e1; " +
|
"-fx-text-fill: #cbd5e1; " +
|
||||||
"-fx-background-radius: 10; " +
|
"-fx-background-radius: 10; " +
|
||||||
@@ -331,9 +332,11 @@ public class MainLayoutController {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] imageBytes = AuthApi.getInstance().getMyAvatarFile();
|
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;
|
return image.isError() ? null : image;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
avatarExifOrientation = 1;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -342,20 +345,32 @@ public class MainLayoutController {
|
|||||||
Circle border = new Circle(29);
|
Circle border = new Circle(29);
|
||||||
border.setFill(Color.web("#dbe4ee"));
|
border.setFill(Color.web("#dbe4ee"));
|
||||||
|
|
||||||
|
if (avatarImage != null) {
|
||||||
|
double imgW = avatarImage.getWidth();
|
||||||
|
double imgH = avatarImage.getHeight();
|
||||||
|
double cropSize = Math.min(imgW, imgH);
|
||||||
|
double cropX = (imgW - cropSize) / 2;
|
||||||
|
double cropY = (imgH - cropSize) / 2;
|
||||||
|
|
||||||
|
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 circle = new Circle(26);
|
||||||
|
circle.setFill(Color.web("#4ECDC4"));
|
||||||
Label initials = new Label(initials(displayName));
|
Label initials = new Label(initials(displayName));
|
||||||
initials.setStyle("-fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 16px;");
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
avatarPreview.getChildren().setAll(border, circle, initials);
|
avatarPreview.getChildren().setAll(border, circle, initials);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String initials(String displayName) {
|
private String initials(String displayName) {
|
||||||
if (displayName == null || displayName.isBlank()) {
|
if (displayName == null || displayName.isBlank()) {
|
||||||
@@ -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