Repository: trafficserver Updated Branches: refs/heads/master 9c707a89d -> 39b2eb4b9
TS-4095: New cppapi plugin for converting images formats to webp. This closes #393 Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/39b2eb4b Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/39b2eb4b Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/39b2eb4b Branch: refs/heads/master Commit: 39b2eb4b98cf4973a64407bcb47c9d93ee5c30fa Parents: 9c707a8 Author: Sandeep Davu <[email protected]> Authored: Sat Feb 20 23:36:20 2016 -0800 Committer: Kit Chan <[email protected]> Committed: Sat Feb 20 23:36:20 2016 -0800 ---------------------------------------------------------------------- configure.ac | 11 ++ doc/admin-guide/plugins/index.en.rst | 4 + doc/admin-guide/plugins/webp_transform.en.rst | 39 +++++++ plugins/experimental/Makefile.am | 5 +- .../webp_transform/ImageTransform.cc | 109 +++++++++++++++++++ plugins/experimental/webp_transform/Makefile.am | 28 +++++ plugins/experimental/webp_transform/README | 4 + 7 files changed, 199 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/39b2eb4b/configure.ac ---------------------------------------------------------------------- diff --git a/configure.ac b/configure.ac index a3aa6ca..7d70788 100644 --- a/configure.ac +++ b/configure.ac @@ -409,6 +409,12 @@ PKG_CHECK_MODULES([LIBMEMCACHED], [libmemcached >= 1.0], [have_libmemcached=yes] AM_CONDITIONAL([BUILD_MEMCACHED_REMAP_PLUGIN], [test "x${have_libmemcached}" = "xyes"]) # +# Check Magick++ is available. Enable experimental/webp_transform plugin +# +PKG_CHECK_MODULES([LIBMAGICKCPP],[Magick++], [have_libmagickcpp=yes], [have_libmagickcpp=no]) +AM_CONDITIONAL([BUILD_HAS_IMAGEMAGICKCPP], [test "x${have_libmagickcpp}" = "xyes"]) + +# # Example plugins. The example plugins are always built, but not always installed. Installing # them is useful for QA, but not useful for most users, so we default this to disabled. # @@ -1932,6 +1938,11 @@ AS_IF([test "x$enable_experimental_plugins" = "xyes"], [ plugins/experimental/stream_editor/Makefile ])]) +AS_IF([test "x$enable_experimental_plugins" = "xyes"], [ + AS_IF([test "x$enable_cppapi" = "xyes"], [ + AC_CONFIG_FILES([plugins/experimental/webp_transform/Makefile]) + ])]) + AS_IF([test "x$enable_cppapi" = "xyes"], [ AC_CONFIG_FILES([ lib/atscppapi/Makefile http://git-wip-us.apache.org/repos/asf/trafficserver/blob/39b2eb4b/doc/admin-guide/plugins/index.en.rst ---------------------------------------------------------------------- diff --git a/doc/admin-guide/plugins/index.en.rst b/doc/admin-guide/plugins/index.en.rst index 5745a4d..f237749 100644 --- a/doc/admin-guide/plugins/index.en.rst +++ b/doc/admin-guide/plugins/index.en.rst @@ -116,6 +116,7 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi SSL Headers <sslheaders.en> Stale While Revalidate <stale_while_revalidate.en> TS Lua <ts_lua.en> + WebP Transform <webp_transform.en> X-Debug <xdebug.en> :doc:`AuthProxy <authproxy.en>` @@ -181,6 +182,9 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi :doc:`TS Lua <ts_lua.en>` Allows plugins to be written in Lua instead of C code. +:doc:`WebP Transform <webp_transform.en>` + Converts jpeg and png images to webp format. + :doc:`X-Debug <xdebug.en>` Allows HTTP clients to debug the operation of the Traffic Server cache using the X-Debug header. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/39b2eb4b/doc/admin-guide/plugins/webp_transform.en.rst ---------------------------------------------------------------------- diff --git a/doc/admin-guide/plugins/webp_transform.en.rst b/doc/admin-guide/plugins/webp_transform.en.rst new file mode 100644 index 0000000..280aca6 --- /dev/null +++ b/doc/admin-guide/plugins/webp_transform.en.rst @@ -0,0 +1,39 @@ +.. _webp_transform: + +WebpTransform Plugin +**************** + +.. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +This plugin converts jpeg and png images and transforms them into webp format. +All response with content-type 'image/jpeg' or 'image/png' will go through the transform. +Content-type is changed to 'image/webp' on successful transformation. + +Installation +============ + +Add the following line to :file:`plugin.config`:: + + webp_transform.so + + +Note +=================== + +This plugin only supports jpeg and png and requires Magick++ from ImageMagick. +Other image formats can easily be supported. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/39b2eb4b/plugins/experimental/Makefile.am ---------------------------------------------------------------------- diff --git a/plugins/experimental/Makefile.am b/plugins/experimental/Makefile.am index c5055ae..6aa03fc 100644 --- a/plugins/experimental/Makefile.am +++ b/plugins/experimental/Makefile.am @@ -45,7 +45,8 @@ SUBDIRS = \ url_sig \ xdebug \ mp4 \ - stream_editor + stream_editor \ + webp_transform if HAS_MYSQL SUBDIRS += mysql_remap @@ -54,3 +55,5 @@ endif if BUILD_LUAJIT SUBDIRS += ts_lua endif + + http://git-wip-us.apache.org/repos/asf/trafficserver/blob/39b2eb4b/plugins/experimental/webp_transform/ImageTransform.cc ---------------------------------------------------------------------- diff --git a/plugins/experimental/webp_transform/ImageTransform.cc b/plugins/experimental/webp_transform/ImageTransform.cc new file mode 100644 index 0000000..b5d22bb --- /dev/null +++ b/plugins/experimental/webp_transform/ImageTransform.cc @@ -0,0 +1,109 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include <sstream> +#include <iostream> +#include <atscppapi/PluginInit.h> +#include <atscppapi/GlobalPlugin.h> +#include <atscppapi/TransformationPlugin.h> +#include <atscppapi/Logger.h> + +#include <Magick++.h> + +using std::string; +using namespace Magick; +using namespace atscppapi; + +namespace +{ +#define TAG "webp_transform" +} + +class ImageTransform : public TransformationPlugin +{ +public: + ImageTransform(Transaction &transaction) : TransformationPlugin(transaction, TransformationPlugin::RESPONSE_TRANSFORMATION) + { + TransformationPlugin::registerHook(HOOK_READ_RESPONSE_HEADERS); + } + + void + handleReadResponseHeaders(Transaction &transaction) + { + transaction.getServerResponse().getHeaders()["Content-Type"] = "image/webp"; + transaction.getServerResponse().getHeaders()["Vary"] = "Content-Type"; // to have a separate cache entry. + + TS_DEBUG(TAG, "url %s", transaction.getServerRequest().getUrl().getUrlString().c_str()); + transaction.resume(); + } + + void + consume(const string &data) + { + _img.write(data.data(), data.size()); + } + + void + handleInputComplete() + { + string input_data = _img.str(); + Blob input_blob(input_data.data(), input_data.length()); + Image image; + image.read(input_blob); + + Blob output_blob; + image.magick("WEBP"); + image.write(&output_blob); + string output_data(reinterpret_cast<const char *>(output_blob.data()), output_blob.length()); + produce(output_data); + + setOutputComplete(); + } + + virtual ~ImageTransform() {} + +private: + std::stringstream _img; +}; + + +class GlobalHookPlugin : public GlobalPlugin +{ +public: + GlobalHookPlugin() { registerHook(HOOK_READ_RESPONSE_HEADERS); } + virtual void + handleReadResponseHeaders(Transaction &transaction) + { + string ctype = transaction.getServerResponse().getHeaders().values("Content-Type"); + string user_agent = transaction.getServerRequest().getHeaders().values("User-Agent"); + if (user_agent.find("Chrome") != string::npos && (ctype.find("jpeg") != string::npos || ctype.find("png") != string::npos)) { + TS_DEBUG(TAG, "Content type is either jpeg or png. Converting to webp"); + transaction.addPlugin(new ImageTransform(transaction)); + } + + transaction.resume(); + } +}; + +void +TSPluginInit(int argc ATSCPPAPI_UNUSED, const char *argv[] ATSCPPAPI_UNUSED) +{ + RegisterGlobalPlugin("CPP_Webp_Transform", "apache", "[email protected]"); + InitializeMagick(""); + new GlobalHookPlugin(); +} http://git-wip-us.apache.org/repos/asf/trafficserver/blob/39b2eb4b/plugins/experimental/webp_transform/Makefile.am ---------------------------------------------------------------------- diff --git a/plugins/experimental/webp_transform/Makefile.am b/plugins/experimental/webp_transform/Makefile.am new file mode 100644 index 0000000..64ef1ab --- /dev/null +++ b/plugins/experimental/webp_transform/Makefile.am @@ -0,0 +1,28 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(top_srcdir)/build/plugins.mk + +if BUILD_HAS_IMAGEMAGICKCPP + +AM_CPPFLAGS += -I$(top_srcdir)/lib/atscppapi/src/include -Wno-unused-variable $(LIBMAGICKCPP_CFLAGS) +target=WebpTransform.so +pkglib_LTLIBRARIES = WebpTransform.la +WebpTransform_la_SOURCES = ImageTransform.cc +WebpTransform_la_LDFLAGS = -module -avoid-version -shared -L$(top_srcdir)/lib/atscppapi/src/ -latscppapi $(TS_PLUGIN_LDFLAGS) $(LIBMAGICKCPP_LIBS) + +endif http://git-wip-us.apache.org/repos/asf/trafficserver/blob/39b2eb4b/plugins/experimental/webp_transform/README ---------------------------------------------------------------------- diff --git a/plugins/experimental/webp_transform/README b/plugins/experimental/webp_transform/README new file mode 100644 index 0000000..595d0e6 --- /dev/null +++ b/plugins/experimental/webp_transform/README @@ -0,0 +1,4 @@ +Converting jpeg and png to webp using ImageMagick Magick++ lib +Pre-requisites + +1. Magick++ api for ImageMagick
