getPublicStorage("Pictures") 没有列出任何文件

getPublicStorage("Pictures") lists no files

呼叫

File picturesDir = Services.get(StorageService.class)
            .flatMap(s -> s.getPublicStorage("Pictures"))
            .orElseThrow(() -> new RuntimeException("Error retrieving public storage")); 
for (File pic : picturesDir.listFiles()) {
        System.out.println("file " + pic.getName());
}

未列出任何文件。我认为它应该列出 iPhone.

上我的图片库中的所有文件

尽管调用 s.getPublicStorage("") 它会列出两个文件夹: 胶子,图片。

如何正确访问它?

如前文所述 ,在移动设备上没有 Swing 或 AWT,因此一旦您拥有 JavaFX 图像,就无法使用 SwingFXUtils.

上述问题中提出的解决方案适用于 Android,因为您可以轻松获取文件。在 iOS 上,相反,文件位于图库中,而当前的 Charm Down PicturesService 无法访问图库。

不是修改该服务(使用像这样的本机代码 one),从 JavaFX Image 获取可以发送到 Web 服务的 byteArray 的想法基于两个步骤:

  • 获取图像像素作为字节数组
  • 将字节数组编码为字符串。

如果您检查 PicturesService::takePhoto 的 iOS 实现,来自 iOS 本机层的图像将通过 Base64 encoding and decoding.[=24 发送到 JavaFX 层=]

解决方案 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...
    }
} 

现在您必须解码字符串,获取 int 数组并创建缓冲图像:

// 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);