Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
216 views
in Technique[技术] by (71.8m points)

java - Storing rotated / flipped images in Google App Engine

I'm trying to rotate / flip an image that is already sitting inside Google Cloud Storage.

This is the blobkey:

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

Then I retrieve the image and apply an image transform:

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

The RAW image data I can get in a byte array using:

newImage.getImageData()

Using GCS directly, I can write it to the cloud storage service:

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

Locally I can see the rotated image sitting inside the appengine-generated folder, how do I get the new serving url or what should the objectName be in order to overwrite the original image? Is the objectName the same as the original filename when it was uploaded, is it the blobkey, ...?

Update:

I'm storing the GcsFilename upon upload:

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

The GcsFileName looks like this (locally):

/gs/bucket-name/fake-encoded_gs_key:YXVjdGlvbi1wb3J0YWwtdXBsb2Fkcy84SXp5VGpIUWlZSDY5X1Ytck5TbGtR-0f969f5b4f53a01479ff2d5eaf02fa1a (unindexed)

Then inside my rotate method, I do the following:

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

When I print the new blobKey using bk.getKeyString(), I get an enormous blobkey:

encoded_gs_key:L2dzL2F1Y3Rpb24tcG9ydGFsLXVwbG9hZHMvZmFrZS1lbmNvZGVkX2dzX2tleTpZWFZqZEdsdmJpMXdiM0owWVd3dGRYQnNiMkZrY3k4NFNYcDVWR3BJVVdsWlNEWTVYMVl0Y2s1VGJHdFItMGY5NjlmNWI0ZjUzYTAxNDc5ZmYyZDVlYWYwMmZhMWE

When I try:

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

I now get a INVALID_BLOB_KEY: Could not read blob.

Same with:

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

INVALID_BLOB_KEY: Could not read blob.

Update - Testing On Live:

I've done some logging on live to see if I can pinpoint where things are going wrong.

When I print out the GcsFilename, this is what I'm getting:

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

Then generating the new 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

Then using 3 different methods for getting the new serving urls:

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...

When I access these URLs, all I'm getting is the original image.

When I look in the Cloud Storage Dashboard, the original image is sitting in: Home/bucket-name/

The rotated image however is sitting in: Home/bucket-name//gs/bucket-name/

Hence the reason it's not overwriting the original. I'm guessing either the fileName I'm creating is incorrect or the GcsOutputChannel I'm creating is changing the path? I'm also curious why I'm getting the original image's url instead of the new image's url?

If I split the original GcsFileName and only take the last part, I'm getting an error:

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

Google storage filenames must be prefixed with /gs/

Any ideas?

Solution

Retreive blobKey using:

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

... even though fileName.getObjectName() already contains "/gs/bucket-name/" in front of the objectname. When printing it to standard out, your fileName should contain /gs/bucket-name/ twice, weird, but it works.

Using that blobKey, the correct serving URL is created

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...