C++程序  |  100行  |  3.17 KB

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed 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.
 */
#pragma once

#include <memory>
#include <functional>

/*
 * Provides a wrapper around libjpeg.
 */
namespace jpegutil {

/**
 * Represents a model for accessing pixel data for a single plane of an image.
 * Note that the actual data is not owned by this class, and the underlying
 * data does not need to be stored in separate planes.
 */
class Plane {
 public:
  /**
   * Provides access to several rows of planar data at a time, copied into an
   * intermediate buffer with pixel data packed in contiguous rows which can be
   * passed to libjpeg.
   */
  class RowIterator {
   public:
    RowIterator(const Plane* plane);

    /**
     * Retrieves the y-th row, copying it into a buffer with as much padding
     * as is necessary for use with libjpeg.
     */
    unsigned char* operator()(int y);

   private:
    const Plane* plane_;

    // Stores a ring-buffer of cache-aligned buffers for storing contiguous
    // pixel data for rows of the image to be sent to libjpeg.
    std::unique_ptr<unsigned char[]> buffer_;
    // The cache-aligned start index of buffer_
    unsigned char* alignedBuffer_;
    // The total number of rows in the ring-buffer
    int bufRowCount_;
    // The current ring-buffer row being used
    int bufCurRow_;
    // The number of bytes between consecutive rows in the buffer
    int bufRowStride_;

    // The number of bytes of padding-pixels which must be appended to each row
    // to reach the multiple of 16-bytes required by libjpeg.
    int rowPadding_;
  };

  Plane(int imgWidth, int imgHeight, int planeWidth, int planeHeight,
        unsigned char* data, int pixelStride, int rowStride);

  int imgWidth() const { return imgWidth_; }
  int imgHeight() const { return imgHeight_; }

 private:
  // The dimensions of the entire image
  int imgWidth_;
  int imgHeight_;
  // The dimensions of this plane of the image
  int planeWidth_;
  int planeHeight_;

  // A pointer to raw pixel data
  unsigned char* data_;
  // The difference in address between the start of consecutive rows
  int rowStride_;
  // The difference in address between consecutive pixels in the same row
  int pixelStride_;
};

/**
 * Compresses an image from YUV 420p to JPEG. Output is buffered in outBuf until
 * capacity is reached, at which point flush(size_t) is called to write
 * out the specified number of bytes from outBuf.  Returns the number of bytes
 * written, or -1 in case of an error.
 */
int compress(const Plane& yPlane, const Plane& cbPlane, const Plane& crPlane,
             unsigned char* outBuf, size_t outBufCapacity,
             std::function<void(size_t)> flush, int quality);
}