001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.util;
006
007import java.nio.ByteBuffer;
008
009/**
010 * Class for storing raw frame data between image read call.
011 *
012 * <p>Data is reused for each frame read, rather then reallocating every frame.
013 */
014public class RawFrame implements AutoCloseable {
015  private long m_nativeObj;
016  private ByteBuffer m_data;
017  private int m_width;
018  private int m_height;
019  private int m_stride;
020  private PixelFormat m_pixelFormat = PixelFormat.kUnknown;
021
022  /** Construct a new empty RawFrame. */
023  public RawFrame() {
024    m_nativeObj = WPIUtilJNI.allocateRawFrame();
025  }
026
027  /**
028   * Close the RawFrame, releasing native resources. Any images currently using the data will be
029   * invalidated.
030   */
031  @Override
032  public void close() {
033    WPIUtilJNI.freeRawFrame(m_nativeObj);
034    m_nativeObj = 0;
035  }
036
037  /**
038   * Called from JNI to set data in class.
039   *
040   * @param data A native ByteBuffer pointing to the frame data.
041   * @param width The width of the frame, in pixels
042   * @param height The height of the frame, in pixels
043   * @param stride The number of bytes in each row of image data
044   * @param pixelFormat The PixelFormat of the frame
045   */
046  void setDataJNI(ByteBuffer data, int width, int height, int stride, int pixelFormat) {
047    m_data = data;
048    m_width = width;
049    m_height = height;
050    m_stride = stride;
051    m_pixelFormat = PixelFormat.getFromInt(pixelFormat);
052  }
053
054  /**
055   * Called from JNI to set info in class.
056   *
057   * @param width The width of the frame, in pixels
058   * @param height The height of the frame, in pixels
059   * @param stride The number of bytes in each row of image data
060   * @param pixelFormat The PixelFormat of the frame
061   */
062  void setInfoJNI(int width, int height, int stride, int pixelFormat) {
063    m_width = width;
064    m_height = height;
065    m_stride = stride;
066    m_pixelFormat = PixelFormat.getFromInt(pixelFormat);
067  }
068
069  /**
070   * Set frame data.
071   *
072   * @param data A native ByteBuffer pointing to the frame data.
073   * @param width The width of the frame, in pixels
074   * @param height The height of the frame, in pixels
075   * @param stride The number of bytes in each row of image data
076   * @param pixelFormat The PixelFormat of the frame
077   */
078  public void setData(ByteBuffer data, int width, int height, int stride, PixelFormat pixelFormat) {
079    if (!data.isDirect()) {
080      throw new UnsupportedOperationException("ByteBuffer must be direct");
081    }
082    m_data = data;
083    m_width = width;
084    m_height = height;
085    m_stride = stride;
086    m_pixelFormat = pixelFormat;
087    WPIUtilJNI.setRawFrameData(
088        m_nativeObj, data, data.limit(), width, height, stride, pixelFormat.getValue());
089  }
090
091  /**
092   * Call to set frame information.
093   *
094   * @param width The width of the frame, in pixels
095   * @param height The height of the frame, in pixels
096   * @param stride The number of bytes in each row of image data
097   * @param pixelFormat The PixelFormat of the frame
098   */
099  public void setInfo(int width, int height, int stride, PixelFormat pixelFormat) {
100    m_width = width;
101    m_height = height;
102    m_stride = stride;
103    m_pixelFormat = pixelFormat;
104    WPIUtilJNI.setRawFrameInfo(
105        m_nativeObj,
106        m_data != null ? m_data.limit() : 0,
107        width,
108        height,
109        stride,
110        pixelFormat.getValue());
111  }
112
113  /**
114   * Get the pointer to native representation of this frame.
115   *
116   * @return The pointer to native representation of this frame.
117   */
118  public long getNativeObj() {
119    return m_nativeObj;
120  }
121
122  /**
123   * Get a ByteBuffer pointing to the frame data. This ByteBuffer is backed by the frame directly.
124   * Its lifetime is controlled by the frame. If a new frame gets read, it will overwrite the
125   * current one.
126   *
127   * @return A ByteBuffer pointing to the frame data.
128   */
129  public ByteBuffer getData() {
130    return m_data;
131  }
132
133  /**
134   * Get a long (is a uint8_t* in native code) pointing to the frame data. This pointer is backed by
135   * the frame directly. Its lifetime is controlled by the frame. If a new frame gets read, it will
136   * overwrite the current one.
137   *
138   * @return A long pointing to the frame data.
139   */
140  public long getDataPtr() {
141    return WPIUtilJNI.getRawFrameDataPtr(m_nativeObj);
142  }
143
144  /**
145   * Get the total size of the data stored in the frame, in bytes.
146   *
147   * @return The total size of the data stored in the frame.
148   */
149  public int getSize() {
150    return m_data != null ? m_data.limit() : 0;
151  }
152
153  /**
154   * Get the width of the image.
155   *
156   * @return The width of the image, in pixels.
157   */
158  public int getWidth() {
159    return m_width;
160  }
161
162  /**
163   * Get the height of the image.
164   *
165   * @return The height of the image, in pixels.
166   */
167  public int getHeight() {
168    return m_height;
169  }
170
171  /**
172   * Get the number of bytes in each row of image data.
173   *
174   * @return The image data stride, in bytes.
175   */
176  public int getStride() {
177    return m_stride;
178  }
179
180  /**
181   * Get the PixelFormat of the frame.
182   *
183   * @return The PixelFormat of the frame.
184   */
185  public PixelFormat getPixelFormat() {
186    return m_pixelFormat;
187  }
188}