text: // Copyright 2019 The MediaPipe Authors.
  //
  // 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.
  
  #ifndef MEDIAPIPE_OBJC_UTIL_H_
  #define MEDIAPIPE_OBJC_UTIL_H_
  
  #import <Accelerate/Accelerate.h>
  #import <CoreFoundation/CoreFoundation.h>
  #import <CoreGraphics/CoreGraphics.h>
  #import <CoreVideo/CoreVideo.h>
  
  #include "mediapipe/framework/formats/image_frame.h"
  #include "mediapipe/framework/packet.h"
  #include "mediapipe/framework/port/status.h"
  #include "mediapipe/objc/CFHolder.h"
  
  // TODO: namespace and/or prefix these. Split up the file.
  
  /// Returns a vImage_Buffer describing the data inside the pixel_buffer.
  /// NOTE: the pixel buffer's base address must have been locked before this
  /// call, and it must stay locked as long as the vImage_Buffer is in use.
  inline vImage_Buffer vImageForCVPixelBuffer(CVPixelBufferRef pixel_buffer) {
    return {.data = CVPixelBufferGetBaseAddress(pixel_buffer),
            .width = CVPixelBufferGetWidth(pixel_buffer),
            .height = CVPixelBufferGetHeight(pixel_buffer),
            .rowBytes = CVPixelBufferGetBytesPerRow(pixel_buffer)};
  }
  
  /// Returns a vImage_Buffer describing the data inside the ImageFrame.
  inline vImage_Buffer vImageForImageFrame(const mediapipe::ImageFrame& frame) {
    return {.data = (void*)frame.PixelData(),
            .width = static_cast<vImagePixelCount>(frame.Width()),
            .height = static_cast<vImagePixelCount>(frame.Height()),
            .rowBytes = static_cast<size_t>(frame.WidthStep())};
  }
  
  /// Converts a grayscale image without alpha to BGRA format.
  vImage_Error vImageGrayToBGRA(const vImage_Buffer* src, vImage_Buffer* dst);
  
  /// Converts a BGRA image to grayscale without alpha.
  vImage_Error vImageBGRAToGray(const vImage_Buffer* src, vImage_Buffer* dst);
  
  /// Converts an RGBA image to grayscale without alpha.
  vImage_Error vImageRGBAToGray(const vImage_Buffer* src, vImage_Buffer* dst);
  
  /// Copy from a pixel buffer to another, converting pixel format.
  /// Both pixel buffers should be locked before calling this.
  vImage_Error vImageConvertCVPixelBuffers(CVPixelBufferRef src,
                                           CVPixelBufferRef dst);
  
  // Create a CVPixelBuffer without using a pool. See pixel_buffer_pool_util.h
  // for creation functions that use pools.
  CVReturn CreateCVPixelBufferWithoutPool(int width, int height, OSType cv_format,
                                          CVPixelBufferRef* out_buffer);
  absl::StatusOr<CFHolder<CVPixelBufferRef>> CreateCVPixelBufferWithoutPool(
      int width, int height, OSType cv_format);
  
  /// Returns a CVPixelBuffer that references the data inside the packet. The
  /// packet must contain an ImageFrame. The CVPixelBuffer manages a copy of
  /// the packet, so that the packet's data is kept alive as long as the
  /// CVPixelBuffer is in use.
  ///
  /// For formats which are not supported by both image types, it may be
  /// necessary to convert the data. This is done by creating a new buffer.
  /// If the optional can_overwrite parameter is true, the old buffer may be
  /// modified instead.
  absl::Status CreateCVPixelBufferForImageFramePacket(
      const mediapipe::Packet& image_frame_packet,
      CFHolder<CVPixelBufferRef>* out_buffer);
  absl::Status CreateCVPixelBufferForImageFramePacket(
      const mediapipe::Packet& image_frame_packet, bool can_overwrite,
      CFHolder<CVPixelBufferRef>* out_buffer);
  absl::StatusOr<CFHolder<CVPixelBufferRef>> CreateCVPixelBufferCopyingImageFrame(
      const mediapipe::ImageFrame& image_frame);
  absl::StatusOr<CFHolder<CVPixelBufferRef>> CreateCVPixelBufferForImageFrame(
      std::shared_ptr<mediapipe::ImageFrame> image_frame,
      bool can_overwrite = false);
  
  /// Creates a CVPixelBuffer with a copy of the contents of the CGImage.
  absl::Status CreateCVPixelBufferFromCGImage(
      CGImageRef image, CFHolder<CVPixelBufferRef>* out_buffer);
  
  /// Creates a CGImage with a copy of the contents of the CVPixelBuffer.
  absl::Status CreateCGImageFromCVPixelBuffer(CVPixelBufferRef image_buffer,
                                              CFHolder<CGImageRef>* image);
  
  /// DEPRECATED: use the version that returns absl::Status instead.
  CVPixelBufferRef CreateCVPixelBufferForImageFramePacket(
      const mediapipe::Packet& image_frame_packet);
  
  /// Returns an ImageFrame that references the data inside the pixel_buffer.
  /// The ImageFrame retains the pixel_buffer and keeps it locked as long as it
  /// is in use.
  ///
  /// For formats which are not supported by both image types, it may be
  /// necessary to convert the data. This is done by creating a new buffer.
  /// If the optional can_overwrite parameter is true, the old buffer may be
  /// modified instead.
  ///
  /// ImageFrame does not have a format for BGRA data, so we normally swap the
  /// channels to produce RGBA. But many graphs do not care about the order of
  /// the channels; in those cases, setting the optional bgr_as_rgb parameter
  /// to true skips the channel swap.
  std::unique_ptr<mediapipe::ImageFrame> CreateImageFrameForCVPixelBuffer(
      CVPixelBufferRef pixel_buffer);
  std::unique_ptr<mediapipe::ImageFrame> CreateImageFrameForCVPixelBuffer(
      CVPixelBufferRef pixel_buffer, bool can_overwrite, bool bgr_as_rgb);
  
  /// Returns a CFDictionaryRef that can be passed to CVPixelBufferCreate to
  /// ensure that the pixel buffer is compatible with OpenGL ES and with
  /// CVOpenGLESTextureCacheCreateTextureFromImage.
  /// The returned object is persistent and should not be released.
  CFDictionaryRef GetCVPixelBufferAttributesForGlCompatibility();
  
  /// Prints debug information about available CoreVideo pixel formats.
  /// This prints to stdout.
  void DumpCVPixelFormats();
  
  #endif  // MEDIAPIPE_OBJC_UTIL_H_
  