Open source address
github: https://github.com/liujinpen/picgo-plugin-compress-tinypng.git
npm: https://www.npmjs.com/package/picgo-plugin-tinypng
Foreword
When writing a personal blog, you need to upload pictures to the picture bed. PicGo is a pretty good tool, but when you find that the pictures are large in size during use, it will waste cloud storage space because you don’t need such a high resolution. Before, I chose to manually compress larger image files, which was very troublesome.
Fortunately, PicGo itself supports plug-ins. After searching, I found that there is already a plug-in that supports compression: picgo-plugin-compress, but PicGo-Core starts from v1.5.0
, and the bottom layer of the request package starts from Request-Promise -Native has been transferred to axios, so this plugin will report an error when used after PicGo client version 2.3.0, and the author has not updated it for a long time.
After learning about tinify, I decided to develop a picture compression plug-in adapted to PicGo.
Compression effect
tinify official: The impact of compressed pictures on vision is almost invisible, but there is a very big difference in file size.
There are few test samples here, but the effect can already be felt:
-
Original image: 1.78MB -> Compressed: 511.9KB
-
Original image: 27.4KB -> Compressed: 11.5KB
tinify-API usage
tinify provides developers with a variety of API usage methods. You can register your email address to obtain an API key. An API key is available for 500 free times per month. For specific API usage, please refer to https://tinify.cn/developers.
PicGo plug-in development
The development process is described in more detail in the official plug-in development document, which requires a certain js foundation.
1. Use plugin template
To use the plugin template, you first need to install picgo globally
npm install picgo -g
Initialize the project
picgo init plugin tinypng Note: tinypng is the project name
The creation process can customize options as needed, from top to bottom:
- plugin name
- plugin description
- author
- The component corresponding to the developed plug-in (see the document for details), what needs to be done to compress the image is to convert the image into a buffer and provide it to picgo, so here select the transformer component
- Whether CLI plug-in (select No if it needs to be used in the graphical client)
- Use TypeScript or JavaScript (the official recommendation is that TS can have better syntax prompts. In fact, if you develop in WebStorm, the experience of using JS is also very good)
- Whether the plugin needs to configure shortcut keys
After the project is created, you can use the IDE for development.
2. Plug-in configuration items
Using tinify’s API requires a key, so configure the entry in the plugin:
const config = ctx => {<!-- --> let config = ctx.getConfig('tinypng') || ctx.getConfig('picgo-plugin-tinypng') if (!config) {<!-- --> config = {<!-- -->} } ctx.log.info('read config:', config) return [{<!-- --> name: 'key', // configuration name type: 'input', // configuration type, input is displayed as an input box default: config.key || null, // default value required: true, // is required message: 'Fill in the API Key of tinypng' // placeholder }] }
3. Compressed file
When we drag a local image into PicGo, what we get is the path of the local file.
Compressed logic:
- Use the
readFile
method of the fs-extra library to convert the image into a binary stream; - Construct the request required by tinify (formatted API key, file buffer, other parameters, etc.)
- Use PicGo’s request library to send requests
- Get the compressed image address returned by tinify
- Use PicGo’s request library to download the picture (the file buffer is obtained)
- Construct the output format required by the transformer component
So far, most of the work of the plug-in has been completed. After returning the result of our construction, PicGo can upload the compressed file to the image bed.
/** * Read the local image, upload it to tinypng for compression, get the compressed url, and download the image buffer * * @param ctx PicGo * @param imageUrl local image path * @param key api key in configuration * @returns {Promise<Buffer>} */ async function tinypngKeyCompress(ctx, imageUrl, key) {<!-- --> return await fs.readFile(imageUrl).then(fileData => {<!-- --> // 1. Refer to https://tinify.cn/developers/reference for the format of the construction request parameters (request to tinypng) const bearer = Base64. stringify(Utf8. parse(`api:${<!-- -->key}`)) const fetchOptions = {<!-- --> method: 'POST', url: 'https://api.tinify.com/shrink', json: true, resolveWithFullResponse: true, headers: {<!-- --> Host: 'api.tinify.com', Authorization: `Basic ${<!-- -->bearer}` }, data: fileData } // 2. Send compression request return ctx.request(fetchOptions).then(response => {<!-- --> // 3. Get the url of the compressed image if (response.status & amp; & amp; response.status >= 200 & amp; & amp; response.status <= 299) {<!-- --> const location = response. headers. location ctx.log.info('compressed address:', location) // 4. Get the network image from the url return utils.fetchImage(ctx, location).then(res => {<!-- --> // 5. Obtain the compressed image buffer and construct the format required by picGO return utils.getImageInfo(imageUrl, res.data) }) } throw new Error('compression error') }) }) }
Related Tools
/** * Get image information * @param imageUrl * @param buffer * @returns {<!-- -->{fileName: string, width: number, buffer, extname: string, height: number}} */ function getImageInfo(imageUrl, buffer) {<!-- --> const {<!-- -->width, height} = imageSize. imageSize(buffer) return {<!-- --> buffer, width: width, //width height: height, //height fileName: path.basename(imageUrl), // file name extname: path.extname(imageUrl), //extension name } } /** * Get file information according to url * @param imageUrl * @returns {<!-- -->{fileName: string, extname: string}} */ function getUrlInfo(imageUrl) {<!-- --> return {<!-- --> fileName: path. basename(imageUrl), extname: path.extname(imageUrl) } } /** * Download network pictures * @param ctx * @param url * @returns {*} */ function fetchImage(ctx, url) {<!-- --> return ctx.request({<!-- --> method: 'GET', url, encoding: null, resolveWithFullResponse: true, responseType: 'arraybuffer' }) }
4. Complete the plug-in process
This part of the code needs to be organized according to the PicGo plug-in development requirements
module.exports = (ctx) => {<!-- --> const handle = ctx => {<!-- --> // Get the configured key const config = ctx.getConfig('tinypng') || ctx.getConfig('picgo-plugin-tinypng') const key = config['key'] // input is a list of paths, and the pictures of each path are compressed first const tasks = ctx.input.map(imageUrl => {<!-- --> ctx.log.info('Image address:' + imageUrl) // call compression method return tinypng.tinypngKeyCompress(ctx, imageUrl, key).then(res => {<!-- --> return res }) }) return Promise.all(tasks).then((output) => {<!-- --> ctx. output = output return ctx }) } const config = ctx => {<!-- --> let config = ctx.getConfig('tinypng') || ctx.getConfig('picgo-plugin-tinypng') if (!config) {<!-- --> config = {<!-- -->} } ctx.log.info('read config:', config) return [{<!-- --> name: 'key', // configuration name type: 'input', // configuration type, input is displayed as an input box default: config.key || null, // default value required: true, // is required message: 'Fill in the API Key of tinypng' // placeholder }] } const register = () => {<!-- --> ctx.helper.transformer.register('tinypng', {<!-- -->handle}) } return {<!-- --> transformer: 'tinypng', register, config } }
Local testing
If the development template uses JS, you can directly go to PicGo main interface->plug-in settings->import icon in the upper right corner->select the source code directory after the development is completed.
Yes, select the source code directory, and PicGo can successfully load the plug-in. After the loading is complete, it needs to be restarted to take effect.
After importing the plug-in, you need to enable the transformer-tinypng option
(disabled means the enable is successful):
Configure the plugin -picgo-plugin-tinypng
option to fill in the requested API key and picture bed configuration name (custom):
NPM publish
The plug-in of this article has been released, just search for tinypng in the plug-in settings of PicGo.
For npm publishing, please refer to How to publish your own npm package.
In this way, others can search for it in PicGo’s plug-in settings.
Reference
Develop a PicGo plugin
Getting Started with PicGo Plugin Development
PicGo Official Plugin Development Guide
PicGo configures image compression (no longer available)
picgo-plugin-compress (plugin has been stopped)