mirror of
https://github.com/lovell/sharp.git
synced 2026-02-06 06:36:17 +01:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1cce56b024 | ||
|
|
2126f9afc1 | ||
|
|
41420eedcf | ||
|
|
1b6ab19b6d | ||
|
|
fbe5c18762 |
@@ -5,12 +5,12 @@ node_js:
|
|||||||
before_install:
|
before_install:
|
||||||
- sudo add-apt-repository ppa:lyrasis/precise-backports -y
|
- sudo add-apt-repository ppa:lyrasis/precise-backports -y
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
- sudo apt-get install -qq automake gobject-introspection gtk-doc-tools libfftw3-dev libglib2.0-dev libjpeg-turbo8-dev libpng12-dev libwebp-dev libtiff4-dev libexif-dev libxml2-dev swig graphicsmagick libmagick++-dev
|
- sudo apt-get install -qq automake gobject-introspection gtk-doc-tools libglib2.0-dev libjpeg-turbo8-dev libpng12-dev libwebp-dev libtiff4-dev libexif-dev libxml2-dev swig graphicsmagick libmagick++-dev
|
||||||
- git clone https://github.com/jcupitt/libvips.git
|
- git clone https://github.com/jcupitt/libvips.git
|
||||||
- cd libvips
|
- cd libvips
|
||||||
- git checkout 7.38
|
- git checkout 7.38
|
||||||
- ./bootstrap.sh
|
- ./bootstrap.sh
|
||||||
- ./configure --enable-debug=no --enable-cxx=yes --without-orc --without-python
|
- ./configure --enable-debug=no --enable-cxx=yes --without-orc --without-python --without-fftw
|
||||||
- make
|
- make
|
||||||
- sudo make install
|
- sudo make install
|
||||||
- sudo ldconfig
|
- sudo ldconfig
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -48,12 +48,12 @@ The _gettext_ dependency of _libvips_ [can lead](https://github.com/lovell/sharp
|
|||||||
|
|
||||||
Compiling from source is recommended:
|
Compiling from source is recommended:
|
||||||
|
|
||||||
sudo apt-get install automake build-essential git gobject-introspection gtk-doc-tools libfftw3-dev libglib2.0-dev libjpeg-turbo8-dev libpng12-dev libwebp-dev libtiff5-dev libexif-dev libxml2-dev swig
|
sudo apt-get install automake build-essential git gobject-introspection gtk-doc-tools libglib2.0-dev libjpeg-turbo8-dev libpng12-dev libwebp-dev libtiff5-dev libexif-dev libxml2-dev swig
|
||||||
git clone https://github.com/jcupitt/libvips.git
|
git clone https://github.com/jcupitt/libvips.git
|
||||||
cd libvips
|
cd libvips
|
||||||
git checkout 7.38
|
git checkout 7.38
|
||||||
./bootstrap.sh
|
./bootstrap.sh
|
||||||
./configure --enable-debug=no --enable-cxx=yes --without-python --without-orc
|
./configure --enable-debug=no --enable-cxx=yes --without-python --without-orc --without-fftw
|
||||||
make
|
make
|
||||||
sudo make install
|
sudo make install
|
||||||
sudo ldconfig
|
sudo ldconfig
|
||||||
@@ -68,6 +68,10 @@ Requires `libtiff4-dev` instead of `libtiff5-dev` and has [a bug](https://bugs.l
|
|||||||
|
|
||||||
Then follow Ubuntu 13.x instructions.
|
Then follow Ubuntu 13.x instructions.
|
||||||
|
|
||||||
|
### Install libvips on Heroku
|
||||||
|
|
||||||
|
[Alessandro Tagliapietra](https://github.com/alex88) maintains an [Heroku buildpack for libvips](https://github.com/alex88/heroku-buildpack-vips) and its dependencies.
|
||||||
|
|
||||||
## Usage examples
|
## Usage examples
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@@ -160,11 +164,11 @@ Embed the resized image on a black background of the exact size specified.
|
|||||||
|
|
||||||
### rotate([angle])
|
### rotate([angle])
|
||||||
|
|
||||||
Rotate the output image by either an explicit angle or auto-orient based on the EXIF `Orientation` tag. Mirroring is not supported.
|
Rotate the output image by either an explicit angle or auto-orient based on the EXIF `Orientation` tag.
|
||||||
|
|
||||||
`angle`, if present, is a Number with a value of `0`, `90`, `180` or `270`.
|
`angle`, if present, is a Number with a value of `0`, `90`, `180` or `270`.
|
||||||
|
|
||||||
Use this method without `angle` to determine the angle from EXIF data.
|
Use this method without `angle` to determine the angle from EXIF data. Mirroring is currently unsupported.
|
||||||
|
|
||||||
### withoutEnlargement()
|
### withoutEnlargement()
|
||||||
|
|
||||||
@@ -257,9 +261,9 @@ This method always returns cache statistics, useful for determining how much wor
|
|||||||
Warnings such as _Application transferred too many scanlines_ are a good indicator you've set this value too low.
|
Warnings such as _Application transferred too many scanlines_ are a good indicator you've set this value too low.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var stats = sharp.cache(); // { current: 98, high: 115, limit: 100 }
|
var stats = sharp.cache(); // { current: 98, high: 115, limit: 100, queue: 0 }
|
||||||
sharp.cache(200); // { current: 98, high: 115, limit: 200 }
|
sharp.cache(200); // { current: 98, high: 115, limit: 200, queue: 0 }
|
||||||
sharp.cache(50); // { current: 49, high: 115, limit: 50 }
|
sharp.cache(50); // { current: 49, high: 115, limit: 50, queue: 0 }
|
||||||
```
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|||||||
@@ -12,7 +12,10 @@
|
|||||||
'<!(PKG_CONFIG_PATH="<(PKG_CONFIG_PATH)" pkg-config --cflags vips glib-2.0)',
|
'<!(PKG_CONFIG_PATH="<(PKG_CONFIG_PATH)" pkg-config --cflags vips glib-2.0)',
|
||||||
'<!(node -e "require(\'nan\')")'
|
'<!(node -e "require(\'nan\')")'
|
||||||
],
|
],
|
||||||
'cflags': ['-fexceptions', '-pedantic', '-Wall', '-O3'],
|
'cflags': ['-fexceptions', '-Wall', '-O3'],
|
||||||
'cflags_cc': ['-fexceptions', '-pedantic', '-Wall', '-O3']
|
'cflags_cc': ['-fexceptions', '-Wall', '-O3'],
|
||||||
|
'xcode_settings': {
|
||||||
|
'OTHER_CFLAGS': ['-fexceptions', '-Wall', '-O3']
|
||||||
|
}
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sharp",
|
"name": "sharp",
|
||||||
"version": "0.5.1",
|
"version": "0.5.2",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Pierre Inglebert <pierre.inglebert@gmail.com>",
|
"Pierre Inglebert <pierre.inglebert@gmail.com>",
|
||||||
@@ -33,11 +33,11 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nan": "^1.2.0",
|
"nan": "^1.2.0",
|
||||||
"bluebird": "^2.1.2"
|
"bluebird": "^2.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"imagemagick": "^0.1.3",
|
"imagemagick": "^0.1.3",
|
||||||
"imagemagick-native": "^1.1.1",
|
"imagemagick-native": "^1.2.2",
|
||||||
"gm": "^1.16.0",
|
"gm": "^1.16.0",
|
||||||
"async": "^0.9.0",
|
"async": "^0.9.0",
|
||||||
"benchmark": "^1.0.0"
|
"benchmark": "^1.0.0"
|
||||||
|
|||||||
52
src/sharp.cc
52
src/sharp.cc
@@ -54,6 +54,9 @@ unsigned char const MARKER_JPEG[] = {0xff, 0xd8};
|
|||||||
unsigned char const MARKER_PNG[] = {0x89, 0x50};
|
unsigned char const MARKER_PNG[] = {0x89, 0x50};
|
||||||
unsigned char const MARKER_WEBP[] = {0x52, 0x49};
|
unsigned char const MARKER_WEBP[] = {0x52, 0x49};
|
||||||
|
|
||||||
|
// How many tasks are in the queue?
|
||||||
|
volatile int queue_length = 0;
|
||||||
|
|
||||||
static bool ends_with(std::string const &str, std::string const &end) {
|
static bool ends_with(std::string const &str, std::string const &end) {
|
||||||
return str.length() >= end.length() && 0 == str.compare(str.length() - end.length(), end.length(), end);
|
return str.length() >= end.length() && 0 == str.compare(str.length() - end.length(), end.length(), end);
|
||||||
}
|
}
|
||||||
@@ -370,46 +373,58 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
vips_colourspace(sharpened, &colourspaced, VIPS_INTERPRETATION_sRGB, NULL);
|
vips_colourspace(sharpened, &colourspaced, VIPS_INTERPRETATION_sRGB, NULL);
|
||||||
g_object_unref(sharpened);
|
g_object_unref(sharpened);
|
||||||
|
|
||||||
|
// Generate image tile cache when interlace output is required
|
||||||
|
VipsImage *cached = vips_image_new();
|
||||||
|
if (baton->progressive) {
|
||||||
|
if (vips_tilecache(colourspaced, &cached, "threaded", TRUE, "persistent", TRUE, "max_tiles", -1, NULL)) {
|
||||||
|
return resize_error(baton, colourspaced);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vips_copy(colourspaced, &cached, NULL);
|
||||||
|
}
|
||||||
|
g_object_unref(colourspaced);
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
|
VipsImage *output = cached;
|
||||||
if (baton->file_out == "__jpeg" || (baton->file_out == "__input" && inputImageType == JPEG)) {
|
if (baton->file_out == "__jpeg" || (baton->file_out == "__input" && inputImageType == JPEG)) {
|
||||||
// Write JPEG to buffer
|
// Write JPEG to buffer
|
||||||
if (vips_jpegsave_buffer(colourspaced, &baton->buffer_out, &baton->buffer_out_len, "strip", TRUE, "Q", baton->quality, "optimize_coding", TRUE, "interlace", baton->progressive, NULL)) {
|
if (vips_jpegsave_buffer(output, &baton->buffer_out, &baton->buffer_out_len, "strip", TRUE, "Q", baton->quality, "optimize_coding", TRUE, "interlace", baton->progressive, NULL)) {
|
||||||
return resize_error(baton, colourspaced);
|
return resize_error(baton, output);
|
||||||
}
|
}
|
||||||
} else if (baton->file_out == "__png" || (baton->file_out == "__input" && inputImageType == PNG)) {
|
} else if (baton->file_out == "__png" || (baton->file_out == "__input" && inputImageType == PNG)) {
|
||||||
// Write PNG to buffer
|
// Write PNG to buffer
|
||||||
if (vips_pngsave_buffer(colourspaced, &baton->buffer_out, &baton->buffer_out_len, "strip", TRUE, "compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
if (vips_pngsave_buffer(output, &baton->buffer_out, &baton->buffer_out_len, "strip", TRUE, "compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
||||||
return resize_error(baton, colourspaced);
|
return resize_error(baton, output);
|
||||||
}
|
}
|
||||||
} else if (baton->file_out == "__webp" || (baton->file_out == "__input" && inputImageType == WEBP)) {
|
} else if (baton->file_out == "__webp" || (baton->file_out == "__input" && inputImageType == WEBP)) {
|
||||||
// Write WEBP to buffer
|
// Write WEBP to buffer
|
||||||
if (vips_webpsave_buffer(colourspaced, &baton->buffer_out, &baton->buffer_out_len, "strip", TRUE, "Q", baton->quality, NULL)) {
|
if (vips_webpsave_buffer(output, &baton->buffer_out, &baton->buffer_out_len, "strip", TRUE, "Q", baton->quality, NULL)) {
|
||||||
return resize_error(baton, colourspaced);
|
return resize_error(baton, output);
|
||||||
}
|
}
|
||||||
} else if (is_jpeg(baton->file_out)) {
|
} else if (is_jpeg(baton->file_out)) {
|
||||||
// Write JPEG to file
|
// Write JPEG to file
|
||||||
if (vips_jpegsave(colourspaced, baton->file_out.c_str(), "strip", TRUE, "Q", baton->quality, "optimize_coding", TRUE, "interlace", baton->progressive, NULL)) {
|
if (vips_jpegsave(output, baton->file_out.c_str(), "strip", TRUE, "Q", baton->quality, "optimize_coding", TRUE, "interlace", baton->progressive, NULL)) {
|
||||||
return resize_error(baton, colourspaced);
|
return resize_error(baton, output);
|
||||||
}
|
}
|
||||||
} else if (is_png(baton->file_out)) {
|
} else if (is_png(baton->file_out)) {
|
||||||
// Write PNG to file
|
// Write PNG to file
|
||||||
if (vips_pngsave(colourspaced, baton->file_out.c_str(), "strip", TRUE, "compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
if (vips_pngsave(output, baton->file_out.c_str(), "strip", TRUE, "compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
||||||
return resize_error(baton, colourspaced);
|
return resize_error(baton, output);
|
||||||
}
|
}
|
||||||
} else if (is_webp(baton->file_out)) {
|
} else if (is_webp(baton->file_out)) {
|
||||||
// Write WEBP to file
|
// Write WEBP to file
|
||||||
if (vips_webpsave(colourspaced, baton->file_out.c_str(), "strip", TRUE, "Q", baton->quality, NULL)) {
|
if (vips_webpsave(output, baton->file_out.c_str(), "strip", TRUE, "Q", baton->quality, NULL)) {
|
||||||
return resize_error(baton, colourspaced);
|
return resize_error(baton, output);
|
||||||
}
|
}
|
||||||
} else if (is_tiff(baton->file_out)) {
|
} else if (is_tiff(baton->file_out)) {
|
||||||
// Write TIFF to file
|
// Write TIFF to file
|
||||||
if (vips_tiffsave(colourspaced, baton->file_out.c_str(), "strip", TRUE, "compression", VIPS_FOREIGN_TIFF_COMPRESSION_JPEG, "Q", baton->quality, NULL)) {
|
if (vips_tiffsave(output, baton->file_out.c_str(), "strip", TRUE, "compression", VIPS_FOREIGN_TIFF_COMPRESSION_JPEG, "Q", baton->quality, NULL)) {
|
||||||
return resize_error(baton, colourspaced);
|
return resize_error(baton, output);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(baton->err).append("Unsupported output " + baton->file_out);
|
(baton->err).append("Unsupported output " + baton->file_out);
|
||||||
}
|
}
|
||||||
g_object_unref(colourspaced);
|
g_object_unref(output);
|
||||||
vips_thread_shutdown();
|
vips_thread_shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,6 +442,8 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
}
|
}
|
||||||
delete baton;
|
delete baton;
|
||||||
callback->Call(2, argv);
|
callback->Call(2, argv);
|
||||||
|
// Decrement queue length
|
||||||
|
g_atomic_int_dec_and_test(&queue_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -480,6 +497,10 @@ NAN_METHOD(resize) {
|
|||||||
// Join queue for worker thread
|
// Join queue for worker thread
|
||||||
NanCallback *callback = new NanCallback(args[2].As<v8::Function>());
|
NanCallback *callback = new NanCallback(args[2].As<v8::Function>());
|
||||||
NanAsyncQueueWorker(new ResizeWorker(callback, baton));
|
NanAsyncQueueWorker(new ResizeWorker(callback, baton));
|
||||||
|
|
||||||
|
// Increment queue length
|
||||||
|
g_atomic_int_inc(&queue_length);
|
||||||
|
|
||||||
NanReturnUndefined();
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,6 +517,7 @@ NAN_METHOD(cache) {
|
|||||||
cache->Set(NanNew<String>("current"), NanNew<Number>(vips_tracked_get_mem() / 1048576));
|
cache->Set(NanNew<String>("current"), NanNew<Number>(vips_tracked_get_mem() / 1048576));
|
||||||
cache->Set(NanNew<String>("high"), NanNew<Number>(vips_tracked_get_mem_highwater() / 1048576));
|
cache->Set(NanNew<String>("high"), NanNew<Number>(vips_tracked_get_mem_highwater() / 1048576));
|
||||||
cache->Set(NanNew<String>("limit"), NanNew<Number>(vips_cache_get_max_mem() / 1048576));
|
cache->Set(NanNew<String>("limit"), NanNew<Number>(vips_cache_get_max_mem() / 1048576));
|
||||||
|
cache->Set(NanNew<String>("queue"), NanNew<Number>(queue_length));
|
||||||
NanReturnValue(cache);
|
NanReturnValue(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ var inputJpg = path.join(__dirname, "fixtures/2569067123_aca715a2ee_o.jpg"); //
|
|||||||
var width = 720;
|
var width = 720;
|
||||||
var height = 480;
|
var height = 480;
|
||||||
|
|
||||||
|
var timer = setInterval(function() {
|
||||||
|
console.dir(sharp.cache());
|
||||||
|
}, 100);
|
||||||
|
|
||||||
async.mapSeries([1, 1, 2, 4, 8, 16, 32, 64, 128], function(parallelism, next) {
|
async.mapSeries([1, 1, 2, 4, 8, 16, 32, 64, 128], function(parallelism, next) {
|
||||||
var start = new Date().getTime();
|
var start = new Date().getTime();
|
||||||
async.times(parallelism,
|
async.times(parallelism,
|
||||||
@@ -28,5 +32,6 @@ async.mapSeries([1, 1, 2, 4, 8, 16, 32, 64, 128], function(parallelism, next) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}, function() {
|
}, function() {
|
||||||
|
clearInterval(timer);
|
||||||
console.dir(sharp.cache());
|
console.dir(sharp.cache());
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user