akoenig/gulp-svg2png

Error when trying to convert the same image twice

jacksleight opened this issue · 14 comments

I'm trying to generate 1x and 2x versions of my SVGs, like this:

gulp.task('images-1x', function() {
    gulp.src('*.svg')
        .pipe(svg2png(1.0))
        .pipe(rename({suffix: '.1x'}))
        .pipe(gulp.dest('.'));
});
gulp.task('images-2x', function() {
    gulp.src('*.svg')
        .pipe(svg2png(2.0))
        .pipe(rename({suffix: '.2x'}))
        .pipe(gulp.dest('.'));
});
gulp.task('images', ['images-1x', 'images-2x']);

However, I get the following error when I run it:

/Server/gulp/node_modules/gulp-svg2png/index.js:53
        throw new gutil.PluginError(PLUGIN_NAME, message);
              ^
Error: ENOENT, unlink '/var/folders/7s/0dbbv97n6rs1p7b83cb_rx4c0000gn/T/tick.png'

There are no errors if I just run one of the tasks (1x or 2x).

+1
Just ran into this myself...

Hej,

okay, I implemented a bugfix for this. Could you please check if the bug still persists with the latest version v0.2.1?

/André

The problem here is line 100 of index.js:

var temp = path.join(os.tmpdir(), rename(path.basename(source.path))),

os.tmpdir() always returns the same path (for me on OS X 10.9), so if you're tying to generate two PNGs from the same SVG at the time one will overwrite the other, causing this error when the system attempts to unlink the second.

The solution is to make the temp paths different each time. I made a quick fix which just includes the timestamp:

var temp = path.join(os.tmpdir(), new Date().getTime().toString(), rename(path.basename(source.path))),

But there's still a risk of collisions here, there's probably a more robust solution.

The fix seems to help.
Thank you very much!

Ha, you beat me to it :-) . Yup that works great!

Cool :)

I'm glad I could help.

@jacksleight Does scaling work for you? For me it only resizes the canvas, not the contents...

Yes, but only after fixing my SVGs, see this issue: domenic/svg2png#10

If your SVG has width/height and viewbox attributes it doesn't work. I'm using gulp-svgmin to remove the viewbox automatically:

.pipe(svgmin([{removeViewBox: true}]))

@jacksleight Super duper. Thanks!
I'm new to svg's, but I guessed it may be one of these weird Ai properties. Now I have to get my head around svgmin, because it's causing me trouble.

I've found the output from Ai leaves a lot to be desired. For example the content isn't always positioned at 0 0 (even if the artboard fits the content), instead you get weird offsets. This causes an issue if you remove the viewbox attr, as all the other measurements are based on that offset, so you get clipped images from svg2png.

An easy fix is to just remove the width/height instead of the viewbox, but svgmin can't do that automatically. The other solution is to get clean output from Ai in the first place, by creating a new document, and aligning your content perfectly to the top left corner of the artboard. This will give you an SVG with a viewbox that should start 0 0, and you can then safely throw that away and rely on the width/height. Source

@jacksleight Yea, I figured that when I tried to understand the viewBox, so all my files have artboards at 0, 0. Now I'm trying to bypass some svgo errors I'm getting, cause I prefer to have that automated.
Thanks for the post!

@jacksleight Do you have svgmin & svg2png chained with pipes? Svgmin alone removes viewBox, but they seem to run in parallel when chained, generating bigger canvas as before.

I have two separate tasks, the svgmin task is a dependency of the svg2png task, which ensures svgmin runs and completes before svg2png. (This is because I actually have two svg2png tasks, 1x and 2x, so it can't all be chained together.)

I think it did work when when I tested chaining svgmin and svg2png though, but I'm not on my laptop right now (where I was testing gulp) so can't check.

I filed report here: ben-eb/gulp-svgmin#6
Dependencies are a nice way to go, but they don't allow different svgmin options for svg2png and outputting svg's.
Thx for the idea though!