Skip to content
Merged
30 changes: 14 additions & 16 deletions functions/imagemagick/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
'use strict';

// [START functions_imagemagick_setup]
const gm = require('gm').subClass({imageMagick: true});
const sharp = require('sharp');
const fs = require('fs').promises;
const path = require('path');
const vision = require('@google-cloud/vision');
Expand Down Expand Up @@ -63,6 +63,7 @@ exports.blurOffensiveImages = async event => {
// Blurs the given file using ImageMagick, and uploads it to another bucket.
const blurImage = async (file, blurredBucketName) => {
const tempLocalPath = `/tmp/${path.parse(file.name).base}`;
const tempLocalBlurredPath = `/tmp/blurred-${path.parse(file.name).base}`; // 1. Declarar la variable
Comment thread
angelcaamal marked this conversation as resolved.
Outdated

// Download file from bucket.
try {
Expand All @@ -72,34 +73,31 @@ const blurImage = async (file, blurredBucketName) => {
} catch (err) {
throw new Error(`File download failed: ${err}`);
}
try {
await sharp(tempLocalPath)
.blur(16) // A sigma of 16 provides a strong blur equivalent to the old gm settings
.toFile(tempLocalBlurredPath);

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

// 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}/${file.name}`;
try {
await blurredBucket.upload(tempLocalPath, {destination: file.name});
await blurredBucket.upload(tempLocalBlurredPath, {destination: file.name});
console.log(`Uploaded blurred image to: ${gcsPath}`);
} catch (err) {
throw new Error(`Unable to upload blurred image to ${gcsPath}: ${err}`);
}

// Delete the temporary file.
return fs.unlink(tempLocalPath);
await fs.unlink(tempLocalPath);
return fs.unlink(tempLocalBlurredPath);
Comment thread
angelcaamal marked this conversation as resolved.
Outdated
};
// [END functions_imagemagick_blur]
2 changes: 1 addition & 1 deletion functions/imagemagick/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"dependencies": {
"@google-cloud/storage": "^7.0.0",
"@google-cloud/vision": "^4.0.0",
"gm": "^1.23.1"
"sharp": "^0.34.5"
Comment thread
angelcaamal marked this conversation as resolved.
},
"devDependencies": {
"@google-cloud/functions-framework": "^3.0.0",
Expand Down
66 changes: 40 additions & 26 deletions functions/imagemagick/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
'use strict';

const assert = require('assert');
const {execSync, spawn} = require('child_process');

Check failure on line 18 in functions/imagemagick/test/index.test.js

View workflow job for this annotation

GitHub Actions / lint

'execSync' is assigned a value but never used
const {Storage} = require('@google-cloud/storage');
const sinon = require('sinon');
const {request} = require('gaxios');
Expand All @@ -25,7 +25,7 @@

const BUCKET_NAME = process.env.FUNCTIONS_BUCKET;
const {BLURRED_BUCKET_NAME} = process.env;
const blurredBucket = storage.bucket(BLURRED_BUCKET_NAME);

Check failure on line 28 in functions/imagemagick/test/index.test.js

View workflow job for this annotation

GitHub Actions / lint

'blurredBucket' is assigned a value but never used

const testFiles = {
safe: 'bicycle.jpg',
Expand Down Expand Up @@ -65,7 +65,7 @@
// ImageMagick is available by default in Cloud Run Functions environments
// https://cloud.google.com/functions/1stgendocs/tutorials/imagemagick-1st-gen.md#importing_dependencies
// Manually install it for testing only.
execSync('sudo apt-get install imagemagick -y');
//execSync('sudo apt-get install imagemagick -y');
Comment thread
angelcaamal marked this conversation as resolved.
Outdated

describe('functions/imagemagick tests', () => {
before(async () => {
Expand All @@ -92,40 +92,54 @@
it('blurOffensiveImages detects safe images using Cloud Vision', async () => {
const PORT = 8080;
const {ffProc, ffProcHandler} = await startFF(PORT);

await request({
url: `http://localhost:${PORT}/blurOffensiveImages`,
method: 'POST',
data: {
let stdout;
try {
await request({
url: `http://localhost:${PORT}/blurOffensiveImages`,
method: 'POST',
data: {
bucket: BUCKET_NAME,
name: testFiles.safe,
data: {
bucket: BUCKET_NAME,
name: testFiles.safe,
},
},
},
});
ffProc.kill();
const stdout = await ffProcHandler;
});
} catch (err) {
console.error(
`[Cloud Function Error]: ${err.response?.data || err.message}`
);
throw err;
} finally {
ffProc.kill();
stdout = await ffProcHandler;
}
assert.ok(stdout.includes(`Detected ${testFiles.safe} as OK.`));
});

it('blurOffensiveImages successfully blurs offensive images', async () => {
const PORT = 8081;
const {ffProc, ffProcHandler} = await startFF(PORT);

await request({
url: `http://localhost:${PORT}/blurOffensiveImages`,
method: 'POST',
data: {
let stdout;
try {
await request({
url: `http://localhost:${PORT}/blurOffensiveImages`,
method: 'POST',
data: {
bucket: BUCKET_NAME,
name: testFiles.offensive,
data: {
bucket: BUCKET_NAME,
name: testFiles.offensive,
},
},
},
});

ffProc.kill();
const stdout = await ffProcHandler;

});
} catch (err) {
console.error(
`[Cloud Function Error]: ${err.response?.data || err.message}`
);
throw err;
} finally {
ffProc.kill();
stdout = await ffProcHandler;
}
assert.ok(stdout.includes(`Blurred image: ${testFiles.offensive}`));
assert.ok(
stdout.includes(
Expand Down Expand Up @@ -164,7 +178,7 @@

after(async () => {
try {
await blurredBucket.file(testFiles.offensive).delete();
// await blurredBucket.file(testFiles.offensive).delete();
Comment thread
angelcaamal marked this conversation as resolved.
Outdated
} catch (err) {
console.log('Error deleting uploaded file:', err.message);
}
Expand Down
Loading