blob: 5540f9d492123253f810ab408848afb4bd4c4da0 [file] [log] [blame]
/*
* 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.
*/
#ifndef PAGESPEED_KERNEL_IMAGE_IMAGE_OPTIMIZER_H_
#define PAGESPEED_KERNEL_IMAGE_IMAGE_OPTIMIZER_H_
#include <memory>
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/http/image_types.pb.h"
#include "pagespeed/kernel/image/image_optimizer.pb.h"
#include "pagespeed/kernel/image/image_util.h"
namespace net_instaweb {
class Timer;
}
namespace pagespeed {
namespace image_compression {
// Optimizes an image. The supported formats include GIF (both single-frame
// and animated), PNG, and JPEG. They can be converted to PNG, JPEG, or WebP
// (including lossy, lossless, or animated WebP). They can be resized to
// smaller dimensions. You specify the allowed options and the requested
// dimensions, and the method returns the format, dimensions, and contents
// for the actual output.
//
// If you specify a timer and the max_timeout_ms parameter, the method
// applies them to WebP images (other images are not affected by these
// parameters).
//
// This class can only be used to optimize one image, i.e., an ImageOptimizer
// object can only have the Optimize method called once.
class ImageOptimizer {
public:
explicit ImageOptimizer(net_instaweb::MessageHandler* message_handler) :
message_handler_(message_handler) {
}
// Applies all optimizations, for example, removing metadata, reducing chroma
// sampling, and reducing dimension, to the image.
//
// TODO(huibao): Instead of buffering the optimized image contents in a string
// let the Optimize method take a writer and stream the contents to the output
// directly.
bool Optimize(StringPiece original_contents,
GoogleString* optimized_contents,
ImageFormat* optimized_format);
void set_options(const pagespeed::image_compression::ImageOptions& options) {
options_ = options;
}
// Specifies the dimensions for resizing the image to. This parameter only
// applies to single-frame images. You can specify either width or height,
// or both. If you specify only one dimension, the image will be resized
// with the original aspect ratio. If the dimensions cannot be honored,
// the image can still be optimized in other ways. You can get the actual
// dimension of the optimized image by using the OutputDimension method.
void set_requested_dimension(
const pagespeed::image_compression::ImageDimensions&
requested_dimensions) {
requested_dim_ = requested_dimensions;
}
// Returns the actual dimensions of the optimized image, even when the image
// is not resized.
int optimized_width() { return optimized_width_; }
int optimized_height() { return optimized_height_; }
// Timer and was_timed_out only apply to WebP images.
void set_timer(net_instaweb::Timer* timer) { timer_ = timer; }
bool was_timed_out() const { return was_timed_out_; }
// Returns whether the image was encoded in lossy format, if the optimization
// succeeded.
bool UsesLossyFormat() const { return !desired_lossless_; }
private:
bool Run();
bool ComputeDesiredFormat();
bool ComputeResizedDimension();
bool ComputeDesiredQualityProgressive();
ImageFormat ImageTypeToImageFormat(net_instaweb::ImageType image_type);
bool ConfigureWriter();
bool RewriteSingleFrameImage();
bool RewriteAnimatedImage();
// External data.
net_instaweb::MessageHandler* const message_handler_;
pagespeed::image_compression::ImageOptions options_;
StringPiece original_contents_;
pagespeed::image_compression::ImageDimensions requested_dim_;
GoogleString* optimized_contents_ = nullptr;
net_instaweb::Timer* timer_ = nullptr;
std::unique_ptr<ConversionTimeoutHandler> timeout_handler_;
bool was_timed_out_ = false;
// Information about input image.
ImageFormat original_format_;
int original_width_ = -1;
int original_height_ = -1;
bool is_progressive_ = false;
bool is_animated_ = false;
bool is_transparent_ = false;
bool is_photo_ = false;
int original_quality_ = -1;
// Information about desired output.
ImageFormat optimized_format_;
int optimized_width_ = -1;
int optimized_height_ = -1;
int desired_quality_ = -1;
bool desired_progressive_ = false;
bool desired_lossless_ = false;
std::unique_ptr<ScanlineWriterConfig> writer_config_;
bool is_valid_ = true;
DISALLOW_COPY_AND_ASSIGN(ImageOptimizer);
};
} // namespace image_compression
} // namespace pagespeed
#endif // PAGESPEED_KERNEL_IMAGE_IMAGE_OPTIMIZER_H__