Open JostBaron opened 10 years ago
Could you provide your full Grunt file please?
Ok, here are:
The gruntfile is a bit longish, sorry for that.
configuration.json:
{
"distribution": {
"root": "distribution",
"pages": "distribution",
"styles": "distribution",
"scripts": "distribution",
"images": "distribution/images",
"contentimages": "distribution/content/images"
},
"build": {
"absRefPrefix": "/",
"root": "build",
"pages": "build",
"styles": "build/styles",
"scripts": "build/scripts",
"images": "build/images",
"contentimages": "build/content/images"
},
"source": {
"root": "source",
"styles": "source/styles",
"images": "source/images",
"markup": "source/markup"
},
"content": {
"images": "source/content/images",
"data": "source/content/data",
"pages": "source/markup/pages"
},
"deployment": {
"host": "doesnt-matter",
"port": 21,
"authkey": "somekey",
"targetdir": "/",
"contentimages": "/content/images"
}
}
package.json:
{
"name": "doesnt-matter",
"version": "0.1.0",
"dependencies": {},
"devDependencies": {
"grunt": "latest",
"grunt-contrib-less": "latest",
"grunt-contrib-copy": "latest",
"grunt-contrib-uglify": "latest",
"grunt-contrib-cssmin": "latest",
"grunt-ftp-deploy": "latest",
"swig": "latest",
"grunt-swig2": "latest",
"grunt-contrib-compress": "latest",
"grunt-contrib-watch": "latest",
"grunt-contrib-connect": "latest",
"grunt-modernizr": "latest",
"grunt-responsive-images": "^0.1.2",
"markdown": "^0.5.0",
"grunt-contrib-clean": "latest"
},
"engines": {
"node": ">=0.8.0"
}
}
Gruntfile.js
"use strict";
module.exports = function (grunt) {
var path = require('path');
var LIVERELOAD_PORT = 12345;
var swig = require('swig');
var markdown = require( "markdown" ).markdown;
var configuration = grunt.file.readJSON('configuration.json');
function getContentImageFileNames() {
var result = {};
grunt.file.recurse(
configuration.content.images,
function(abspath, rootdir, subdir, filename) {
subdir = subdir || '';
if (!(subdir in result)) {
result[subdir] = [];
}
if ('data.json' === filename) {
var data = grunt.file.readJSON(abspath);
for (var i = 0; i < data.length; i++) {
var imagedata = data[i];
filename = imagedata.name;
result[subdir].push(
{
subdirectory: path.relative(configuration.distribution.root, configuration.distribution.contentimages) + '/' + subdir,
extension: path.extname(filename),
name: path.basename(filename, path.extname(filename)),
slideshowlink: 'referenzen/' + subdir + '.html',
alttext: imagedata.alttext,
title: imagedata.title,
caption: imagedata.caption
}
)
}
}
}
)
return result;
}
function getImageSizes() {
return [
{
name: '320',
width: 320,
suffix: '-1x'
},
{
name: '320',
width: 480,
suffix: '-1.5x'
},
{
name: '320',
width: 640,
suffix: '-2x'
},
{
name: '320',
width: 960,
suffix: '-3x'
},
{
name: '480',
width: 480,
suffix: '-1x'
},
{
name: '480',
width: 720,
suffix: '-1.5x'
},
{
name: '480',
width: 960,
suffix: '-2x'
},
{
name: '480',
width: 1440,
suffix: '-3x'
},
{
name: '720',
width: 720,
suffix: '-1x'
},
{
name: '720',
width: 1080,
suffix: '-1.5x'
},
{
name: '720',
width: 1440,
suffix: '-2x'
},
{
name: '720',
width: 2160,
suffix: '-3x'
},
{
name: '1000',
width: 1000,
suffix: '-1x'
},
{
name: '1000',
width: 1500,
suffix: '-1.5x'
},
{
name: '1000',
width: 2000,
suffix: '-2x'
},
{
name: '1000',
width: 3000,
suffix: '-3x'
},
{
name: 'thumb-130',
width: 130,
height: 130,
aspectRatio: false,
suffix: '-1x'
},
{
name: 'thumb-130',
width: 185,
height: 185,
aspectRatio: false,
suffix: '-1.5x'
},
{
name: 'thumb-130',
width: 260,
height: 260,
aspectRatio: false,
suffix: '-2x'
},
{
name: 'thumb-130',
width: 390,
height: 390,
aspectRatio: false,
suffix: '-3x'
}
];
}
grunt.initConfig({
configuration: configuration,
less: {
options: {
modifyVars: {
// example: assetBasePath: '"/test"' (mind the inner quotes)
}
},
all: {
options: {
paths: [
'bower_components'
]
},
files: {
'<%= configuration.build.styles %>/main.css': '<%= configuration.source.styles %>/main.less'
}
}
},
modernizr: {
build: {
"devFile" : "remote",
"outputFile" : "<%= configuration.build.scripts %>/modernizr-custom.js",
"extra" : {
"shiv" : false,
"printshiv" : false,
"load" : false,
"mq" : false,
"cssclasses" : true
},
"extensibility" : {
"addtest" : false,
"prefixed" : false,
"teststyles" : false,
"testprops" : false,
"testallprops" : false,
"hasevents" : false,
"prefixes" : false,
"domprefixes" : false
},
"uglify" : false,
"tests" : [],
"parseFiles" : false,
"matchCommunityTests" : false,
"customTests" : []
}
},
uglify: {
options: {
mangle: {
except: ['jQuery']
}
},
head: {
files: {
'<%= configuration.build.scripts %>/head.js': [
'<%= configuration.build.scripts %>/modernizr-custom.js',
'bower_components/html5shiv/dist/html5shiv.js'
]
}
},
body: {
files: {
'<%= configuration.build.scripts %>/body.js': [
'bower_components/respond/dest/respond.src.js',
'bower_components/picturefill/dist/picturefill.js',
'bower_components/swiper/dist/idangerous.swiper.js',
'source/scripts/slideshow.js',
'source/scripts/menu.js'
]
}
}
},
swig: {
options: {
data: function() {
var path = require('path');
var result = {};
grunt.file.recurse(
process.cwd() + '/' + configuration.content.data,
function(abspath, rootdir, subdir, filename) {
result[path.basename(filename, '.json')] = grunt.file.readJSON(abspath);
}
);
if ('contentimages' in result) {
console.warn('Name conflict. The data key \'contentimages\' is reserved.');
}
result['contentimages'] = getContentImageFileNames();
if ('imagesizes' in result) {
console.warn('Name conflict. The data key \'imagesizes\' is reserved.');
}
result['imagesizes'] = getImageSizes();
return result;
},
filters: {
markdown: function(input) {
return markdown.toHTML(input, 'Maruku');
}
},
swigOptions: {
loader: swig.loaders.fs(__dirname)
}
},
pages: {
files: [
{
expand: true,
cwd: '<%= configuration.content.pages %>',
src: ['**/*.html'],
dest: '<%= configuration.build.pages %>'
}
]
}
},
copy: {
images: {
files: [
{
expand: true,
dot: true,
cwd: '<%= configuration.source.images %>',
dest: '<%= configuration.build.images %>',
src: [
'**',
'!background/**'
]
}
]
},
htaccess: {
files: [
{
expand: true,
dot: true,
cwd: '<%= configuration.source.root %>',
dest: '<%= configuration.build.root %>',
src: [
'.htaccess'
]
}
]
},
distribution: {
files: [
{
expand: true,
dot: true,
cwd: '<%= configuration.build.root %>',
dest: '<%= configuration.distribution.root %>',
src: [
'**',
'!styles/**',
'!scripts/**'
]
}
]
}
},
compress: {
options: {
mode: 'gzip',
level: 9,
pretty: true
},
distribution: {
files: [
{
src: '<%= configuration.build.scripts %>/head.js',
dest: '<%= configuration.distribution.scripts %>/head.gz.js',
ext: '.gz.js',
filter: 'isFile'
},
{
src: '<%= configuration.build.scripts %>/body.js',
dest: '<%= configuration.distribution.scripts %>/body.gz.js',
ext: '.gz.js',
filter: 'isFile'
},
{
src: '<%= configuration.build.styles %>/**',
dest: '<%= configuration.distribution.styles %>/styles.gz.css',
ext: '.gz.css',
filter: 'isFile'
}
]
}
},
watch: {
livereload: {
options: {
livereload: LIVERELOAD_PORT
},
files: [
'<%= configuration.source.root %>/**'
],
tasks: ['default']
}
},
connect: {
options: {
port: 9010,
// change this to '0.0.0.0' to access the server from outside
hostname: '127.0.0.1'
},
livereload: {
options: {
livereload: LIVERELOAD_PORT,
base: '<%= configuration.distribution.root %>',
middleware: function(connect, options, middlewares) {
middlewares.unshift(function(req, res, next) {
if (-1 !== req.url.search('.gz')) {
res.setHeader('Content-Encoding', 'gzip');
}
next();
});
return middlewares;
}
}
}
},
responsive_images: {
contentimages: {
options: {
engine: 'im',
quality: 70,
sizes: getImageSizes()
},
files: [
{
expand: true,
dot: true,
cwd: '<%= configuration.content.images %>',
dest: '<%= configuration.build.contentimages %>',
filter: 'isFile',
src: [
'**',
'!**/data.json'
]
}
]
}
},
'ftp-deploy': {
'no-images': {
auth: {
host: '<%= configuration.deployment.host %>',
port: '<%= configuration.deployment.port %>',
authKey: '<%= configuration.deployment.authkey %>'
},
src: '<%= configuration.distribution.root %>',
dest: '<%= configuration.deployment.targetdir %>',
exclusions: [
'<%= configuration.distribution.contentimages %>/**'
]
},
'images': {
auth: {
host: '<%= configuration.deployment.host %>',
port: '<%= configuration.deployment.port %>',
authKey: '<%= configuration.deployment.authkey %>'
},
src: '<%= configuration.distribution.contentimages %>',
dest: '<%= configuration.deployment.contentimages %>'
}
},
clean: {
options: {
// 'no-write': true
},
build: [
'<%= configuration.build.root %>/**'
],
distribution: [
'<%= configuration.distribution.root %>/**'
]
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-modernizr');
grunt.loadNpmTasks('grunt-responsive-images');
grunt.loadNpmTasks('grunt-swig2');
grunt.loadNpmTasks('grunt-ftp-deploy');
grunt.registerTask(
'build',
[
'less:all',
'modernizr:build',
'uglify:head',
'uglify:body',
'swig:pages',
'copy:images',
'copy:htaccess',
'copy:distribution',
'compress:distribution'
]
);
grunt.registerTask(
'server',
[
'build',
'connect:livereload',
'watch'
]
);
grunt.registerTask(
'images',
[
'responsive_images:contentimages'
]
);
grunt.registerTask(
'full',
[
'images',
'build'
]
);
grunt.registerTask(
'deploy',
[
'build',
'ftp-deploy:no-images'
]
);
grunt.registerTask(
'deploy-images',
[
// 'images',
'ftp-deploy:images'
]
);
grunt.registerTask(
'deploy-full',
[
'full',
'ftp-deploy:no-images',
'ftp-deploy:images'
]
);
grunt.registerTask(
'default',
[
'build'
]
);
};
What type of image file is it? Is it an animated GIF?
No, all of the images were JPEGs (file extension differed, either jpg or JPG).
I've released a new version that changes the internals for how options work. Does this still happen with v0.1.4? Have you tried running Grunt in verbose mode?
The problem is not fixed - upscale: false is respected when using GraphicsMagick, but not when using ImageMagick.
I ran Grunt in verbose mode, but that did not reveal anything.
Seems like
sizingMethod = '\>';
would work
At least I tried it and it seems to stop upscaling.. See also: http://stackoverflow.com/questions/3504931/cli-imagemagick-resize-downscale-only
I have the same problem...using a simple configuration file it upscale the image (e.g. 80px to 400px)
'use strict';
module.exports = function(grunt){
grunt.initConfig({
responsive_images: {
options: {
sizes: [{
name: "small",
width: 480,
upscale: false
}]
},
files:{
expand: true,
src: ['**.{jpg,gif,png}'],
cwd: 'images/',
dest:'ejemplo/'
}
}
})
grunt.loadNpmTasks('grunt-responsive-images');
grunt.registerTask('default', ['responsive_images']);
}
If you adjust the tests to start with a small image, you'll see it get upscaled in the default options test.
I also got it to work (with imagemagick 6 ) thanks to @hamsterbacke23 by changing this upscale bit of code on line 337 to:
if (sizeOptions.upscale) {
// upscale
if (sizeOptions.aspectRatio) {
sizingMethod = '^';
} else {
sizingMethod = '!';
}
}else {
sizingMethod= '>';
}
which is just setting the sizing method to '>' if options.upscale
is set to false. Which is described here as:
"Another commonly used option is to restrict IM so that it will only shrink images to fit into the size given. Never enlarge. This is the '>' resize option. Think of it only applying the resize to images 'greater than' the size given (its a little counter intuitive)."
Happy to open a PR!
This issue is also affecting me.
Environment:
I had the same problem, fixed it last year somehow, but can't find that project. This also affects GraphicsMagic on Windows. There is an undocumented option that fixes the problem: createNoScaledImage
. Set it to true in your options like:
options: {
// Task-specific options go here.
createNoScaledImage: true,
sizes: [{
...
}]
},
maybe that option is not getting set correctly?
@malducin-vfxfan
I suppose it depends on what people here want. As the name implies, createNoScaledImage:true
skips over creating any files that would be upscaled. This causes a problem when there are references in static code, with no if/then/else constructs (like css), to images that don't exist (because they were skipped because they would have been upscaled).
Personally, I'd like a new file to be created, which is effectively just the original image duplicated but with a filename that uses the naming convention specified in the options.
@JostBaron - would you clarify which problem you were describing in the ticket?
Thanks, that makes sense. In my case I'm handling the images with code (PHP/Python) so I can check their presence, or just creating a ton of thumbnails (for galleries or contact sheets), so I hadn't considered the CSS case. I'm fine if it keeps working that same way. Maybe just indicate createNoScaledImage:true
in the README or a wiki entry for those hitting this problem.
Now I have to check my setup on Windows, because I do have both ImageMagick and GraphicsMagic installed, and even when specifying GraphicsMagic explicitly, it still upscales, so it might be a case where it's finding IM first (maybe because of the registry).
Awaiting response from @JostBaron - possibly this can be closed as issue #82 requests documentation enhancement.
I do hope that @isaacchansky commit can be merged, as the suggestion in #82 requires a more complicated Grunt setup involving additional copying of those images that are not resized.
another potential fix is to expose sizingMethod
as a config variable.
When I have defined this size
an 800x600 image is upscaled to 3000x2250. My other options are: