Retrieve image from Cloud Storage to blur and then upload to a storage bucket
Stay organized with collections
Save and categorize content based on your preferences.
This tutorial demonstrates using Cloud Run, Cloud Vision API, and ImageMagick to detect and blur offensive images uploaded to a Cloud Storage bucket.
Explore further
For detailed documentation that includes this code sample, see the following:
Code sample
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],[],[],[],null,["# Retrieve image from Cloud Storage to blur and then upload to a storage bucket\n\nThis tutorial demonstrates using Cloud Run, Cloud Vision API, and ImageMagick to detect and blur offensive images uploaded to a Cloud Storage bucket.\n\nExplore further\n---------------\n\n\nFor detailed documentation that includes this code sample, see the following:\n\n- [Process images from Cloud Storage tutorial](/run/docs/tutorials/image-processing)\n- [Processing images asynchronously](/anthos/run/archive/docs/tutorials/image-processing)\n\nCode sample\n-----------\n\n### Go\n\n\nTo authenticate to Cloud Run, set up Application Default Credentials.\nFor more information, see\n\n[Set up authentication for a local development environment](/docs/authentication/set-up-adc-local-dev-environment).\n\n\n // blur blurs the image stored at gs://inputBucket/name and stores the result in\n // gs://outputBucket/name.\n func blur(ctx context.Context, inputBucket, outputBucket, name string) error {\n \tinputBlob := storageClient.Bucket(inputBucket).Object(name)\n \tr, err := inputBlob.NewReader(ctx)\n \tif err != nil {\n \t\treturn fmt.Errorf(\"NewReader: %w\", err)\n \t}\n\n \toutputBlob := storageClient.Bucket(outputBucket).Object(name)\n \tw := outputBlob.NewWriter(ctx)\n \tdefer w.Close()\n\n \t// Use - as input and output to use stdin and stdout.\n \tcmd := exec.Command(\"convert\", \"-\", \"-blur\", \"0x8\", \"-\")\n \tcmd.Stdin = r\n \tcmd.Stdout = w\n\n \tif err := cmd.Run(); err != nil {\n \t\treturn fmt.Errorf(\"cmd.Run: %w\", err)\n \t}\n\n \tlog.Printf(\"Blurred image uploaded to gs://%s/%s\", outputBlob.BucketName(), outputBlob.ObjectName())\n\n \treturn nil\n }\n\n### Java\n\n\nTo authenticate to Cloud Run, set up Application Default Credentials.\nFor more information, see\n\n[Set up authentication for a local development environment](/docs/authentication/set-up-adc-local-dev-environment).\n\n // Blurs the file described by blobInfo using ImageMagick,\n // and uploads it to the blurred bucket.\n public static void blur(BlobInfo blobInfo) throws IOException {\n String bucketName = blobInfo.getBucket();\n String fileName = blobInfo.getName();\n // Download image\n Blob blob = storage.get(BlobId.of(bucketName, fileName));\n Path download = Paths.get(\"/tmp/\", fileName);\n blob.downloadTo(download);\n\n // Construct the command.\n List\u003cString\u003e args = new ArrayList\u003c\u003e();\n args.add(\"convert\");\n args.add(download.toString());\n args.add(\"-blur\");\n args.add(\"0x8\");\n Path upload = Paths.get(\"/tmp/\", \"blurred-\" + fileName);\n args.add(upload.toString());\n try {\n ProcessBuilder pb = new ProcessBuilder(args);\n Process process = pb.start();\n process.waitFor();\n } catch (Exception e) {\n System.out.println(String.format(\"Error: %s\", e.getMessage()));\n }\n\n // Upload image to blurred bucket.\n BlobId blurredBlobId = BlobId.of(BLURRED_BUCKET_NAME, fileName);\n BlobInfo blurredBlobInfo =\n BlobInfo.newBuilder(blurredBlobId).setContentType(blob.getContentType()).build();\n try {\n byte[] blurredFile = Files.readAllBytes(upload);\n Blob blurredBlob = storage.create(blurredBlobInfo, blurredFile);\n System.out.println(\n String.format(\"Blurred image uploaded to: gs://%s/%s\", BLURRED_BUCKET_NAME, fileName));\n } catch (Exception e) {\n System.out.println(String.format(\"Error in upload: %s\", e.getMessage()));\n }\n\n // Remove images from fileSystem\n Files.delete(download);\n Files.delete(upload);\n }\n }\n\n### Node.js\n\n\nTo authenticate to Cloud Run, set up Application Default Credentials.\nFor more information, see\n\n[Set up authentication for a local development environment](/docs/authentication/set-up-adc-local-dev-environment).\n\n // Blurs the given file using ImageMagick, and uploads it to another bucket.\n const blurImage = async (file, blurredBucketName) =\u003e {\n const tempLocalPath = `/tmp/${path.parse(file.name).base}`;\n\n // Download file from bucket.\n try {\n await file.download({destination: tempLocalPath});\n\n console.log(`Downloaded ${file.name} to ${tempLocalPath}.`);\n } catch (err) {\n throw new Error(`File download failed: ${err}`);\n }\n\n await new Promise((resolve, reject) =\u003e {\n gm(tempLocalPath)\n .blur(0, 16)\n .write(tempLocalPath, (err, stdout) =\u003e {\n if (err) {\n console.error('Failed to blur image.', err);\n reject(err);\n } else {\n console.log(`Blurred image: ${file.name}`);\n resolve(stdout);\n }\n });\n });\n\n // Upload result to a different bucket, to avoid re-triggering this function.\n const blurredBucket = storage.bucket(blurredBucketName);\n\n // Upload the Blurred image back into the bucket.\n const gcsPath = `gs://${blurredBucketName}/${file.name}`;\n try {\n await blurredBucket.upload(tempLocalPath, {destination: file.name});\n console.log(`Uploaded blurred image to: ${gcsPath}`);\n } catch (err) {\n throw new Error(`Unable to upload blurred image to ${gcsPath}: ${err}`);\n }\n\n // Delete the temporary file.\n const unlink = promisify(fs.unlink);\n return unlink(tempLocalPath);\n };\n\n### Python\n\n\nTo authenticate to Cloud Run, set up Application Default Credentials.\nFor more information, see\n\n[Set up authentication for a local development environment](/docs/authentication/set-up-adc-local-dev-environment).\n\n def __blur_image(current_blob):\n \"\"\"Blurs the given file using ImageMagick.\n\n Args:\n current_blob: a Cloud Storage blob\n \"\"\"\n file_name = current_blob.name\n _, temp_local_filename = tempfile.mkstemp()\n\n # Download file from bucket.\n current_blob.download_to_filename(temp_local_filename)\n print(f\"Image {file_name} was downloaded to {temp_local_filename}.\")\n\n # Blur the image using ImageMagick.\n with Image(filename=temp_local_filename) as image:\n image.resize(*image.size, blur=16, filter=\"hamming\")\n image.save(filename=temp_local_filename)\n\n print(f\"Image {file_name} was blurred.\")\n\n # Upload result to a second bucket, to avoid re-triggering the function.\n # You could instead re-upload it to the same bucket + tell your function\n # to ignore files marked as blurred (e.g. those with a \"blurred\" prefix)\n blur_bucket_name = os.getenv(\"BLURRED_BUCKET_NAME\")\n blur_bucket = storage_client.bucket(blur_bucket_name)\n new_blob = blur_bucket.blob(file_name)\n new_blob.upload_from_filename(temp_local_filename)\n print(f\"Blurred image uploaded to: gs://{blur_bucket_name}/{file_name}\")\n\n # Delete the temporary file.\n os.remove(temp_local_filename)\n\nWhat's next\n-----------\n\n\nTo search and filter code samples for other Google Cloud products, see the\n[Google Cloud sample browser](/docs/samples?product=cloudrun)."]]