Paso 2 del instructivo de ImageMagick: Desenfocar imagen

Demuestra cómo usar ImageMagick y la API de Google Cloud Vision para detectar y desenfocar imágenes ofensivas que se suben al bucket de Cloud Storage.

Páginas de documentación que incluyen esta muestra de código

Para ver la muestra de código usada en contexto, consulta la siguiente documentación:

Muestra de código


/// <summary>
/// Downloads the Storage object specified by <paramref name="data"/>,
/// blurs it using ImageMagick, and uploads it to the "blurred" bucket.
/// </summary>
private async Task BlurImageAsync(StorageObjectData data, CancellationToken cancellationToken)
    // Download image
    string originalImageFile = Path.GetTempFileName();
    using (Stream output = File.Create(originalImageFile))
        await _storageClient.DownloadObjectAsync(data.Bucket, data.Name, output, cancellationToken: cancellationToken);

    // Construct the ImageMagick command
    string blurredImageFile = Path.GetTempFileName();
    // Command-line arguments for ImageMagick.
    // Paths are wrapped in quotes in case they contain spaces.
    string arguments = $"\"{originalImageFile}\" -blur 0x8, \"{blurredImageFile}\"";

    // Run the ImageMagick command line tool ("convert").
    Process process = Process.Start("convert", arguments);
    // Process doesn't expose a way of asynchronously waiting for completion.
    // See for examples of how
    // this can be achieved using events, but for the sake of brevity,
    // this sample just waits synchronously.

    // If ImageMagick failed, log the error but complete normally to avoid retrying.
    if (process.ExitCode != 0)
        _logger.LogError("ImageMagick exited with code {exitCode}", process.ExitCode);

    // Upload image to blurred bucket.
    using (Stream input = File.OpenRead(blurredImageFile))
        await _storageClient.UploadObjectAsync(
            s_blurredBucketName, data.Name, data.ContentType, input, cancellationToken: cancellationToken);

    string uri = $"gs://{s_blurredBucketName}/{data.Name}";
    _logger.LogInformation("Blurred image uploaded to: {uri}", uri);

    // Remove images from the file system.


// blur blurs the image stored at gs://inputBucket/name and stores the result in
// gs://outputBucket/name.
func blur(ctx context.Context, inputBucket, outputBucket, name string) error {
	inputBlob := storageClient.Bucket(inputBucket).Object(name)
	r, err := inputBlob.NewReader(ctx)
	if err != nil {
		return fmt.Errorf("NewReader: %v", err)

	outputBlob := storageClient.Bucket(outputBucket).Object(name)
	w := outputBlob.NewWriter(ctx)
	defer w.Close()

	// Use - as input and output to use stdin and stdout.
	cmd := exec.Command("convert", "-", "-blur", "0x8", "-")
	cmd.Stdin = r
	cmd.Stdout = w

	if err := cmd.Run(); err != nil {
		return fmt.Errorf("cmd.Run: %v", err)

	log.Printf("Blurred image uploaded to gs://%s/%s", outputBlob.BucketName(), outputBlob.ObjectName())

	return nil


// Blurs the file described by blobInfo using ImageMagick,
// and uploads it to the blurred bucket.
private static void blur(BlobInfo blobInfo) throws IOException {
  String bucketName = blobInfo.getBucket();
  String fileName = blobInfo.getName();

  // Download image
  Blob blob = storage.get(BlobId.of(bucketName, fileName));
  Path download = Paths.get("/tmp/", fileName);

  // Construct the command.
  Path upload = Paths.get("/tmp/", "blurred-" + fileName);
  List<String> args = List.of("convert", download.toString(), "-blur", "0x8", upload.toString());
  try {
    ProcessBuilder pb = new ProcessBuilder(args);
    Process process = pb.start();
  } catch (Exception e) {"Error: %s", e.getMessage()));

  // Upload image to blurred bucket.
  BlobId blurredBlobId = BlobId.of(BLURRED_BUCKET_NAME, fileName);
  BlobInfo blurredBlobInfo =

  byte[] blurredFile = Files.readAllBytes(upload);
  storage.create(blurredBlobInfo, blurredFile);
      String.format("Blurred image uploaded to: gs://%s/%s", BLURRED_BUCKET_NAME, fileName));

  // Remove images from fileSystem


// Blurs the given file using ImageMagick, and uploads it to another bucket.
const blurImage = async (file, blurredBucketName) => {
  const tempLocalPath = `/tmp/${path.parse(}`;

  // Download file from bucket.
  try {
    await{destination: tempLocalPath});

    console.log(`Downloaded ${} to ${tempLocalPath}.`);
  } catch (err) {
    throw new Error(`File download failed: ${err}`);

  await new Promise((resolve, reject) => {
      .blur(0, 16)
      .write(tempLocalPath, (err, stdout) => {
        if (err) {
          console.error('Failed to blur image.', err);
        } else {
          console.log(`Blurred image: ${}`);

  // Upload result to a different bucket, to avoid re-triggering this function.
  const blurredBucket = storage.bucket(blurredBucketName);

  // Upload the Blurred image back into the bucket.
  const gcsPath = `gs://${blurredBucketName}/${}`;
  try {
    await blurredBucket.upload(tempLocalPath, {destination:});
    console.log(`Uploaded blurred image to: ${gcsPath}`);
  } catch (err) {
    throw new Error(`Unable to upload blurred image to ${gcsPath}: ${err}`);

  // Delete the temporary file.
  const unlink = promisify(fs.unlink);
  return unlink(tempLocalPath);


// Blurs the given file using ImageMagick, and uploads it to another bucket.
function blurImage(
    Object $file,
    string $blurredBucketName
): void {
    $tempLocalPath = sys_get_temp_dir() . '/' . $file->name();

    // Download file from bucket.
    $image = new Imagick();
    try {
    } catch (Exception $e) {
        throw new Exception('Streaming download failed: ' . $e);

    // Blur file using ImageMagick
    // (The Imagick class is from the PECL 'imagick' package)
    $image->blurImage(0, 16);

    // Stream blurred image result to a different bucket. // (This avoids re-triggering this function.)
    $storage = new StorageClient();
    $blurredBucket = $storage->bucket($blurredBucketName);

    // Upload the Blurred image back into the bucket.
    $gcsPath = 'gs://' . $blurredBucketName . '/' . $file->name();
    try {
        $blurredBucket->upload($image->getImageBlob(), [
            'name' => $file->name()
        fwrite($log, 'Streamed blurred image to: ' . $gcsPath . PHP_EOL);
    } catch (Exception $e) {
        throw new Exception(
            sprintf('Unable to stream blurred image to %s: %s',


# Blurs the given file using ImageMagick.
def __blur_image(current_blob):
    file_name =
    _, temp_local_filename = tempfile.mkstemp()

    # Download file from bucket.
    print(f"Image {file_name} was downloaded to {temp_local_filename}.")

    # Blur the image using ImageMagick.
    with Image(filename=temp_local_filename) as image:
        image.resize(*image.size, blur=16, filter="hamming")

    print(f"Image {file_name} was blurred.")

    # Upload result to a second bucket, to avoid re-triggering the function.
    # You could instead re-upload it to the same bucket + tell your function
    # to ignore files marked as blurred (e.g. those with a "blurred" prefix)
    blur_bucket_name = os.getenv("BLURRED_BUCKET_NAME")
    blur_bucket = storage_client.bucket(blur_bucket_name)
    new_blob = blur_bucket.blob(file_name)
    print(f"Blurred image uploaded to: gs://{blur_bucket_name}/{file_name}")

    # Delete the temporary file.


require "tempfile"
require "mini_magick"

# Blurs the given file using ImageMagick.
def blur_image bucket_name, file_name
  tempfile =
    # Download the image file
    bucket = global(:storage_client).bucket bucket_name
    file = bucket.file file_name tempfile

    # Blur the image using ImageMagick tempfile.path do |image|
      image.blur "0x16"
    end "Image #{file_name} was blurred"

    # Upload result to a second bucket, to avoid re-triggering the function.
    # You could instead re-upload it to the same bucket and tell your function
    # to ignore files marked as blurred (e.g. those with a "blurred" prefix.)
    blur_bucket_name = ENV["BLURRED_BUCKET_NAME"]
    blur_bucket = global(:storage_client).bucket blur_bucket_name
    blur_bucket.create_file tempfile.path, file_name "Blurred image uploaded to gs://#{blur_bucket_name}/#{file_name}"
    # Ruby will remove the temp file when garbage collecting the object,
    # but it is good practice to remove it explicitly.

¿Qué sigue?

A fin de buscar y filtrar muestras de código para otros productos de Google Cloud, consulta el navegador de muestra de Google Cloud.