1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
17
18#include <memory>
19#include <functional>
20
21/*
22 * Provides a wrapper around libjpeg.
23 */
24namespace jpegutil {
25
26/**
27 * Represents a model for accessing pixel data for a single plane of an image.
28 * Note that the actual data is not owned by this class, and the underlying
29 * data does not need to be stored in separate planes.
30 */
31class Plane {
32 public:
33  /**
34   * Provides access to several rows of planar data at a time, copied into an
35   * intermediate buffer with pixel data packed in contiguous rows which can be
36   * passed to libjpeg.
37   */
38  class RowIterator {
39   public:
40    RowIterator(const Plane* plane);
41
42    /**
43     * Retrieves the y-th row, copying it into a buffer with as much padding
44     * as is necessary for use with libjpeg.
45     */
46    unsigned char* operator()(int y);
47
48   private:
49    const Plane* plane_;
50
51    // Stores a ring-buffer of cache-aligned buffers for storing contiguous
52    // pixel data for rows of the image to be sent to libjpeg.
53    std::unique_ptr<unsigned char[]> buffer_;
54    // The cache-aligned start index of buffer_
55    unsigned char* alignedBuffer_;
56    // The total number of rows in the ring-buffer
57    int bufRowCount_;
58    // The current ring-buffer row being used
59    int bufCurRow_;
60    // The number of bytes between consecutive rows in the buffer
61    int bufRowStride_;
62
63    // The number of bytes of padding-pixels which must be appended to each row
64    // to reach the multiple of 16-bytes required by libjpeg.
65    int rowPadding_;
66  };
67
68  Plane(int imgWidth, int imgHeight, int planeWidth, int planeHeight,
69        unsigned char* data, int pixelStride, int rowStride);
70
71  int imgWidth() const { return imgWidth_; }
72  int imgHeight() const { return imgHeight_; }
73
74 private:
75  // The dimensions of the entire image
76  int imgWidth_;
77  int imgHeight_;
78  // The dimensions of this plane of the image
79  int planeWidth_;
80  int planeHeight_;
81
82  // A pointer to raw pixel data
83  unsigned char* data_;
84  // The difference in address between the start of consecutive rows
85  int rowStride_;
86  // The difference in address between consecutive pixels in the same row
87  int pixelStride_;
88};
89
90/**
91 * Compresses an image from YUV 420p to JPEG. Output is buffered in outBuf until
92 * capacity is reached, at which point flush(size_t) is called to write
93 * out the specified number of bytes from outBuf.  Returns the number of bytes
94 * written, or -1 in case of an error.
95 */
96int compress(const Plane& yPlane, const Plane& cbPlane, const Plane& crPlane,
97             unsigned char* outBuf, size_t outBufCapacity,
98             std::function<void(size_t)> flush, int quality);
99}
100