Skip to content

Instantly share code, notes, and snippets.

@remy
Last active April 5, 2024 12:49
Show Gist options
  • Star 92 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save remy/784508 to your computer and use it in GitHub Desktop.
Save remy/784508 to your computer and use it in GitHub Desktop.
Trims the surrounding transparent pixels from a canvas
// MIT http://rem.mit-license.org
function trim(c) {
var ctx = c.getContext('2d'),
copy = document.createElement('canvas').getContext('2d'),
pixels = ctx.getImageData(0, 0, c.width, c.height),
l = pixels.data.length,
i,
bound = {
top: null,
left: null,
right: null,
bottom: null
},
x, y;
for (i = 0; i < l; i += 4) {
if (pixels.data[i+3] !== 0) {
x = (i / 4) % c.width;
y = ~~((i / 4) / c.width);
if (bound.top === null) {
bound.top = y;
}
if (bound.left === null) {
bound.left = x;
} else if (x < bound.left) {
bound.left = x;
}
if (bound.right === null) {
bound.right = x;
} else if (bound.right < x) {
bound.right = x;
}
if (bound.bottom === null) {
bound.bottom = y;
} else if (bound.bottom < y) {
bound.bottom = y;
}
}
}
var trimHeight = bound.bottom - bound.top,
trimWidth = bound.right - bound.left,
trimmed = ctx.getImageData(bound.left, bound.top, trimWidth, trimHeight);
copy.canvas.width = trimWidth;
copy.canvas.height = trimHeight;
copy.putImageData(trimmed, 0, 0);
// open new window with trimmed image:
return copy.canvas;
}
@joloco
Copy link

joloco commented Feb 13, 2012

Great code, just what I needed! The only thing I changed was that bound.bottom and bound.right both need incrementing by one after the loop, or the bottom-most and right-most rows of pixels get trimmed off.

@jamespcole
Copy link

Awesome, thanks for that

Copy link

ghost commented Apr 26, 2013

Hello remy, just wondering if is possible to add an example.
Thank you for the code.

@smaier
Copy link

smaier commented Jun 11, 2014

thanks a lot! Great

@EricJLD
Copy link

EricJLD commented Jun 15, 2014

Hello Remy, your tool seems to be what I am looking for. great I hv been spending my wknd browsing over many sites.
however, i'm very new in html/js ...
may I you to add some more lines to make it a full concrete example with an image file that I could copy/past and make work. then, I will adapt to my need ? sorry for this request but it's necessary for me to get started. thk you very much in avance. Eric

@drumfiend21
Copy link

Using this in a school project. Thank you very much

@br750
Copy link

br750 commented Nov 27, 2015

Awesome, just too much guy ;-)

@onassar
Copy link

onassar commented Feb 5, 2016

@joloco Any chance you have your code for this, so many years later?

@tomswatermelon
Copy link

Man this saves my life, thanks!

@WingMrL
Copy link

WingMrL commented Dec 2, 2016

Thank you very much !

@huanle0610
Copy link

Wooh, awesome!
Working with konvajs, I use it like this:

window.open(trim(layer.children[77].toCanvas()).toDataURL());

@nnyit
Copy link

nnyit commented May 22, 2017

This isn't working for me, it is only trimming 1px on each dimension.

@holethienthanh
Copy link

Thanks a lot.

@peterchibunna
Copy link

Awesome and intelligent code! I just modified it to add padding to the image cropped.

@timdown
Copy link

timdown commented Jul 24, 2017

Thanks, just what I needed. One tiny improvement: you could use the original canvas element's ownerDocument rather than document to create the copy so that they both exist in the same document. This could be important if your canvas comes from an iframe which has different fonts loaded to the main document and you want to draw text on the trimmed canvas (which happens to be exactly what I want to do).

@timdown
Copy link

timdown commented Jul 25, 2017

Also, this crops one pixel too much on the right and bottom. You need to add one to bounds.bottom and bounds.right (or to trimWidth and trimHeight).

@timdown
Copy link

timdown commented Jul 26, 2017

I created my own with some optimizations to minimize the number of pixels examined:

https://gist.github.com/timdown/021d9c8f2aabc7092df564996f5afbbf

@ranasoyab
Copy link

Thank you very much !

@TomFranssen
Copy link

Is it possible to modify this to trim white pixels also?

@onassar
Copy link

onassar commented Aug 27, 2018

I'm with @TomFranssen
Anyone have a modification that can trim all consistent pixels? (eg. like Photoshop's trim feature).

@minhnhatspk
Copy link

minhnhatspk commented Dec 26, 2018

Thanks for sharing code.
Your solution and this solution https://github.com/szimek/signature_pad/issues/49#issuecomment-260976909 have the same result.
but I don't know why they don't work with a small canvas.
I receive a cropped base64 string like this data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJoAAACwCAYAAAD3yHdHAAAWqklEQ…R2XRtoY4vDik3+K4DY27CgyngC092SXi3pl3sR9BxnnAL/C1ghAjtx4zZSAAAAAElFTkSuQmCC.
It does not display since it is broken.

@shaangidwani
Copy link

its not working on ipad. can someone help us urgently.

@hangj
Copy link

hangj commented Jun 5, 2019

var trimHeight = bound.bottom - bound.top,
trimWidth = bound.right - bound.left,
SHOULD BE:
var trimHeight = bound.bottom - bound.top + 1,
trimWidth = bound.right - bound.left + 1,

@javix
Copy link

javix commented Nov 4, 2020

I created my own with some optimizations to minimize the number of pixels examined:

https://gist.github.com/timdown/021d9c8f2aabc7092df564996f5afbbf

This function is almost 300% faster.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment