Как обсуждалось ранее в этом документе question, на мобильном телефоне нет ни Swing, ни AWT, поэтому, как только вы получите изображение JavaFX, вы можете его использовать, вы не можете использовать SwingFXUtils
.
Решение, предложенное в упомянутом вопросе, работает на Android, так как вы можете легко получить файл. На iOS, напротив, файл находится в галерее, и текущий Charm Down PicturesService
не имеет доступа к галерее.
Вместо того, чтобы модифицировать эту услугу (с машинным кодом, как этот one), идея, чтобы получить ByteArray, с помощью JavaFX Image
, который можно отправить на веб-сервиса на основе двух этапов:
- Получить пиксели изображения в виде байтового массива
- Кодировать массив байтов в строку.
Если проверка реализации IOS для PicturesService::takePhoto
, образ из родного слоя IOS отправляется к слою JavaFX с помощью Base6 и decoding.
Решение 1
Этот фрагмент кода работает для меня:
// Take a photo and add image to imageView
Button button = new Button("Take Photo");
button.setOnAction(e ->
Services.get(PicturesService.class)
.ifPresent(s -> s.takePhoto(false).ifPresent(imageView::setImage)));
// Encode image
imageView.imageProperty().addListener((obs, ov, image) -> {
if (image != null) {
// 1. image to byte array
PixelReader pixelReader = image.getPixelReader();
int width = (int) image.getWidth();
int height = (int) image.getHeight();
byte[] buffer = new byte[width * height * 4];
pixelReader.getPixels(0, 0, width, height, PixelFormat.getByteBgraInstance(), buffer, 0, width * 4);
// 2. Encode to String
String encoded = Base64.getEncoder().encodeToString(buffer);
// 3. send string...
}
}
Вы можете проверить процесс работы путем изменения этих шагов и создания образа из закодированной строки:
byte[] imageBytes = Base64.getDecoder().decode(encoded.getBytes(StandardCharsets.UTF_8));
WritablePixelFormat<ByteBuffer> wf = PixelFormat.getByteBgraInstance();
WritableImage writableImage = new WritableImage(width, height);
PixelWriter pixelWriter = writableImage.getPixelWriter();
pixelWriter.setPixels(0, 0, width, height, wf, imageBytes, 0, width * 4);
imageView.setImage(writableImage);
Решение 2
Если вы хотите преобразовать массив байтов из PixelReader::getPixels
в BufferedImage
, это не сработает: массивы байтов разные.
Поэтому вам нужно использовать что-то, что буферизованное изображение сможет обрабатывать.
Если вы посмотрите на реализацию SwingFXUtils
, вместо этого он использует массив int.
Так что это еще одна возможности:
// Take a photo and add image to imageView
Button button = new Button("Take Photo");
button.setOnAction(e ->
Services.get(PicturesService.class)
.ifPresent(s -> s.takePhoto(false).ifPresent(imageView::setImage)));
// Encode image
imageView.imageProperty().addListener((obs, ov, image) -> {
if (image != null) {
// 1. image to int array
PixelReader pixelReader = image.getPixelReader();
int width = (int) image.getWidth();
int height = (int) image.getHeight();
int[] data = new int[width * height];
pixelReader.getPixels(0, 0, width, height, PixelFormat.getIntArgbPreInstance(), data, 0, width);
// 2. int array to byte array
ByteBuffer byteBuffer = ByteBuffer.allocate(data.length * 4);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(data);
// 3. Encode to String
String encoded = Base64.getEncoder().encodeToString(byteBuffer.array());
// 4. send string...
}
}
Теперь вам придется декодировать строку, получить целочисленный массив и создать буферизованное изображение:
// 1. Decode string
byte[] imageBytes = Base64.getDecoder().decode(encoded.getBytes(StandardCharsets.UTF_8));
// 2. get int array
ByteBuffer byteBuffer2 = ByteBuffer.wrap(imageBytes);
IntBuffer intBuffer2 = byteBuffer2.asIntBuffer();
int[] imageData = new int[intBuffer2.limit()];
intBuffer2.get(imageData);
// 3. create buffered image
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
bufferedImage.setRGB(0, 0, width, height, imageData, 0, width);
Если вы посмотрите на прошивке [реализации] (https: // Bitbucket.org/gluon-oss/charm-down/src/1942aa27c6b60d890511667cf64c3f9d8a0e69b6/plugins/plugin-storage/ios/src/main/native/Storage.m? at = default & fileviewer = file-view-default # Storage.m-52) из Службы хранения вы заметите, что хранилище локально для вашего приложения (см. Использование 'NSDocumentDirectory'). Хотя у Android есть несколько общих папок (т. Е. 'Sdcard/Pictures'), iOS не позволяет этого, поэтому реализация StorageService приводит к различным результатам в этом случае. –
ОК. поэтому, когда я сохранил изображение с помощью функции picturesservice, как я могу получить доступ к самому файлу - не как изображение с loadImageFromGallery - на ios? можете ли вы дать мне подсказку в этом направлении. – tonimaroni
Почему бы не получить доступ через загрузку из галереи? это даст мне изображение, которое будет хорошо. но я не могу преобразовать его в файл/ByteArrayInputStream, который затем можно загрузить в веб-сервис. Это окончательный результат, чтобы дать, возможно, более подробную информацию о том, что нужно решить. спасибо за любую помощь снова. – tonimaroni