From 7c3b92403958e8970e901fd15b2fc904e7996eee Mon Sep 17 00:00:00 2001 From: Georgios Pinitas Date: Thu, 21 Jun 2018 19:01:25 +0100 Subject: COMPMID-1308: Add and validate JPEG accessors Change-Id: I93d7345a795b26153600287346d672209dbb2622 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/137479 Tested-by: Jenkins Reviewed-by: Anthony Barbier --- utils/Utils.h | 260 ---------------------------------------------------------- 1 file changed, 260 deletions(-) (limited to 'utils/Utils.h') diff --git a/utils/Utils.h b/utils/Utils.h index 6cb71fd3ba..c18ad217a4 100644 --- a/utils/Utils.h +++ b/utils/Utils.h @@ -254,266 +254,6 @@ inline void unmap(GCTensor &tensor) } #endif /* ARM_COMPUTE_GC */ -/** Class to load the content of a PPM file into an Image - */ -class PPMLoader -{ -public: - PPMLoader() - : _fs(), _width(0), _height(0) - { - } - /** Open a PPM file and reads its metadata (Width, height) - * - * @param[in] ppm_filename File to open - */ - void open(const std::string &ppm_filename) - { - ARM_COMPUTE_ERROR_ON(is_open()); - try - { - _fs.exceptions(std::ifstream::failbit | std::ifstream::badbit); - _fs.open(ppm_filename, std::ios::in | std::ios::binary); - - unsigned int max_val = 0; - std::tie(_width, _height, max_val) = parse_ppm_header(_fs); - - ARM_COMPUTE_ERROR_ON_MSG(max_val >= 256, "2 bytes per colour channel not supported in file %s", ppm_filename.c_str()); - } - catch(std::runtime_error &e) - { - ARM_COMPUTE_ERROR("Accessing %s: %s", ppm_filename.c_str(), e.what()); - } - } - /** Return true if a PPM file is currently open - */ - bool is_open() - { - return _fs.is_open(); - } - - /** Initialise an image's metadata with the dimensions of the PPM file currently open - * - * @param[out] image Image to initialise - * @param[in] format Format to use for the image (Must be RGB888 or U8) - */ - template - void init_image(T &image, arm_compute::Format format) - { - ARM_COMPUTE_ERROR_ON(!is_open()); - ARM_COMPUTE_ERROR_ON(format != arm_compute::Format::RGB888 && format != arm_compute::Format::U8); - - // Use the size of the input PPM image - arm_compute::TensorInfo image_info(_width, _height, format); - image.allocator()->init(image_info); - } - - /** Fill an image with the content of the currently open PPM file. - * - * @note If the image is a CLImage, the function maps and unmaps the image - * - * @param[in,out] image Image to fill (Must be allocated, and of matching dimensions with the opened PPM). - */ - template - void fill_image(T &image) - { - ARM_COMPUTE_ERROR_ON(!is_open()); - ARM_COMPUTE_ERROR_ON(image.info()->dimension(0) != _width || image.info()->dimension(1) != _height); - ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(&image, arm_compute::Format::U8, arm_compute::Format::RGB888); - try - { - // Map buffer if creating a CLTensor/GCTensor - map(image, true); - - // Check if the file is large enough to fill the image - const size_t current_position = _fs.tellg(); - _fs.seekg(0, std::ios_base::end); - const size_t end_position = _fs.tellg(); - _fs.seekg(current_position, std::ios_base::beg); - - ARM_COMPUTE_ERROR_ON_MSG((end_position - current_position) < image.info()->tensor_shape().total_size() * image.info()->element_size(), - "Not enough data in file"); - ARM_COMPUTE_UNUSED(end_position); - - switch(image.info()->format()) - { - case arm_compute::Format::U8: - { - // We need to convert the data from RGB to grayscale: - // Iterate through every pixel of the image - arm_compute::Window window; - window.set(arm_compute::Window::DimX, arm_compute::Window::Dimension(0, _width, 1)); - window.set(arm_compute::Window::DimY, arm_compute::Window::Dimension(0, _height, 1)); - - arm_compute::Iterator out(&image, window); - - unsigned char red = 0; - unsigned char green = 0; - unsigned char blue = 0; - - arm_compute::execute_window_loop(window, [&](const arm_compute::Coordinates & id) - { - red = _fs.get(); - green = _fs.get(); - blue = _fs.get(); - - *out.ptr() = 0.2126f * red + 0.7152f * green + 0.0722f * blue; - }, - out); - - break; - } - case arm_compute::Format::RGB888: - { - // There is no format conversion needed: we can simply copy the content of the input file to the image one row at the time. - // Create a vertical window to iterate through the image's rows: - arm_compute::Window window; - window.set(arm_compute::Window::DimY, arm_compute::Window::Dimension(0, _height, 1)); - - arm_compute::Iterator out(&image, window); - - arm_compute::execute_window_loop(window, [&](const arm_compute::Coordinates & id) - { - // Copy one row from the input file to the current row of the image: - _fs.read(reinterpret_cast(out.ptr()), _width * image.info()->element_size()); - }, - out); - - break; - } - default: - ARM_COMPUTE_ERROR("Unsupported format"); - } - - // Unmap buffer if creating a CLTensor/GCTensor - unmap(image); - } - catch(const std::ifstream::failure &e) - { - ARM_COMPUTE_ERROR("Loading PPM file: %s", e.what()); - } - } - - /** Fill a tensor with 3 planes (one for each channel) with the content of the currently open PPM file. - * - * @note If the image is a CLImage, the function maps and unmaps the image - * - * @param[in,out] tensor Tensor with 3 planes to fill (Must be allocated, and of matching dimensions with the opened PPM). Data types supported: U8/F32 - * @param[in] bgr (Optional) Fill the first plane with blue channel (default = false) - */ - template - void fill_planar_tensor(T &tensor, bool bgr = false) - { - ARM_COMPUTE_ERROR_ON(!is_open()); - ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&tensor, 1, DataType::U8, DataType::F32); - - const DataLayout data_layout = tensor.info()->data_layout(); - const TensorShape tensor_shape = tensor.info()->tensor_shape(); - - ARM_COMPUTE_UNUSED(tensor_shape); - ARM_COMPUTE_ERROR_ON(tensor_shape[get_data_layout_dimension_index(data_layout, DataLayoutDimension::WIDTH)] != _width); - ARM_COMPUTE_ERROR_ON(tensor_shape[get_data_layout_dimension_index(data_layout, DataLayoutDimension::HEIGHT)] != _height); - ARM_COMPUTE_ERROR_ON(tensor_shape[get_data_layout_dimension_index(data_layout, DataLayoutDimension::CHANNEL)] != 3); - - try - { - // Map buffer if creating a CLTensor - map(tensor, true); - - // Check if the file is large enough to fill the image - const size_t current_position = _fs.tellg(); - _fs.seekg(0, std::ios_base::end); - const size_t end_position = _fs.tellg(); - _fs.seekg(current_position, std::ios_base::beg); - - ARM_COMPUTE_ERROR_ON_MSG((end_position - current_position) < tensor.info()->tensor_shape().total_size(), - "Not enough data in file"); - ARM_COMPUTE_UNUSED(end_position); - - // Stride across channels - size_t stride_z = 0; - - // Iterate through every pixel of the image - arm_compute::Window window; - if(data_layout == DataLayout::NCHW) - { - window.set(arm_compute::Window::DimX, arm_compute::Window::Dimension(0, _width, 1)); - window.set(arm_compute::Window::DimY, arm_compute::Window::Dimension(0, _height, 1)); - window.set(arm_compute::Window::DimZ, arm_compute::Window::Dimension(0, 1, 1)); - stride_z = tensor.info()->strides_in_bytes()[2]; - } - else - { - window.set(arm_compute::Window::DimX, arm_compute::Window::Dimension(0, 1, 1)); - window.set(arm_compute::Window::DimY, arm_compute::Window::Dimension(0, _width, 1)); - window.set(arm_compute::Window::DimZ, arm_compute::Window::Dimension(0, _height, 1)); - stride_z = tensor.info()->strides_in_bytes()[0]; - } - - arm_compute::Iterator out(&tensor, window); - - unsigned char red = 0; - unsigned char green = 0; - unsigned char blue = 0; - - arm_compute::execute_window_loop(window, [&](const arm_compute::Coordinates & id) - { - red = _fs.get(); - green = _fs.get(); - blue = _fs.get(); - - switch(tensor.info()->data_type()) - { - case arm_compute::DataType::U8: - { - *(out.ptr() + 0 * stride_z) = bgr ? blue : red; - *(out.ptr() + 1 * stride_z) = green; - *(out.ptr() + 2 * stride_z) = bgr ? red : blue; - break; - } - case arm_compute::DataType::F32: - { - *reinterpret_cast(out.ptr() + 0 * stride_z) = static_cast(bgr ? blue : red); - *reinterpret_cast(out.ptr() + 1 * stride_z) = static_cast(green); - *reinterpret_cast(out.ptr() + 2 * stride_z) = static_cast(bgr ? red : blue); - break; - } - default: - { - ARM_COMPUTE_ERROR("Unsupported data type"); - } - } - }, - out); - - // Unmap buffer if creating a CLTensor - unmap(tensor); - } - catch(const std::ifstream::failure &e) - { - ARM_COMPUTE_ERROR("Loading PPM file: %s", e.what()); - } - } - - /** Return the width of the currently open PPM file. - */ - unsigned int width() const - { - return _width; - } - - /** Return the height of the currently open PPM file. - */ - unsigned int height() const - { - return _height; - } - -private: - std::ifstream _fs; - unsigned int _width, _height; -}; - /** Numpy data loader */ class NPYLoader { -- cgit v1.2.1