You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bc...@apache.org on 2020/10/06 00:44:59 UTC
[trafficserver] 01/03: Updates to webp_transform to convert webp to
jpeg
This is an automated email from the ASF dual-hosted git repository.
bcall pushed a commit to branch webp_to_jpeg
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 9a0f785db5a5ffb370141762b474fe5dbb19a2f5
Author: Bryan Call <bc...@apache.org>
AuthorDate: Mon Oct 5 12:33:28 2020 -0700
Updates to webp_transform to convert webp to jpeg
---
.../experimental/webp_transform/ImageTransform.cc | 102 +++++++++++++++++----
1 file changed, 86 insertions(+), 16 deletions(-)
diff --git a/plugins/experimental/webp_transform/ImageTransform.cc b/plugins/experimental/webp_transform/ImageTransform.cc
index 88d19cd..96ecc73 100644
--- a/plugins/experimental/webp_transform/ImageTransform.cc
+++ b/plugins/experimental/webp_transform/ImageTransform.cc
@@ -23,10 +23,10 @@
#include "tscpp/api/GlobalPlugin.h"
#include "tscpp/api/TransformationPlugin.h"
#include "tscpp/api/Logger.h"
+#include "tscpp/api/Stat.h"
#include <Magick++.h>
-using std::string;
using namespace Magick;
using namespace atscppapi;
@@ -35,12 +35,21 @@ using namespace atscppapi;
namespace
{
GlobalPlugin *plugin;
-}
+
+enum class TransformImageType { webp, jpeg };
+
+bool config_convert_to_webp = false;
+bool config_convert_to_jpeg = false;
+
+Stat stat_convert_to_webp;
+Stat stat_convert_to_jpeg;
+} // namespace
class ImageTransform : public TransformationPlugin
{
public:
- ImageTransform(Transaction &transaction) : TransformationPlugin(transaction, TransformationPlugin::RESPONSE_TRANSFORMATION)
+ ImageTransform(Transaction &transaction, TransformImageType image_type)
+ : TransformationPlugin(transaction, TransformationPlugin::RESPONSE_TRANSFORMATION), _image_type(image_type)
{
TransformationPlugin::registerHook(HOOK_READ_RESPONSE_HEADERS);
}
@@ -48,8 +57,12 @@ public:
void
handleReadResponseHeaders(Transaction &transaction) override
{
- transaction.getServerResponse().getHeaders()["Content-Type"] = "image/webp";
- transaction.getServerResponse().getHeaders()["Vary"] = "Content-Type"; // to have a separate cache entry.
+ if (_image_type == TransformImageType::webp) {
+ transaction.getServerResponse().getHeaders()["Content-Type"] = "image/webp";
+ } else {
+ transaction.getServerResponse().getHeaders()["Content-Type"] = "image/jpeg";
+ }
+ transaction.getServerResponse().getHeaders()["Vary"] = "Accpet"; // to have a separate cache entry
TS_DEBUG(TAG, "url %s", transaction.getServerRequest().getUrl().getUrlString().c_str());
transaction.resume();
@@ -64,13 +77,21 @@ public:
void
handleInputComplete() override
{
- string input_data = _img.str();
+ std::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");
+ if (_image_type == TransformImageType::webp) {
+ stat_convert_to_webp.increment(1);
+ TSDebug(TAG, "Transforming jpeg or png to webp");
+ image.magick("WEBP");
+ } else {
+ stat_convert_to_jpeg.increment(1);
+ TSDebug(TAG, "Transforming wepb to jpeg");
+ image.magick("JPEG");
+ }
image.write(&output_blob);
produce(std::string_view(reinterpret_cast<const char *>(output_blob.data()), output_blob.length()));
@@ -81,6 +102,7 @@ public:
private:
std::stringstream _img;
+ TransformImageType _image_type;
};
class GlobalHookPlugin : public GlobalPlugin
@@ -90,16 +112,40 @@ public:
void
handleReadResponseHeaders(Transaction &transaction) override
{
- string ctype = transaction.getServerResponse().getHeaders().values("Content-Type");
- string user_agent = transaction.getServerRequest().getHeaders().values("User-Agent");
- string accept = transaction.getServerRequest().getHeaders().values("Accept");
+ // This method tries to optimize the amount of string searching at the expense of double checking some of the booleans
+
+ std::string ctype = transaction.getServerResponse().getHeaders().values("Content-Type");
- bool webp_supported = accept.find("image/webp") != string::npos || user_agent.find("Chrome") != string::npos;
- bool image_format = ctype.find("jpeg") != string::npos || ctype.find("png") != string::npos;
+ // Test to if in this transaction we might want to convert jpeg or png to webp
+ bool transaction_convert_to_wepb = false;
+ if (config_convert_to_webp == true) {
+ transaction_convert_to_wepb = ctype.find("image/jpeg") != std::string::npos || ctype.find("image/png") != std::string::npos;
+ }
- if (webp_supported && image_format) {
- TS_DEBUG(TAG, "Content type is either jpeg or png. Converting to webp");
- transaction.addPlugin(new ImageTransform(transaction));
+ // Test to if in this transaction we might want to convert webp to jpeg
+ bool transaction_convert_to_jpeg = false;
+ if (config_convert_to_jpeg == true && transaction_convert_to_wepb == false) {
+ transaction_convert_to_jpeg = ctype.find("image/webp") != std::string::npos;
+ }
+
+ TSDebug(TAG, "User-Agent: %s transaction_convert_to_wepb: %d transaction_convert_to_jpeg: %d", ctype.c_str(),
+ transaction_convert_to_wepb, transaction_convert_to_jpeg);
+
+ // If we might need to convert check to see if what the browser supports
+ if (transaction_convert_to_wepb == true || transaction_convert_to_jpeg == true) {
+ std::string accept = transaction.getServerRequest().getHeaders().values("Accept");
+ bool webp_supported = accept.find("image/webp") != std::string::npos;
+ TSDebug(TAG, "Accept: %s webp_suppported: %d", accept.c_str(), webp_supported);
+
+ if (webp_supported == true && transaction_convert_to_wepb == true) {
+ TSDebug(TAG, "Content type is either jpeg or png. Converting to webp");
+ transaction.addPlugin(new ImageTransform(transaction, TransformImageType::webp));
+ } else if (webp_supported == false && transaction_convert_to_jpeg == true) {
+ TSDebug(TAG, "Content type is webp. Converting to jpeg");
+ transaction.addPlugin(new ImageTransform(transaction, TransformImageType::jpeg));
+ } else {
+ TSDebug(TAG, "Nothing to convert");
+ }
}
transaction.resume();
@@ -107,11 +153,35 @@ public:
};
void
-TSPluginInit(int argc ATSCPPAPI_UNUSED, const char *argv[] ATSCPPAPI_UNUSED)
+TSPluginInit(int argc, const char *argv[])
{
if (!RegisterGlobalPlugin("CPP_Webp_Transform", "apache", "dev@trafficserver.apache.org")) {
return;
}
+
+ if (argc >= 2) {
+ std::string option(argv[1]);
+ if (option.find("convert_to_webp") != std::string::npos) {
+ TSDebug(TAG, "Configured to convert to wepb");
+ config_convert_to_webp = true;
+ }
+ if (option.find("convert_to_jpeg") != std::string::npos) {
+ TSDebug(TAG, "Configured to convert to jpeg");
+ config_convert_to_jpeg = true;
+ }
+ if (config_convert_to_webp == false && config_convert_to_jpeg == false) {
+ TSDebug(TAG, "Unknown option: %s", option.c_str());
+ TSError("Unknown option: %s", option.c_str());
+ }
+ } else {
+ TSDebug(TAG, "Default configuration is to convert both webp and jpeg");
+ config_convert_to_webp = true;
+ config_convert_to_jpeg = true;
+ }
+
+ stat_convert_to_webp.init("plugin." TAG ".convert_to_webp", Stat::SYNC_SUM, false);
+ stat_convert_to_jpeg.init("plugin." TAG ".convert_to_jpeg", Stat::SYNC_SUM, false);
+
InitializeMagick("");
plugin = new GlobalHookPlugin();
}