当前位置: 首页 > 面试题库 >

在Google App Engine中存储旋转/翻转的图像

郑富
2023-03-14
问题内容

我正在尝试旋转/翻转已经位于Google Cloud Storage内部的图像。

这是Blobkey:

BlobKey blobKey = new BlobKey(upload.getBlobKey());

然后,我检索图像并应用图像变换:

ImagesService imagesService = ImagesServiceFactory.getImagesService();
Image image = ImagesServiceFactory.makeImageFromBlob(blobKey);
Transform transform = ImagesServiceFactory.makeRotate(90);
Image newImage = imagesService.applyTransform(transform, image);

我可以使用以下方式在字节数组中获取RAW图像数据:

newImage.getImageData()

直接使用GCS,我可以将其写入云存储服务:

GcsFilename fileName = new GcsFilename("bucket-name", upload.getFileName());
GcsOutputChannel outputChannel = GcsServiceFactory.createGcsService().createOrReplace(fileName, GcsFileOptions.getDefaultInstance());
outputChannel.write(ByteBuffer.wrap(newImage.getImageData()));
outputChannel.close();

在本地,我可以看到旋转的图像位于appengine生成的文件夹中,如何获取新的服务url或objectName应该是什么以覆盖原始图像?objectName是否与上传时的原始文件名相同,是Blobkey,…?

更新:

上传时,我将存储GcsFilename:

BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
Map<String,List<FileInfo>> finfos = blobstoreService.getFileInfos(req);
String gcsFileName = finfos.get("uploadKey").get(0).getGsObjectName();
upload.setGcsFileName(gcsFileName);
upload.persist();

GcsFileName看起来像这样(本地):

/ gs /存储桶名称/ fake-
encoded_gs_key:YXVjdGlvbi1wb3J0YWwtdXBsb2Fkcy84SXp5VGpIUWlZSDY5X1Ytck5TbGtR-0f969f5b4f53a01479ff2d5eaf02fa1a)

然后在我的rotate方法中,执行以下操作:

GcsFilename fileName = new GcsFilename( "bucket-name", upload.getGcsFileName());
GcsOutputChannel outputChannel = GcsServiceFactory.createGcsService().createOrReplace(fileName, GcsFileOptions.getDefaultInstance());
outputChannel.write(ByteBuffer.wrap(newImage.getImageData()));
outputChannel.close();

BlobstoreService bs = BlobstoreServiceFactory.getBlobstoreService();
BlobKey bk = bs.createGsBlobKey(fileName.getObjectName());

当我使用bk.getKeyString()打印新的blobKey时,我得到了一个巨大的blobkey:

encoded_gs_key:L2dzL2F1Y3Rpb24tcG9ydGFsLXVwbG9hZHMvZmFrZS1lbmNvZGVkX2dzX2tleTpZWFZqZEdsdmJpMXdiM0owWVd3dGRYQnNiMkZrY3k4NFNYcDVWR3BJVVdsWlNEWTVYMVl0Y2s1VGJHdFItMGY5NjlmNWI0ZjUzYTAxNDc5ZmYyZDVlYWYwMmZhMWE

当我尝试:

imagesService.getServingUrl(ServingUrlOptions.Builder.withBlobKey(bk);

我现在得到一个 INVALID_BLOB_KEY:无法读取blob。

与:

imagesService.getServingUrl(ServingUrlOptions.Builder.withGoogleStorageFileName(fileName.getObjectName()));

INVALID_BLOB_KEY:无法读取Blob。

更新-实时测试:

我已经进行了一些实时登录,以查看是否可以查明哪里出了问题。

当我打印出GcsFilename时,这就是我得到的:

GcsFilename fileName = new GcsFilename("bucket-name", upload.getGcsFileName());
System.out.println("fileName.getObjectName(): " + fileName.getObjectName());
System.out.println("fileName.getBucketName(): " + fileName.getBucketName());

2014-03-08 09:31:35.076 [s~_____/live-1-0-2.374269833496060124].<stdout>: fileName.getObjectName(): /gs/bucket-name/L2FwcGhvc3RpbmdfcHJvZC9ibG9icy9BRW5CMlI 
2014-03-08 09:31:35.076 [s~_____/live-1-0-2.374269833496060124].<stdout>: fileName.getBucketName(): bucket-name

然后生成新的blobkey:

BlobstoreService bs = BlobstoreServiceFactory.getBlobstoreService();
BlobKey bk = bs.createGsBlobKey(fileName.getObjectName());

System.out.println("GSBlobKey: " + bk.getKeyString());

2014-03-08 09:31:37.993 [s~_____/live-1-0-2.374269833496060124].<stdout>: GSBlobKey: AMIfv94Tj3xO9hPWwMm314Id0obQs1gVWOHYVuGaaAjjMbieBUD6x0nNGbqiY8o5Jk9iLga4pPe9-8L1

然后使用3种不同的方法来获取新的投放网址:

String newImageUrl1 = imagesService.getServingUrl(ServingUrlOptions.Builder.withGoogleStorageFileName(fileName.getObjectName())); 
System.out.println("newImageUrl1: " + newImageUrl1);

String newImageUrl2 = imagesService.getServingUrl(ServingUrlOptions.Builder.withBlobKey(bk));
System.out.println("newImageUrl2: " + newImageUrl2);

String newImageUrl3 = imagesService.getServingUrl(bk);
System.out.println("newImageUrl3: " + newImageUrl3);


2014-03-08 09:31:38.116 [s~_____/live-1-0-2.374269833496060124].<stdout>: newImageUrl1: http://lh3.ggpht.com/My7zTT79xOltI3cMzHidx7-Us91Qlp13jdv-vJceQ_OpX3FONSr9YzI2...
2014-03-08 09:31:38.152 [s~_____/live-1-0-2.374269833496060124].<stdout>: newImageUrl2: http://lh3.ggpht.com/My7zTT79xOltI3cMzHidx7-Us91Qlp13jdv-vJceQ_OpX3FONSr9YzI2... 
2014-03-08 09:31:38.218 [s~_____/live-1-0-2.374269833496060124].<stdout>: newImageUrl3: http://lh3.ggpht.com/My7zTT79xOltI3cMzHidx7-Us91Qlp13jdv-vJceQ_OpX3FONSr9YzI2...

当我访问这些URL时,我得到的只是原始图像。

当我在Cloud Storage Dashboard中查看时,原始图像位于:Home / bucket-name /

但是,旋转后的图像位于:主页/存储桶名称// gs /存储桶名称/

因此,它没有覆盖原件的原因。我猜我正在创建的文件名不正确,或者我正在创建的GcsOutputChannel正在更改路径?我也很好奇为什么我要获取原始图像的URL而不是新图像的URL?

如果我分割了原始的GcsFileName并只使用了最后一部分,那么我会得到一个错误:

GcsFilename fileName = new GcsFilename("bucket-name", upload.getGcsFileName().split("/")[3]);

Google存储空间文件名必须以/ gs /作为前缀

有任何想法吗?

使用以下命令检索blobKey:

BlobKey blobKey = blobstoreService.createGsBlobKey("/gs/" + fileName.getBucketName() + "/" + fileName.getObjectName());

…即使fileName.getObjectName()在对象名前面已经包含“ / gs / bucket-name
/”。当将其打印为标准输出时,您的fileName应该包含两次/ gs / bucket-name /,很奇怪,但是可以使用。

使用该blobKey创建正确的服务网址


问题答案:

要覆盖原始映像,您只需要指定相同的Cloud Storage文件名。

我们了解您已通过BlobStore API通过App Engine将图像上传到Cloud Storage。要获取原始图像的实际文件名,必须
在上传servlet中 添加以下代码

  Map<String,List<BlobInfo>> uploadInfos = getFileInfos(httpServletRequest);
  String theGCSFilename = uploadInfos.get("yourFileName").getGsObjectName();

请注意,如果您不想覆盖原始文件,但想向客户提供服务网址,则可以:

  • 像这样使用ImageService:

    ImagesService imagesService = ImagesServiceFactory.getImagesService();
    

    String url = imagesService.getServingUrl(ServingUrlOptions.Builder.withGoogleStorageFileName(java));

  • 创建一个GCSServingServlet将使用该BlobstoreService.serve()方法为Blobstore或Cloud Storage中的文件提供服务的自定义用户。在这种情况下,您必须自己检查权限。请注意,您可以创建一个BlobKeyGCSFilename使用BlobStoreService.createGSBlobKey()

  • 使用Cloud Storage服务网址:

    • 私人:http : //commondatastorage.googleapis.com/bucket/filename
    • 公开:http : //storage.googleapis.com//bucket/filename


 类似资料:
  • 这就是它没有覆盖原始内容的原因。我猜是我创建的文件名不正确,还是我创建的GcsOutputChannel正在更改路径?我也很好奇为什么我得到的是原始图像的url而不是新图像的url? 如果我拆分原始的GcsFileName并只取最后一部分,我将得到一个错误: Google存储文件名必须以/gs/为前缀 解决方案 使用以下方法检索blobKey: ...即使FileName.getObjectNam

  • 在我的应用中,我提示用户捕获图像。用户相机活动在按钮单击时开始,用户可以选择使用相机捕获图像。 此图像保存在用户手机上。然后将图像上传到firebase Storage,一切正常。来自一位使用三星Note 8的用户的反馈是,当图像以肖像模式拍摄时,他稍后会在应用程序中以风景模式显示。 我查看了firebase存储,发现图像以横向模式保存在存储中,即使用户以纵向模式捕获图像。 我想我必须将元数据传递

  • 本文向大家介绍C#控制图像旋转和翻转的方法,包括了C#控制图像旋转和翻转的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#控制图像旋转和翻转的方法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的C#程序设计有所帮助。

  • 我正在从相机中保存一个处于横向模式的图像。所以它被保存在横向模式下,然后我在它上面应用一个覆盖层,它也是在横向模式下。我想旋转那个图像,然后保存。例如,如果我有这个 我想顺时针旋转90度一次,这样做,并将其保存到SD卡: 如何做到这一点?

  • 在我的应用程序中,图像是从相机捕获的,然后显示在 我已经成功地完成了此方法,但是当我的图像显示在中时,图像显示在旋转后 我想旋转图像,然后在中显示 当我单击前摄像头上的图像时,在下面代码的帮助下,图像显示正确 但当我从后摄像头点击时,图像将显示在前摄像头的对面。还有一件事,当我从不同角度单击“来自摄影机的图像”时,图像将以不同角度显示在中。

  • 我有一个一维数组,它代表一个二维网格。行和列的数量是已知的。从“左上角”到“右下角”读取,因此第一项为R1C1,最后一项为RXCY(其中X=行编号,Y=列编号; 我的目标是翻转或旋转二维数组,并返回一个新的一维数组表示转换。 我尝试了按位操作,但无法让它与行/行计数可能是奇数或偶数的事实一起工作。我也尝试了迭代方法,但在逻辑杂草中迷失了方向。 一个最简单的javascript示例:9项数组中的3^