fixed rotated image for pets and product as well

This commit is contained in:
Alex
2026-04-13 00:30:26 -06:00
parent d85530dd2c
commit fba042d2b9
2 changed files with 77 additions and 6 deletions

View File

@@ -380,7 +380,7 @@ public class PetController {
setGraphic(null); setGraphic(null);
return; return;
} }
DesktopImageSupport.loadImageInto(imageView, item, 24, 24); DesktopImageSupport.loadImageInto(imageView, item, 48, 48);
setGraphic(container); setGraphic(container);
} }
}); });

View File

@@ -12,6 +12,7 @@ import java.util.concurrent.ConcurrentHashMap;
public final class DesktopImageSupport { public final class DesktopImageSupport {
private static final Map<String, Image> IMAGE_CACHE = new ConcurrentHashMap<>(); private static final Map<String, Image> IMAGE_CACHE = new ConcurrentHashMap<>();
private static final Map<String, Integer> ORIENTATION_CACHE = new ConcurrentHashMap<>();
private DesktopImageSupport() { private DesktopImageSupport() {
} }
@@ -22,32 +23,49 @@ public final class DesktopImageSupport {
imageView.setPreserveRatio(true); imageView.setPreserveRatio(true);
imageView.setSmooth(true); imageView.setSmooth(true);
imageView.setImage(null); imageView.setImage(null);
imageView.setRotate(0);
if (imageUrl == null || imageUrl.isBlank()) { if (imageUrl == null || imageUrl.isBlank()) {
return; return;
} }
if (imageUrl.startsWith("file:")) { if (imageUrl.startsWith("file:")) {
Image image = new Image(imageUrl, 0, 0, true, true); new Thread(() -> {
if (!image.isError()) { try {
imageView.setImage(image); byte[] bytes = java.net.URI.create(imageUrl).toURL().openStream().readAllBytes();
} int orientation = readExifOrientation(bytes);
Image image = new Image(new ByteArrayInputStream(bytes));
if (!image.isError()) {
Platform.runLater(() -> {
imageView.setImage(image);
imageView.setRotate(exifOrientationToAngle(orientation));
});
}
} catch (Exception ignored) {
}
}, "desktop-image-loader").start();
return; return;
} }
Image cached = IMAGE_CACHE.get(imageUrl); Image cached = IMAGE_CACHE.get(imageUrl);
if (cached != null) { if (cached != null) {
imageView.setImage(cached); imageView.setImage(cached);
imageView.setRotate(exifOrientationToAngle(ORIENTATION_CACHE.getOrDefault(imageUrl, 1)));
return; return;
} }
new Thread(() -> { new Thread(() -> {
try { try {
byte[] bytes = ApiClient.getInstance().getBytes(imageUrl); byte[] bytes = ApiClient.getInstance().getBytes(imageUrl);
int orientation = readExifOrientation(bytes);
Image image = new Image(new ByteArrayInputStream(bytes)); Image image = new Image(new ByteArrayInputStream(bytes));
if (!image.isError()) { if (!image.isError()) {
IMAGE_CACHE.put(imageUrl, image); IMAGE_CACHE.put(imageUrl, image);
Platform.runLater(() -> imageView.setImage(image)); ORIENTATION_CACHE.put(imageUrl, orientation);
Platform.runLater(() -> {
imageView.setImage(image);
imageView.setRotate(exifOrientationToAngle(orientation));
});
} }
} catch (Exception ignored) { } catch (Exception ignored) {
} }
@@ -57,6 +75,59 @@ public final class DesktopImageSupport {
public static void evict(String imageUrl) { public static void evict(String imageUrl) {
if (imageUrl != null && !imageUrl.isBlank()) { if (imageUrl != null && !imageUrl.isBlank()) {
IMAGE_CACHE.remove(imageUrl); IMAGE_CACHE.remove(imageUrl);
ORIENTATION_CACHE.remove(imageUrl);
} }
} }
private static double exifOrientationToAngle(int orientation) {
return switch (orientation) {
case 3 -> 180;
case 6 -> 90;
case 8 -> -90;
default -> 0;
};
}
private static 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 static 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 static 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);
}
} }