Giter VIP home page Giter VIP logo

image-blob-reduce's Introduction

image-blob-reduce - downscale blobs with images inside

CI NPM version

Wrapper for pica to work with blobs, with some sugar.

This is pica wrapper for convenient work with images from file input fields. While pica works with raw bitmaps, this package operates with "image files". Additional features are:

  • [jpeg] Apply orientation to downscaled result.
  • [jpeg] Keep metadata, but with patched orientation & removed original color profile.
  • Easy to monkey-patch for your needs.

Demo

Install

npm install image-blob-reduce

Known issues

This package is not compaible with some minification options. If you use terser, disable evaluate or all compress options:

  • { compress: { evaluate: false } }
  • { compress: false }

This should not cause notable assets increase

Usage

const reduce = require('image-blob-reduce')();

//...

reduce
  .toBlob(image_blob, { max: 1000 })
  .then(blob => { ... });

If you load prebuild script in browser, use window.ImageBlobReduce

API

new ImageBlobReduce([options])

Create new reducer. Options:

  • pica - instance of pica, if you wish different defaults or shareable webworkers pool.

Short call: require('image_blob_reduce')()

.toBlob(in_blob, options) => Promise(out_blob)

Downscale image to fit into max*max size. If blob contains jpeg, then orientation is applied and metadata from original image reused (with minimal change).

Options:

  • max - max allowed image size.
  • pica .resize() options - alpha, unsharpAmount, unsharpRadius, unsharpThreshold, cancelToken

.toCanvas(in_blob, options) => Promise(out_canvas)

The same as .toBlob(), but with canvas output.

.before(method_name, hook_fn)

Inject your custom handler before specified method. See .init() source code for example.

.after(method_name, hook_fn)

The same as .before(), but handler is injected after specified method.

.use(plugin_init, ...params) => this

Sugar to simplify assign of external plugins. Just calls plugin_init(this, ...params).

.utils

require('./lib/utils'), to simplify modifications.

Reexports

  • ImageBlobReduce.pica => require('pica') - useful to customize pica options.

Customization

Since it's difficult to implement all possible options, this package is specially designed for easy customization. See source code first.

  • You can inherit class & replace existing methods.
  • You can add extra actions before/after existing method.
  • You can override existing methods of instance.

For example, if you wish force output to be always jpeg with some quality:

const reducer = require('image-blob-reduce')();

reducer._create_blob = function (env) {
  return this.pica.toBlob(env.out_canvas, 'image/jpeg', 0.8)
    .then(function (blob) {
      env.out_blob = blob;
      return env;
    });
};

Or rewrite scaling logic, introducing min option instead:

const reducer = require('image-blob-reduce')();

reducer._calculate_size = function (env) {
  const scale_factor = env.opts.min / Math.min(env.image.width, env.image.height);

  if (scale_factor > 1) scale_factor = 1;

  env.transform_width = Math.max(Math.round(env.image.width * scale_factor), 1);
  env.transform_height = Math.max(Math.round(env.image.height * scale_factor), 1);
  
  return env;
};

image-blob-reduce's People

Contributors

nloehlein-godaddy avatar rlidwka avatar tanmuhittin avatar zauni avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

image-blob-reduce's Issues

Could not find a declaration file for module 'image-blob-reduce'

I get this error when trying to use the module. Here's my code:

const reduce = require('image-blob-reduce');

export async function reduceBlob(originalBlob) {
  await reduce
  .toBlob(originalBlob, { max: 300 })
  .then(blob => { 
    console.log(blob);
    return blob;
  });
}

Not sure how to solve this issue :P

Thank you!

Chrome image is black , works fine on Safari

Hi,

I am using Chrome Version 93.0.4577.82 (Official Build) (x86_64) on OSX 11.6

Screen Shot 2021-09-21 at 5 44 25 pm

d

The same image in Safari works fine. Any ideas. I have had others hit it with what seems to be the same version of chrome and it works for them.

could there be some security setting on my machine that causes this?

thanks

CRA fix "ReferenceError: a is not defined" with CRACO

I'm creating this issue just for latecomers using create-react-app run into the issue mentioned in doc.

If you are using create-react-app, you can either eject it and apply the change to webpack.config.js as instructed above, or you can extend/modify CRA's webpack config with CRACO

To apply the same change:

// craco.config.js
module.exports = {
    plugins: [
        {
            plugin: {
                overrideWebpackConfig: ({ // https://github.com/gsoft-inc/craco/issues/44#issuecomment-573554956
                    webpackConfig,
                }) => {
                    const minimizerIndex = webpackConfig
                        .optimization
                        .minimizer
                        .findIndex(item => item.options.terserOptions);

                    webpackConfig
                        .optimization
                        .minimizer[minimizerIndex]
                        .options
                        .terserOptions
                        .compress
                        .evaluate = false;

                    return webpackConfig;
                },
            },
        },]
};

toBlob then not working without debugger

Hello there,
while searching for a library to compress images taken from camera before uploading i found this project. I tried with pica first but went into some problems with the exif data when pictures were taken with apple products.
Now i got everything i want to work with your example but when i try this on mobile devices it does not work anymore. Additionally i found out that it even does not work, when i disable the developer console in firefox.

Below is a minimal example of the code. Do you know any reason for this to fail? While asking google on this all i found some hints that this could be come from any debug prints to console while no console exists when developer tools are not enabled.

<!DOCTYPE html>
<html lang="de">
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<title>Test image resize</title>
	<!-- JS -->
	<script src="/js/jquery.js" type="text/javascript"></script>
	<script src="/js/image-blob-reduce.js" type="text/javascript"></script>
</head>
<body>
	<form id="form" method="post">
		<button type="submit" disabled style="display: none" aria-hidden="true"></button>
		<div class="grid">
			<div class="grid-1">
				<label>
					<span class="fieldname">Debug</span>
					<input type="text" name="debug" id="debug" />
				</label>
				<label>
					<span class="fieldname">Bild</span>
					<input type="file" name="image_orig" id="image-filename" accept="image/*" />
				</label>
				<label>
					<span class="fieldname">Speichern</span>
					<button type="button" id="submit">Speichern</button>
				</label>
			</div>
			<div class="grid-1">
				<div class="image" style="max-width: 130px">
					<img id="image" src="images/person-bild-dummy.jpg" />
				</div>
			</div>
		</div>
	</form>
<script>
var reducer;
var image_new = false;


function create_resizer() {
  var opts = [ 'js', 'wasm', 'ww' ];

  reducer = new window.ImageBlobReduce();
}


function reduce_input(image_url) {
  //$('#image')[0].src = URL.createObjectURL(blob);
  $('#debug')[0].value = "reduce_input start";
  reducer.toBlob(image_url,
    {
      max: 200,
      unsharpAmount: 80,
      unsharpRadius: 0.6,
      unsharpThreshold: 2,
    }
  )
  .then(function (blob) {
    $('#debug')[0].value = "reduce_input resize finished";
    //image_new = blob;
    $('#image')[0].src = URL.createObjectURL(blob);
  });
  $('#debug')[0].value = "reduce_input finished";
}

create_resizer();

$('#image').on('click', function () {
  $('#image-filename').trigger('click');
});

$('#submit').on('click', function () {
  var post;
  post = $('#form').serialize();

  if (image_new) {
    var reader = new FileReader();
    reader.readAsDataURL(image_new);
    post += '&image=' + encodeURIComponent(reader.result);
  }

  $.post('/submit.php', post, function(data, status, xhr) {
    location.reload();
  });
});

$('#image-filename').on('change', function () {
  var files = $(this)[0].files;

  if (files.length === 0) { return; }

  reduce_input(files[0]);
});
	</script>
</body>
</html>

mozjpeg encoding

Thanks again for this very useful library. Just wondering if there is a way to encode output as mozjpeg to further reduce size without having to resort to another utility (with additional jpeg compression). Currently I am saving output as high jpeg quality (somewhat defeats purpose of blob reduce) > uploading to server > recompress with mozjpeg. It would be great if this could be done in pica during the blob > jpeg transformation (or with blob > mozjpeg javascript library).

Request for update to documentation.

Is this in bytes

Downscale image to fit into max*max size. If blob contains jpeg, then orientation is applied and metadata from original image reused (with minimal change).

Options:

max - max allowed image size.

Is Pica a requirement or is it bundled?

I am hitten an error that seems to suggest Pica is not present. I see the module in my node_modules, but this code

// file is an instance of File which is also an instance of Blob
imageReduce.toBlob(file, { max: 1000 })
    .then(blob => { 
        console.log("***BLOB", blob);
    });

yields this error

Uncaught (in promise) TypeError: image_blob_reduce__WEBPACK_IMPORTED_MODULE_5___default.a.toBlob is not a function

gif converted to png

processing a jpg results in a jpg.
processing a png results in a png.

However, processing a gif results in a png. According to both mime checks on the server and checking the resultant file with IrfanView.

Is there a way to prevent this from happening? If not, what is the benefit for the why the conversion should occur? It's actually increasing my file size.

Thanks!

Black line with big images

Hello

Reducing some big images to not so big (but still big images) a black line appears in the resized image.

To reproduce try {max:2880, unsharpAmount: 80, unsharpRadius: 0.6, unsharpThreshold: 2 } with this image:

Downsizing to max:4096 already shows a black line, but in different place.

https://imagecompression.info/test_images/
RGB 16 bits set, big_building or big_tree images.

Thanks

Detect auto-rotation

Not sure if this issue is relevant to your library. So this may be a non-issue.

But we've ran into a problem where the image loaded from an element would be rotated by the browser based on EXIF data.

We found a solution to this in another library:
https://github.com/blueimp/JavaScript-Load-Image/blob/v3.0.0/js/load-image-orientation.js#L37-L53

Just wanted to share this code with you, in case you run into the same problem.

I've used pica for a while and are very happy. Thanks for a great library! ๐Ÿ…

/**
 * Determine if the browser defaults to auto-rotating images based on EXIF orientation when
 * loading images into an <img> element (e.g. when using the web API method `Image`).
 *
 * This neat trick is inspired by:
 * https://github.com/blueimp/JavaScript-Load-Image/blob/v3.0.0/js/load-image-orientation.js#L37-L53
 * (versions >3.0 take even more issues into account, but we don't need that)
 *
 * The image data consists of a black 2px wide, 1px tall JPEG with the following meta information set:
 * - EXIF orientation: 6 (camera rotated 90ยฐ CW)
 *
 * @return {Promise} Resolves with `true` if HTML images are auto-rotated
 */
let determineAutoRotation = function() {
  if (!autoRotationPromise) {
    autoRotationPromise = new Promise((resolve, reject) => {
      let img = document.createElement('img');
      let rotatedImageUrl = 'data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQ' +
        'ESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE' +
        'BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB' +
        'AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACE' +
        'QEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAA' +
        'AAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==';

      img.onload = function() {
        // `true` if image is rotated according to EXIF orientation
        resolve(img.width === 1 && img.height === 2);
      };

      img.onerror = function() {
        reject(new Error('Determining image auto-rotation failed'));
      };

      img.src = rotatedImageUrl;
    });
  }

  return autoRotationPromise;
};

Simplify passing unsharp opions

Currently users are expeced to modify processing with ease. But probably passing unsharp options need something special.

At first glance, possible alternatives are:

  • pass unsharp params the same way as { max: ... }
    • need to limit list of allowed params (currently unsharpAmount, unsharpRadius, unsharpThreshold).
  • pass unsharp params as { max: ..., pica_opts: ... } - separate object to merge on pica call.
    • if user doesn't knows about pica, this looks unnatural.
  • suggest to pass pica into construcor with overrien .resize()
    • mad science :)

Additional quesions:

  • do we need to pass pica's alpha? It's logic is hardcoded now. Can be changed with _.transform() override only.
  • do we need to pass jpeg quality option? Can be changed with .toBlob() override, not a big deal.

Output is blank when running on mobile

Hi, I have the following function that I am using to get a blob URL to use inside some <img /> elements in the application:

import ImageBlobReduce from 'image-blob-reduce';

export const resizeBlobImage = (file: Blob, size?: number): Promise<string> =>
    new ImageBlobReduce()
        .toBlob(file, {
            max: size ?? 1000,
        })
        .then(blob => URL.createObjectURL(blob));

I am using this to display previews of files selected by the user for upload.

Although this works perfectly on a desktop, the previews are blank when I run the application on Google Chrome on Android.

Has anyone else encountered this issue? Is there any potential fix that I can use?

Add example to use ES6 Import

Currently the docs (readme.md) uses the below example

const reduce = require('image-blob-reduce')();

It would be awesome if you could add document on how to use the same when using ES6 Module

// Something like this (Not sure if this is the right way to do)
import Reduce from "image-blob-reduce"
const reduce = Reduce()

Using esbuild instead of Rollup fixes known terser bug

Hello @puzrin, locally I tried to build this library with esbuild instead of Rollup and this fixed the known issue with terser. Would you be interested in a PR to change the build from Rollup to esbuild?

Locally I built the ESM version with esbuild by issuing this command:
npx esbuild index.js --bundle --format=esm --outfile=dist/image-blob-reduce.esm.mjs and by using npm link I could try it out on a local project which is suffering from the terser bug, but as said with the esbuild version this bug did not appear.

The only problem with changing bundlers is that there could be other subtle problems coming up, but in my limited testing with the ESM version it was working just fine. But maybe you have more projects (best would be CJS projects) to test some new bundled versions.

Update: I saw that esbuild does not generate UMD bundles, so maybe these should be generated by Rollup like before. And just the ESM bundle which is also exported by the package.json will be generated by esbuild.

Calculate size in separate method?

This may slightly reduce size of code to override.

ImageBlobReduce.prototype._calculate_size = function (env) {
  var scale_factor = env.opts.max / Math.max(env.image.width, env.image.height);

  if (scale_factor > 1) scale_factor = 1;

  env.out_width = Math.max(Math.round(env.image.width * scale_factor), 1);
  env.out_height = Math.max(Math.round(env.image.height * scale_factor), 1);
};

ImageBlobReduce.prototype._transform = function (env) {
  env.out_canvas = this.pica.options.createCanvas(env.out_width, env.out_height);

  // By default use alpha for png only
  var pica_opts = { alpha: env.blob.type === 'image/png' };

  // Extract pica options if been passed
  this.utils.assign(pica_opts, this.utils.pick_pica_resize_options(env.opts));

  return this.pica
    .resize(env.image, env.out_canvas, pica_opts)
    .then(function () { return env; });
};

ESM Module CLI Warning

Great library. But, the Angular CLI gives a warning related to CommonJS.

WARNING in /...REDACTED...dia-input.component.ts depends on 'image-blob-reduce'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies

I'm importing as:

import imageReducer from 'image-blob-reduce';
import pica from 'pica';

If I change the import to import imageReducer from 'image-blob-reduce/dist/image-blob-reduce.min.js' then my bundle size increases by 20kb (but the warning goes away).

It works either way so this is not a high priority.

Post your customization use-cases here

As you may note, reducer has very few resize options. This is intended, because it's very difficult to predict all possible needs and keep api clean.

If you had to extend default behaviour - please post description of your concrete use case here. This may help to plan new options.

Add min to options

In my case I need 300px x 300px square images. So after resizing, I cut the images to 300px x 300px.

If I cut the image to square before resizing It consumes a lot of ram. So I prefer cutting after resize operation.

For this purpose I need short edge to be 300px. So, in such case min option is needed.

After some digging I found that it must be added to _transform function :

var scale_factor = env.opts.max / Math.max(env.image.width, env.image.height);

slow image resizing

Hello,

I am trying to use image-blob-reduce to create thumbnails by resizing input images.
But I discovered that it takes very long to resize images (up to 2 seconds for ~4MB jpeg)

This is the code I use for testing

var reducer = new window.ImageBlobReduce();

fetch("https://images.pexels.com/photos/1670187/pexels-photo-1670187.jpeg?fm=jpg&w=3840&h=5760")
  .then(function (response) {
    return response.blob();
  })
  .then(function (blob) {
    var start = window.performance.now();
    reducer
      .toBlob(blob, {max: 500})
      .then(function (blob) {
        console.log(window.performance.now() - start);
      });
  });

https://jsfiddle.net/c46uz3hp/

Running this takes around 1.6seconds (up to 2seconds), I have tested this on a MacBook Pro (2,5 GHz Dual-Core Intel Core i5) with Safari and Chrome.

Are these times expected? It seems very slow to me.
Any advice on how I can improve this?

Thank you!

Add new image dimension instead of overriding the transform function

This module should support resizing out of the box without needing to re-implement the entire _transform function.

The usage could simply be :

const reduce = require('image-blob-reduce')();

//...

// only specify width, causing height to be calculated proportionally
reduce
  .toBlob(image_blob, { max: 1000, width: 800 })
  .then(blob => { ... });

// only specify height, causing width to be calculated proportionally
reduce
  .toBlob(image_blob, { max: 1000, height: 500 })     // width calculated proportionally
  .then(blob => { ... });

// specifying both will cause the image to have custom scaling
reduce
  .toBlob(image_blob, { max: 1000, width: 800, height: 200 })
  .then(blob => { ... });

Error when used in create-react-app build (but not development)

I'm pretty new to web development, so I'm not sure if this is something you can help with. I'm getting an error of the form:

ReferenceError: o is not defined
    at e (blob:http://localhost:5000/2bdae74b-66c2-443f-8a8f-6b18edc7fb4c:1:313)
    at blob:http://localhost:5000/2bdae74b-66c2-443f-8a8f-6b18edc7fb4c:1:352

The stack trace is all minified, but the top looks like this:

e (2bdae74b-66c2-443f-8a8f-6b18edc7fb4c:formatted:23)
(anonymous) (2bdae74b-66c2-443f-8a8f-6b18edc7fb4c:formatted:27)
Worker Created (async)
t.exports (image-blob-reduce.esm.mjs:1613)
w (image-blob-reduce.esm.mjs:1689)
n.acquire (image-blob-reduce.esm.mjs:575)
(anonymous) (image-blob-reduce.esm.mjs:1933)
(anonymous) (image-blob-reduce.esm.mjs:1932)
Promise.then (async)
(anonymous) (image-blob-reduce.esm.mjs:1930)
(anonymous) (image-blob-reduce.esm.mjs:2016)

Is this expected to work with Create React App? Why might it be failing only in a production build? As far as I can tell, everything is fine until I get to a call to toBlob().

compressed image corrupted (firefox 89)

Running into a new issue I've never seen before. Using Firefox for Windows 89.0 (64-bit). Not sure when it started happening in firefox.

I have my code setup where a user selects a file input. When they press a button, javascript checks to see if an image is > 1024 pixels. If it is bigger than 1024, it calls image-blob-reduce on the file and compresses the image and attaches the resized image to the form before uploading.

Now, the image is no longer getting uploaded correctly. The resized image is now black and green vertical stripes. I noticed in the debugging console the following error message:

Blocked {URL} from extracting canvas data because no user input was detected.
image-blob-reduce_v3.js:1922:29
image-blob-reduce_v3.js:2250:17

As you can see I've tried using v3 hoping this fixed the issue which it didn't.

This seems to be the same issue referenced here (you can see the green and black stripes in the screenshot attached):
https://githubmemory.com/repo/fengyuanchen/compressorjs/issues/122

My same exact site/JS code/picture works fine in Chrome Version 91.0.4472.77 (Official Build) (64-bit). So it seems to be a firefox issue.

Any thoughts? Thanks!

Uncaught TypeError: __webpack_require__(...) is not a function

I'm developing an app using Vue.js 2 and I'm including the const reduce = require('image-blob-reduce')() in a View component. Page didn't load and consoled out an error (Uncaught TypeError: webpack_require(...) is not a function).

Tried removing the () in require('image-blob-reduce')() and when it hits the reduce.toBlob function (refer to the function below), it gives an error saying reduce.toBlob is not a function .

// The function
reduce.toBlob(file, { max: 1000 }).then(blob => {
          console.log(blob)
})

I'm not familiar with webpack and I don't have any webpack configuration file. There are babel.config.js and vue.config.js. Not sure if anything needs to be added within these files or if I'm required to create a webpack.config.js .

Would appreciate it if anyone could help me with this issue.

Simple html example

Any chance of a simple example without all JS embedded into the index.js file?

eg. just the normal dist js used <script src="image-blob-reduce.min.js"></script>, all additional js in <script> inside index.html.

This would make it easier for people new to JS understand how to initialize and use the code, since example in readme currently uses require and that is not part of the package if you're using a browser and not NodeJS

Pica v8 upgrade

Pica has updated to v8 with the breaking change that .quality has been replaced with .filter.

Looking through this codebase I don't think any changes are required to support v8?

UI is blocking on Safari

Hello,

on Safari (Version 15.4 (15613.1.17.1.13, 15613)) the UI is blocked when using image-blob-reduce.
Here is some example code to reproduce

var reducer = new window.ImageBlobReduce();

function imageBlobReduce() {
  console.log("start")
  fetch("https://images.pexels.com/photos/1670187/pexels-photo-1670187.jpeg?fm=jpg&w=3840&h=5760")
    .then(function (response) {
      return response.blob();
    })
    .then(function (blob) {
      return reducer.toBlob(blob, {max: 500});
    })
    .then(() => console.log("done"));
}
<body onload="imageBlobReduce()">
  <img 
    width="100px" 
    src="https://i.stack.imgur.com/kOnzy.gif"
  />
</body>

jsfiddle

In the example the loading gif is blocking for around 1-2 seconds while the image is being resized.

Anything I can do to avoid this? Or is this a bug?

Bug in scaling logic example in documentation

Hi, thanks for this amazing library. I was having some problems using the example provided in the documentation to change scaling logic. After looking at the actual function I finally got it to work after adding return Promise.resolve(env); at the end of the function. I would recommend updating the documentation.

reducer._calculate_size = function (env) {
.
.
.
	return Promise.resolve(env);
};

Set output quality and type

Hi,

I may have overlooked something, however there does not seem to be any way to pass any parameters to the underlying PICA type and quality setting when using toBlob:

pica.resize(from, to)
  .then(result => pica.toBlob(result, 'image/jpeg', 0.90))

If there is a way to do this, I would appreciate some pointers and perhaps an example in the readme.

If not, I would suggest the following syntax:

reduce().toBlob(event.target.files[0], {
    max: 1280,
    ...
    quality: 0.8,
    type: 'image/jpeg'
})

Thanks,
Anthony Edmonds

Uncaught ReferenceError: sp is not defined

It's working locally but after deploying to production I'm getting this exception when trying to await reduce.toBlob(file, { max: 1000 });.

I'm using Chrome on Macbook pro.

toBlob is not a function

I tried to use pica but Exif was a big pain. Thank you for this package :)

When I try to use it using the code below

            let fr = new FileReader();
            const reduce = require('image-blob-reduce')();
            reduce.toBlob(fr.readAsBinaryString(file), {
                max: 300,
                unsharpAmount: 90,
                unsharpRadius: 0.6,
                unsharpThreshold: 2 })
                .then(blob => {
                    addThumbnail(blob)
                });

I got error
Uncaught (in promise) TypeError: reduce.toBlob is not a function

I could not get it worked. Is it me or something is wrong?

Web worker compatibility

I would like to be able to process large batches of images - maybe as many as 100 - using a web worker script, so that I don't tie up the UI thread. When I tried, I discovered that this library uses some DOM features (creating an <img>) and APIs (eg window.URL) that there's no way of using with a worker.

I wanted to use this library rather than pica so that the metadata would be retained, as it's extremely useful for the use case (a PWA for engineers doing kitchen appliance fittings - they have to take photos during their work). Before I try and implement something myself, do you know of any way to achieve what I'm trying to do without rewriting most of it?

EXIF not preserved

Hi, I don't think EXIF data is being copied correctly. Here is a sample image containing EXIF data:

exif

I noticed the demo strips all of the EXIF data (I think it should only strip orientation and color profile if working properly):

https://nodeca.github.io/image-blob-reduce/

Curiously enough I found your comment on stack overflow regarding 20 bytes header:

https://stackoverflow.com/questions/18297120/html5-resize-image-and-keep-exif-in-resized-image

I also noticed copyExif.js (latest answer) assumes 2 byte header and it seems to copy EXIF properly.

https://codepen.io/tonytonyjan/project/editor/XEkOkv

I am not sure if the reason image-blob-reduce is not preserving EXIF is due to this or something else?

Edit 1: also I'm not sure I understand the following snippet of code. The text 'ICC_PROFILE' is 11 characters but the slice is 4 to 11 = 7 characters?

          var hdr = data.slice(segment.offset + 4, segment.offset + 11);
          if (String.fromCharCode.apply(hdr) === 'ICC_PROFILE') {
            return false;

Edit 2: OMG, the entire jpeg_attach_orig_segments function is riddled with bugs! Was it ever tested? I finally got it to work by changing these lines :

added ! (not)

    if (!image_traverse.is_jpeg(data_out)) return Promise.resolve(env);`

ditched flaky string comparison

          if (segment.code === 0xE2) return false;

changed blob to out_blob, data to data_out and slice from 20 to 2:

      env.out_blob = new Blob(
        [ data_out.slice(0, 2) ].concat(segments).concat([ data_out.slice(2) ]),
        { type: 'image/jpeg' }
      );

However, it doesn't strip orientation now, seems that should be handled here as opposed to other functions?

Handle more orientation changes

We've used pica for a while and are very happy with it! It's an awesome library ๐Ÿ…

Maybe I'm reading the code wrong, but it seems like all orientation changes aren't handled by this library.

On top of Pica we are using our own orientation code. I just wanted to share it with you, in case you find it useful!

[redacted]

Pass-through mode for `.toBlob()`

Currently .toBlob() always "rewrites" image, even if it may stay intact. For example, pass-through may be useful when pre-processing is used only to reduce transfer size, and server does final processing anyway.

Examples:

  • Image may be "skipped" if not JPEG (technical drafts in PNG format)
  • JPEG may be skipped:
    • if size is small
    • if downscale (? and rotate) not required
    • ...

Note, mime-type and file size check can be done externally. We should focus first on use-cases, which can not be implemented without this package.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.