add part of opencv

This commit is contained in:
Tang1705
2020-01-27 20:20:56 +08:00
parent 0c4ac1d8bb
commit a71fa47620
6518 changed files with 3122580 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
set(the_description "Image I/O")
ocv_add_module(imgcodecs opencv_imgproc WRAP java python)
# ----------------------------------------------------------------------------
# CMake file for imgcodecs. See root CMakeLists.txt
# Some parts taken from version of Hartmut Seichter, HIT Lab NZ.
# Jose Luis Blanco, 2008
# ----------------------------------------------------------------------------
ocv_clear_vars(GRFMT_LIBS)
if(HAVE_WINRT_CX AND NOT WINRT)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /ZW")
endif()
if(HAVE_PNG OR HAVE_TIFF OR HAVE_OPENEXR)
ocv_include_directories(${ZLIB_INCLUDE_DIRS})
list(APPEND GRFMT_LIBS ${ZLIB_LIBRARIES})
endif()
if(HAVE_JPEG)
ocv_include_directories(${JPEG_INCLUDE_DIR} ${${JPEG_LIBRARY}_BINARY_DIR})
list(APPEND GRFMT_LIBS ${JPEG_LIBRARIES})
endif()
if(HAVE_WEBP)
add_definitions(-DHAVE_WEBP)
ocv_include_directories(${WEBP_INCLUDE_DIR})
list(APPEND GRFMT_LIBS ${WEBP_LIBRARIES})
endif()
if(HAVE_PNG)
add_definitions(${PNG_DEFINITIONS})
ocv_include_directories(${PNG_INCLUDE_DIR})
list(APPEND GRFMT_LIBS ${PNG_LIBRARIES})
endif()
if(HAVE_GDCM)
ocv_include_directories(${GDCM_INCLUDE_DIRS})
list(APPEND GRFMT_LIBS ${GDCM_LIBRARIES})
endif()
if(HAVE_TIFF)
ocv_include_directories(${TIFF_INCLUDE_DIR})
list(APPEND GRFMT_LIBS ${TIFF_LIBRARIES})
endif()
if(HAVE_JASPER)
ocv_include_directories(${JASPER_INCLUDE_DIR})
list(APPEND GRFMT_LIBS ${JASPER_LIBRARIES})
if(OPENCV_IO_FORCE_JASPER)
add_definitions(-DOPENCV_IMGCODECS_FORCE_JASPER=1)
endif()
endif()
if(HAVE_OPENEXR)
include_directories(SYSTEM ${OPENEXR_INCLUDE_PATHS})
list(APPEND GRFMT_LIBS ${OPENEXR_LIBRARIES})
endif()
if(HAVE_GDAL)
include_directories(SYSTEM ${GDAL_INCLUDE_DIR})
list(APPEND GRFMT_LIBS ${GDAL_LIBRARY})
endif()
if(HAVE_IMGCODEC_HDR)
add_definitions(-DHAVE_IMGCODEC_HDR)
endif()
if(HAVE_IMGCODEC_SUNRASTER)
add_definitions(-DHAVE_IMGCODEC_SUNRASTER)
endif()
if(HAVE_IMGCODEC_PXM)
add_definitions(-DHAVE_IMGCODEC_PXM)
endif()
if (HAVE_IMGCODEC_PFM)
add_definitions(-DHAVE_IMGCODEC_PFM)
endif()
file(GLOB grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/grfmt*.hpp)
file(GLOB grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/grfmt*.cpp)
list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.hpp)
list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.cpp)
list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.hpp)
list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.cpp)
list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/exif.hpp)
list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/exif.cpp)
source_group("Src\\grfmts" FILES ${grfmt_hdrs} ${grfmt_srcs})
set(imgcodecs_hdrs
${CMAKE_CURRENT_LIST_DIR}/src/precomp.hpp
${CMAKE_CURRENT_LIST_DIR}/src/utils.hpp
)
set(imgcodecs_srcs
${CMAKE_CURRENT_LIST_DIR}/src/loadsave.cpp
${CMAKE_CURRENT_LIST_DIR}/src/utils.cpp
)
file(GLOB imgcodecs_ext_hdrs
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/*.hpp"
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/*.hpp"
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/*.h"
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/legacy/*.h"
)
if(IOS)
list(APPEND imgcodecs_srcs ${CMAKE_CURRENT_LIST_DIR}/src/ios_conversions.mm)
list(APPEND IMGCODECS_LIBRARIES "-framework Accelerate" "-framework CoreGraphics" "-framework QuartzCore" "-framework AssetsLibrary")
endif()
if(APPLE_FRAMEWORK)
list(APPEND IMGCODECS_LIBRARIES "-framework UIKit")
endif()
if(TRUE)
# these variables are set by 'ocv_append_build_options(IMGCODECS ...)'
foreach(P ${IMGCODECS_INCLUDE_DIRS})
ocv_include_directories(${P})
endforeach()
foreach(P ${IMGCODECS_LIBRARY_DIRS})
link_directories(${P})
endforeach()
endif()
source_group("Src" FILES ${imgcodecs_srcs} ${imgcodecs_hdrs})
source_group("Include" FILES ${imgcodecs_ext_hdrs})
ocv_set_module_sources(HEADERS ${imgcodecs_ext_hdrs} SOURCES ${imgcodecs_srcs} ${imgcodecs_hdrs} ${grfmt_srcs} ${grfmt_hdrs})
ocv_module_include_directories()
ocv_create_module(${GRFMT_LIBS} ${IMGCODECS_LIBRARIES})
macro(ocv_imgcodecs_configure_target)
if(APPLE)
add_apple_compiler_options(the_module)
endif()
if(MSVC)
set_target_properties(${the_module} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /NODEFAULTLIB:libcmt.lib /DEBUG")
endif()
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-deprecated-declarations)
endmacro()
if(NOT BUILD_opencv_world)
ocv_imgcodecs_configure_target()
endif()
ocv_add_accuracy_tests()
if(TARGET opencv_test_imgcodecs AND HAVE_JASPER AND "$ENV{OPENCV_IO_ENABLE_JASPER}")
ocv_target_compile_definitions(opencv_test_imgcodecs PRIVATE OPENCV_IMGCODECS_ENABLE_JASPER_TESTS=1)
endif()
ocv_add_perf_tests()

View File

@@ -0,0 +1,277 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef OPENCV_IMGCODECS_HPP
#define OPENCV_IMGCODECS_HPP
#include "opencv2/core.hpp"
/**
@defgroup imgcodecs Image file reading and writing
@{
@defgroup imgcodecs_c C API
@defgroup imgcodecs_ios iOS glue
@}
*/
//////////////////////////////// image codec ////////////////////////////////
namespace cv
{
//! @addtogroup imgcodecs
//! @{
//! Imread flags
enum ImreadModes {
IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).
IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image (codec internal conversion).
IMREAD_COLOR = 1, //!< If set, always convert image to the 3 channel BGR color image.
IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format.
IMREAD_LOAD_GDAL = 8, //!< If set, use the gdal driver for loading the image.
IMREAD_REDUCED_GRAYSCALE_2 = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2.
IMREAD_REDUCED_COLOR_2 = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2.
IMREAD_REDUCED_GRAYSCALE_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4.
IMREAD_REDUCED_COLOR_4 = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.
IMREAD_REDUCED_GRAYSCALE_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8.
IMREAD_REDUCED_COLOR_8 = 65, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.
IMREAD_IGNORE_ORIENTATION = 128 //!< If set, do not rotate the image according to EXIF's orientation flag.
};
//! Imwrite flags
enum ImwriteFlags {
IMWRITE_JPEG_QUALITY = 1, //!< For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default value is 95.
IMWRITE_JPEG_PROGRESSIVE = 2, //!< Enable JPEG features, 0 or 1, default is False.
IMWRITE_JPEG_OPTIMIZE = 3, //!< Enable JPEG features, 0 or 1, default is False.
IMWRITE_JPEG_RST_INTERVAL = 4, //!< JPEG restart interval, 0 - 65535, default is 0 - no restart.
IMWRITE_JPEG_LUMA_QUALITY = 5, //!< Separate luma quality level, 0 - 100, default is 0 - don't use.
IMWRITE_JPEG_CHROMA_QUALITY = 6, //!< Separate chroma quality level, 0 - 100, default is 0 - don't use.
IMWRITE_PNG_COMPRESSION = 16, //!< For PNG, it can be the compression level from 0 to 9. A higher value means a smaller size and longer compression time. If specified, strategy is changed to IMWRITE_PNG_STRATEGY_DEFAULT (Z_DEFAULT_STRATEGY). Default value is 1 (best speed setting).
IMWRITE_PNG_STRATEGY = 17, //!< One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_RLE.
IMWRITE_PNG_BILEVEL = 18, //!< Binary level PNG, 0 or 1, default is 0.
IMWRITE_PXM_BINARY = 32, //!< For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1. Default value is 1.
IMWRITE_EXR_TYPE = (3 << 4) + 0, /* 48 */ //!< override EXR storage type (FLOAT (FP32) is default)
IMWRITE_WEBP_QUALITY = 64, //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used.
IMWRITE_PAM_TUPLETYPE = 128,//!< For PAM, sets the TUPLETYPE field to the corresponding string value that is defined for the format
IMWRITE_TIFF_RESUNIT = 256,//!< For TIFF, use to specify which DPI resolution unit to set; see libtiff documentation for valid values
IMWRITE_TIFF_XDPI = 257,//!< For TIFF, use to specify the X direction DPI
IMWRITE_TIFF_YDPI = 258, //!< For TIFF, use to specify the Y direction DPI
IMWRITE_TIFF_COMPRESSION = 259, //!< For TIFF, use to specify the image compression scheme. See libtiff for integer constants corresponding to compression formats. Note, for images whose depth is CV_32F, only libtiff's SGILOG compression scheme is used. For other supported depths, the compression scheme can be specified by this flag; LZW compression is the default.
IMWRITE_JPEG2000_COMPRESSION_X1000 = 272 //!< For JPEG2000, use to specify the target compression rate (multiplied by 1000). The value can be from 0 to 1000. Default is 1000.
};
enum ImwriteEXRTypeFlags {
/*IMWRITE_EXR_TYPE_UNIT = 0, //!< not supported */
IMWRITE_EXR_TYPE_HALF = 1, //!< store as HALF (FP16)
IMWRITE_EXR_TYPE_FLOAT = 2 //!< store as FP32 (default)
};
//! Imwrite PNG specific flags used to tune the compression algorithm.
/** These flags will be modify the way of PNG image compression and will be passed to the underlying zlib processing stage.
- The effect of IMWRITE_PNG_STRATEGY_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between IMWRITE_PNG_STRATEGY_DEFAULT and IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY.
- IMWRITE_PNG_STRATEGY_RLE is designed to be almost as fast as IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY, but give better compression for PNG image data.
- The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately.
- IMWRITE_PNG_STRATEGY_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications.
*/
enum ImwritePNGFlags {
IMWRITE_PNG_STRATEGY_DEFAULT = 0, //!< Use this value for normal data.
IMWRITE_PNG_STRATEGY_FILTERED = 1, //!< Use this value for data produced by a filter (or predictor).Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better.
IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY = 2, //!< Use this value to force Huffman encoding only (no string match).
IMWRITE_PNG_STRATEGY_RLE = 3, //!< Use this value to limit match distances to one (run-length encoding).
IMWRITE_PNG_STRATEGY_FIXED = 4 //!< Using this value prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications.
};
//! Imwrite PAM specific tupletype flags used to define the 'TUPETYPE' field of a PAM file.
enum ImwritePAMFlags {
IMWRITE_PAM_FORMAT_NULL = 0,
IMWRITE_PAM_FORMAT_BLACKANDWHITE = 1,
IMWRITE_PAM_FORMAT_GRAYSCALE = 2,
IMWRITE_PAM_FORMAT_GRAYSCALE_ALPHA = 3,
IMWRITE_PAM_FORMAT_RGB = 4,
IMWRITE_PAM_FORMAT_RGB_ALPHA = 5,
};
/** @brief Loads an image from a file.
@anchor imread
The function imread loads an image from the specified file and returns it. If the image cannot be
read (because of missing file, improper permissions, unsupported or invalid format), the function
returns an empty matrix ( Mat::data==NULL ).
Currently, the following file formats are supported:
- Windows bitmaps - \*.bmp, \*.dib (always supported)
- JPEG files - \*.jpeg, \*.jpg, \*.jpe (see the *Note* section)
- JPEG 2000 files - \*.jp2 (see the *Note* section)
- Portable Network Graphics - \*.png (see the *Note* section)
- WebP - \*.webp (see the *Note* section)
- Portable image format - \*.pbm, \*.pgm, \*.ppm \*.pxm, \*.pnm (always supported)
- PFM files - \*.pfm (see the *Note* section)
- Sun rasters - \*.sr, \*.ras (always supported)
- TIFF files - \*.tiff, \*.tif (see the *Note* section)
- OpenEXR Image files - \*.exr (see the *Note* section)
- Radiance HDR - \*.hdr, \*.pic (always supported)
- Raster and Vector geospatial data supported by GDAL (see the *Note* section)
@note
- The function determines the type of an image by the content, not by the file extension.
- In the case of color images, the decoded images will have the channels stored in **B G R** order.
- When using IMREAD_GRAYSCALE, the codec's internal grayscale conversion will be used, if available.
Results may differ to the output of cvtColor()
- On Microsoft Windows\* OS and MacOSX\*, the codecs shipped with an OpenCV image (libjpeg,
libpng, libtiff, and libjasper) are used by default. So, OpenCV can always read JPEGs, PNGs,
and TIFFs. On MacOSX, there is also an option to use native MacOSX image readers. But beware
that currently these native image loaders give images with different pixel values because of
the color management embedded into MacOSX.
- On Linux\*, BSD flavors and other Unix-like open-source operating systems, OpenCV looks for
codecs supplied with an OS image. Install the relevant packages (do not forget the development
files, for example, "libjpeg-dev", in Debian\* and Ubuntu\*) to get the codec support or turn
on the OPENCV_BUILD_3RDPARTY_LIBS flag in CMake.
- In the case you set *WITH_GDAL* flag to true in CMake and @ref IMREAD_LOAD_GDAL to load the image,
then the [GDAL](http://www.gdal.org) driver will be used in order to decode the image, supporting
the following formats: [Raster](http://www.gdal.org/formats_list.html),
[Vector](http://www.gdal.org/ogr_formats.html).
- If EXIF information are embedded in the image file, the EXIF orientation will be taken into account
and thus the image will be rotated accordingly except if the flag @ref IMREAD_IGNORE_ORIENTATION is passed.
- Use the IMREAD_UNCHANGED flag to keep the floating point values from PFM image.
- By default number of pixels must be less than 2^30. Limit can be set using system
variable OPENCV_IO_MAX_IMAGE_PIXELS
@param filename Name of file to be loaded.
@param flags Flag that can take values of cv::ImreadModes
*/
CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR );
/** @brief Loads a multi-page image from a file.
The function imreadmulti loads a multi-page image from the specified file into a vector of Mat objects.
@param filename Name of file to be loaded.
@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_ANYCOLOR.
@param mats A vector of Mat objects holding each page, if more than one.
@sa cv::imread
*/
CV_EXPORTS_W bool imreadmulti(const String& filename, CV_OUT std::vector<Mat>& mats, int flags = IMREAD_ANYCOLOR);
/** @brief Saves an image to a specified file.
The function imwrite saves the image to the specified file. The image format is chosen based on the
filename extension (see cv::imread for the list of extensions). In general, only 8-bit
single-channel or 3-channel (with 'BGR' channel order) images
can be saved using this function, with these exceptions:
- 16-bit unsigned (CV_16U) images can be saved in the case of PNG, JPEG 2000, and TIFF formats
- 32-bit float (CV_32F) images can be saved in PFM, TIFF, OpenEXR, and Radiance HDR formats;
3-channel (CV_32FC3) TIFF images will be saved using the LogLuv high dynamic range encoding
(4 bytes per pixel)
- PNG images with an alpha channel can be saved using this function. To do this, create
8-bit (or 16-bit) 4-channel image BGRA, where the alpha channel goes last. Fully transparent pixels
should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535 (see the code sample below).
If the format, depth or channel order is different, use
Mat::convertTo and cv::cvtColor to convert it before saving. Or, use the universal FileStorage I/O
functions to save the image to XML or YAML format.
The sample below shows how to create a BGRA image and save it to a PNG file. It also demonstrates how to set custom
compression parameters:
@include snippets/imgcodecs_imwrite.cpp
@param filename Name of the file.
@param img Image to be saved.
@param params Format-specific parameters encoded as pairs (paramId_1, paramValue_1, paramId_2, paramValue_2, ... .) see cv::ImwriteFlags
*/
CV_EXPORTS_W bool imwrite( const String& filename, InputArray img,
const std::vector<int>& params = std::vector<int>());
/** @brief Reads an image from a buffer in memory.
The function imdecode reads an image from the specified buffer in the memory. If the buffer is too short or
contains invalid data, the function returns an empty matrix ( Mat::data==NULL ).
See cv::imread for the list of supported formats and flags description.
@note In the case of color images, the decoded images will have the channels stored in **B G R** order.
@param buf Input array or vector of bytes.
@param flags The same flags as in cv::imread, see cv::ImreadModes.
*/
CV_EXPORTS_W Mat imdecode( InputArray buf, int flags );
/** @overload
@param buf
@param flags
@param dst The optional output placeholder for the decoded matrix. It can save the image
reallocations when the function is called repeatedly for images of the same size.
*/
CV_EXPORTS Mat imdecode( InputArray buf, int flags, Mat* dst);
/** @brief Encodes an image into a memory buffer.
The function imencode compresses the image and stores it in the memory buffer that is resized to fit the
result. See cv::imwrite for the list of supported formats and flags description.
@param ext File extension that defines the output format.
@param img Image to be written.
@param buf Output buffer resized to fit the compressed image.
@param params Format-specific parameters. See cv::imwrite and cv::ImwriteFlags.
*/
CV_EXPORTS_W bool imencode( const String& ext, InputArray img,
CV_OUT std::vector<uchar>& buf,
const std::vector<int>& params = std::vector<int>());
/** @brief Returns true if the specified image can be decoded by OpenCV
@param filename File name of the image
*/
CV_EXPORTS_W bool haveImageReader( const String& filename );
/** @brief Returns true if an image with the specified filename can be encoded by OpenCV
@param filename File name of the image
*/
CV_EXPORTS_W bool haveImageWriter( const String& filename );
//! @} imgcodecs
} // cv
#endif //OPENCV_IMGCODECS_HPP

View File

@@ -0,0 +1,48 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifdef __OPENCV_BUILD
#error this is a compatibility header which should not be used inside the OpenCV library
#endif
#include "opencv2/imgcodecs.hpp"

View File

@@ -0,0 +1 @@
#error "This header with legacy C API declarations has been removed from OpenCV. Legacy constants are available from legacy/constants_c.h file."

View File

@@ -0,0 +1,57 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#import <UIKit/UIKit.h>
#import <Accelerate/Accelerate.h>
#import <AVFoundation/AVFoundation.h>
#import <ImageIO/ImageIO.h>
#include "opencv2/core/core.hpp"
//! @addtogroup imgcodecs_ios
//! @{
CV_EXPORTS UIImage* MatToUIImage(const cv::Mat& image);
CV_EXPORTS void UIImageToMat(const UIImage* image,
cv::Mat& m, bool alphaExist = false);
//! @}

View File

@@ -0,0 +1,54 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_IMGCODECS_LEGACY_CONSTANTS_H
#define OPENCV_IMGCODECS_LEGACY_CONSTANTS_H
/* duplicate of "ImreadModes" enumeration for better compatibility with OpenCV 3.x */
enum
{
/* 8bit, color or not */
CV_LOAD_IMAGE_UNCHANGED =-1,
/* 8bit, gray */
CV_LOAD_IMAGE_GRAYSCALE =0,
/* ?, color */
CV_LOAD_IMAGE_COLOR =1,
/* any depth, ? */
CV_LOAD_IMAGE_ANYDEPTH =2,
/* ?, any color */
CV_LOAD_IMAGE_ANYCOLOR =4,
/* ?, no rotate */
CV_LOAD_IMAGE_IGNORE_ORIENTATION =128
};
/* duplicate of "ImwriteFlags" enumeration for better compatibility with OpenCV 3.x */
enum
{
CV_IMWRITE_JPEG_QUALITY =1,
CV_IMWRITE_JPEG_PROGRESSIVE =2,
CV_IMWRITE_JPEG_OPTIMIZE =3,
CV_IMWRITE_JPEG_RST_INTERVAL =4,
CV_IMWRITE_JPEG_LUMA_QUALITY =5,
CV_IMWRITE_JPEG_CHROMA_QUALITY =6,
CV_IMWRITE_PNG_COMPRESSION =16,
CV_IMWRITE_PNG_STRATEGY =17,
CV_IMWRITE_PNG_BILEVEL =18,
CV_IMWRITE_PNG_STRATEGY_DEFAULT =0,
CV_IMWRITE_PNG_STRATEGY_FILTERED =1,
CV_IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY =2,
CV_IMWRITE_PNG_STRATEGY_RLE =3,
CV_IMWRITE_PNG_STRATEGY_FIXED =4,
CV_IMWRITE_PXM_BINARY =32,
CV_IMWRITE_EXR_TYPE = 48,
CV_IMWRITE_WEBP_QUALITY =64,
CV_IMWRITE_PAM_TUPLETYPE = 128,
CV_IMWRITE_PAM_FORMAT_NULL = 0,
CV_IMWRITE_PAM_FORMAT_BLACKANDWHITE = 1,
CV_IMWRITE_PAM_FORMAT_GRAYSCALE = 2,
CV_IMWRITE_PAM_FORMAT_GRAYSCALE_ALPHA = 3,
CV_IMWRITE_PAM_FORMAT_RGB = 4,
CV_IMWRITE_PAM_FORMAT_RGB_ALPHA = 5,
};
#endif // OPENCV_IMGCODECS_LEGACY_CONSTANTS_H

View File

@@ -0,0 +1,63 @@
package org.opencv.test.imgcodecs;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfInt;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.test.OpenCVTestCase;
import org.opencv.test.OpenCVTestRunner;
public class ImgcodecsTest extends OpenCVTestCase {
public void testImdecode() {
fail("Not yet implemented");
}
public void testImencodeStringMatListOfByte() {
MatOfByte buff = new MatOfByte();
assertEquals(0, buff.total());
assertTrue( Imgcodecs.imencode(".jpg", gray127, buff) );
assertFalse(0 == buff.total());
}
public void testImencodeStringMatListOfByteListOfInteger() {
MatOfInt params40 = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 40);
MatOfInt params90 = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 90);
/* or
MatOfInt params = new MatOfInt();
params.fromArray(Imgcodecs.IMWRITE_JPEG_QUALITY, 40);
*/
MatOfByte buff40 = new MatOfByte();
MatOfByte buff90 = new MatOfByte();
assertTrue( Imgcodecs.imencode(".jpg", rgbLena, buff40, params40) );
assertTrue( Imgcodecs.imencode(".jpg", rgbLena, buff90, params90) );
assertTrue(buff40.total() > 0);
assertTrue(buff40.total() < buff90.total());
}
public void testImreadString() {
dst = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH);
assertFalse(dst.empty());
assertEquals(3, dst.channels());
assertTrue(512 == dst.cols());
assertTrue(512 == dst.rows());
}
public void testImreadStringInt() {
dst = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH, 0);
assertFalse(dst.empty());
assertEquals(1, dst.channels());
assertTrue(512 == dst.cols());
assertTrue(512 == dst.rows());
}
public void testImwriteStringMat() {
fail("Not yet implemented");
}
public void testImwriteStringMatListOfInteger() {
fail("Not yet implemented");
}
}

View File

@@ -0,0 +1,10 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "perf_precomp.hpp"
#if defined(HAVE_HPX)
#include <hpx/hpx_main.hpp>
#endif
CV_PERF_TEST_MAIN(imgcodecs)

View File

@@ -0,0 +1,10 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#ifndef __OPENCV_PERF_PRECOMP_HPP__
#define __OPENCV_PERF_PRECOMP_HPP__
#include "opencv2/ts.hpp"
#include "opencv2/imgcodecs.hpp"
#endif

View File

@@ -0,0 +1,594 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "bitstrm.hpp"
#include "utils.hpp"
namespace cv
{
const int BS_DEF_BLOCK_SIZE = 1<<15;
bool bsIsBigEndian( void )
{
return (((const int*)"\0\x1\x2\x3\x4\x5\x6\x7")[0] & 255) != 0;
}
///////////////////////// RBaseStream ////////////////////////////
bool RBaseStream::isOpened()
{
return m_is_opened;
}
void RBaseStream::allocate()
{
if( !m_allocated )
{
m_start = new uchar[m_block_size];
m_end = m_start + m_block_size;
m_current = m_end;
m_allocated = true;
}
}
RBaseStream::RBaseStream()
{
m_start = m_end = m_current = 0;
m_file = 0;
m_block_pos = 0;
m_block_size = BS_DEF_BLOCK_SIZE;
m_is_opened = false;
m_allocated = false;
}
RBaseStream::~RBaseStream()
{
close(); // Close files
release(); // free buffers
}
void RBaseStream::readBlock()
{
setPos( getPos() ); // normalize position
if( m_file == 0 )
{
if( m_block_pos == 0 && m_current < m_end )
return;
throw RBS_THROW_EOS;
}
fseek( m_file, m_block_pos, SEEK_SET );
size_t readed = fread( m_start, 1, m_block_size, m_file );
m_end = m_start + readed;
if( readed == 0 || m_current >= m_end )
throw RBS_THROW_EOS;
}
bool RBaseStream::open( const String& filename )
{
close();
allocate();
m_file = fopen( filename.c_str(), "rb" );
if( m_file )
{
m_is_opened = true;
setPos(0);
readBlock();
}
return m_file != 0;
}
bool RBaseStream::open( const Mat& buf )
{
close();
if( buf.empty() )
return false;
CV_Assert(buf.isContinuous());
m_start = buf.data;
m_end = m_start + buf.cols*buf.rows*buf.elemSize();
m_allocated = false;
m_is_opened = true;
setPos(0);
return true;
}
void RBaseStream::close()
{
if( m_file )
{
fclose( m_file );
m_file = 0;
}
m_is_opened = false;
if( !m_allocated )
m_start = m_end = m_current = 0;
}
void RBaseStream::release()
{
if( m_allocated )
delete[] m_start;
m_start = m_end = m_current = 0;
m_allocated = false;
}
void RBaseStream::setPos( int pos )
{
CV_Assert(isOpened() && pos >= 0);
if( !m_file )
{
m_current = m_start + pos;
m_block_pos = 0;
return;
}
int offset = pos % m_block_size;
int old_block_pos = m_block_pos;
m_block_pos = pos - offset;
m_current = m_start + offset;
if (old_block_pos != m_block_pos)
readBlock();
}
int RBaseStream::getPos()
{
CV_Assert(isOpened());
int pos = validateToInt((m_current - m_start) + m_block_pos);
CV_Assert(pos >= m_block_pos); // overflow check
CV_Assert(pos >= 0); // overflow check
return pos;
}
void RBaseStream::skip( int bytes )
{
CV_Assert(bytes >= 0);
uchar* old = m_current;
m_current += bytes;
CV_Assert(m_current >= old); // overflow check
}
///////////////////////// RLByteStream ////////////////////////////
RLByteStream::~RLByteStream()
{
}
int RLByteStream::getByte()
{
uchar *current = m_current;
int val;
if( current >= m_end )
{
readBlock();
current = m_current;
}
CV_Assert(current < m_end);
val = *((uchar*)current);
m_current = current + 1;
return val;
}
int RLByteStream::getBytes( void* buffer, int count )
{
uchar* data = (uchar*)buffer;
int readed = 0;
CV_Assert(count >= 0);
while( count > 0 )
{
int l;
for(;;)
{
l = (int)(m_end - m_current);
if( l > count ) l = count;
if( l > 0 ) break;
readBlock();
}
memcpy( data, m_current, l );
m_current += l;
data += l;
count -= l;
readed += l;
}
return readed;
}
//////////// RLByteStream & RMByteStream <Get[d]word>s ////////////////
RMByteStream::~RMByteStream()
{
}
int RLByteStream::getWord()
{
uchar *current = m_current;
int val;
if( current+1 < m_end )
{
val = current[0] + (current[1] << 8);
m_current = current + 2;
}
else
{
val = getByte();
val|= getByte() << 8;
}
return val;
}
int RLByteStream::getDWord()
{
uchar *current = m_current;
int val;
if( current+3 < m_end )
{
val = current[0] + (current[1] << 8) +
(current[2] << 16) + (current[3] << 24);
m_current = current + 4;
}
else
{
val = getByte();
val |= getByte() << 8;
val |= getByte() << 16;
val |= getByte() << 24;
}
return val;
}
int RMByteStream::getWord()
{
uchar *current = m_current;
int val;
if( current+1 < m_end )
{
val = (current[0] << 8) + current[1];
m_current = current + 2;
}
else
{
val = getByte() << 8;
val|= getByte();
}
return val;
}
int RMByteStream::getDWord()
{
uchar *current = m_current;
int val;
if( current+3 < m_end )
{
val = (current[0] << 24) + (current[1] << 16) +
(current[2] << 8) + current[3];
m_current = current + 4;
}
else
{
val = getByte() << 24;
val |= getByte() << 16;
val |= getByte() << 8;
val |= getByte();
}
return val;
}
/////////////////////////// WBaseStream /////////////////////////////////
// WBaseStream - base class for output streams
WBaseStream::WBaseStream()
{
m_start = m_end = m_current = 0;
m_file = 0;
m_block_pos = 0;
m_block_size = BS_DEF_BLOCK_SIZE;
m_is_opened = false;
m_buf = 0;
}
WBaseStream::~WBaseStream()
{
close();
release();
}
bool WBaseStream::isOpened()
{
return m_is_opened;
}
void WBaseStream::allocate()
{
if( !m_start )
m_start = new uchar[m_block_size];
m_end = m_start + m_block_size;
m_current = m_start;
}
void WBaseStream::writeBlock()
{
int size = (int)(m_current - m_start);
CV_Assert(isOpened());
if( size == 0 )
return;
if( m_buf )
{
size_t sz = m_buf->size();
m_buf->resize( sz + size );
memcpy( &(*m_buf)[sz], m_start, size );
}
else
{
fwrite( m_start, 1, size, m_file );
}
m_current = m_start;
m_block_pos += size;
}
bool WBaseStream::open( const String& filename )
{
close();
allocate();
m_file = fopen( filename.c_str(), "wb" );
if( m_file )
{
m_is_opened = true;
m_block_pos = 0;
m_current = m_start;
}
return m_file != 0;
}
bool WBaseStream::open( std::vector<uchar>& buf )
{
close();
allocate();
m_buf = &buf;
m_is_opened = true;
m_block_pos = 0;
m_current = m_start;
return true;
}
void WBaseStream::close()
{
if( m_is_opened )
writeBlock();
if( m_file )
{
fclose( m_file );
m_file = 0;
}
m_buf = 0;
m_is_opened = false;
}
void WBaseStream::release()
{
if( m_start )
delete[] m_start;
m_start = m_end = m_current = 0;
}
int WBaseStream::getPos()
{
CV_Assert(isOpened());
return m_block_pos + (int)(m_current - m_start);
}
///////////////////////////// WLByteStream ///////////////////////////////////
WLByteStream::~WLByteStream()
{
}
void WLByteStream::putByte( int val )
{
*m_current++ = (uchar)val;
if( m_current >= m_end )
writeBlock();
}
void WLByteStream::putBytes( const void* buffer, int count )
{
uchar* data = (uchar*)buffer;
CV_Assert(data && m_current && count >= 0);
while( count )
{
int l = (int)(m_end - m_current);
if( l > count )
l = count;
if( l > 0 )
{
memcpy( m_current, data, l );
m_current += l;
data += l;
count -= l;
}
if( m_current == m_end )
writeBlock();
}
}
void WLByteStream::putWord( int val )
{
uchar *current = m_current;
if( current+1 < m_end )
{
current[0] = (uchar)val;
current[1] = (uchar)(val >> 8);
m_current = current + 2;
if( m_current == m_end )
writeBlock();
}
else
{
putByte(val);
putByte(val >> 8);
}
}
void WLByteStream::putDWord( int val )
{
uchar *current = m_current;
if( current+3 < m_end )
{
current[0] = (uchar)val;
current[1] = (uchar)(val >> 8);
current[2] = (uchar)(val >> 16);
current[3] = (uchar)(val >> 24);
m_current = current + 4;
if( m_current == m_end )
writeBlock();
}
else
{
putByte(val);
putByte(val >> 8);
putByte(val >> 16);
putByte(val >> 24);
}
}
///////////////////////////// WMByteStream ///////////////////////////////////
WMByteStream::~WMByteStream()
{
}
void WMByteStream::putWord( int val )
{
uchar *current = m_current;
if( current+1 < m_end )
{
current[0] = (uchar)(val >> 8);
current[1] = (uchar)val;
m_current = current + 2;
if( m_current == m_end )
writeBlock();
}
else
{
putByte(val >> 8);
putByte(val);
}
}
void WMByteStream::putDWord( int val )
{
uchar *current = m_current;
if( current+3 < m_end )
{
current[0] = (uchar)(val >> 24);
current[1] = (uchar)(val >> 16);
current[2] = (uchar)(val >> 8);
current[3] = (uchar)val;
m_current = current + 4;
if( m_current == m_end )
writeBlock();
}
else
{
putByte(val >> 24);
putByte(val >> 16);
putByte(val >> 8);
putByte(val);
}
}
}

View File

@@ -0,0 +1,189 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _BITSTRM_H_
#define _BITSTRM_H_
#include <stdio.h>
namespace cv
{
#define DECLARE_RBS_EXCEPTION(name) \
class RBS_ ## name ## _Exception : public cv::Exception \
{ \
public: \
RBS_ ## name ## _Exception(int code_, const String& err_, const String& func_, const String& file_, int line_) : \
cv::Exception(code_, err_, func_, file_, line_) \
{} \
};
DECLARE_RBS_EXCEPTION(THROW_EOS)
#define RBS_THROW_EOS RBS_THROW_EOS_Exception(cv::Error::StsError, "Unexpected end of input stream", CV_Func, __FILE__, __LINE__)
DECLARE_RBS_EXCEPTION(THROW_FORB)
#define RBS_THROW_FORB RBS_THROW_FORB_Exception(cv::Error::StsError, "Forrbidden huffman code", CV_Func, __FILE__, __LINE__)
DECLARE_RBS_EXCEPTION(BAD_HEADER)
#define RBS_BAD_HEADER RBS_BAD_HEADER_Exception(cv::Error::StsError, "Invalid header", CV_Func, __FILE__, __LINE__)
typedef unsigned long ulong;
// class RBaseStream - base class for other reading streams.
class RBaseStream
{
public:
//methods
RBaseStream();
virtual ~RBaseStream();
virtual bool open( const String& filename );
virtual bool open( const Mat& buf );
virtual void close();
bool isOpened();
void setPos( int pos );
int getPos();
void skip( int bytes );
protected:
bool m_allocated;
uchar* m_start;
uchar* m_end;
uchar* m_current;
FILE* m_file;
int m_block_size;
int m_block_pos;
bool m_is_opened;
virtual void readBlock();
virtual void release();
virtual void allocate();
};
// class RLByteStream - uchar-oriented stream.
// l in prefix means that the least significant uchar of a multi-uchar value goes first
class RLByteStream : public RBaseStream
{
public:
virtual ~RLByteStream();
int getByte();
int getBytes( void* buffer, int count );
int getWord();
int getDWord();
};
// class RMBitStream - uchar-oriented stream.
// m in prefix means that the most significant uchar of a multi-uchar value go first
class RMByteStream : public RLByteStream
{
public:
virtual ~RMByteStream();
int getWord();
int getDWord();
};
// WBaseStream - base class for output streams
class WBaseStream
{
public:
//methods
WBaseStream();
virtual ~WBaseStream();
virtual bool open( const String& filename );
virtual bool open( std::vector<uchar>& buf );
virtual void close();
bool isOpened();
int getPos();
protected:
uchar* m_start;
uchar* m_end;
uchar* m_current;
int m_block_size;
int m_block_pos;
FILE* m_file;
bool m_is_opened;
std::vector<uchar>* m_buf;
virtual void writeBlock();
virtual void release();
virtual void allocate();
};
// class WLByteStream - uchar-oriented stream.
// l in prefix means that the least significant uchar of a multi-byte value goes first
class WLByteStream : public WBaseStream
{
public:
virtual ~WLByteStream();
void putByte( int val );
void putBytes( const void* buffer, int count );
void putWord( int val );
void putDWord( int val );
};
// class WLByteStream - uchar-oriented stream.
// m in prefix means that the least significant uchar of a multi-byte value goes last
class WMByteStream : public WLByteStream
{
public:
virtual ~WMByteStream();
void putWord( int val );
void putDWord( int val );
};
inline unsigned BSWAP(unsigned v)
{
return (v<<24)|((v&0xff00)<<8)|((v>>8)&0xff00)|((unsigned)v>>24);
}
bool bsIsBigEndian( void );
}
#endif/*_BITSTRM_H_*/

View File

@@ -0,0 +1,617 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "exif.hpp"
namespace {
class ExifParsingError {
};
}
namespace cv
{
ExifEntry_t::ExifEntry_t() :
field_float(0), field_double(0), field_u32(0), field_s32(0),
tag(INVALID_TAG), field_u16(0), field_s16(0), field_u8(0), field_s8(0)
{
}
/**
* @brief ExifReader constructor
*/
ExifReader::ExifReader(std::istream& stream) : m_stream(stream), m_format(NONE)
{
}
/**
* @brief ExifReader destructor
*/
ExifReader::~ExifReader()
{
}
/**
* @brief Parsing the file and prepare (internally) exif directory structure
* @return true if parsing was successful and exif information exists in JpegReader object
* false in case of unsuccessful parsing
*/
bool ExifReader::parse()
{
try {
m_exif = getExif();
if( !m_exif.empty() )
{
return true;
}
return false;
} catch (ExifParsingError&) {
return false;
}
}
/**
* @brief Get tag value by tag number
*
* @param [in] tag The tag number
*
* @return ExifEntru_t structure. Caller has to know what tag it calls in order to extract proper field from the structure ExifEntry_t
*
*/
ExifEntry_t ExifReader::getTag(const ExifTagName tag)
{
ExifEntry_t entry;
std::map<int, ExifEntry_t>::iterator it = m_exif.find(tag);
if( it != m_exif.end() )
{
entry = it->second;
}
return entry;
}
/**
* @brief Get exif directory structure contained in file (if any)
* This is internal function and is not exposed to client
*
* @return Map where key is tag number and value is ExifEntry_t structure
*/
std::map<int, ExifEntry_t > ExifReader::getExif()
{
const std::streamsize markerSize = 2;
const std::streamsize offsetToTiffHeader = 6; //bytes from Exif size field to the first TIFF header
unsigned char appMarker[markerSize];
m_exif.erase( m_exif.begin(), m_exif.end() );
std::streamsize count;
bool exifFound = false, stopSearch = false;
while( ( !m_stream.eof() ) && !exifFound && !stopSearch )
{
m_stream.read( reinterpret_cast<char*>(appMarker), markerSize );
count = m_stream.gcount();
if( count < markerSize )
{
break;
}
unsigned char marker = appMarker[1];
size_t bytesToSkip;
size_t exifSize;
switch( marker )
{
//For all the markers just skip bytes in file pointed by followed two bytes (field size)
case SOF0: case SOF2: case DHT: case DQT: case DRI: case SOS:
case RST0: case RST1: case RST2: case RST3: case RST4: case RST5: case RST6: case RST7:
case APP0: case APP2: case APP3: case APP4: case APP5: case APP6: case APP7: case APP8:
case APP9: case APP10: case APP11: case APP12: case APP13: case APP14: case APP15:
case COM:
bytesToSkip = getFieldSize();
if (bytesToSkip < markerSize) {
throw ExifParsingError();
}
m_stream.seekg( static_cast<long>( bytesToSkip - markerSize ), m_stream.cur );
if ( m_stream.fail() ) {
throw ExifParsingError();
}
break;
//SOI and EOI don't have the size field after the marker
case SOI: case EOI:
break;
case APP1: //actual Exif Marker
exifSize = getFieldSize();
if (exifSize <= offsetToTiffHeader) {
throw ExifParsingError();
}
m_data.resize( exifSize - offsetToTiffHeader );
m_stream.seekg( static_cast<long>( offsetToTiffHeader ), m_stream.cur );
if ( m_stream.fail() ) {
throw ExifParsingError();
}
m_stream.read( reinterpret_cast<char*>(&m_data[0]), exifSize - offsetToTiffHeader );
exifFound = true;
break;
default: //No other markers are expected according to standard. May be a signal of error
stopSearch = true;
break;
}
}
if( !exifFound )
{
return m_exif;
}
parseExif();
return m_exif;
}
/**
* @brief Get the size of exif field (required to properly ready whole exif from the file)
* This is internal function and is not exposed to client
*
* @return size of exif field in the file
*/
size_t ExifReader::getFieldSize ()
{
unsigned char fieldSize[2];
m_stream.read( reinterpret_cast<char*>(fieldSize), 2 );
std::streamsize count = m_stream.gcount();
if (count < 2)
{
return 0;
}
return ( fieldSize[0] << 8 ) + fieldSize[1];
}
/**
* @brief Filling m_exif member with exif directory elements
* This is internal function and is not exposed to client
*
* @return The function doesn't return any value. In case of unsuccessful parsing
* the m_exif member is not filled up
*/
void ExifReader::parseExif()
{
m_format = getFormat();
if( !checkTagMark() )
{
return;
}
uint32_t offset = getStartOffset();
size_t numEntry = getNumDirEntry( offset );
offset += 2; //go to start of tag fields
for( size_t entry = 0; entry < numEntry; entry++ )
{
ExifEntry_t exifEntry = parseExifEntry( offset );
m_exif.insert( std::make_pair( exifEntry.tag, exifEntry ) );
offset += tiffFieldSize;
}
}
/**
* @brief Get endianness of exif information
* This is internal function and is not exposed to client
*
* @return INTEL, MOTO or NONE
*/
Endianess_t ExifReader::getFormat() const
{
if (m_data.size() < 1)
return NONE;
if( m_data.size() > 1 && m_data[0] != m_data[1] )
{
return NONE;
}
if( m_data[0] == 'I' )
{
return INTEL;
}
if( m_data[0] == 'M' )
{
return MOTO;
}
return NONE;
}
/**
* @brief Checking whether Tag Mark (0x002A) correspond to one contained in the Jpeg file
* This is internal function and is not exposed to client
*
* @return true if tag mark equals 0x002A, false otherwise
*/
bool ExifReader::checkTagMark() const
{
uint16_t tagMark = getU16( 2 );
if( tagMark != tagMarkRequired )
{
return false;
}
return true;
}
/**
* @brief The utility function for extracting actual offset exif IFD0 info is started from
* This is internal function and is not exposed to client
*
* @return offset of IFD0 field
*/
uint32_t ExifReader::getStartOffset() const
{
return getU32( 4 );
}
/**
* @brief Get the number of Directory Entries in Jpeg file
*
* @return The number of directory entries
*/
size_t ExifReader::getNumDirEntry(const size_t offsetNumDir) const
{
return getU16( offsetNumDir );
}
/**
* @brief Parsing particular entry in exif directory
* This is internal function and is not exposed to client
*
* Entries are divided into 12-bytes blocks each
* Each block corresponds the following structure:
*
* +------+-------------+-------------------+------------------------+
* | Type | Data format | Num of components | Data or offset to data |
* +======+=============+===================+========================+
* | TTTT | ffff | NNNNNNNN | DDDDDDDD |
* +------+-------------+-------------------+------------------------+
*
* Details can be found here: http://www.media.mit.edu/pia/Research/deepview/exif.html
*
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return ExifEntry_t structure which corresponds to particular entry
*
*/
ExifEntry_t ExifReader::parseExifEntry(const size_t offset)
{
ExifEntry_t entry;
uint16_t tagNum = getExifTag( offset );
entry.tag = tagNum;
switch( tagNum )
{
case IMAGE_DESCRIPTION:
entry.field_str = getString( offset );
break;
case MAKE:
entry.field_str = getString( offset );
break;
case MODEL:
entry.field_str = getString( offset );
break;
case ORIENTATION:
entry.field_u16 = getOrientation( offset );
break;
case XRESOLUTION:
entry.field_u_rational = getResolution( offset );
break;
case YRESOLUTION:
entry.field_u_rational = getResolution( offset );
break;
case RESOLUTION_UNIT:
entry.field_u16 = getResolutionUnit( offset );
break;
case SOFTWARE:
entry.field_str = getString( offset );
break;
case DATE_TIME:
entry.field_str = getString( offset );
break;
case WHITE_POINT:
entry.field_u_rational = getWhitePoint( offset );
break;
case PRIMARY_CHROMATICIES:
entry.field_u_rational = getPrimaryChromaticies( offset );
break;
case Y_CB_CR_COEFFICIENTS:
entry.field_u_rational = getYCbCrCoeffs( offset );
break;
case Y_CB_CR_POSITIONING:
entry.field_u16 = getYCbCrPos( offset );
break;
case REFERENCE_BLACK_WHITE:
entry.field_u_rational = getRefBW( offset );
break;
case COPYRIGHT:
entry.field_str = getString( offset );
break;
case EXIF_OFFSET:
break;
default:
entry.tag = INVALID_TAG;
break;
}
return entry;
}
/**
* @brief Get tag number from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return tag number
*/
uint16_t ExifReader::getExifTag(const size_t offset) const
{
return getU16( offset );
}
/**
* @brief Get string information from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return string value
*/
std::string ExifReader::getString(const size_t offset) const
{
size_t size = getU32( offset + 4 );
size_t dataOffset = 8; // position of data in the field
if( size > maxDataSize )
{
dataOffset = getU32( offset + 8 );
}
if (dataOffset > m_data.size() || dataOffset + size > m_data.size()) {
throw ExifParsingError();
}
std::vector<uint8_t>::const_iterator it = m_data.begin() + dataOffset;
std::string result( it, it + size ); //copy vector content into result
return result;
}
/**
* @brief Get unsigned short data from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return Unsigned short data
*/
uint16_t ExifReader::getU16(const size_t offset) const
{
if (offset + 1 >= m_data.size())
throw ExifParsingError();
if( m_format == INTEL )
{
return m_data[offset] + ( m_data[offset + 1] << 8 );
}
return ( m_data[offset] << 8 ) + m_data[offset + 1];
}
/**
* @brief Get unsigned 32-bit data from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return Unsigned 32-bit data
*/
uint32_t ExifReader::getU32(const size_t offset) const
{
if (offset + 3 >= m_data.size())
throw ExifParsingError();
if( m_format == INTEL )
{
return m_data[offset] +
( m_data[offset + 1] << 8 ) +
( m_data[offset + 2] << 16 ) +
( m_data[offset + 3] << 24 );
}
return ( m_data[offset] << 24 ) +
( m_data[offset + 1] << 16 ) +
( m_data[offset + 2] << 8 ) +
m_data[offset + 3];
}
/**
* @brief Get unsigned rational data from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return Unsigned rational data
*
* "rational" means a fractional value, it contains 2 signed/unsigned long integer value,
* and the first represents the numerator, the second, the denominator.
*/
u_rational_t ExifReader::getURational(const size_t offset) const
{
uint32_t numerator = getU32( offset );
uint32_t denominator = getU32( offset + 4 );
return std::make_pair( numerator, denominator );
}
/**
* @brief Get orientation information from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return orientation number
*/
uint16_t ExifReader::getOrientation(const size_t offset) const
{
return getU16( offset + 8 );
}
/**
* @brief Get resolution information from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return resolution value
*/
std::vector<u_rational_t> ExifReader::getResolution(const size_t offset) const
{
std::vector<u_rational_t> result;
uint32_t rationalOffset = getU32( offset + 8 );
result.push_back( getURational( rationalOffset ) );
return result;
}
/**
* @brief Get resolution unit from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return resolution unit value
*/
uint16_t ExifReader::getResolutionUnit(const size_t offset) const
{
return getU16( offset + 8 );
}
/**
* @brief Get White Point information from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return White Point value
*
* If the image uses CIE Standard Illumination D65(known as international
* standard of 'daylight'), the values are '3127/10000,3290/10000'.
*/
std::vector<u_rational_t> ExifReader::getWhitePoint(const size_t offset) const
{
std::vector<u_rational_t> result;
uint32_t rationalOffset = getU32( offset + 8 );
result.push_back( getURational( rationalOffset ) );
result.push_back( getURational( rationalOffset + 8 ) );
return result;
}
/**
* @brief Get Primary Chromaticies information from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return vector with primary chromaticies values
*
*/
std::vector<u_rational_t> ExifReader::getPrimaryChromaticies(const size_t offset) const
{
std::vector<u_rational_t> result;
uint32_t rationalOffset = getU32( offset + 8 );
for( size_t i = 0; i < primaryChromaticiesComponents; i++ )
{
result.push_back( getURational( rationalOffset ) );
rationalOffset += 8;
}
return result;
}
/**
* @brief Get YCbCr Coefficients information from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return vector with YCbCr coefficients values
*
*/
std::vector<u_rational_t> ExifReader::getYCbCrCoeffs(const size_t offset) const
{
std::vector<u_rational_t> result;
uint32_t rationalOffset = getU32( offset + 8 );
for( size_t i = 0; i < ycbcrCoeffs; i++ )
{
result.push_back( getURational( rationalOffset ) );
rationalOffset += 8;
}
return result;
}
/**
* @brief Get YCbCr Positioning information from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return vector with YCbCr positioning value
*
*/
uint16_t ExifReader::getYCbCrPos(const size_t offset) const
{
return getU16( offset + 8 );
}
/**
* @brief Get Reference Black&White point information from raw exif data
* This is internal function and is not exposed to client
* @param [in] offset Offset to entry in bytes inside raw exif data
* @return vector with reference BW points
*
* In case of YCbCr format, first 2 show black/white of Y, next 2 are Cb,
* last 2 are Cr. In case of RGB format, first 2 show black/white of R,
* next 2 are G, last 2 are B.
*
*/
std::vector<u_rational_t> ExifReader::getRefBW(const size_t offset) const
{
const size_t rationalFieldSize = 8;
std::vector<u_rational_t> result;
uint32_t rationalOffset = getU32( offset + rationalFieldSize );
for( size_t i = 0; i < refBWComponents; i++ )
{
result.push_back( getURational( rationalOffset ) );
rationalOffset += rationalFieldSize;
}
return result;
}
} //namespace cv

View File

@@ -0,0 +1,249 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _OPENCV_EXIF_HPP_
#define _OPENCV_EXIF_HPP_
#include <cstdio>
#include <map>
#include <utility>
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
namespace cv
{
/**
* @brief Jpeg markers that can encounter in Jpeg file
*/
enum AppMarkerTypes
{
SOI = 0xD8, SOF0 = 0xC0, SOF2 = 0xC2, DHT = 0xC4,
DQT = 0xDB, DRI = 0xDD, SOS = 0xDA,
RST0 = 0xD0, RST1 = 0xD1, RST2 = 0xD2, RST3 = 0xD3,
RST4 = 0xD4, RST5 = 0xD5, RST6 = 0xD6, RST7 = 0xD7,
APP0 = 0xE0, APP1 = 0xE1, APP2 = 0xE2, APP3 = 0xE3,
APP4 = 0xE4, APP5 = 0xE5, APP6 = 0xE6, APP7 = 0xE7,
APP8 = 0xE8, APP9 = 0xE9, APP10 = 0xEA, APP11 = 0xEB,
APP12 = 0xEC, APP13 = 0xED, APP14 = 0xEE, APP15 = 0xEF,
COM = 0xFE, EOI = 0xD9
};
/**
* @brief Base Exif tags used by IFD0 (main image)
*/
enum ExifTagName
{
IMAGE_DESCRIPTION = 0x010E, ///< Image Description: ASCII string
MAKE = 0x010F, ///< Description of manufacturer: ASCII string
MODEL = 0x0110, ///< Description of camera model: ASCII string
ORIENTATION = 0x0112, ///< Orientation of the image: unsigned short
XRESOLUTION = 0x011A, ///< Resolution of the image across X axis: unsigned rational
YRESOLUTION = 0x011B, ///< Resolution of the image across Y axis: unsigned rational
RESOLUTION_UNIT = 0x0128, ///< Resolution units. '1' no-unit, '2' inch, '3' centimeter
SOFTWARE = 0x0131, ///< Shows firmware(internal software of digicam) version number
DATE_TIME = 0x0132, ///< Date/Time of image was last modified
WHITE_POINT = 0x013E, ///< Chromaticity of white point of the image
PRIMARY_CHROMATICIES = 0x013F, ///< Chromaticity of the primaries of the image
Y_CB_CR_COEFFICIENTS = 0x0211, ///< constant to translate an image from YCbCr to RGB format
Y_CB_CR_POSITIONING = 0x0213, ///< Chroma sample point of subsampling pixel array
REFERENCE_BLACK_WHITE = 0x0214, ///< Reference value of black point/white point
COPYRIGHT = 0x8298, ///< Copyright information
EXIF_OFFSET = 0x8769, ///< Offset to Exif Sub IFD
INVALID_TAG = 0xFFFF ///< Shows that the tag was not recognized
};
enum Endianess_t
{
INTEL = 0x49,
MOTO = 0x4D,
NONE = 0x00
};
typedef std::pair<uint32_t, uint32_t> u_rational_t;
/**
* @brief Entry which contains possible values for different exif tags
*/
struct ExifEntry_t
{
ExifEntry_t();
std::vector<u_rational_t> field_u_rational; ///< vector of rational fields
std::string field_str; ///< any kind of textual information
float field_float; ///< Currently is not used
double field_double; ///< Currently is not used
uint32_t field_u32; ///< Unsigned 32-bit value
int32_t field_s32; ///< Signed 32-bit value
uint16_t tag; ///< Tag number
uint16_t field_u16; ///< Unsigned 16-bit value
int16_t field_s16; ///< Signed 16-bit value
uint8_t field_u8; ///< Unsigned 8-bit value
int8_t field_s8; ///< Signed 8-bit value
};
/**
* @brief Picture orientation which may be taken from EXIF
* Orientation usually matters when the picture is taken by
* smartphone or other camera with orientation sensor support
* Corresponds to EXIF 2.3 Specification
*/
enum ImageOrientation
{
IMAGE_ORIENTATION_TL = 1, ///< Horizontal (normal)
IMAGE_ORIENTATION_TR = 2, ///< Mirrored horizontal
IMAGE_ORIENTATION_BR = 3, ///< Rotate 180
IMAGE_ORIENTATION_BL = 4, ///< Mirrored vertical
IMAGE_ORIENTATION_LT = 5, ///< Mirrored horizontal & rotate 270 CW
IMAGE_ORIENTATION_RT = 6, ///< Rotate 90 CW
IMAGE_ORIENTATION_RB = 7, ///< Mirrored horizontal & rotate 90 CW
IMAGE_ORIENTATION_LB = 8 ///< Rotate 270 CW
};
/**
* @brief Reading exif information from Jpeg file
*
* Usage example for getting the orientation of the image:
*
* @code
* ExifReader reader(fileName);
* if( reader.parse() )
* {
* int orientation = reader.getTag(Orientation).field_u16;
* }
* @endcode
*
*/
class ExifReader
{
public:
/**
* @brief ExifReader constructor. Constructs an object of exif reader
*
* @param [in]stream An istream to look for EXIF bytes from
*/
explicit ExifReader( std::istream& stream );
~ExifReader();
/**
* @brief Parse the file with exif info
*
* @return true if parsing was successful and exif information exists in JpegReader object
*/
bool parse();
/**
* @brief Get tag info by tag number
*
* @param [in] tag The tag number
* @return ExifEntru_t structure. Caller has to know what tag it calls in order to extract proper field from the structure ExifEntry_t
*/
ExifEntry_t getTag( const ExifTagName tag );
private:
std::istream& m_stream;
std::vector<unsigned char> m_data;
std::map<int, ExifEntry_t > m_exif;
Endianess_t m_format;
void parseExif();
bool checkTagMark() const;
size_t getFieldSize ();
size_t getNumDirEntry( const size_t offsetNumDir ) const;
uint32_t getStartOffset() const;
uint16_t getExifTag( const size_t offset ) const;
uint16_t getU16( const size_t offset ) const;
uint32_t getU32( const size_t offset ) const;
uint16_t getOrientation( const size_t offset ) const;
uint16_t getResolutionUnit( const size_t offset ) const;
uint16_t getYCbCrPos( const size_t offset ) const;
Endianess_t getFormat() const;
ExifEntry_t parseExifEntry( const size_t offset );
u_rational_t getURational( const size_t offset ) const;
std::map<int, ExifEntry_t > getExif();
std::string getString( const size_t offset ) const;
std::vector<u_rational_t> getResolution( const size_t offset ) const;
std::vector<u_rational_t> getWhitePoint( const size_t offset ) const;
std::vector<u_rational_t> getPrimaryChromaticies( const size_t offset ) const;
std::vector<u_rational_t> getYCbCrCoeffs( const size_t offset ) const;
std::vector<u_rational_t> getRefBW( const size_t offset ) const;
private:
static const uint16_t tagMarkRequired = 0x2A;
//max size of data in tag.
//'DDDDDDDD' contains the value of that Tag. If its size is over 4bytes,
//'DDDDDDDD' contains the offset to data stored address.
static const size_t maxDataSize = 4;
//bytes per tag field
static const size_t tiffFieldSize = 12;
//number of primary chromaticies components
static const size_t primaryChromaticiesComponents = 6;
//number of YCbCr coefficients in field
static const size_t ycbcrCoeffs = 3;
//number of Reference Black&White components
static const size_t refBWComponents = 6;
};
}
#endif /* _OPENCV_EXIF_HPP_ */

View File

@@ -0,0 +1,151 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "grfmt_base.hpp"
#include "bitstrm.hpp"
namespace cv
{
BaseImageDecoder::BaseImageDecoder()
{
m_width = m_height = 0;
m_type = -1;
m_buf_supported = false;
m_scale_denom = 1;
}
bool BaseImageDecoder::setSource( const String& filename )
{
m_filename = filename;
m_buf.release();
return true;
}
bool BaseImageDecoder::setSource( const Mat& buf )
{
if( !m_buf_supported )
return false;
m_filename = String();
m_buf = buf;
return true;
}
size_t BaseImageDecoder::signatureLength() const
{
return m_signature.size();
}
bool BaseImageDecoder::checkSignature( const String& signature ) const
{
size_t len = signatureLength();
return signature.size() >= len && memcmp( signature.c_str(), m_signature.c_str(), len ) == 0;
}
int BaseImageDecoder::setScale( const int& scale_denom )
{
int temp = m_scale_denom;
m_scale_denom = scale_denom;
return temp;
}
ImageDecoder BaseImageDecoder::newDecoder() const
{
return ImageDecoder();
}
BaseImageEncoder::BaseImageEncoder()
{
m_buf = 0;
m_buf_supported = false;
}
bool BaseImageEncoder::isFormatSupported( int depth ) const
{
return depth == CV_8U;
}
String BaseImageEncoder::getDescription() const
{
return m_description;
}
bool BaseImageEncoder::setDestination( const String& filename )
{
m_filename = filename;
m_buf = 0;
return true;
}
bool BaseImageEncoder::setDestination( std::vector<uchar>& buf )
{
if( !m_buf_supported )
return false;
m_buf = &buf;
m_buf->clear();
m_filename = String();
return true;
}
bool BaseImageEncoder::writemulti(const std::vector<Mat>&, const std::vector<int>& )
{
return false;
}
ImageEncoder BaseImageEncoder::newEncoder() const
{
return ImageEncoder();
}
void BaseImageEncoder::throwOnEror() const
{
if(!m_last_error.empty())
{
String msg = "Raw image encoder error: " + m_last_error;
CV_Error( Error::BadImageSize, msg.c_str() );
}
}
}
/* End of file. */

View File

@@ -0,0 +1,123 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_BASE_H_
#define _GRFMT_BASE_H_
#include "utils.hpp"
#include "bitstrm.hpp"
namespace cv
{
class BaseImageDecoder;
class BaseImageEncoder;
typedef Ptr<BaseImageEncoder> ImageEncoder;
typedef Ptr<BaseImageDecoder> ImageDecoder;
///////////////////////////////// base class for decoders ////////////////////////
class BaseImageDecoder
{
public:
BaseImageDecoder();
virtual ~BaseImageDecoder() {}
int width() const { return m_width; }
int height() const { return m_height; }
virtual int type() const { return m_type; }
virtual bool setSource( const String& filename );
virtual bool setSource( const Mat& buf );
virtual int setScale( const int& scale_denom );
virtual bool readHeader() = 0;
virtual bool readData( Mat& img ) = 0;
/// Called after readData to advance to the next page, if any.
virtual bool nextPage() { return false; }
virtual size_t signatureLength() const;
virtual bool checkSignature( const String& signature ) const;
virtual ImageDecoder newDecoder() const;
protected:
int m_width; // width of the image ( filled by readHeader )
int m_height; // height of the image ( filled by readHeader )
int m_type;
int m_scale_denom;
String m_filename;
String m_signature;
Mat m_buf;
bool m_buf_supported;
};
///////////////////////////// base class for encoders ////////////////////////////
class BaseImageEncoder
{
public:
BaseImageEncoder();
virtual ~BaseImageEncoder() {}
virtual bool isFormatSupported( int depth ) const;
virtual bool setDestination( const String& filename );
virtual bool setDestination( std::vector<uchar>& buf );
virtual bool write( const Mat& img, const std::vector<int>& params ) = 0;
virtual bool writemulti(const std::vector<Mat>& img_vec, const std::vector<int>& params);
virtual String getDescription() const;
virtual ImageEncoder newEncoder() const;
virtual void throwOnEror() const;
protected:
String m_description;
String m_filename;
std::vector<uchar>* m_buf;
bool m_buf_supported;
String m_last_error;
};
}
#endif/*_GRFMT_BASE_H_*/

View File

@@ -0,0 +1,588 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "grfmt_bmp.hpp"
namespace cv
{
static const char* fmtSignBmp = "BM";
/************************ BMP decoder *****************************/
BmpDecoder::BmpDecoder()
{
m_signature = fmtSignBmp;
m_offset = -1;
m_buf_supported = true;
m_origin = ORIGIN_TL;
m_bpp = 0;
m_rle_code = BMP_RGB;
}
BmpDecoder::~BmpDecoder()
{
}
void BmpDecoder::close()
{
m_strm.close();
}
ImageDecoder BmpDecoder::newDecoder() const
{
return makePtr<BmpDecoder>();
}
bool BmpDecoder::readHeader()
{
bool result = false;
bool iscolor = false;
if( !m_buf.empty() )
{
if( !m_strm.open( m_buf ) )
return false;
}
else if( !m_strm.open( m_filename ))
return false;
try
{
m_strm.skip( 10 );
m_offset = m_strm.getDWord();
int size = m_strm.getDWord();
CV_Assert(size > 0); // overflow, 2Gb limit
if( size >= 36 )
{
m_width = m_strm.getDWord();
m_height = m_strm.getDWord();
m_bpp = m_strm.getDWord() >> 16;
int m_rle_code_ = m_strm.getDWord();
CV_Assert(m_rle_code_ >= 0 && m_rle_code_ <= BMP_BITFIELDS);
m_rle_code = (BmpCompression)m_rle_code_;
m_strm.skip(12);
int clrused = m_strm.getDWord();
m_strm.skip( size - 36 );
if( m_width > 0 && m_height != 0 &&
(((m_bpp == 1 || m_bpp == 4 || m_bpp == 8 ||
m_bpp == 24 || m_bpp == 32 ) && m_rle_code == BMP_RGB) ||
((m_bpp == 16 || m_bpp == 32) && (m_rle_code == BMP_RGB || m_rle_code == BMP_BITFIELDS)) ||
(m_bpp == 4 && m_rle_code == BMP_RLE4) ||
(m_bpp == 8 && m_rle_code == BMP_RLE8)))
{
iscolor = true;
result = true;
if( m_bpp <= 8 )
{
CV_Assert(clrused >= 0 && clrused <= 256);
memset(m_palette, 0, sizeof(m_palette));
m_strm.getBytes(m_palette, (clrused == 0? 1<<m_bpp : clrused)*4 );
iscolor = IsColorPalette( m_palette, m_bpp );
}
else if( m_bpp == 16 && m_rle_code == BMP_BITFIELDS )
{
int redmask = m_strm.getDWord();
int greenmask = m_strm.getDWord();
int bluemask = m_strm.getDWord();
if( bluemask == 0x1f && greenmask == 0x3e0 && redmask == 0x7c00 )
m_bpp = 15;
else if( bluemask == 0x1f && greenmask == 0x7e0 && redmask == 0xf800 )
;
else
result = false;
}
else if (m_bpp == 32 && m_rle_code == BMP_BITFIELDS)
{
// 32bit BMP not require to check something - we can simply allow it to use
;
}
else if( m_bpp == 16 && m_rle_code == BMP_RGB )
m_bpp = 15;
}
}
else if( size == 12 )
{
m_width = m_strm.getWord();
m_height = m_strm.getWord();
m_bpp = m_strm.getDWord() >> 16;
m_rle_code = BMP_RGB;
if( m_width > 0 && m_height != 0 &&
(m_bpp == 1 || m_bpp == 4 || m_bpp == 8 ||
m_bpp == 24 || m_bpp == 32 ))
{
if( m_bpp <= 8 )
{
uchar buffer[256*3];
int j, clrused = 1 << m_bpp;
m_strm.getBytes( buffer, clrused*3 );
for( j = 0; j < clrused; j++ )
{
m_palette[j].b = buffer[3*j+0];
m_palette[j].g = buffer[3*j+1];
m_palette[j].r = buffer[3*j+2];
}
}
result = true;
}
}
}
catch(...)
{
throw;
}
// in 32 bit case alpha channel is used - so require CV_8UC4 type
m_type = iscolor ? (m_bpp == 32 ? CV_8UC4 : CV_8UC3 ) : CV_8UC1;
m_origin = m_height > 0 ? ORIGIN_BL : ORIGIN_TL;
m_height = std::abs(m_height);
if( !result )
{
m_offset = -1;
m_width = m_height = -1;
m_strm.close();
}
return result;
}
bool BmpDecoder::readData( Mat& img )
{
uchar* data = img.ptr();
int step = validateToInt(img.step);
bool color = img.channels() > 1;
uchar gray_palette[256] = {0};
bool result = false;
int src_pitch = ((m_width*(m_bpp != 15 ? m_bpp : 16) + 7)/8 + 3) & -4;
int nch = color ? 3 : 1;
int y, width3 = m_width*nch;
// FIXIT: use safe pointer arithmetic (avoid 'int'), use size_t, intptr_t, etc
CV_Assert(((uint64)m_height * m_width * nch < (CV_BIG_UINT(1) << 30)) && "BMP reader implementation doesn't support large images >= 1Gb");
if( m_offset < 0 || !m_strm.isOpened())
return false;
if( m_origin == ORIGIN_BL )
{
data += (m_height - 1)*(size_t)step;
step = -step;
}
AutoBuffer<uchar> _src, _bgr;
_src.allocate(src_pitch + 32);
if( !color )
{
if( m_bpp <= 8 )
{
CvtPaletteToGray( m_palette, gray_palette, 1 << m_bpp );
}
_bgr.allocate(m_width*3 + 32);
}
uchar *src = _src.data(), *bgr = _bgr.data();
try
{
m_strm.setPos( m_offset );
switch( m_bpp )
{
/************************* 1 BPP ************************/
case 1:
for( y = 0; y < m_height; y++, data += step )
{
m_strm.getBytes( src, src_pitch );
FillColorRow1( color ? data : bgr, src, m_width, m_palette );
if( !color )
icvCvt_BGR2Gray_8u_C3C1R( bgr, 0, data, 0, Size(m_width,1) );
}
result = true;
break;
/************************* 4 BPP ************************/
case 4:
if( m_rle_code == BMP_RGB )
{
for( y = 0; y < m_height; y++, data += step )
{
m_strm.getBytes( src, src_pitch );
if( color )
FillColorRow4( data, src, m_width, m_palette );
else
FillGrayRow4( data, src, m_width, gray_palette );
}
result = true;
}
else if( m_rle_code == BMP_RLE4 ) // rle4 compression
{
uchar* line_end = data + width3;
y = 0;
for(;;)
{
int code = m_strm.getWord();
const int len = code & 255;
code >>= 8;
if( len != 0 ) // encoded mode
{
PaletteEntry clr[2];
uchar gray_clr[2];
int t = 0;
clr[0] = m_palette[code >> 4];
clr[1] = m_palette[code & 15];
gray_clr[0] = gray_palette[code >> 4];
gray_clr[1] = gray_palette[code & 15];
uchar* end = data + len*nch;
if( end > line_end ) goto decode_rle4_bad;
do
{
if( color )
WRITE_PIX( data, clr[t] );
else
*data = gray_clr[t];
t ^= 1;
}
while( (data += nch) < end );
}
else if( code > 2 ) // absolute mode
{
if( data + code*nch > line_end ) goto decode_rle4_bad;
int sz = (((code + 1)>>1) + 1) & (~1);
CV_Assert((size_t)sz < _src.size());
m_strm.getBytes(src, sz);
if( color )
data = FillColorRow4( data, src, code, m_palette );
else
data = FillGrayRow4( data, src, code, gray_palette );
}
else
{
int x_shift3 = (int)(line_end - data);
if( code == 2 )
{
x_shift3 = m_strm.getByte()*nch;
m_strm.getByte();
}
if( color )
data = FillUniColor( data, line_end, step, width3,
y, m_height, x_shift3,
m_palette[0] );
else
data = FillUniGray( data, line_end, step, width3,
y, m_height, x_shift3,
gray_palette[0] );
if( y >= m_height )
break;
}
}
result = true;
decode_rle4_bad: ;
}
break;
/************************* 8 BPP ************************/
case 8:
if( m_rle_code == BMP_RGB )
{
for( y = 0; y < m_height; y++, data += step )
{
m_strm.getBytes( src, src_pitch );
if( color )
FillColorRow8( data, src, m_width, m_palette );
else
FillGrayRow8( data, src, m_width, gray_palette );
}
result = true;
}
else if( m_rle_code == BMP_RLE8 ) // rle8 compression
{
uchar* line_end = data + width3;
int line_end_flag = 0;
y = 0;
for(;;)
{
int code = m_strm.getWord();
int len = code & 255;
code >>= 8;
if( len != 0 ) // encoded mode
{
int prev_y = y;
len *= nch;
if( data + len > line_end )
goto decode_rle8_bad;
if( color )
data = FillUniColor( data, line_end, step, width3,
y, m_height, len,
m_palette[code] );
else
data = FillUniGray( data, line_end, step, width3,
y, m_height, len,
gray_palette[code] );
line_end_flag = y - prev_y;
if( y >= m_height )
break;
}
else if( code > 2 ) // absolute mode
{
int prev_y = y;
int code3 = code*nch;
if( data + code3 > line_end )
goto decode_rle8_bad;
int sz = (code + 1) & (~1);
CV_Assert((size_t)sz < _src.size());
m_strm.getBytes(src, sz);
if( color )
data = FillColorRow8( data, src, code, m_palette );
else
data = FillGrayRow8( data, src, code, gray_palette );
line_end_flag = y - prev_y;
}
else
{
int x_shift3 = (int)(line_end - data);
int y_shift = m_height - y;
if( code || !line_end_flag || x_shift3 < width3 )
{
if( code == 2 )
{
x_shift3 = m_strm.getByte()*nch;
y_shift = m_strm.getByte();
}
x_shift3 += (y_shift * width3) & ((code == 0) - 1);
if( y >= m_height )
break;
if( color )
data = FillUniColor( data, line_end, step, width3,
y, m_height, x_shift3,
m_palette[0] );
else
data = FillUniGray( data, line_end, step, width3,
y, m_height, x_shift3,
gray_palette[0] );
if( y >= m_height )
break;
}
line_end_flag = 0;
if( y >= m_height )
break;
}
}
result = true;
decode_rle8_bad: ;
}
break;
/************************* 15 BPP ************************/
case 15:
for( y = 0; y < m_height; y++, data += step )
{
m_strm.getBytes( src, src_pitch );
if( !color )
icvCvt_BGR5552Gray_8u_C2C1R( src, 0, data, 0, Size(m_width,1) );
else
icvCvt_BGR5552BGR_8u_C2C3R( src, 0, data, 0, Size(m_width,1) );
}
result = true;
break;
/************************* 16 BPP ************************/
case 16:
for( y = 0; y < m_height; y++, data += step )
{
m_strm.getBytes( src, src_pitch );
if( !color )
icvCvt_BGR5652Gray_8u_C2C1R( src, 0, data, 0, Size(m_width,1) );
else
icvCvt_BGR5652BGR_8u_C2C3R( src, 0, data, 0, Size(m_width,1) );
}
result = true;
break;
/************************* 24 BPP ************************/
case 24:
for( y = 0; y < m_height; y++, data += step )
{
m_strm.getBytes( src, src_pitch );
if(!color)
icvCvt_BGR2Gray_8u_C3C1R( src, 0, data, 0, Size(m_width,1) );
else
memcpy( data, src, m_width*3 );
}
result = true;
break;
/************************* 32 BPP ************************/
case 32:
for( y = 0; y < m_height; y++, data += step )
{
m_strm.getBytes( src, src_pitch );
if( !color )
icvCvt_BGRA2Gray_8u_C4C1R( src, 0, data, 0, Size(m_width,1) );
else if( img.channels() == 3 )
icvCvt_BGRA2BGR_8u_C4C3R(src, 0, data, 0, Size(m_width, 1));
else if( img.channels() == 4 )
memcpy(data, src, m_width * 4);
}
result = true;
break;
default:
CV_Error(cv::Error::StsError, "Invalid/unsupported mode");
}
}
catch(...)
{
throw;
}
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////
BmpEncoder::BmpEncoder()
{
m_description = "Windows bitmap (*.bmp;*.dib)";
m_buf_supported = true;
}
BmpEncoder::~BmpEncoder()
{
}
ImageEncoder BmpEncoder::newEncoder() const
{
return makePtr<BmpEncoder>();
}
bool BmpEncoder::write( const Mat& img, const std::vector<int>& )
{
int width = img.cols, height = img.rows, channels = img.channels();
int fileStep = (width*channels + 3) & -4;
uchar zeropad[] = "\0\0\0\0";
WLByteStream strm;
if( m_buf )
{
if( !strm.open( *m_buf ) )
return false;
}
else if( !strm.open( m_filename ))
return false;
int bitmapHeaderSize = 40;
int paletteSize = channels > 1 ? 0 : 1024;
int headerSize = 14 /* fileheader */ + bitmapHeaderSize + paletteSize;
size_t fileSize = (size_t)fileStep*height + headerSize;
PaletteEntry palette[256];
if( m_buf )
m_buf->reserve( alignSize(fileSize + 16, 256) );
// write signature 'BM'
strm.putBytes( fmtSignBmp, (int)strlen(fmtSignBmp) );
// write file header
strm.putDWord( validateToInt(fileSize) ); // file size
strm.putDWord( 0 );
strm.putDWord( headerSize );
// write bitmap header
strm.putDWord( bitmapHeaderSize );
strm.putDWord( width );
strm.putDWord( height );
strm.putWord( 1 );
strm.putWord( channels << 3 );
strm.putDWord( BMP_RGB );
strm.putDWord( 0 );
strm.putDWord( 0 );
strm.putDWord( 0 );
strm.putDWord( 0 );
strm.putDWord( 0 );
if( channels == 1 )
{
FillGrayPalette( palette, 8 );
strm.putBytes( palette, sizeof(palette));
}
width *= channels;
for( int y = height - 1; y >= 0; y-- )
{
strm.putBytes( img.ptr(y), width );
if( fileStep > width )
strm.putBytes( zeropad, fileStep - width );
}
strm.close();
return true;
}
}

View File

@@ -0,0 +1,105 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_BMP_H_
#define _GRFMT_BMP_H_
#include "grfmt_base.hpp"
namespace cv
{
enum BmpCompression
{
BMP_RGB = 0,
BMP_RLE8 = 1,
BMP_RLE4 = 2,
BMP_BITFIELDS = 3
};
// Windows Bitmap reader
class BmpDecoder CV_FINAL : public BaseImageDecoder
{
public:
BmpDecoder();
~BmpDecoder() CV_OVERRIDE;
bool readData( Mat& img ) CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
void close();
ImageDecoder newDecoder() const CV_OVERRIDE;
protected:
enum Origin
{
ORIGIN_TL = 0,
ORIGIN_BL = 1
};
RLByteStream m_strm;
PaletteEntry m_palette[256];
Origin m_origin;
int m_bpp;
int m_offset;
BmpCompression m_rle_code;
};
// ... writer
class BmpEncoder CV_FINAL : public BaseImageEncoder
{
public:
BmpEncoder();
~BmpEncoder() CV_OVERRIDE;
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE;
};
}
#endif/*_GRFMT_BMP_H_*/

View File

@@ -0,0 +1,666 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#ifdef HAVE_OPENEXR
#if defined _MSC_VER && _MSC_VER >= 1200
# pragma warning( disable: 4100 4244 4267 )
#endif
#if defined __GNUC__ && defined __APPLE__
# pragma GCC diagnostic ignored "-Wshadow"
#endif
/// C++ Standard Libraries
#include <iostream>
#include <stdexcept>
#include <ImfHeader.h>
#include <ImfInputFile.h>
#include <ImfOutputFile.h>
#include <ImfChannelList.h>
#include <ImfStandardAttributes.h>
#include <half.h>
#include "grfmt_exr.hpp"
#if defined _WIN32
#undef UINT
#define UINT ((Imf::PixelType)0)
#undef HALF
#define HALF ((Imf::PixelType)1)
#undef FLOAT
#define FLOAT ((Imf::PixelType)2)
#endif
namespace cv
{
/////////////////////// ExrDecoder ///////////////////
ExrDecoder::ExrDecoder()
{
m_signature = "\x76\x2f\x31\x01";
m_file = 0;
m_red = m_green = m_blue = 0;
m_type = ((Imf::PixelType)0);
m_iscolor = false;
m_bit_depth = 0;
m_isfloat = false;
m_ischroma = false;
m_native_depth = false;
}
ExrDecoder::~ExrDecoder()
{
close();
}
void ExrDecoder::close()
{
if( m_file )
{
delete m_file;
m_file = 0;
}
}
int ExrDecoder::type() const
{
return CV_MAKETYPE((m_isfloat ? CV_32F : CV_32S), m_iscolor ? 3 : 1);
}
bool ExrDecoder::readHeader()
{
bool result = false;
m_file = new InputFile( m_filename.c_str() );
if( !m_file ) // probably paranoid
return false;
m_datawindow = m_file->header().dataWindow();
m_width = m_datawindow.max.x - m_datawindow.min.x + 1;
m_height = m_datawindow.max.y - m_datawindow.min.y + 1;
// the type HALF is converted to 32 bit float
// and the other types supported by OpenEXR are 32 bit anyway
m_bit_depth = 32;
if( hasChromaticities( m_file->header() ))
m_chroma = chromaticities( m_file->header() );
const ChannelList &channels = m_file->header().channels();
m_red = channels.findChannel( "R" );
m_green = channels.findChannel( "G" );
m_blue = channels.findChannel( "B" );
if( m_red || m_green || m_blue )
{
m_iscolor = true;
m_ischroma = false;
result = true;
}
else
{
m_green = channels.findChannel( "Y" );
if( m_green )
{
m_ischroma = true;
m_red = channels.findChannel( "RY" );
m_blue = channels.findChannel( "BY" );
m_iscolor = (m_blue || m_red);
result = true;
}
else
result = false;
}
if( result )
{
m_type = FLOAT;
m_isfloat = ( m_type == FLOAT );
}
if( !result )
close();
return result;
}
bool ExrDecoder::readData( Mat& img )
{
m_native_depth = CV_MAT_DEPTH(type()) == img.depth();
bool color = img.channels() > 1;
int channels = 0;
uchar* data = img.ptr();
size_t step = img.step;
bool justcopy = ( m_native_depth && (color == m_iscolor) );
bool chromatorgb = ( m_ischroma && color );
bool rgbtogray = ( !m_ischroma && m_iscolor && !color );
bool result = true;
FrameBuffer frame;
int xsample[3] = {1, 1, 1};
char *buffer;
size_t xstep = 0;
size_t ystep = 0;
xstep = m_native_depth ? 4 : 1;
AutoBuffer<char> copy_buffer;
if( !justcopy )
{
copy_buffer.allocate(sizeof(float) * m_width * 3);
buffer = copy_buffer.data();
ystep = 0;
}
else
{
buffer = (char *)data;
ystep = step;
}
if( m_ischroma )
{
if( color )
{
if( m_blue )
{
frame.insert( "BY", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep,
12, ystep, m_blue->xSampling, m_blue->ySampling, 0.0 ));
xsample[0] = m_blue->ySampling;
}
else
{
frame.insert( "BY", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep,
12, ystep, 1, 1, 0.0 ));
}
if( m_green )
{
frame.insert( "Y", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 4,
12, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
xsample[1] = m_green->ySampling;
}
else
{
frame.insert( "Y", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 4,
12, ystep, 1, 1, 0.0 ));
}
if( m_red )
{
frame.insert( "RY", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 8,
12, ystep, m_red->xSampling, m_red->ySampling, 0.0 ));
xsample[2] = m_red->ySampling;
}
else
{
frame.insert( "RY", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 8,
12, ystep, 1, 1, 0.0 ));
}
}
else
{
frame.insert( "Y", Slice( m_type,
buffer - m_datawindow.min.x * 4 - m_datawindow.min.y * ystep,
4, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
xsample[0] = m_green->ySampling;
}
}
else
{
if( m_blue )
{
frame.insert( "B", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep,
12, ystep, m_blue->xSampling, m_blue->ySampling, 0.0 ));
xsample[0] = m_blue->ySampling;
}
else
{
frame.insert( "B", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep,
12, ystep, 1, 1, 0.0 ));
}
if( m_green )
{
frame.insert( "G", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 4,
12, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
xsample[1] = m_green->ySampling;
}
else
{
frame.insert( "G", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 4,
12, ystep, 1, 1, 0.0 ));
}
if( m_red )
{
frame.insert( "R", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 8,
12, ystep, m_red->xSampling, m_red->ySampling, 0.0 ));
xsample[2] = m_red->ySampling;
}
else
{
frame.insert( "R", Slice( m_type,
buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 8,
12, ystep, 1, 1, 0.0 ));
}
}
for (FrameBuffer::Iterator it = frame.begin(); it != frame.end(); it++) {
channels++;
}
m_file->setFrameBuffer( frame );
if( justcopy )
{
m_file->readPixels( m_datawindow.min.y, m_datawindow.max.y );
if( color )
{
if( m_blue && (m_blue->xSampling != 1 || m_blue->ySampling != 1) )
UpSample( data, 3, step / xstep, xsample[0], m_blue->ySampling );
if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
UpSample( data + xstep, 3, step / xstep, xsample[1], m_green->ySampling );
if( m_red && (m_red->xSampling != 1 || m_red->ySampling != 1) )
UpSample( data + 2 * xstep, 3, step / xstep, xsample[2], m_red->ySampling );
}
else if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
UpSample( data, 1, step / xstep, xsample[0], m_green->ySampling );
if( chromatorgb )
ChromaToBGR( (float *)data, m_height, step / xstep );
}
else
{
uchar *out = data;
int x, y;
for( y = m_datawindow.min.y; y <= m_datawindow.max.y; y++ )
{
m_file->readPixels( y, y );
for( int i = 0; i < channels; i++ )
{
if( xsample[i] != 1 )
UpSampleX( (float *)buffer + i, channels, xsample[i] );
}
if( rgbtogray )
{
RGBToGray( (float *)buffer, (float *)out );
}
else
{
if( chromatorgb )
ChromaToBGR( (float *)buffer, 1, step );
if( m_type == FLOAT )
{
float *fi = (float *)buffer;
for( x = 0; x < m_width * img.channels(); x++)
{
out[x] = cv::saturate_cast<uchar>(fi[x]);
}
}
else
{
unsigned *ui = (unsigned *)buffer;
for( x = 0; x < m_width * img.channels(); x++)
{
out[x] = cv::saturate_cast<uchar>(ui[x]);
}
}
}
out += step;
}
if( color )
{
if( m_blue && (m_blue->xSampling != 1 || m_blue->ySampling != 1) )
UpSampleY( data, 3, step / xstep, m_blue->ySampling );
if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
UpSampleY( data + xstep, 3, step / xstep, m_green->ySampling );
if( m_red && (m_red->xSampling != 1 || m_red->ySampling != 1) )
UpSampleY( data + 2 * xstep, 3, step / xstep, m_red->ySampling );
}
else if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
UpSampleY( data, 1, step / xstep, m_green->ySampling );
}
close();
return result;
}
/**
// on entry pixel values are stored packed in the upper left corner of the image
// this functions expands them by duplication to cover the whole image
*/
void ExrDecoder::UpSample( uchar *data, int xstep, int ystep, int xsample, int ysample )
{
for( int y = (m_height - 1) / ysample, yre = m_height - ysample; y >= 0; y--, yre -= ysample )
{
for( int x = (m_width - 1) / xsample, xre = m_width - xsample; x >= 0; x--, xre -= xsample )
{
for( int i = 0; i < ysample; i++ )
{
for( int n = 0; n < xsample; n++ )
{
if( !m_native_depth )
data[(yre + i) * ystep + (xre + n) * xstep] = data[y * ystep + x * xstep];
else if( m_type == FLOAT )
((float *)data)[(yre + i) * ystep + (xre + n) * xstep] = ((float *)data)[y * ystep + x * xstep];
else
((unsigned *)data)[(yre + i) * ystep + (xre + n) * xstep] = ((unsigned *)data)[y * ystep + x * xstep];
}
}
}
}
}
/**
// on entry pixel values are stored packed in the upper left corner of the image
// this functions expands them by duplication to cover the whole image
*/
void ExrDecoder::UpSampleX( float *data, int xstep, int xsample )
{
for( int x = (m_width - 1) / xsample, xre = m_width - xsample; x >= 0; x--, xre -= xsample )
{
for( int n = 0; n < xsample; n++ )
{
if( m_type == FLOAT )
((float *)data)[(xre + n) * xstep] = ((float *)data)[x * xstep];
else
((unsigned *)data)[(xre + n) * xstep] = ((unsigned *)data)[x * xstep];
}
}
}
/**
// on entry pixel values are stored packed in the upper left corner of the image
// this functions expands them by duplication to cover the whole image
*/
void ExrDecoder::UpSampleY( uchar *data, int xstep, int ystep, int ysample )
{
for( int y = m_height - ysample, yre = m_height - ysample; y >= 0; y -= ysample, yre -= ysample )
{
for( int x = 0; x < m_width; x++ )
{
for( int i = 1; i < ysample; i++ )
{
if( !m_native_depth )
data[(yre + i) * ystep + x * xstep] = data[y * ystep + x * xstep];
else if( m_type == FLOAT )
((float *)data)[(yre + i) * ystep + x * xstep] = ((float *)data)[y * ystep + x * xstep];
else
((unsigned *)data)[(yre + i) * ystep + x * xstep] = ((unsigned *)data)[y * ystep + x * xstep];
}
}
}
}
/**
// algorithm from ImfRgbaYca.cpp
*/
void ExrDecoder::ChromaToBGR( float *data, int numlines, int step )
{
for( int y = 0; y < numlines; y++ )
{
for( int x = 0; x < m_width; x++ )
{
double b, Y, r;
if( m_type == FLOAT )
{
b = data[y * step + x * 3];
Y = data[y * step + x * 3 + 1];
r = data[y * step + x * 3 + 2];
}
else
{
b = ((unsigned *)data)[y * step + x * 3];
Y = ((unsigned *)data)[y * step + x * 3 + 1];
r = ((unsigned *)data)[y * step + x * 3 + 2];
}
r = (r + 1) * Y;
b = (b + 1) * Y;
Y = (Y - b * m_chroma.blue[1] - r * m_chroma.red[1]) / m_chroma.green[1];
if( m_type == FLOAT )
{
data[y * step + x * 3] = (float)b;
data[y * step + x * 3 + 1] = (float)Y;
data[y * step + x * 3 + 2] = (float)r;
}
else
{
int t = cvRound(b);
((unsigned *)data)[y * step + x * 3 + 0] = (unsigned)MAX(t, 0);
t = cvRound(Y);
((unsigned *)data)[y * step + x * 3 + 1] = (unsigned)MAX(t, 0);
t = cvRound(r);
((unsigned *)data)[y * step + x * 3 + 2] = (unsigned)MAX(t, 0);
}
}
}
}
/**
// convert one row to gray
*/
void ExrDecoder::RGBToGray( float *in, float *out )
{
if( m_type == FLOAT )
{
if( m_native_depth )
{
for( int i = 0, n = 0; i < m_width; i++, n += 3 )
out[i] = in[n] * m_chroma.blue[0] + in[n + 1] * m_chroma.green[0] + in[n + 2] * m_chroma.red[0];
}
else
{
uchar *o = (uchar *)out;
for( int i = 0, n = 0; i < m_width; i++, n += 3 )
o[i] = (uchar) (in[n] * m_chroma.blue[0] + in[n + 1] * m_chroma.green[0] + in[n + 2] * m_chroma.red[0]);
}
}
else // UINT
{
if( m_native_depth )
{
unsigned *ui = (unsigned *)in;
for( int i = 0; i < m_width * 3; i++ )
ui[i] -= 0x80000000;
int *si = (int *)in;
for( int i = 0, n = 0; i < m_width; i++, n += 3 )
((int *)out)[i] = int(si[n] * m_chroma.blue[0] + si[n + 1] * m_chroma.green[0] + si[n + 2] * m_chroma.red[0]);
}
else // how to best convert float to uchar?
{
unsigned *ui = (unsigned *)in;
for( int i = 0, n = 0; i < m_width; i++, n += 3 )
((uchar *)out)[i] = uchar((ui[n] * m_chroma.blue[0] + ui[n + 1] * m_chroma.green[0] + ui[n + 2] * m_chroma.red[0]) * (256.0 / 4294967296.0));
}
}
}
ImageDecoder ExrDecoder::newDecoder() const
{
return makePtr<ExrDecoder>();
}
/////////////////////// ExrEncoder ///////////////////
ExrEncoder::ExrEncoder()
{
m_description = "OpenEXR Image files (*.exr)";
}
ExrEncoder::~ExrEncoder()
{
}
bool ExrEncoder::isFormatSupported( int depth ) const
{
return ( CV_MAT_DEPTH(depth) == CV_32F );
}
bool ExrEncoder::write( const Mat& img, const std::vector<int>& params )
{
int width = img.cols, height = img.rows;
int depth = img.depth();
CV_Assert( depth == CV_32F );
int channels = img.channels();
CV_Assert( channels == 3 || channels == 1 );
bool result = false;
Header header( width, height );
Imf::PixelType type = FLOAT;
for( size_t i = 0; i < params.size(); i += 2 )
{
if( params[i] == CV_IMWRITE_EXR_TYPE )
{
switch( params[i+1] )
{
case IMWRITE_EXR_TYPE_HALF:
type = HALF;
break;
case IMWRITE_EXR_TYPE_FLOAT:
type = FLOAT;
break;
default:
throw std::runtime_error( "IMWRITE_EXR_TYPE is invalid or not supported" );
}
}
}
if( channels == 3 )
{
header.channels().insert( "R", Channel( type ) );
header.channels().insert( "G", Channel( type ) );
header.channels().insert( "B", Channel( type ) );
//printf("bunt\n");
}
else
{
header.channels().insert( "Y", Channel( type ) );
//printf("gray\n");
}
OutputFile file( m_filename.c_str(), header );
FrameBuffer frame;
char *buffer;
size_t bufferstep;
int size;
Mat exrMat;
if( type == HALF )
{
convertFp16(img, exrMat);
buffer = (char *)const_cast<uchar *>( exrMat.ptr() );
bufferstep = exrMat.step;
size = 2;
}
else
{
buffer = (char *)const_cast<uchar *>( img.ptr() );
bufferstep = img.step;
size = 4;
}
if( channels == 3 )
{
frame.insert( "B", Slice( type, buffer, size * 3, bufferstep ));
frame.insert( "G", Slice( type, buffer + size, size * 3, bufferstep ));
frame.insert( "R", Slice( type, buffer + size * 2, size * 3, bufferstep ));
}
else
frame.insert( "Y", Slice( type, buffer, size, bufferstep ));
file.setFrameBuffer( frame );
result = true;
try
{
file.writePixels( height );
}
catch(...)
{
result = false;
}
return result;
}
ImageEncoder ExrEncoder::newEncoder() const
{
return makePtr<ExrEncoder>();
}
}
#endif
/* End of file. */

View File

@@ -0,0 +1,121 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_EXR_H_
#define _GRFMT_EXR_H_
#ifdef HAVE_OPENEXR
#if defined __GNUC__ && defined __APPLE__
# pragma GCC diagnostic ignored "-Wshadow"
#endif
#include <ImfChromaticities.h>
#include <ImfInputFile.h>
#include <ImfChannelList.h>
#include <ImathBox.h>
#include "grfmt_base.hpp"
namespace cv
{
using namespace Imf;
using namespace Imath;
/* libpng version only */
class ExrDecoder CV_FINAL : public BaseImageDecoder
{
public:
ExrDecoder();
~ExrDecoder() CV_OVERRIDE;
int type() const CV_OVERRIDE;
bool readData( Mat& img ) CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
void close();
ImageDecoder newDecoder() const CV_OVERRIDE;
protected:
void UpSample( uchar *data, int xstep, int ystep, int xsample, int ysample );
void UpSampleX( float *data, int xstep, int xsample );
void UpSampleY( uchar *data, int xstep, int ystep, int ysample );
void ChromaToBGR( float *data, int numlines, int step );
void RGBToGray( float *in, float *out );
InputFile *m_file;
Imf::PixelType m_type;
Box2i m_datawindow;
bool m_ischroma;
const Channel *m_red;
const Channel *m_green;
const Channel *m_blue;
Chromaticities m_chroma;
int m_bit_depth;
bool m_native_depth;
bool m_iscolor;
bool m_isfloat;
private:
ExrDecoder(const ExrDecoder &); // copy disabled
ExrDecoder& operator=(const ExrDecoder &); // assign disabled
};
class ExrEncoder CV_FINAL : public BaseImageEncoder
{
public:
ExrEncoder();
~ExrEncoder() CV_OVERRIDE;
bool isFormatSupported( int depth ) const CV_OVERRIDE;
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE;
};
}
#endif
#endif/*_GRFMT_EXR_H_*/

View File

@@ -0,0 +1,572 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
// GDAL Macros
#include "cvconfig.h"
#ifdef HAVE_GDAL
// Our Header
#include "grfmt_gdal.hpp"
/// C++ Standard Libraries
#include <iostream>
#include <stdexcept>
#include <string>
namespace cv{
/**
* Convert GDAL Palette Interpretation to OpenCV Pixel Type
*/
int gdalPaletteInterpretation2OpenCV( GDALPaletteInterp const& paletteInterp, GDALDataType const& gdalType ){
switch( paletteInterp ){
/// GRAYSCALE
case GPI_Gray:
if( gdalType == GDT_Byte ){ return CV_8UC1; }
if( gdalType == GDT_UInt16 ){ return CV_16UC1; }
if( gdalType == GDT_Int16 ){ return CV_16SC1; }
if( gdalType == GDT_UInt32 ){ return CV_32SC1; }
if( gdalType == GDT_Int32 ){ return CV_32SC1; }
if( gdalType == GDT_Float32 ){ return CV_32FC1; }
if( gdalType == GDT_Float64 ){ return CV_64FC1; }
return -1;
/// RGB
case GPI_RGB:
if( gdalType == GDT_Byte ){ return CV_8UC3; }
if( gdalType == GDT_UInt16 ){ return CV_16UC3; }
if( gdalType == GDT_Int16 ){ return CV_16SC3; }
if( gdalType == GDT_UInt32 ){ return CV_32SC3; }
if( gdalType == GDT_Int32 ){ return CV_32SC3; }
if( gdalType == GDT_Float32 ){ return CV_32FC3; }
if( gdalType == GDT_Float64 ){ return CV_64FC3; }
return -1;
/// otherwise
default:
return -1;
}
}
/**
* Convert gdal type to opencv type
*/
int gdal2opencv( const GDALDataType& gdalType, const int& channels ){
switch( gdalType ){
/// UInt8
case GDT_Byte:
return CV_8UC(channels);
/// UInt16
case GDT_UInt16:
return CV_16UC(channels);
/// Int16
case GDT_Int16:
return CV_16SC(channels);
/// UInt32
case GDT_UInt32:
case GDT_Int32:
return CV_32SC(channels);
case GDT_Float32:
return CV_32FC(channels);
case GDT_Float64:
return CV_64FC(channels);
default:
std::cout << "Unknown GDAL Data Type" << std::endl;
std::cout << "Type: " << GDALGetDataTypeName(gdalType) << std::endl;
return -1;
}
}
/**
* GDAL Decoder Constructor
*/
GdalDecoder::GdalDecoder(){
// set a dummy signature
m_signature="0";
for( size_t i=0; i<160; i++ ){
m_signature += "0";
}
/// Register the driver
GDALAllRegister();
m_driver = NULL;
m_dataset = NULL;
}
/**
* GDAL Decoder Destructor
*/
GdalDecoder::~GdalDecoder(){
if( m_dataset != NULL ){
close();
}
}
/**
* Convert data range
*/
double range_cast( const GDALDataType& gdalType,
const int& cvDepth,
const double& value )
{
// uint8 -> uint8
if( gdalType == GDT_Byte && cvDepth == CV_8U ){
return value;
}
// uint8 -> uint16
if( gdalType == GDT_Byte && (cvDepth == CV_16U || cvDepth == CV_16S)){
return (value*256);
}
// uint8 -> uint32
if( gdalType == GDT_Byte && (cvDepth == CV_32F || cvDepth == CV_32S)){
return (value*16777216);
}
// int16 -> uint8
if( (gdalType == GDT_UInt16 || gdalType == GDT_Int16) && cvDepth == CV_8U ){
return std::floor(value/256.0);
}
// int16 -> int16
if( (gdalType == GDT_UInt16 || gdalType == GDT_Int16) &&
( cvDepth == CV_16U || cvDepth == CV_16S )){
return value;
}
// float32 -> float32
// float64 -> float64
if( (gdalType == GDT_Float32 || gdalType == GDT_Float64) &&
( cvDepth == CV_32F || cvDepth == CV_64F )){
return value;
}
std::cout << GDALGetDataTypeName( gdalType ) << std::endl;
std::cout << "warning: unknown range cast requested." << std::endl;
return (value);
}
/**
* There are some better mpl techniques for doing this.
*/
void write_pixel( const double& pixelValue,
const GDALDataType& gdalType,
const int& gdalChannels,
Mat& image,
const int& row,
const int& col,
const int& channel ){
// convert the pixel
double newValue = range_cast(gdalType, image.depth(), pixelValue );
// input: 1 channel, output: 1 channel
if( gdalChannels == 1 && image.channels() == 1 ){
if( image.depth() == CV_8U ){ image.ptr<uchar>(row)[col] = newValue; }
else if( image.depth() == CV_16U ){ image.ptr<unsigned short>(row)[col] = newValue; }
else if( image.depth() == CV_16S ){ image.ptr<short>(row)[col] = newValue; }
else if( image.depth() == CV_32S ){ image.ptr<int>(row)[col] = newValue; }
else if( image.depth() == CV_32F ){ image.ptr<float>(row)[col] = newValue; }
else if( image.depth() == CV_64F ){ image.ptr<double>(row)[col] = newValue; }
else{ throw std::runtime_error("Unknown image depth, gdal: 1, img: 1"); }
}
// input: 1 channel, output: 3 channel
else if( gdalChannels == 1 && image.channels() == 3 ){
if( image.depth() == CV_8U ){ image.ptr<Vec3b>(row)[col] = Vec3b(newValue,newValue,newValue); }
else if( image.depth() == CV_16U ){ image.ptr<Vec3s>(row)[col] = Vec3s(newValue,newValue,newValue); }
else if( image.depth() == CV_16S ){ image.ptr<Vec3s>(row)[col] = Vec3s(newValue,newValue,newValue); }
else if( image.depth() == CV_32S ){ image.ptr<Vec3i>(row)[col] = Vec3i(newValue,newValue,newValue); }
else if( image.depth() == CV_32F ){ image.ptr<Vec3f>(row)[col] = Vec3f(newValue,newValue,newValue); }
else if( image.depth() == CV_64F ){ image.ptr<Vec3d>(row)[col] = Vec3d(newValue,newValue,newValue); }
else{ throw std::runtime_error("Unknown image depth, gdal:1, img: 3"); }
}
// input: 3 channel, output: 1 channel
else if( gdalChannels == 3 && image.channels() == 1 ){
if( image.depth() == CV_8U ){ image.ptr<uchar>(row)[col] += (newValue/3.0); }
else{ throw std::runtime_error("Unknown image depth, gdal:3, img: 1"); }
}
// input: 4 channel, output: 1 channel
else if( gdalChannels == 4 && image.channels() == 1 ){
if( image.depth() == CV_8U ){ image.ptr<uchar>(row)[col] = newValue; }
else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 1"); }
}
// input: 3 channel, output: 3 channel
else if( gdalChannels == 3 && image.channels() == 3 ){
if( image.depth() == CV_8U ){ (*image.ptr<Vec3b>(row,col))[channel] = newValue; }
else if( image.depth() == CV_16U ){ (*image.ptr<Vec3s>(row,col))[channel] = newValue; }
else if( image.depth() == CV_16S ){ (*image.ptr<Vec3s>(row,col))[channel] = newValue; }
else if( image.depth() == CV_32S ){ (*image.ptr<Vec3i>(row,col))[channel] = newValue; }
else if( image.depth() == CV_32F ){ (*image.ptr<Vec3f>(row,col))[channel] = newValue; }
else if( image.depth() == CV_64F ){ (*image.ptr<Vec3d>(row,col))[channel] = newValue; }
else{ throw std::runtime_error("Unknown image depth, gdal: 3, image: 3"); }
}
// input: 4 channel, output: 3 channel
else if( gdalChannels == 4 && image.channels() == 3 ){
if( channel >= 4 ){ return; }
else if( image.depth() == CV_8U && channel < 4 ){ (*image.ptr<Vec3b>(row,col))[channel] = newValue; }
else if( image.depth() == CV_16U && channel < 4 ){ (*image.ptr<Vec3s>(row,col))[channel] = newValue; }
else if( image.depth() == CV_16S && channel < 4 ){ (*image.ptr<Vec3s>(row,col))[channel] = newValue; }
else if( image.depth() == CV_32S && channel < 4 ){ (*image.ptr<Vec3i>(row,col))[channel] = newValue; }
else if( image.depth() == CV_32F && channel < 4 ){ (*image.ptr<Vec3f>(row,col))[channel] = newValue; }
else if( image.depth() == CV_64F && channel < 4 ){ (*image.ptr<Vec3d>(row,col))[channel] = newValue; }
else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 3"); }
}
// input: 4 channel, output: 4 channel
else if( gdalChannels == 4 && image.channels() == 4 ){
if( image.depth() == CV_8U ){ (*image.ptr<Vec4b>(row,col))[channel] = newValue; }
else if( image.depth() == CV_16U ){ (*image.ptr<Vec4s>(row,col))[channel] = newValue; }
else if( image.depth() == CV_16S ){ (*image.ptr<Vec4s>(row,col))[channel] = newValue; }
else if( image.depth() == CV_32S ){ (*image.ptr<Vec4i>(row,col))[channel] = newValue; }
else if( image.depth() == CV_32F ){ (*image.ptr<Vec4f>(row,col))[channel] = newValue; }
else if( image.depth() == CV_64F ){ (*image.ptr<Vec4d>(row,col))[channel] = newValue; }
else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 4"); }
}
// input: > 4 channels, output: > 4 channels
else if( gdalChannels > 4 && image.channels() > 4 ){
if( image.depth() == CV_8U ){ image.ptr<uchar>(row,col)[channel] = newValue; }
else if( image.depth() == CV_16U ){ image.ptr<unsigned short>(row,col)[channel] = newValue; }
else if( image.depth() == CV_16S ){ image.ptr<short>(row,col)[channel] = newValue; }
else if( image.depth() == CV_32S ){ image.ptr<int>(row,col)[channel] = newValue; }
else if( image.depth() == CV_32F ){ image.ptr<float>(row,col)[channel] = newValue; }
else if( image.depth() == CV_64F ){ image.ptr<double>(row,col)[channel] = newValue; }
else{ throw std::runtime_error("Unknown image depth, gdal: N, img: N"); }
}
// otherwise, throw an error
else{
throw std::runtime_error("error: can't convert types.");
}
}
void write_ctable_pixel( const double& pixelValue,
const GDALDataType& gdalType,
GDALColorTable const* gdalColorTable,
Mat& image,
const int& y,
const int& x,
const int& c ){
if( gdalColorTable == NULL ){
write_pixel( pixelValue, gdalType, 1, image, y, x, c );
}
// if we are Grayscale, then do a straight conversion
if( gdalColorTable->GetPaletteInterpretation() == GPI_Gray ){
write_pixel( pixelValue, gdalType, 1, image, y, x, c );
}
// if we are rgb, then convert here
else if( gdalColorTable->GetPaletteInterpretation() == GPI_RGB ){
// get the pixel
short r = gdalColorTable->GetColorEntry( (int)pixelValue )->c1;
short g = gdalColorTable->GetColorEntry( (int)pixelValue )->c2;
short b = gdalColorTable->GetColorEntry( (int)pixelValue )->c3;
short a = gdalColorTable->GetColorEntry( (int)pixelValue )->c4;
write_pixel( r, gdalType, 4, image, y, x, 2 );
write_pixel( g, gdalType, 4, image, y, x, 1 );
write_pixel( b, gdalType, 4, image, y, x, 0 );
if( image.channels() > 3 ){
write_pixel( a, gdalType, 4, image, y, x, 1 );
}
}
// otherwise, set zeros
else{
write_pixel( pixelValue, gdalType, 1, image, y, x, c );
}
}
/**
* read data
*/
bool GdalDecoder::readData( Mat& img ){
// make sure the image is the proper size
if( img.size() != Size(m_width, m_height) ){
return false;
}
// make sure the raster is alive
if( m_dataset == NULL || m_driver == NULL ){
return false;
}
// set the image to zero
img = 0;
// iterate over each raster band
// note that OpenCV does bgr rather than rgb
int nChannels = m_dataset->GetRasterCount();
GDALColorTable* gdalColorTable = NULL;
if( m_dataset->GetRasterBand(1)->GetColorTable() != NULL ){
gdalColorTable = m_dataset->GetRasterBand(1)->GetColorTable();
}
const GDALDataType gdalType = m_dataset->GetRasterBand(1)->GetRasterDataType();
int nRows, nCols;
if( nChannels > img.channels() ){
nChannels = img.channels();
}
for( int c = 0; c<nChannels; c++ ){
// get the GDAL Band
GDALRasterBand* band = m_dataset->GetRasterBand(c+1);
/* Map palette band and gray band to color index 0 and red, green,
blue, alpha bands to BGRA indexes. Note: ignoring HSL, CMY,
CMYK, and YCbCr color spaces, rather than converting them
to BGR. */
int color = 0;
switch (band->GetColorInterpretation()) {
case GCI_PaletteIndex:
case GCI_GrayIndex:
case GCI_BlueBand:
color = 0;
break;
case GCI_GreenBand:
color = 1;
break;
case GCI_RedBand:
color = 2;
break;
case GCI_AlphaBand:
color = 3;
break;
default:
CV_Error(cv::Error::StsError, "Invalid/unsupported mode");
}
// make sure the image band has the same dimensions as the image
if( band->GetXSize() != m_width || band->GetYSize() != m_height ){ return false; }
// grab the raster size
nRows = band->GetYSize();
nCols = band->GetXSize();
// create a temporary scanline pointer to store data
double* scanline = new double[nCols];
// iterate over each row and column
for( int y=0; y<nRows; y++ ){
// get the entire row
CPLErr err = band->RasterIO( GF_Read, 0, y, nCols, 1, scanline, nCols, 1, GDT_Float64, 0, 0);
CV_Assert(err == CE_None);
// set inside the image
for( int x=0; x<nCols; x++ ){
// set depending on image types
// given boost, I would use enable_if to speed up. Avoid for now.
if( hasColorTable == false ){
write_pixel( scanline[x], gdalType, nChannels, img, y, x, color );
}
else{
write_ctable_pixel( scanline[x], gdalType, gdalColorTable, img, y, x, color );
}
}
}
// delete our temp pointer
delete [] scanline;
}
return true;
}
/**
* Read image header
*/
bool GdalDecoder::readHeader(){
// load the dataset
m_dataset = (GDALDataset*) GDALOpen( m_filename.c_str(), GA_ReadOnly);
// if dataset is null, then there was a problem
if( m_dataset == NULL ){
return false;
}
// make sure we have pixel data inside the raster
if( m_dataset->GetRasterCount() <= 0 ){
return false;
}
//extract the driver information
m_driver = m_dataset->GetDriver();
// if the driver failed, then exit
if( m_driver == NULL ){
return false;
}
// get the image dimensions
m_width = m_dataset->GetRasterXSize();
m_height= m_dataset->GetRasterYSize();
// make sure we have at least one band/channel
if( m_dataset->GetRasterCount() <= 0 ){
return false;
}
// check if we have a color palette
int tempType;
if( m_dataset->GetRasterBand(1)->GetColorInterpretation() == GCI_PaletteIndex ){
// remember that we have a color palette
hasColorTable = true;
// if the color tables does not exist, then we failed
if( m_dataset->GetRasterBand(1)->GetColorTable() == NULL ){
return false;
}
// otherwise, get the pixeltype
else{
// convert the palette interpretation to opencv type
tempType = gdalPaletteInterpretation2OpenCV( m_dataset->GetRasterBand(1)->GetColorTable()->GetPaletteInterpretation(),
m_dataset->GetRasterBand(1)->GetRasterDataType() );
if( tempType == -1 ){
return false;
}
m_type = tempType;
}
}
// otherwise, we have standard channels
else{
// remember that we don't have a color table
hasColorTable = false;
// convert the datatype to opencv
tempType = gdal2opencv( m_dataset->GetRasterBand(1)->GetRasterDataType(), m_dataset->GetRasterCount() );
if( tempType == -1 ){
return false;
}
m_type = tempType;
}
return true;
}
/**
* Close the module
*/
void GdalDecoder::close(){
GDALClose((GDALDatasetH)m_dataset);
m_dataset = NULL;
m_driver = NULL;
}
/**
* Create a new decoder
*/
ImageDecoder GdalDecoder::newDecoder()const{
return makePtr<GdalDecoder>();
}
/**
* Test the file signature
*/
bool GdalDecoder::checkSignature( const String& signature )const{
// look for NITF
std::string str(signature);
if( str.substr(0,4).find("NITF") != std::string::npos ){
return true;
}
// look for DTED
if( str.size() > 144 && str.substr(140,4) == "DTED" ){
return true;
}
return false;
}
} /// End of cv Namespace
#endif /**< End of HAVE_GDAL Definition */

View File

@@ -0,0 +1,166 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __GRFMT_GDAL_HPP__
#define __GRFMT_GDAL_HPP__
/// OpenCV FMT Base Type
#include "grfmt_base.hpp"
/// Macro to make sure we specified GDAL in CMake
#ifdef HAVE_GDAL
/// C++ Libraries
#include <iostream>
/// Geospatial Data Abstraction Library
#include <cpl_conv.h>
#include <gdal_priv.h>
#include <gdal.h>
/// Start of CV Namespace
namespace cv {
/**
* Convert GDAL Pixel Range to OpenCV Pixel Range
*/
double range_cast( const GDALDataType& gdalType,
const int& cvDepth,
const double& value );
/**
* Convert GDAL Palette Interpretation to OpenCV Pixel Type
*/
int gdalPaletteInterpretation2OpenCV( GDALPaletteInterp const& paletteInterp,
GDALDataType const& gdalType );
/**
* Convert a GDAL Raster Type to OpenCV Type
*/
int gdal2opencv( const GDALDataType& gdalType, const int& channels );
/**
* Write an image to pixel
*/
void write_pixel( const double& pixelValue,
GDALDataType const& gdalType,
const int& gdalChannels,
Mat& image,
const int& row,
const int& col,
const int& channel );
/**
* Write a color table pixel to the image
*/
void write_ctable_pixel( const double& pixelValue,
const GDALDataType& gdalType,
const GDALColorTable* gdalColorTable,
Mat& image,
const int& y,
const int& x,
const int& c );
/**
* Loader for GDAL
*/
class GdalDecoder CV_FINAL : public BaseImageDecoder{
public:
/**
* Default Constructor
*/
GdalDecoder();
/**
* Destructor
*/
~GdalDecoder() CV_OVERRIDE;
/**
* Read image data
*/
bool readData( Mat& img ) CV_OVERRIDE;
/**
* Read the image header
*/
bool readHeader() CV_OVERRIDE;
/**
* Close the module
*/
void close();
/**
* Create a new decoder
*/
ImageDecoder newDecoder() const CV_OVERRIDE;
/**
* Test the file signature
*
* In general, this should be avoided as the user should specifically request GDAL.
* The reason is that GDAL tends to overlap with other image formats and it is probably
* safer to use other formats first.
*/
virtual bool checkSignature( const String& signature ) const CV_OVERRIDE;
protected:
/// GDAL Dataset
GDALDataset* m_dataset;
/// GDAL Driver
GDALDriver* m_driver;
/// Check if we are reading from a color table
bool hasColorTable;
}; /// End of GdalDecoder Class
} /// End of Namespace cv
#endif/*HAVE_GDAL*/
#endif/*__GRFMT_GDAL_HPP__*/

View File

@@ -0,0 +1,197 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "grfmt_gdcm.hpp"
#ifdef HAVE_GDCM
//#define DBG(...) printf(__VA_ARGS__)
#define DBG(...)
#include <gdcmImageReader.h>
static const size_t preamble_skip = 128;
static const size_t magic_len = 4;
inline cv::String getMagic()
{
return cv::String("\x44\x49\x43\x4D", 4);
}
namespace cv
{
/************************ DICOM decoder *****************************/
DICOMDecoder::DICOMDecoder()
{
// DICOM preamble is 128 bytes (can have any value, defaults to 0) + 4 bytes magic number (DICM)
m_signature = String(preamble_skip, (char)'\x0') + getMagic();
m_buf_supported = false;
}
bool DICOMDecoder::checkSignature( const String& signature ) const
{
if (signature.size() >= preamble_skip + magic_len)
{
if (signature.substr(preamble_skip, magic_len) == getMagic())
{
return true;
}
}
DBG("GDCM | Signature does not match\n");
return false;
}
ImageDecoder DICOMDecoder::newDecoder() const
{
return makePtr<DICOMDecoder>();
}
bool DICOMDecoder::readHeader()
{
gdcm::ImageReader csImageReader;
csImageReader.SetFileName(m_filename.c_str());
if(!csImageReader.Read())
{
DBG("GDCM | Failed to open DICOM file\n");
return(false);
}
const gdcm::Image &csImage = csImageReader.GetImage();
bool bOK = true;
switch (csImage.GetPhotometricInterpretation().GetType())
{
case gdcm::PhotometricInterpretation::MONOCHROME1:
case gdcm::PhotometricInterpretation::MONOCHROME2:
{
switch (csImage.GetPixelFormat().GetScalarType())
{
case gdcm::PixelFormat::INT8: m_type = CV_8SC1; break;
case gdcm::PixelFormat::UINT8: m_type = CV_8UC1; break;
case gdcm::PixelFormat::INT16: m_type = CV_16SC1; break;
case gdcm::PixelFormat::UINT16: m_type = CV_16UC1; break;
case gdcm::PixelFormat::INT32: m_type = CV_32SC1; break;
case gdcm::PixelFormat::FLOAT32: m_type = CV_32FC1; break;
case gdcm::PixelFormat::FLOAT64: m_type = CV_64FC1; break;
default: bOK = false; DBG("GDCM | Monochrome scalar type not supported\n"); break;
}
break;
}
case gdcm::PhotometricInterpretation::RGB:
{
switch (csImage.GetPixelFormat().GetScalarType())
{
case gdcm::PixelFormat::UINT8: m_type = CV_8UC3; break;
default: bOK = false; DBG("GDCM | RGB scalar type not supported\n"); break;
}
break;
}
default:
{
bOK = false;
DBG("GDCM | PI not supported: %s\n", csImage.GetPhotometricInterpretation().GetString());
break;
}
}
if(bOK)
{
unsigned int ndim = csImage.GetNumberOfDimensions();
if (ndim != 2)
{
DBG("GDCM | Invalid dimensions number: %d\n", ndim);
bOK = false;
}
}
if (bOK)
{
const unsigned int *piDimension = csImage.GetDimensions();
m_height = piDimension[0];
m_width = piDimension[1];
if( ( m_width <=0 ) || ( m_height <=0 ) )
{
DBG("GDCM | Invalid dimensions: %d x %d\n", piDimension[0], piDimension[1]);
bOK = false;
}
}
return(bOK);
}
bool DICOMDecoder::readData( Mat& csImage )
{
csImage.create(m_width,m_height,m_type);
gdcm::ImageReader csImageReader;
csImageReader.SetFileName(m_filename.c_str());
if(!csImageReader.Read())
{
DBG("GDCM | Failed to Read\n");
return false;
}
const gdcm::Image &img = csImageReader.GetImage();
unsigned long len = img.GetBufferLength();
if (len > csImage.elemSize() * csImage.total())
{
DBG("GDCM | Buffer is bigger than Mat: %ld > %ld * %ld\n", len, csImage.elemSize(), csImage.total());
return false;
}
if (!img.GetBuffer((char*)csImage.ptr()))
{
DBG("GDCM | Failed to GetBuffer\n");
return false;
}
DBG("GDCM | Read OK\n");
return true;
}
}
#endif // HAVE_GDCM

View File

@@ -0,0 +1,70 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GDCM_DICOM_H_
#define _GDCM_DICOM_H_
#include "cvconfig.h"
#ifdef HAVE_GDCM
#include "grfmt_base.hpp"
namespace cv
{
// DICOM image reader using GDCM
class DICOMDecoder CV_FINAL : public BaseImageDecoder
{
public:
DICOMDecoder();
bool readData( Mat& img ) CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
ImageDecoder newDecoder() const CV_OVERRIDE;
virtual bool checkSignature( const String& signature ) const CV_OVERRIDE;
};
}
#endif // HAVE_GDCM
#endif/*_GDCM_DICOM_H_*/

View File

@@ -0,0 +1,172 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "grfmt_hdr.hpp"
#include "rgbe.hpp"
#ifdef HAVE_IMGCODEC_HDR
namespace cv
{
HdrDecoder::HdrDecoder()
{
m_signature = "#?RGBE";
m_signature_alt = "#?RADIANCE";
file = NULL;
m_type = CV_32FC3;
}
HdrDecoder::~HdrDecoder()
{
}
size_t HdrDecoder::signatureLength() const
{
return m_signature.size() > m_signature_alt.size() ?
m_signature.size() : m_signature_alt.size();
}
bool HdrDecoder::readHeader()
{
file = fopen(m_filename.c_str(), "rb");
if(!file) {
return false;
}
RGBE_ReadHeader(file, &m_width, &m_height, NULL);
if(m_width <= 0 || m_height <= 0) {
fclose(file);
file = NULL;
return false;
}
return true;
}
bool HdrDecoder::readData(Mat& _img)
{
Mat img(m_height, m_width, CV_32FC3);
if(!file) {
if(!readHeader()) {
return false;
}
}
RGBE_ReadPixels_RLE(file, const_cast<float*>(img.ptr<float>()), img.cols, img.rows);
fclose(file); file = NULL;
if(_img.depth() == img.depth()) {
img.convertTo(_img, _img.type());
} else {
img.convertTo(_img, _img.type(), 255);
}
return true;
}
bool HdrDecoder::checkSignature( const String& signature ) const
{
if (signature.size() >= m_signature.size() &&
0 == memcmp(signature.c_str(), m_signature.c_str(), m_signature.size())
)
return true;
if (signature.size() >= m_signature_alt.size() &&
0 == memcmp(signature.c_str(), m_signature_alt.c_str(), m_signature_alt.size())
)
return true;
return false;
}
ImageDecoder HdrDecoder::newDecoder() const
{
return makePtr<HdrDecoder>();
}
HdrEncoder::HdrEncoder()
{
m_description = "Radiance HDR (*.hdr;*.pic)";
}
HdrEncoder::~HdrEncoder()
{
}
bool HdrEncoder::write( const Mat& input_img, const std::vector<int>& params )
{
Mat img;
CV_Assert(input_img.channels() == 3 || input_img.channels() == 1);
if(input_img.channels() == 1) {
std::vector<Mat> splitted(3, input_img);
merge(splitted, img);
} else {
input_img.copyTo(img);
}
if(img.depth() != CV_32F) {
img.convertTo(img, CV_32FC3, 1/255.0f);
}
CV_Assert(params.empty() || params[0] == HDR_NONE || params[0] == HDR_RLE);
FILE *fout = fopen(m_filename.c_str(), "wb");
if(!fout) {
return false;
}
RGBE_WriteHeader(fout, img.cols, img.rows, NULL);
if(params.empty() || params[0] == HDR_RLE) {
RGBE_WritePixels_RLE(fout, const_cast<float*>(img.ptr<float>()), img.cols, img.rows);
} else {
RGBE_WritePixels(fout, const_cast<float*>(img.ptr<float>()), img.cols * img.rows);
}
fclose(fout);
return true;
}
ImageEncoder HdrEncoder::newEncoder() const
{
return makePtr<HdrEncoder>();
}
bool HdrEncoder::isFormatSupported( int depth ) const {
return depth != CV_64F;
}
}
#endif // HAVE_IMGCODEC_HDR

View File

@@ -0,0 +1,92 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_HDR_H_
#define _GRFMT_HDR_H_
#include "grfmt_base.hpp"
#ifdef HAVE_IMGCODEC_HDR
namespace cv
{
enum HdrCompression
{
HDR_NONE = 0,
HDR_RLE = 1
};
// Radiance rgbe (.hdr) reader
class HdrDecoder CV_FINAL : public BaseImageDecoder
{
public:
HdrDecoder();
~HdrDecoder() CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
bool readData( Mat& img ) CV_OVERRIDE;
bool checkSignature( const String& signature ) const CV_OVERRIDE;
ImageDecoder newDecoder() const CV_OVERRIDE;
size_t signatureLength() const CV_OVERRIDE;
protected:
String m_signature_alt;
FILE *file;
};
// ... writer
class HdrEncoder CV_FINAL : public BaseImageEncoder
{
public:
HdrEncoder();
~HdrEncoder() CV_OVERRIDE;
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE;
bool isFormatSupported( int depth ) const CV_OVERRIDE;
protected:
};
}
#endif // HAVE_IMGCODEC_HDR
#endif/*_GRFMT_HDR_H_*/

View File

@@ -0,0 +1,726 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "grfmt_jpeg.hpp"
#ifdef HAVE_JPEG
#ifdef _MSC_VER
//interaction between '_setjmp' and C++ object destruction is non-portable
#pragma warning(disable: 4611)
#endif
#include <stdio.h>
#include <setjmp.h>
// the following defines are a hack to avoid multiple problems with frame pointer handling and setjmp
// see http://gcc.gnu.org/ml/gcc/2011-10/msg00324.html for some details
#define mingw_getsp(...) 0
#define __builtin_frame_address(...) 0
#ifdef _WIN32
#define XMD_H // prevent redefinition of INT32
#undef FAR // prevent FAR redefinition
#endif
#if defined _WIN32 && defined __GNUC__
typedef unsigned char boolean;
#endif
#undef FALSE
#undef TRUE
extern "C" {
#include "jpeglib.h"
}
namespace cv
{
struct JpegErrorMgr
{
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
struct JpegSource
{
struct jpeg_source_mgr pub;
int skip;
};
struct JpegState
{
jpeg_decompress_struct cinfo; // IJG JPEG codec structure
JpegErrorMgr jerr; // error processing manager state
JpegSource source; // memory buffer source
};
/////////////////////// Error processing /////////////////////
METHODDEF(void)
stub(j_decompress_ptr)
{
}
METHODDEF(boolean)
fill_input_buffer(j_decompress_ptr)
{
return FALSE;
}
// emulating memory input stream
METHODDEF(void)
skip_input_data(j_decompress_ptr cinfo, long num_bytes)
{
JpegSource* source = (JpegSource*) cinfo->src;
if( num_bytes > (long)source->pub.bytes_in_buffer )
{
// We need to skip more data than we have in the buffer.
// This will force the JPEG library to suspend decoding.
source->skip = (int)(num_bytes - source->pub.bytes_in_buffer);
source->pub.next_input_byte += source->pub.bytes_in_buffer;
source->pub.bytes_in_buffer = 0;
}
else
{
// Skip portion of the buffer
source->pub.bytes_in_buffer -= num_bytes;
source->pub.next_input_byte += num_bytes;
source->skip = 0;
}
}
static void jpeg_buffer_src(j_decompress_ptr cinfo, JpegSource* source)
{
cinfo->src = &source->pub;
// Prepare for suspending reader
source->pub.init_source = stub;
source->pub.fill_input_buffer = fill_input_buffer;
source->pub.skip_input_data = skip_input_data;
source->pub.resync_to_restart = jpeg_resync_to_restart;
source->pub.term_source = stub;
source->pub.bytes_in_buffer = 0; // forces fill_input_buffer on first read
source->skip = 0;
}
METHODDEF(void)
error_exit( j_common_ptr cinfo )
{
JpegErrorMgr* err_mgr = (JpegErrorMgr*)(cinfo->err);
/* Return control to the setjmp point */
longjmp( err_mgr->setjmp_buffer, 1 );
}
/////////////////////// JpegDecoder ///////////////////
JpegDecoder::JpegDecoder()
{
m_signature = "\xFF\xD8\xFF";
m_state = 0;
m_f = 0;
m_buf_supported = true;
}
JpegDecoder::~JpegDecoder()
{
close();
}
void JpegDecoder::close()
{
if( m_state )
{
JpegState* state = (JpegState*)m_state;
jpeg_destroy_decompress( &state->cinfo );
delete state;
m_state = 0;
}
if( m_f )
{
fclose( m_f );
m_f = 0;
}
m_width = m_height = 0;
m_type = -1;
}
ImageDecoder JpegDecoder::newDecoder() const
{
return makePtr<JpegDecoder>();
}
bool JpegDecoder::readHeader()
{
volatile bool result = false;
close();
JpegState* state = new JpegState;
m_state = state;
state->cinfo.err = jpeg_std_error(&state->jerr.pub);
state->jerr.pub.error_exit = error_exit;
if( setjmp( state->jerr.setjmp_buffer ) == 0 )
{
jpeg_create_decompress( &state->cinfo );
if( !m_buf.empty() )
{
jpeg_buffer_src(&state->cinfo, &state->source);
state->source.pub.next_input_byte = m_buf.ptr();
state->source.pub.bytes_in_buffer = m_buf.cols*m_buf.rows*m_buf.elemSize();
}
else
{
m_f = fopen( m_filename.c_str(), "rb" );
if( m_f )
jpeg_stdio_src( &state->cinfo, m_f );
}
if (state->cinfo.src != 0)
{
jpeg_read_header( &state->cinfo, TRUE );
state->cinfo.scale_num=1;
state->cinfo.scale_denom = m_scale_denom;
m_scale_denom=1; // trick! to know which decoder used scale_denom see imread_
jpeg_calc_output_dimensions(&state->cinfo);
m_width = state->cinfo.output_width;
m_height = state->cinfo.output_height;
m_type = state->cinfo.num_components > 1 ? CV_8UC3 : CV_8UC1;
result = true;
}
}
if( !result )
close();
return result;
}
/***************************************************************************
* following code is for supporting MJPEG image files
* based on a message of Laurent Pinchart on the video4linux mailing list
***************************************************************************/
/* JPEG DHT Segment for YCrCb omitted from MJPEG data */
static
unsigned char my_jpeg_odml_dht[0x1a4] = {
0xff, 0xc4, 0x01, 0xa2,
0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
0x04, 0x00, 0x00, 0x01, 0x7d,
0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
0x13, 0x51, 0x61, 0x07,
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1,
0x15, 0x52, 0xd1, 0xf0,
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a,
0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
0x46, 0x47, 0x48, 0x49,
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65,
0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85,
0x86, 0x87, 0x88, 0x89,
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3,
0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
0xc2, 0xc3, 0xc4, 0xc5,
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
0xd9, 0xda, 0xe1, 0xe2,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4,
0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa,
0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
0x04, 0x00, 0x01, 0x02, 0x77,
0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
0x51, 0x07, 0x61, 0x71,
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09,
0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17,
0x18, 0x19, 0x1a, 0x26,
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a,
0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
0xb9, 0xba, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
0xd7, 0xd8, 0xd9, 0xda,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa
};
/*
* Parse the DHT table.
* This code comes from jpeg6b (jdmarker.c).
*/
static
int my_jpeg_load_dht (struct jpeg_decompress_struct *info, unsigned char *dht,
JHUFF_TBL *ac_tables[], JHUFF_TBL *dc_tables[])
{
unsigned int length = (dht[2] << 8) + dht[3] - 2;
unsigned int pos = 4;
unsigned int count, i;
int index;
JHUFF_TBL **hufftbl;
unsigned char bits[17];
unsigned char huffval[256] = {0};
while (length > 16)
{
bits[0] = 0;
index = dht[pos++];
count = 0;
for (i = 1; i <= 16; ++i)
{
bits[i] = dht[pos++];
count += bits[i];
}
length -= 17;
if (count > 256 || count > length)
return -1;
for (i = 0; i < count; ++i)
huffval[i] = dht[pos++];
length -= count;
if (index & 0x10)
{
index &= ~0x10;
hufftbl = &ac_tables[index];
}
else
hufftbl = &dc_tables[index];
if (index < 0 || index >= NUM_HUFF_TBLS)
return -1;
if (*hufftbl == NULL)
*hufftbl = jpeg_alloc_huff_table ((j_common_ptr)info);
if (*hufftbl == NULL)
return -1;
memcpy ((*hufftbl)->bits, bits, sizeof (*hufftbl)->bits);
memcpy ((*hufftbl)->huffval, huffval, sizeof (*hufftbl)->huffval);
}
if (length != 0)
return -1;
return 0;
}
/***************************************************************************
* end of code for supportting MJPEG image files
* based on a message of Laurent Pinchart on the video4linux mailing list
***************************************************************************/
bool JpegDecoder::readData( Mat& img )
{
volatile bool result = false;
size_t step = img.step;
bool color = img.channels() > 1;
if( m_state && m_width && m_height )
{
jpeg_decompress_struct* cinfo = &((JpegState*)m_state)->cinfo;
JpegErrorMgr* jerr = &((JpegState*)m_state)->jerr;
JSAMPARRAY buffer = 0;
if( setjmp( jerr->setjmp_buffer ) == 0 )
{
/* check if this is a mjpeg image format */
if ( cinfo->ac_huff_tbl_ptrs[0] == NULL &&
cinfo->ac_huff_tbl_ptrs[1] == NULL &&
cinfo->dc_huff_tbl_ptrs[0] == NULL &&
cinfo->dc_huff_tbl_ptrs[1] == NULL )
{
/* yes, this is a mjpeg image format, so load the correct
huffman table */
my_jpeg_load_dht( cinfo,
my_jpeg_odml_dht,
cinfo->ac_huff_tbl_ptrs,
cinfo->dc_huff_tbl_ptrs );
}
if( color )
{
if( cinfo->num_components != 4 )
{
cinfo->out_color_space = JCS_RGB;
cinfo->out_color_components = 3;
}
else
{
cinfo->out_color_space = JCS_CMYK;
cinfo->out_color_components = 4;
}
}
else
{
if( cinfo->num_components != 4 )
{
cinfo->out_color_space = JCS_GRAYSCALE;
cinfo->out_color_components = 1;
}
else
{
cinfo->out_color_space = JCS_CMYK;
cinfo->out_color_components = 4;
}
}
jpeg_start_decompress( cinfo );
buffer = (*cinfo->mem->alloc_sarray)((j_common_ptr)cinfo,
JPOOL_IMAGE, m_width*4, 1 );
uchar* data = img.ptr();
for( ; m_height--; data += step )
{
jpeg_read_scanlines( cinfo, buffer, 1 );
if( color )
{
if( cinfo->out_color_components == 3 )
icvCvt_RGB2BGR_8u_C3R( buffer[0], 0, data, 0, Size(m_width,1) );
else
icvCvt_CMYK2BGR_8u_C4C3R( buffer[0], 0, data, 0, Size(m_width,1) );
}
else
{
if( cinfo->out_color_components == 1 )
memcpy( data, buffer[0], m_width );
else
icvCvt_CMYK2Gray_8u_C4C1R( buffer[0], 0, data, 0, Size(m_width,1) );
}
}
result = true;
jpeg_finish_decompress( cinfo );
}
}
close();
return result;
}
/////////////////////// JpegEncoder ///////////////////
struct JpegDestination
{
struct jpeg_destination_mgr pub;
std::vector<uchar> *buf, *dst;
};
METHODDEF(void)
stub(j_compress_ptr)
{
}
METHODDEF(void)
term_destination (j_compress_ptr cinfo)
{
JpegDestination* dest = (JpegDestination*)cinfo->dest;
size_t sz = dest->dst->size(), bufsz = dest->buf->size() - dest->pub.free_in_buffer;
if( bufsz > 0 )
{
dest->dst->resize(sz + bufsz);
memcpy( &(*dest->dst)[0] + sz, &(*dest->buf)[0], bufsz);
}
}
METHODDEF(boolean)
empty_output_buffer (j_compress_ptr cinfo)
{
JpegDestination* dest = (JpegDestination*)cinfo->dest;
size_t sz = dest->dst->size(), bufsz = dest->buf->size();
dest->dst->resize(sz + bufsz);
memcpy( &(*dest->dst)[0] + sz, &(*dest->buf)[0], bufsz);
dest->pub.next_output_byte = &(*dest->buf)[0];
dest->pub.free_in_buffer = bufsz;
return TRUE;
}
static void jpeg_buffer_dest(j_compress_ptr cinfo, JpegDestination* destination)
{
cinfo->dest = &destination->pub;
destination->pub.init_destination = stub;
destination->pub.empty_output_buffer = empty_output_buffer;
destination->pub.term_destination = term_destination;
}
JpegEncoder::JpegEncoder()
{
m_description = "JPEG files (*.jpeg;*.jpg;*.jpe)";
m_buf_supported = true;
}
JpegEncoder::~JpegEncoder()
{
}
ImageEncoder JpegEncoder::newEncoder() const
{
return makePtr<JpegEncoder>();
}
bool JpegEncoder::write( const Mat& img, const std::vector<int>& params )
{
m_last_error.clear();
struct fileWrapper
{
FILE* f;
fileWrapper() : f(0) {}
~fileWrapper() { if(f) fclose(f); }
};
volatile bool result = false;
fileWrapper fw;
int width = img.cols, height = img.rows;
std::vector<uchar> out_buf(1 << 12);
AutoBuffer<uchar> _buffer;
uchar* buffer;
struct jpeg_compress_struct cinfo;
JpegErrorMgr jerr;
JpegDestination dest;
jpeg_create_compress(&cinfo);
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = error_exit;
if( !m_buf )
{
fw.f = fopen( m_filename.c_str(), "wb" );
if( !fw.f )
goto _exit_;
jpeg_stdio_dest( &cinfo, fw.f );
}
else
{
dest.dst = m_buf;
dest.buf = &out_buf;
jpeg_buffer_dest( &cinfo, &dest );
dest.pub.next_output_byte = &out_buf[0];
dest.pub.free_in_buffer = out_buf.size();
}
if( setjmp( jerr.setjmp_buffer ) == 0 )
{
cinfo.image_width = width;
cinfo.image_height = height;
int _channels = img.channels();
int channels = _channels > 1 ? 3 : 1;
cinfo.input_components = channels;
cinfo.in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE;
int quality = 95;
int progressive = 0;
int optimize = 0;
int rst_interval = 0;
int luma_quality = -1;
int chroma_quality = -1;
for( size_t i = 0; i < params.size(); i += 2 )
{
if( params[i] == CV_IMWRITE_JPEG_QUALITY )
{
quality = params[i+1];
quality = MIN(MAX(quality, 0), 100);
}
if( params[i] == CV_IMWRITE_JPEG_PROGRESSIVE )
{
progressive = params[i+1];
}
if( params[i] == CV_IMWRITE_JPEG_OPTIMIZE )
{
optimize = params[i+1];
}
if( params[i] == CV_IMWRITE_JPEG_LUMA_QUALITY )
{
if (params[i+1] >= 0)
{
luma_quality = MIN(MAX(params[i+1], 0), 100);
quality = luma_quality;
if (chroma_quality < 0)
{
chroma_quality = luma_quality;
}
}
}
if( params[i] == CV_IMWRITE_JPEG_CHROMA_QUALITY )
{
if (params[i+1] >= 0)
{
chroma_quality = MIN(MAX(params[i+1], 0), 100);
}
}
if( params[i] == CV_IMWRITE_JPEG_RST_INTERVAL )
{
rst_interval = params[i+1];
rst_interval = MIN(MAX(rst_interval, 0), 65535L);
}
}
jpeg_set_defaults( &cinfo );
cinfo.restart_interval = rst_interval;
jpeg_set_quality( &cinfo, quality,
TRUE /* limit to baseline-JPEG values */ );
if( progressive )
jpeg_simple_progression( &cinfo );
if( optimize )
cinfo.optimize_coding = TRUE;
#if JPEG_LIB_VERSION >= 70
if (luma_quality >= 0 && chroma_quality >= 0)
{
cinfo.q_scale_factor[0] = jpeg_quality_scaling(luma_quality);
cinfo.q_scale_factor[1] = jpeg_quality_scaling(chroma_quality);
if ( luma_quality != chroma_quality )
{
/* disable subsampling - ref. Libjpeg.txt */
cinfo.comp_info[0].v_samp_factor = 1;
cinfo.comp_info[0].h_samp_factor = 1;
cinfo.comp_info[1].v_samp_factor = 1;
cinfo.comp_info[1].h_samp_factor = 1;
}
jpeg_default_qtables( &cinfo, TRUE );
}
#endif // #if JPEG_LIB_VERSION >= 70
jpeg_start_compress( &cinfo, TRUE );
if( channels > 1 )
_buffer.allocate(width*channels);
buffer = _buffer.data();
for( int y = 0; y < height; y++ )
{
uchar *data = img.data + img.step*y, *ptr = data;
if( _channels == 3 )
{
icvCvt_BGR2RGB_8u_C3R( data, 0, buffer, 0, Size(width,1) );
ptr = buffer;
}
else if( _channels == 4 )
{
icvCvt_BGRA2BGR_8u_C4C3R( data, 0, buffer, 0, Size(width,1), 2 );
ptr = buffer;
}
jpeg_write_scanlines( &cinfo, &ptr, 1 );
}
jpeg_finish_compress( &cinfo );
result = true;
}
_exit_:
if(!result)
{
char jmsg_buf[JMSG_LENGTH_MAX];
jerr.pub.format_message((j_common_ptr)&cinfo, jmsg_buf);
m_last_error = jmsg_buf;
}
jpeg_destroy_compress( &cinfo );
return result;
}
}
#endif
/* End of file. */

View File

@@ -0,0 +1,94 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_JPEG_H_
#define _GRFMT_JPEG_H_
#include "grfmt_base.hpp"
#include "bitstrm.hpp"
#ifdef HAVE_JPEG
// IJG-based Jpeg codec
namespace cv
{
class JpegDecoder CV_FINAL : public BaseImageDecoder
{
public:
JpegDecoder();
virtual ~JpegDecoder();
bool readData( Mat& img ) CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
void close();
ImageDecoder newDecoder() const CV_OVERRIDE;
protected:
FILE* m_f;
void* m_state;
private:
JpegDecoder(const JpegDecoder &); // copy disabled
JpegDecoder& operator=(const JpegDecoder &); // assign disabled
};
class JpegEncoder CV_FINAL : public BaseImageEncoder
{
public:
JpegEncoder();
virtual ~JpegEncoder();
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE;
};
}
#endif
#endif/*_GRFMT_JPEG_H_*/

View File

@@ -0,0 +1,642 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#ifdef HAVE_JASPER
#include <sstream>
#include <opencv2/core/utils/configuration.private.hpp>
#include <opencv2/core/utils/logger.hpp>
#include "grfmt_jpeg2000.hpp"
#include "opencv2/imgproc.hpp"
#ifdef _WIN32
#define JAS_WIN_MSVC_BUILD 1
#ifdef __GNUC__
#define HAVE_STDINT_H 1
#endif
#endif
#undef VERSION
#include <jasper/jasper.h>
// FIXME bad hack
#undef uchar
#undef ulong
namespace cv
{
struct JasperInitializer
{
JasperInitializer() { jas_init(); }
~JasperInitializer() { jas_cleanup(); }
};
static JasperInitializer& _initJasper()
{
static JasperInitializer initialize_jasper;
return initialize_jasper;
}
static bool isJasperEnabled()
{
static const bool PARAM_ENABLE_JASPER = utils::getConfigurationParameterBool("OPENCV_IO_ENABLE_JASPER",
#ifdef OPENCV_IMGCODECS_FORCE_JASPER
true
#else
false
#endif
);
return PARAM_ENABLE_JASPER;
}
static JasperInitializer& initJasper()
{
if (isJasperEnabled())
{
return _initJasper();
}
else
{
const char* message = "imgcodecs: Jasper (JPEG-2000) codec is disabled. You can enable it via 'OPENCV_IO_ENABLE_JASPER' option. Refer for details and cautions here: https://github.com/opencv/opencv/issues/14058";
CV_LOG_WARNING(NULL, message);
CV_Error(Error::StsNotImplemented, message);
}
}
/////////////////////// Jpeg2KDecoder ///////////////////
Jpeg2KDecoder::Jpeg2KDecoder()
{
static const unsigned char signature_[12] = { 0, 0, 0, 0x0c, 'j', 'P', ' ', ' ', 13, 10, 0x87, 10};
m_signature = String((const char*)signature_, (const char*)signature_ + sizeof(signature_));
m_stream = 0;
m_image = 0;
}
Jpeg2KDecoder::~Jpeg2KDecoder()
{
}
ImageDecoder Jpeg2KDecoder::newDecoder() const
{
initJasper();
return makePtr<Jpeg2KDecoder>();
}
void Jpeg2KDecoder::close()
{
if( m_stream )
{
CV_Assert(isJasperEnabled());
jas_stream_close( (jas_stream_t*)m_stream );
m_stream = 0;
}
if( m_image )
{
CV_Assert(isJasperEnabled());
jas_image_destroy( (jas_image_t*)m_image );
m_image = 0;
}
}
bool Jpeg2KDecoder::readHeader()
{
CV_Assert(isJasperEnabled());
bool result = false;
close();
jas_stream_t* stream = jas_stream_fopen( m_filename.c_str(), "rb" );
m_stream = stream;
if( stream )
{
jas_image_t* image = jas_image_decode( stream, -1, 0 );
m_image = image;
if( image ) {
CV_Assert(0 == (jas_image_tlx(image)) && "not supported");
CV_Assert(0 == (jas_image_tly(image)) && "not supported");
m_width = jas_image_width( image );
m_height = jas_image_height( image );
int cntcmpts = 0; // count the known components
int numcmpts = jas_image_numcmpts( image );
int depth = 0;
for( int i = 0; i < numcmpts; i++ )
{
int depth_i = jas_image_cmptprec( image, i );
CV_Assert(depth == 0 || depth == depth_i); // component data type mismatch
depth = MAX(depth, depth_i);
if( jas_image_cmpttype( image, i ) > 2 )
continue;
int sgnd = jas_image_cmptsgnd(image, i);
int xstart = jas_image_cmpttlx(image, i);
int xend = jas_image_cmptbrx(image, i);
int xstep = jas_image_cmpthstep(image, i);
int ystart = jas_image_cmpttly(image, i);
int yend = jas_image_cmptbry(image, i);
int ystep = jas_image_cmptvstep(image, i);
CV_Assert(sgnd == 0 && "not supported");
CV_Assert(xstart == 0 && "not supported");
CV_Assert(ystart == 0 && "not supported");
CV_Assert(xstep == 1 && "not supported");
CV_Assert(ystep == 1 && "not supported");
CV_Assert(xend == m_width);
CV_Assert(yend == m_height);
cntcmpts++;
}
if( cntcmpts )
{
CV_Assert(depth == 8 || depth == 16);
CV_Assert(cntcmpts == 1 || cntcmpts == 3);
m_type = CV_MAKETYPE(depth <= 8 ? CV_8U : CV_16U, cntcmpts > 1 ? 3 : 1);
result = true;
}
}
}
if( !result )
close();
return result;
}
static void Jpeg2KDecoder_close(Jpeg2KDecoder* ptr)
{
ptr->close();
}
bool Jpeg2KDecoder::readData( Mat& img )
{
CV_Assert(isJasperEnabled());
Ptr<Jpeg2KDecoder> close_this(this, Jpeg2KDecoder_close);
bool result = false;
bool color = img.channels() > 1;
uchar* data = img.ptr();
size_t step = img.step;
jas_stream_t* stream = (jas_stream_t*)m_stream;
jas_image_t* image = (jas_image_t*)m_image;
#ifndef _WIN32
// At least on some Linux instances the
// system libjasper segfaults when
// converting color to grey.
// We do this conversion manually at the end.
Mat clr;
if (CV_MAT_CN(img.type()) < CV_MAT_CN(this->type()))
{
clr.create(img.size().height, img.size().width, this->type());
color = true;
data = clr.ptr();
step = (int)clr.step;
}
#endif
if( stream && image )
{
bool convert;
int colorspace;
if( color )
{
convert = (jas_image_clrspc( image ) != JAS_CLRSPC_SRGB);
colorspace = JAS_CLRSPC_SRGB;
}
else
{
convert = (jas_clrspc_fam( jas_image_clrspc( image ) ) != JAS_CLRSPC_FAM_GRAY);
colorspace = JAS_CLRSPC_SGRAY; // TODO GENGRAY or SGRAY? (GENGRAY fails on Win.)
}
// convert to the desired colorspace
if( convert )
{
jas_cmprof_t *clrprof = jas_cmprof_createfromclrspc( colorspace );
if( clrprof )
{
jas_image_t *_img = jas_image_chclrspc( image, clrprof, JAS_CMXFORM_INTENT_RELCLR );
if( _img )
{
jas_image_destroy( image );
m_image = image = _img;
result = true;
}
else
{
jas_cmprof_destroy(clrprof);
CV_Error(Error::StsError, "JPEG 2000 LOADER ERROR: cannot convert colorspace");
}
jas_cmprof_destroy( clrprof );
}
else
{
CV_Error(Error::StsError, "JPEG 2000 LOADER ERROR: unable to create colorspace");
}
}
else
result = true;
if( result )
{
int ncmpts;
int cmptlut[3];
if( color )
{
cmptlut[0] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_RGB_B );
cmptlut[1] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_RGB_G );
cmptlut[2] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_RGB_R );
if( cmptlut[0] < 0 || cmptlut[1] < 0 || cmptlut[2] < 0 )
result = false;
ncmpts = 3;
}
else
{
cmptlut[0] = jas_image_getcmptbytype( image, JAS_IMAGE_CT_GRAY_Y );
if( cmptlut[0] < 0 )
result = false;
ncmpts = 1;
}
if( result )
{
for( int i = 0; i < ncmpts; i++ )
{
int maxval = 1 << jas_image_cmptprec( image, cmptlut[i] );
int offset = jas_image_cmptsgnd( image, cmptlut[i] ) ? maxval / 2 : 0;
int yend = jas_image_cmptbry( image, cmptlut[i] );
int ystep = jas_image_cmptvstep( image, cmptlut[i] );
int xend = jas_image_cmptbrx( image, cmptlut[i] );
int xstep = jas_image_cmpthstep( image, cmptlut[i] );
jas_matrix_t *buffer = jas_matrix_create( yend / ystep, xend / xstep );
if( buffer )
{
if( !jas_image_readcmpt( image, cmptlut[i], 0, 0, xend / xstep, yend / ystep, buffer ))
{
if( img.depth() == CV_8U )
result = readComponent8u( data + i, buffer, validateToInt(step), cmptlut[i], maxval, offset, ncmpts );
else
result = readComponent16u( ((unsigned short *)data) + i, buffer, validateToInt(step / 2), cmptlut[i], maxval, offset, ncmpts );
if( !result )
{
jas_matrix_destroy( buffer );
CV_Error(Error::StsError, "JPEG2000 LOADER ERROR: failed to read component");
}
}
jas_matrix_destroy( buffer );
}
}
}
}
else
{
CV_Error(Error::StsError, "JPEG2000 LOADER ERROR: colorspace conversion failed");
}
}
CV_Assert(result == true);
#ifndef _WIN32
if (!clr.empty())
{
cv::cvtColor(clr, img, COLOR_BGR2GRAY);
}
#endif
return result;
}
bool Jpeg2KDecoder::readComponent8u( uchar *data, void *_buffer,
int step, int cmpt,
int maxval, int offset, int ncmpts )
{
CV_Assert(isJasperEnabled());
jas_matrix_t* buffer = (jas_matrix_t*)_buffer;
jas_image_t* image = (jas_image_t*)m_image;
int xstart = jas_image_cmpttlx( image, cmpt );
int xend = jas_image_cmptbrx( image, cmpt );
int xstep = jas_image_cmpthstep( image, cmpt );
int xoffset = jas_image_tlx( image );
int ystart = jas_image_cmpttly( image, cmpt );
int yend = jas_image_cmptbry( image, cmpt );
int ystep = jas_image_cmptvstep( image, cmpt );
int yoffset = jas_image_tly( image );
int x, y, x1, y1, j;
int rshift = cvRound(std::log(maxval/256.)/std::log(2.));
int lshift = MAX(0, -rshift);
rshift = MAX(0, rshift);
int delta = (rshift > 0 ? 1 << (rshift - 1) : 0) + offset;
for( y = 0; y < yend - ystart; )
{
jas_seqent_t* pix_row = &jas_matrix_get( buffer, y / ystep, 0 );
uchar* dst = data + (y - yoffset) * step - xoffset;
if( xstep == 1 )
{
if( maxval == 256 && offset == 0 )
for( x = 0; x < xend - xstart; x++ )
{
int pix = pix_row[x];
dst[x*ncmpts] = cv::saturate_cast<uchar>(pix);
}
else
for( x = 0; x < xend - xstart; x++ )
{
int pix = ((pix_row[x] + delta) >> rshift) << lshift;
dst[x*ncmpts] = cv::saturate_cast<uchar>(pix);
}
}
else if( xstep == 2 && offset == 0 )
for( x = 0, j = 0; x < xend - xstart; x += 2, j++ )
{
int pix = ((pix_row[j] + delta) >> rshift) << lshift;
dst[x*ncmpts] = dst[(x+1)*ncmpts] = cv::saturate_cast<uchar>(pix);
}
else
for( x = 0, j = 0; x < xend - xstart; j++ )
{
int pix = ((pix_row[j] + delta) >> rshift) << lshift;
pix = cv::saturate_cast<uchar>(pix);
for( x1 = x + xstep; x < x1; x++ )
dst[x*ncmpts] = (uchar)pix;
}
y1 = y + ystep;
for( ++y; y < y1; y++, dst += step )
for( x = 0; x < xend - xstart; x++ )
dst[x*ncmpts + step] = dst[x*ncmpts];
}
return true;
}
bool Jpeg2KDecoder::readComponent16u( unsigned short *data, void *_buffer,
int step, int cmpt,
int maxval, int offset, int ncmpts )
{
CV_Assert(isJasperEnabled());
jas_matrix_t* buffer = (jas_matrix_t*)_buffer;
jas_image_t* image = (jas_image_t*)m_image;
int xstart = jas_image_cmpttlx( image, cmpt );
int xend = jas_image_cmptbrx( image, cmpt );
int xstep = jas_image_cmpthstep( image, cmpt );
int xoffset = jas_image_tlx( image );
int ystart = jas_image_cmpttly( image, cmpt );
int yend = jas_image_cmptbry( image, cmpt );
int ystep = jas_image_cmptvstep( image, cmpt );
int yoffset = jas_image_tly( image );
int x, y, x1, y1, j;
int rshift = cvRound(std::log(maxval/65536.)/std::log(2.));
int lshift = MAX(0, -rshift);
rshift = MAX(0, rshift);
int delta = (rshift > 0 ? 1 << (rshift - 1) : 0) + offset;
for( y = 0; y < yend - ystart; )
{
jas_seqent_t* pix_row = &jas_matrix_get( buffer, y / ystep, 0 );
ushort* dst = data + (y - yoffset) * step - xoffset;
if( xstep == 1 )
{
if( maxval == 65536 && offset == 0 )
for( x = 0; x < xend - xstart; x++ )
{
int pix = pix_row[x];
dst[x*ncmpts] = cv::saturate_cast<ushort>(pix);
}
else
for( x = 0; x < xend - xstart; x++ )
{
int pix = ((pix_row[x] + delta) >> rshift) << lshift;
dst[x*ncmpts] = cv::saturate_cast<ushort>(pix);
}
}
else if( xstep == 2 && offset == 0 )
for( x = 0, j = 0; x < xend - xstart; x += 2, j++ )
{
int pix = ((pix_row[j] + delta) >> rshift) << lshift;
dst[x*ncmpts] = dst[(x+1)*ncmpts] = cv::saturate_cast<ushort>(pix);
}
else
for( x = 0, j = 0; x < xend - xstart; j++ )
{
int pix = ((pix_row[j] + delta) >> rshift) << lshift;
pix = cv::saturate_cast<ushort>(pix);
for( x1 = x + xstep; x < x1; x++ )
dst[x*ncmpts] = (ushort)pix;
}
y1 = y + ystep;
for( ++y; y < y1; y++, dst += step )
for( x = 0; x < xend - xstart; x++ )
dst[x*ncmpts + step] = dst[x*ncmpts];
}
return true;
}
/////////////////////// Jpeg2KEncoder ///////////////////
Jpeg2KEncoder::Jpeg2KEncoder()
{
m_description = "JPEG-2000 files (*.jp2)";
}
Jpeg2KEncoder::~Jpeg2KEncoder()
{
}
ImageEncoder Jpeg2KEncoder::newEncoder() const
{
initJasper();
return makePtr<Jpeg2KEncoder>();
}
bool Jpeg2KEncoder::isFormatSupported( int depth ) const
{
return depth == CV_8U || depth == CV_16U;
}
bool Jpeg2KEncoder::write( const Mat& _img, const std::vector<int>& params )
{
CV_Assert(isJasperEnabled());
int width = _img.cols, height = _img.rows;
int depth = _img.depth(), channels = _img.channels();
depth = depth == CV_8U ? 8 : 16;
if( channels > 3 || channels < 1 )
return false;
CV_Assert(params.size() % 2 == 0);
double target_compression_rate = 1.0;
for( size_t i = 0; i < params.size(); i += 2 )
{
switch(params[i])
{
case cv::IMWRITE_JPEG2000_COMPRESSION_X1000:
target_compression_rate = std::min(std::max(params[i+1], 0), 1000) / 1000.0;
break;
}
}
jas_image_cmptparm_t component_info[3];
for( int i = 0; i < channels; i++ )
{
component_info[i].tlx = 0;
component_info[i].tly = 0;
component_info[i].hstep = 1;
component_info[i].vstep = 1;
component_info[i].width = width;
component_info[i].height = height;
component_info[i].prec = depth;
component_info[i].sgnd = 0;
}
jas_image_t *img = jas_image_create( channels, component_info, (channels == 1) ? JAS_CLRSPC_SGRAY : JAS_CLRSPC_SRGB );
if( !img )
return false;
if(channels == 1)
jas_image_setcmpttype( img, 0, JAS_IMAGE_CT_GRAY_Y );
else
{
jas_image_setcmpttype( img, 0, JAS_IMAGE_CT_RGB_B );
jas_image_setcmpttype( img, 1, JAS_IMAGE_CT_RGB_G );
jas_image_setcmpttype( img, 2, JAS_IMAGE_CT_RGB_R );
}
bool result;
if( depth == 8 )
result = writeComponent8u( img, _img );
else
result = writeComponent16u( img, _img );
if( result )
{
jas_stream_t *stream = jas_stream_fopen( m_filename.c_str(), "wb" );
if( stream )
{
std::stringstream options;
options << "rate=" << target_compression_rate;
result = !jas_image_encode( img, stream, jas_image_strtofmt( (char*)"jp2" ), (char*)options.str().c_str() );
jas_stream_close( stream );
}
}
jas_image_destroy( img );
return result;
}
bool Jpeg2KEncoder::writeComponent8u( void *__img, const Mat& _img )
{
CV_Assert(isJasperEnabled());
jas_image_t* img = (jas_image_t*)__img;
int w = _img.cols, h = _img.rows, ncmpts = _img.channels();
jas_matrix_t *row = jas_matrix_create( 1, w );
if(!row)
return false;
for( int y = 0; y < h; y++ )
{
const uchar* data = _img.ptr(y);
for( int i = 0; i < ncmpts; i++ )
{
for( int x = 0; x < w; x++)
jas_matrix_setv( row, x, data[x * ncmpts + i] );
jas_image_writecmpt( img, i, 0, y, w, 1, row );
}
}
jas_matrix_destroy( row );
return true;
}
bool Jpeg2KEncoder::writeComponent16u( void *__img, const Mat& _img )
{
CV_Assert(isJasperEnabled());
jas_image_t* img = (jas_image_t*)__img;
int w = _img.cols, h = _img.rows, ncmpts = _img.channels();
jas_matrix_t *row = jas_matrix_create( 1, w );
if(!row)
return false;
for( int y = 0; y < h; y++ )
{
const ushort* data = _img.ptr<ushort>(y);
for( int i = 0; i < ncmpts; i++ )
{
for( int x = 0; x < w; x++)
jas_matrix_setv( row, x, data[x * ncmpts + i] );
jas_image_writecmpt( img, i, 0, y, w, 1, row );
}
}
jas_matrix_destroy( row );
return true;
}
}
#endif
/* End of file. */

View File

@@ -0,0 +1,95 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_JASPER_H_
#define _GRFMT_JASPER_H_
#ifdef HAVE_JASPER
#include "grfmt_base.hpp"
namespace cv
{
class Jpeg2KDecoder CV_FINAL : public BaseImageDecoder
{
public:
Jpeg2KDecoder();
virtual ~Jpeg2KDecoder();
bool readData( Mat& img ) CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
void close();
ImageDecoder newDecoder() const CV_OVERRIDE;
protected:
bool readComponent8u( uchar *data, void *buffer, int step, int cmpt,
int maxval, int offset, int ncmpts );
bool readComponent16u( unsigned short *data, void *buffer, int step, int cmpt,
int maxval, int offset, int ncmpts );
void *m_stream;
void *m_image;
};
class Jpeg2KEncoder CV_FINAL : public BaseImageEncoder
{
public:
Jpeg2KEncoder();
virtual ~Jpeg2KEncoder();
bool isFormatSupported( int depth ) const CV_OVERRIDE;
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE;
protected:
bool writeComponent8u( void *img, const Mat& _img );
bool writeComponent16u( void *img, const Mat& _img );
};
}
#endif
#endif/*_GRFMT_JASPER_H_*/

View File

@@ -0,0 +1,727 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
// (3-clause BSD License)
//
// Copyright (C) 2000-2016, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved.
// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
// Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved.
// Copyright (C) 2015-2016, Itseez Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the names of the copyright holders nor the names of the contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall copyright holders or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#ifdef HAVE_IMGCODEC_PXM
#include <cerrno>
#include "utils.hpp"
#include "grfmt_pam.hpp"
namespace cv {
/* the PAM related fields */
#define MAX_PAM_HEADER_IDENITFIER_LENGTH 8
#define MAX_PAM_HEADER_VALUE_LENGTH 255
/* PAM header fields */
typedef enum {
PAM_HEADER_NONE,
PAM_HEADER_COMMENT,
PAM_HEADER_ENDHDR,
PAM_HEADER_HEIGHT,
PAM_HEADER_WIDTH,
PAM_HEADER_DEPTH,
PAM_HEADER_MAXVAL,
PAM_HEADER_TUPLTYPE,
} PamHeaderFieldType;
struct pam_header_field {
PamHeaderFieldType type;
char identifier[MAX_PAM_HEADER_IDENITFIER_LENGTH+1];
};
const static struct pam_header_field fields[] = {
{PAM_HEADER_ENDHDR, "ENDHDR"},
{PAM_HEADER_HEIGHT, "HEIGHT"},
{PAM_HEADER_WIDTH, "WIDTH"},
{PAM_HEADER_DEPTH, "DEPTH"},
{PAM_HEADER_MAXVAL, "MAXVAL"},
{PAM_HEADER_TUPLTYPE, "TUPLTYPE"},
};
#define PAM_FIELDS_NO (sizeof (fields) / sizeof ((fields)[0]))
typedef bool (*cvtFunc) (void *src, void *target, int width, int target_channels,
int target_depth);
struct channel_layout {
uint rchan, gchan, bchan, graychan;
};
struct pam_format {
uint fmt;
char name[MAX_PAM_HEADER_VALUE_LENGTH+1];
cvtFunc cvt_func;
/* the channel layout that should be used when
* imread_ creates a 3 channel or 1 channel image
* used when no conversion function is available
*/
struct channel_layout layout;
};
static bool rgb_convert (void *src, void *target, int width, int target_channels,
int target_depth);
const static struct pam_format formats[] = {
{CV_IMWRITE_PAM_FORMAT_NULL, "", NULL, {0, 0, 0, 0} },
{CV_IMWRITE_PAM_FORMAT_BLACKANDWHITE, "BLACKANDWHITE", NULL, {0, 0, 0, 0} },
{CV_IMWRITE_PAM_FORMAT_GRAYSCALE, "GRAYSCALE", NULL, {0, 0, 0, 0} },
{CV_IMWRITE_PAM_FORMAT_GRAYSCALE_ALPHA, "GRAYSCALE_ALPHA", NULL, {0, 0, 0, 0} },
{CV_IMWRITE_PAM_FORMAT_RGB, "RGB", rgb_convert, {0, 1, 2, 0} },
{CV_IMWRITE_PAM_FORMAT_RGB_ALPHA, "RGB_ALPHA", NULL, {0, 1, 2, 0} },
};
#define PAM_FORMATS_NO (sizeof (fields) / sizeof ((fields)[0]))
/*
* conversion functions
*/
static bool
rgb_convert (void *src, void *target, int width, int target_channels, int target_depth)
{
bool ret = false;
if (target_channels == 3) {
switch (target_depth) {
case CV_8U:
icvCvt_RGB2BGR_8u_C3R( (uchar*) src, 0, (uchar*) target, 0,
Size(width,1) );
ret = true;
break;
case CV_16U:
icvCvt_RGB2BGR_16u_C3R( (ushort *)src, 0, (ushort *)target, 0,
Size(width,1) );
ret = true;
break;
default:
break;
}
} else if (target_channels == 1) {
switch (target_depth) {
case CV_8U:
icvCvt_BGR2Gray_8u_C3C1R( (uchar*) src, 0, (uchar*) target, 0,
Size(width,1), 2 );
ret = true;
break;
case CV_16U:
icvCvt_BGRA2Gray_16u_CnC1R( (ushort *)src, 0, (ushort *)target, 0,
Size(width,1), 3, 2 );
ret = true;
break;
default:
break;
}
}
return ret;
}
/*
* copy functions used as a fall back for undefined formats
* or simpler conversion options
*/
static void
basic_conversion (void *src, const struct channel_layout *layout, int src_sampe_size,
int src_width, void *target, int target_channels, int target_depth)
{
switch (target_depth) {
case CV_8U:
{
uchar *d = (uchar *)target, *s = (uchar *)src,
*end = ((uchar *)src) + src_width;
switch (target_channels) {
case 1:
for( ; s < end; d += 3, s += src_sampe_size )
d[0] = d[1] = d[2] = s[layout->graychan];
break;
case 3:
for( ; s < end; d += 3, s += src_sampe_size ) {
d[0] = s[layout->bchan];
d[1] = s[layout->gchan];
d[2] = s[layout->rchan];
}
break;
default:
CV_Error(Error::StsInternal, "");
}
break;
}
case CV_16U:
{
ushort *d = (ushort *)target, *s = (ushort *)src,
*end = ((ushort *)src) + src_width;
switch (target_channels) {
case 1:
for( ; s < end; d += 3, s += src_sampe_size )
d[0] = d[1] = d[2] = s[layout->graychan];
break;
case 3:
for( ; s < end; d += 3, s += src_sampe_size ) {
d[0] = s[layout->bchan];
d[1] = s[layout->gchan];
d[2] = s[layout->rchan];
}
break;
default:
CV_Error(Error::StsInternal, "");
}
break;
}
default:
CV_Error(Error::StsInternal, "");
}
}
static
bool ReadPAMHeaderLine(
cv::RLByteStream& strm,
CV_OUT PamHeaderFieldType &fieldtype,
CV_OUT char value[MAX_PAM_HEADER_VALUE_LENGTH+1])
{
int code;
char ident[MAX_PAM_HEADER_IDENITFIER_LENGTH+1] = {};
do {
code = strm.getByte();
} while ( isspace(code) );
if (code == '#') {
/* we are in a comment, eat characters until linebreak */
do
{
code = strm.getByte();
} while( code != '\n' && code != '\r' );
fieldtype = PAM_HEADER_COMMENT;
return true;
} else if (code == '\n' || code == '\r' ) {
fieldtype = PAM_HEADER_NONE;
return true;
}
int ident_sz = 0;
for (; ident_sz < MAX_PAM_HEADER_IDENITFIER_LENGTH; ident_sz++)
{
if (isspace(code))
break;
ident[ident_sz] = (char)code;
code = strm.getByte();
}
CV_DbgAssert(ident_sz <= MAX_PAM_HEADER_IDENITFIER_LENGTH);
ident[ident_sz] = 0;
/* we may have filled the buffer and still have data */
if (!isspace(code))
return false;
bool ident_found = false;
for (uint i = 0; i < PAM_FIELDS_NO; i++)
{
if (0 == strncmp(fields[i].identifier, ident, std::min(ident_sz, MAX_PAM_HEADER_IDENITFIER_LENGTH) + 1))
{
fieldtype = fields[i].type;
ident_found = true;
break;
}
}
if (!ident_found)
return false;
memset(value, 0, sizeof(char) * (MAX_PAM_HEADER_VALUE_LENGTH + 1));
/* we may have an identifier that has no value */
if (code == '\n' || code == '\r')
return true;
do {
code = strm.getByte();
} while (isspace(code));
/* read identifier value */
int value_sz = 0;
for (; value_sz < MAX_PAM_HEADER_VALUE_LENGTH; value_sz++)
{
if (code == '\n' || code == '\r')
break;
value[value_sz] = (char)code;
code = strm.getByte();
}
CV_DbgAssert(value_sz <= MAX_PAM_HEADER_VALUE_LENGTH);
value[value_sz] = 0;
int pos = value_sz;
/* should be terminated */
if (code != '\n' && code != '\r')
return false;
/* remove trailing white spaces */
while (--pos >= 0 && isspace(value[pos]))
value[pos] = 0;
return true;
}
static int ParseInt(const char *str, int len)
{
CV_Assert(len > 0);
int pos = 0;
bool is_negative = false;
if (str[0] == '-')
{
is_negative = true;
pos++;
CV_Assert(isdigit(str[pos]));
}
uint64_t number = 0;
while (pos < len && isdigit(str[pos]))
{
char ch = str[pos];
number = (number * 10) + (uint64_t)((int)ch - (int)'0');
CV_Assert(number < INT_MAX);
pos++;
}
if (pos < len)
CV_Assert(str[pos] == 0);
return (is_negative) ? -(int)number : (int)number;
}
PAMDecoder::PAMDecoder()
{
m_offset = -1;
m_buf_supported = true;
bit_mode = false;
selected_fmt = CV_IMWRITE_PAM_FORMAT_NULL;
m_maxval = 0;
m_channels = 0;
m_sampledepth = 0;
}
PAMDecoder::~PAMDecoder()
{
m_strm.close();
}
size_t PAMDecoder::signatureLength() const
{
return 3;
}
bool PAMDecoder::checkSignature( const String& signature ) const
{
return signature.size() >= 3 && signature[0] == 'P' &&
signature[1] == '7' &&
isspace(signature[2]);
}
ImageDecoder PAMDecoder::newDecoder() const
{
return makePtr<PAMDecoder>();
}
bool PAMDecoder::readHeader()
{
PamHeaderFieldType fieldtype = PAM_HEADER_NONE;
char value[MAX_PAM_HEADER_VALUE_LENGTH+1];
int byte;
if( !m_buf.empty() )
{
if( !m_strm.open(m_buf) )
return false;
}
else if( !m_strm.open( m_filename ))
return false;
try
{
byte = m_strm.getByte();
if( byte != 'P' )
throw RBS_BAD_HEADER;
byte = m_strm.getByte();
if (byte != '7')
throw RBS_BAD_HEADER;
byte = m_strm.getByte();
if (byte != '\n' && byte != '\r')
throw RBS_BAD_HEADER;
bool flds_endhdr = false, flds_height = false, flds_width = false, flds_depth = false, flds_maxval = false;
do {
if (!ReadPAMHeaderLine(m_strm, fieldtype, value))
throw RBS_BAD_HEADER;
switch (fieldtype)
{
case PAM_HEADER_NONE:
case PAM_HEADER_COMMENT:
continue;
case PAM_HEADER_ENDHDR:
flds_endhdr = true;
break;
case PAM_HEADER_HEIGHT:
if (flds_height)
throw RBS_BAD_HEADER;
m_height = ParseInt(value, MAX_PAM_HEADER_VALUE_LENGTH);
flds_height = true;
break;
case PAM_HEADER_WIDTH:
if (flds_width)
throw RBS_BAD_HEADER;
m_width = ParseInt(value, MAX_PAM_HEADER_VALUE_LENGTH);
flds_width = true;
break;
case PAM_HEADER_DEPTH:
if (flds_depth)
throw RBS_BAD_HEADER;
m_channels = ParseInt(value, MAX_PAM_HEADER_VALUE_LENGTH);
flds_depth = true;
break;
case PAM_HEADER_MAXVAL:
if (flds_maxval)
throw RBS_BAD_HEADER;
m_maxval = ParseInt(value, MAX_PAM_HEADER_VALUE_LENGTH);
if ( m_maxval > 65535 )
throw RBS_BAD_HEADER;
m_sampledepth = (m_maxval > 255) ? CV_16U : CV_8U;
if (m_maxval == 1)
bit_mode = true;
flds_maxval = true;
break;
case PAM_HEADER_TUPLTYPE:
{
bool format_found = false;
for (uint i=0; i<PAM_FORMATS_NO; i++)
{
if (0 == strncmp(formats[i].name, value, MAX_PAM_HEADER_VALUE_LENGTH+1))
{
selected_fmt = formats[i].fmt;
format_found = true;
break;
}
}
CV_Assert(format_found);
break;
}
default:
throw RBS_BAD_HEADER;
}
} while (fieldtype != PAM_HEADER_ENDHDR);
if (flds_endhdr && flds_height && flds_width && flds_depth && flds_maxval)
{
if (selected_fmt == CV_IMWRITE_PAM_FORMAT_NULL)
{
if (m_channels == 1 && m_maxval == 1)
selected_fmt = CV_IMWRITE_PAM_FORMAT_BLACKANDWHITE;
else if (m_channels == 1 && m_maxval < 256)
selected_fmt = CV_IMWRITE_PAM_FORMAT_GRAYSCALE;
else if (m_channels == 3 && m_maxval < 256)
selected_fmt = CV_IMWRITE_PAM_FORMAT_RGB;
}
m_type = CV_MAKETYPE(m_sampledepth, m_channels);
m_offset = m_strm.getPos();
return true;
}
// failed
m_offset = -1;
m_width = m_height = -1;
m_strm.close();
return false;
}
catch (...)
{
m_offset = -1;
m_width = m_height = -1;
m_strm.close();
throw;
}
}
bool PAMDecoder::readData(Mat& img)
{
uchar* data = img.ptr();
const int target_channels = img.channels();
size_t imp_stride = img.step;
const int sample_depth = CV_ELEM_SIZE1(m_type);
const int src_elems_per_row = m_width*m_channels;
const int src_stride = src_elems_per_row*sample_depth;
PaletteEntry palette[256] = {};
const struct pam_format *fmt = NULL;
struct channel_layout layout = { 0, 0, 0, 0 }; // normalized to 1-channel grey format
/* setting buffer to max data size so scaling up is possible */
AutoBuffer<uchar> _src(src_elems_per_row * 2);
uchar* src = _src.data();
if( m_offset < 0 || !m_strm.isOpened())
return false;
if (selected_fmt != CV_IMWRITE_PAM_FORMAT_NULL)
fmt = &formats[selected_fmt];
else {
/* default layout handling */
if (m_channels >= 3) {
layout.bchan = 0;
layout.gchan = 1;
layout.rchan = 2;
}
}
{
m_strm.setPos( m_offset );
/* the case where data fits the opencv matrix */
if (m_sampledepth == img.depth() && target_channels == m_channels && !bit_mode) {
/* special case for 16bit images with wrong endianness */
if (m_sampledepth == CV_16U && !isBigEndian())
{
for (int y = 0; y < m_height; y++, data += imp_stride)
{
m_strm.getBytes( src, src_stride );
for (int x = 0; x < src_elems_per_row; x++)
{
uchar v = src[x * 2];
data[x * 2] = src[x * 2 + 1];
data[x * 2 + 1] = v;
}
}
}
else {
m_strm.getBytes( data, src_stride * m_height );
}
}
else {
/* black and white mode */
if (bit_mode) {
if( target_channels == 1 )
{
uchar gray_palette[2] = {0, 255};
for (int y = 0; y < m_height; y++, data += imp_stride)
{
m_strm.getBytes( src, src_stride );
FillGrayRow1( data, src, m_width, gray_palette );
}
} else if ( target_channels == 3 )
{
FillGrayPalette( palette, 1 , false );
for (int y = 0; y < m_height; y++, data += imp_stride)
{
m_strm.getBytes( src, src_stride );
FillColorRow1( data, src, m_width, palette );
}
}
} else {
for (int y = 0; y < m_height; y++, data += imp_stride)
{
m_strm.getBytes( src, src_stride );
/* endianness correction */
if( m_sampledepth == CV_16U && !isBigEndian() )
{
for (int x = 0; x < src_elems_per_row; x++)
{
uchar v = src[x * 2];
src[x * 2] = src[x * 2 + 1];
src[x * 2 + 1] = v;
}
}
/* scale down */
if( img.depth() == CV_8U && m_sampledepth == CV_16U )
{
for (int x = 0; x < src_elems_per_row; x++)
{
int v = ((ushort *)src)[x];
src[x] = (uchar)(v >> 8);
}
}
/* if we are only scaling up/down then we can then copy the data */
if (target_channels == m_channels) {
memcpy (data, src, imp_stride);
}
/* perform correct conversion based on format */
else if (fmt) {
bool funcout = false;
if (fmt->cvt_func)
funcout = fmt->cvt_func (src, data, m_width, target_channels,
img.depth());
/* fall back to default if there is no conversion function or it
* can't handle the specified characteristics
*/
if (!funcout)
basic_conversion (src, &fmt->layout, m_channels,
m_width, data, target_channels, img.depth());
/* default to selecting the first available channels */
} else {
basic_conversion (src, &layout, m_channels,
m_width, data, target_channels, img.depth());
}
}
}
}
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////
PAMEncoder::PAMEncoder()
{
m_description = "Portable arbitrary format (*.pam)";
m_buf_supported = true;
}
PAMEncoder::~PAMEncoder()
{
}
ImageEncoder PAMEncoder::newEncoder() const
{
return makePtr<PAMEncoder>();
}
bool PAMEncoder::isFormatSupported( int depth ) const
{
return depth == CV_8U || depth == CV_16U;
}
bool PAMEncoder::write( const Mat& img, const std::vector<int>& params )
{
WLByteStream strm;
int width = img.cols, height = img.rows;
int stride = width*(int)img.elemSize();
const uchar* data = img.ptr();
const struct pam_format *fmt = NULL;
int x, y, tmp, bufsize = 256;
/* parse save file type */
for( size_t i = 0; i < params.size(); i += 2 )
if( params[i] == CV_IMWRITE_PAM_TUPLETYPE ) {
if ( params[i+1] > CV_IMWRITE_PAM_FORMAT_NULL &&
params[i+1] < (int) PAM_FORMATS_NO)
fmt = &formats[params[i+1]];
}
if( m_buf )
{
if( !strm.open(*m_buf) )
return false;
m_buf->reserve( alignSize(256 + stride*height, 256));
}
else if( !strm.open(m_filename) )
return false;
tmp = width * (int)img.elemSize();
if (bufsize < tmp)
bufsize = tmp;
AutoBuffer<char> _buffer(bufsize);
char* buffer = _buffer.data();
/* write header */
tmp = 0;
tmp += sprintf( buffer, "P7\n");
tmp += sprintf( buffer + tmp, "WIDTH %d\n", width);
tmp += sprintf( buffer + tmp, "HEIGHT %d\n", height);
tmp += sprintf( buffer + tmp, "DEPTH %d\n", img.channels());
tmp += sprintf( buffer + tmp, "MAXVAL %d\n", (1 << img.elemSize1()*8) - 1);
if (fmt)
tmp += sprintf( buffer + tmp, "TUPLTYPE %s\n", fmt->name );
sprintf( buffer + tmp, "ENDHDR\n" );
strm.putBytes( buffer, (int)strlen(buffer) );
/* write data */
if (img.depth() == CV_8U)
strm.putBytes( data, stride*height );
else if (img.depth() == CV_16U) {
/* fix endianness */
if (!isBigEndian()) {
for( y = 0; y < height; y++ ) {
memcpy( buffer, img.ptr(y), stride );
for( x = 0; x < stride; x += 2 )
{
uchar v = buffer[x];
buffer[x] = buffer[x + 1];
buffer[x + 1] = v;
}
strm.putBytes( buffer, stride );
}
} else
strm.putBytes( data, stride*height );
} else
CV_Error(Error::StsInternal, "");
strm.close();
return true;
}
}
#endif

View File

@@ -0,0 +1,103 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
// (3-clause BSD License)
//
// Copyright (C) 2000-2016, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved.
// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
// Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved.
// Copyright (C) 2015-2016, Itseez Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the names of the copyright holders nor the names of the contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall copyright holders or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//
//M*/
//Based on "imgcodecs/src/grfmt_pxm.hpp"
//Written by Dimitrios Katsaros <patcherwork@gmail.com>
#ifndef _OPENCV_PAM_HPP_
#define _OPENCV_PAM_HPP_
#ifdef HAVE_IMGCODEC_PXM
#include "grfmt_base.hpp"
#include "bitstrm.hpp"
namespace cv
{
class PAMDecoder CV_FINAL : public BaseImageDecoder
{
public:
PAMDecoder();
virtual ~PAMDecoder() CV_OVERRIDE;
bool readData( Mat& img ) CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
size_t signatureLength() const CV_OVERRIDE;
bool checkSignature( const String& signature ) const CV_OVERRIDE;
ImageDecoder newDecoder() const CV_OVERRIDE;
protected:
RLByteStream m_strm;
int m_maxval, m_channels, m_sampledepth, m_offset,
selected_fmt;
bool bit_mode;
};
class PAMEncoder CV_FINAL : public BaseImageEncoder
{
public:
PAMEncoder();
virtual ~PAMEncoder() CV_OVERRIDE;
bool isFormatSupported( int depth ) const CV_OVERRIDE;
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE;
};
}
#endif
#endif /* _OPENCV_PAM_HPP_ */

View File

@@ -0,0 +1,264 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
#include "utils.hpp"
#include "grfmt_pfm.hpp"
#include <iostream>
#ifdef HAVE_IMGCODEC_PFM
namespace {
static_assert(sizeof(float) == 4, "float must be 32 bit.");
bool is_byte_order_swapped(double scale)
{
// ".pfm" format file specifies that:
// positive scale means big endianness;
// negative scale means little endianness.
#ifdef WORDS_BIGENDIAN
return scale < 0.0;
#else
return scale >= 0.0;
#endif
}
void swap_endianess(uint32_t& ui)
{
static const uint32_t A(0x000000ffU);
static const uint32_t B(0x0000ff00U);
static const uint32_t C(0x00ff0000U);
static const uint32_t D(0xff000000U);
ui = ( (ui & A) << 24 )
| ( (ui & B) << 8 )
| ( (ui & C) >> 8 )
| ( (ui & D) >> 24 );
}
template<typename T> T atoT(const std::string& s);
template<> int atoT<int>(const std::string& s) { return std::atoi(s.c_str()); }
template<> double atoT<double>(const std::string& s) { return std::atof(s.c_str()); }
template<typename T>
T read_number(cv::RLByteStream& strm)
{
// should be enough to take string representation of any number
const size_t buffer_size = 2048;
std::vector<char> buffer(buffer_size, 0);
for (size_t i = 0; i < buffer_size; ++i) {
const int intc = strm.getByte();
CV_Assert(intc >= -128 && intc < 128);
char c = static_cast<char>(intc);
if (std::isspace(c)) {
break;
}
buffer[i] = c;
}
const std::string str(buffer.begin(), buffer.end());
return atoT<T>(str);
}
template<typename T> void write_anything(cv::WLByteStream& strm, const T& t)
{
std::ostringstream ss;
ss << t;
strm.putBytes(ss.str().c_str(), static_cast<int>(ss.str().size()));
}
}
namespace cv {
PFMDecoder::~PFMDecoder()
{
}
PFMDecoder::PFMDecoder() : m_scale_factor(0), m_swap_byte_order(false)
{
m_strm.close();
}
bool PFMDecoder::readHeader()
{
if (m_buf.empty()) {
if (!m_strm.open(m_filename)) {
return false;
}
} else {
if (!m_strm.open(m_buf)) {
return false;
}
}
if (m_strm.getByte() != 'P') {
CV_Error(Error::StsError, "Unexpected file type (expected P)");
}
switch (m_strm.getByte()) {
case 'f':
m_type = CV_32FC1;
break;
case 'F':
m_type = CV_32FC3;
break;
default:
CV_Error(Error::StsError, "Unexpected file type (expected `f` or `F`)");
}
if ('\n' != m_strm.getByte()) {
CV_Error(Error::StsError, "Unexpected header format (expected line break)");
}
m_width = read_number<int>(m_strm);
m_height = read_number<int>(m_strm);
m_scale_factor = read_number<double>(m_strm);
m_swap_byte_order = is_byte_order_swapped(m_scale_factor);
return true;
}
bool PFMDecoder::readData(Mat& mat)
{
if (!m_strm.isOpened()) {
CV_Error(Error::StsError, "Unexpected status in data stream");
}
Mat buffer(mat.size(), m_type);
for (int y = m_height - 1; y >= 0; --y) {
m_strm.getBytes(buffer.ptr(y), static_cast<int>(m_width * buffer.elemSize()));
if (is_byte_order_swapped(m_scale_factor)) {
for (int i = 0; i < m_width * buffer.channels(); ++i) {
static_assert( sizeof(uint32_t) == sizeof(float),
"uint32_t and float must have same size." );
swap_endianess(buffer.ptr<uint32_t>(y)[i]);
}
}
}
if (buffer.channels() == 3) {
cv::cvtColor(buffer, buffer, cv::COLOR_BGR2RGB);
}
CV_Assert(fabs(m_scale_factor) > 0.0f);
buffer *= 1.f / fabs(m_scale_factor);
buffer.convertTo(mat, mat.type());
return true;
}
size_t PFMDecoder::signatureLength() const
{
return 3;
}
bool PFMDecoder::checkSignature( const String& signature ) const
{
return signature.size() >= 3
&& signature[0] == 'P'
&& ( signature[1] == 'f' || signature[1] == 'F' )
&& isspace(signature[2]);
}
void PFMDecoder::close()
{
// noop
}
//////////////////////////////////////////////////////////////////////////////////////////
PFMEncoder::PFMEncoder()
{
m_description = "Portable image format - float (*.pfm)";
}
PFMEncoder::~PFMEncoder()
{
}
bool PFMEncoder::isFormatSupported(int depth) const
{
// any depth will be converted into 32-bit float.
CV_UNUSED(depth);
return true;
}
bool PFMEncoder::write(const Mat& img, const std::vector<int>& params)
{
CV_UNUSED(params);
WLByteStream strm;
if (m_buf) {
if (!strm.open(*m_buf)) {
return false;
} else {
m_buf->reserve(alignSize(256 + sizeof(float) * img.channels() * img.total(), 256));
}
} else if (!strm.open(m_filename)) {
return false;
}
Mat float_img;
strm.putByte('P');
switch (img.channels()) {
case 1:
strm.putByte('f');
img.convertTo(float_img, CV_32FC1);
break;
case 3:
strm.putByte('F');
img.convertTo(float_img, CV_32FC3);
break;
default:
CV_Error(Error::StsBadArg, "Expected 1 or 3 channel image.");
}
strm.putByte('\n');
write_anything(strm, float_img.cols);
strm.putByte(' ');
write_anything(strm, float_img.rows);
strm.putByte('\n');
#ifdef WORDS_BIGENDIAN
write_anything(strm, 1.0);
#else
write_anything(strm, -1.0);
#endif
strm.putByte('\n');
// Comments are not officially supported in this file format.
// write_anything(strm, "# Generated by OpenCV " CV_VERSION "\n");
for (int y = float_img.rows - 1; y >= 0; --y)
{
if (float_img.channels() == 3) {
const float* bgr_row = float_img.ptr<float>(y);
size_t row_size = float_img.cols * float_img.channels();
std::vector<float> rgb_row(row_size);
for (int x = 0; x < float_img.cols; ++x) {
rgb_row[x*3+0] = bgr_row[x*3+2];
rgb_row[x*3+1] = bgr_row[x*3+1];
rgb_row[x*3+2] = bgr_row[x*3+0];
}
strm.putBytes( reinterpret_cast<const uchar*>(rgb_row.data()),
static_cast<int>(sizeof(float) * row_size) );
} else if (float_img.channels() == 1) {
strm.putBytes(float_img.ptr(y), sizeof(float) * float_img.cols);
}
}
return true;
}
}
#endif // HAVE_IMGCODEC_PFM

View File

@@ -0,0 +1,57 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef _GRFMT_PFM_H_
#define _GRFMT_PFM_H_
#include "grfmt_base.hpp"
#include "bitstrm.hpp"
#ifdef HAVE_IMGCODEC_PFM
namespace cv
{
class PFMDecoder CV_FINAL : public BaseImageDecoder
{
public:
PFMDecoder();
virtual ~PFMDecoder() CV_OVERRIDE;
bool readData( Mat& img ) CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
void close();
size_t signatureLength() const CV_OVERRIDE;
bool checkSignature( const String& signature ) const CV_OVERRIDE;
ImageDecoder newDecoder() const CV_OVERRIDE
{
return makePtr<PFMDecoder>();
}
private:
RLByteStream m_strm;
double m_scale_factor;
bool m_swap_byte_order;
};
class PFMEncoder CV_FINAL : public BaseImageEncoder
{
public:
PFMEncoder();
virtual ~PFMEncoder() CV_OVERRIDE;
bool isFormatSupported( int depth ) const CV_OVERRIDE;
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE
{
return makePtr<PFMEncoder>();
}
};
}
#endif // HAVE_IMGCODEC_PXM
#endif/*_GRFMT_PFM_H_*/

View File

@@ -0,0 +1,448 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#ifdef HAVE_PNG
/****************************************************************************************\
This part of the file implements PNG codec on base of libpng library,
in particular, this code is based on example.c from libpng
(see otherlibs/_graphics/readme.txt for copyright notice)
and png2bmp sample from libpng distribution (Copyright (C) 1999-2001 MIYASAKA Masaru)
\****************************************************************************************/
#ifndef _LFS64_LARGEFILE
# define _LFS64_LARGEFILE 0
#endif
#ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 0
#endif
#ifdef HAVE_LIBPNG_PNG_H
#include <libpng/png.h>
#else
#include <png.h>
#endif
#include <zlib.h>
#include "grfmt_png.hpp"
#if defined _MSC_VER && _MSC_VER >= 1200
// interaction between '_setjmp' and C++ object destruction is non-portable
#pragma warning( disable: 4611 )
#endif
// the following defines are a hack to avoid multiple problems with frame pointer handling and setjmp
// see http://gcc.gnu.org/ml/gcc/2011-10/msg00324.html for some details
#define mingw_getsp(...) 0
#define __builtin_frame_address(...) 0
namespace cv
{
/////////////////////// PngDecoder ///////////////////
PngDecoder::PngDecoder()
{
m_signature = "\x89\x50\x4e\x47\xd\xa\x1a\xa";
m_color_type = 0;
m_png_ptr = 0;
m_info_ptr = m_end_info = 0;
m_f = 0;
m_buf_supported = true;
m_buf_pos = 0;
m_bit_depth = 0;
}
PngDecoder::~PngDecoder()
{
close();
}
ImageDecoder PngDecoder::newDecoder() const
{
return makePtr<PngDecoder>();
}
void PngDecoder::close()
{
if( m_f )
{
fclose( m_f );
m_f = 0;
}
if( m_png_ptr )
{
png_structp png_ptr = (png_structp)m_png_ptr;
png_infop info_ptr = (png_infop)m_info_ptr;
png_infop end_info = (png_infop)m_end_info;
png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
m_png_ptr = m_info_ptr = m_end_info = 0;
}
}
void PngDecoder::readDataFromBuf( void* _png_ptr, uchar* dst, size_t size )
{
png_structp png_ptr = (png_structp)_png_ptr;
PngDecoder* decoder = (PngDecoder*)(png_get_io_ptr(png_ptr));
CV_Assert( decoder );
const Mat& buf = decoder->m_buf;
if( decoder->m_buf_pos + size > buf.cols*buf.rows*buf.elemSize() )
{
png_error(png_ptr, "PNG input buffer is incomplete");
return;
}
memcpy( dst, decoder->m_buf.ptr() + decoder->m_buf_pos, size );
decoder->m_buf_pos += size;
}
bool PngDecoder::readHeader()
{
volatile bool result = false;
close();
png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
if( png_ptr )
{
png_infop info_ptr = png_create_info_struct( png_ptr );
png_infop end_info = png_create_info_struct( png_ptr );
m_png_ptr = png_ptr;
m_info_ptr = info_ptr;
m_end_info = end_info;
m_buf_pos = 0;
if( info_ptr && end_info )
{
if( setjmp( png_jmpbuf( png_ptr ) ) == 0 )
{
if( !m_buf.empty() )
png_set_read_fn(png_ptr, this, (png_rw_ptr)readDataFromBuf );
else
{
m_f = fopen( m_filename.c_str(), "rb" );
if( m_f )
png_init_io( png_ptr, m_f );
}
if( !m_buf.empty() || m_f )
{
png_uint_32 wdth, hght;
int bit_depth, color_type, num_trans=0;
png_bytep trans;
png_color_16p trans_values;
png_read_info( png_ptr, info_ptr );
png_get_IHDR( png_ptr, info_ptr, &wdth, &hght,
&bit_depth, &color_type, 0, 0, 0 );
m_width = (int)wdth;
m_height = (int)hght;
m_color_type = color_type;
m_bit_depth = bit_depth;
if( bit_depth <= 8 || bit_depth == 16 )
{
switch(color_type)
{
case PNG_COLOR_TYPE_RGB:
case PNG_COLOR_TYPE_PALETTE:
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values);
if( num_trans > 0 )
m_type = CV_8UC4;
else
m_type = CV_8UC3;
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
case PNG_COLOR_TYPE_RGB_ALPHA:
m_type = CV_8UC4;
break;
default:
m_type = CV_8UC1;
}
if( bit_depth == 16 )
m_type = CV_MAKETYPE(CV_16U, CV_MAT_CN(m_type));
result = true;
}
}
}
}
}
if( !result )
close();
return result;
}
bool PngDecoder::readData( Mat& img )
{
volatile bool result = false;
AutoBuffer<uchar*> _buffer(m_height);
uchar** buffer = _buffer.data();
bool color = img.channels() > 1;
png_structp png_ptr = (png_structp)m_png_ptr;
png_infop info_ptr = (png_infop)m_info_ptr;
png_infop end_info = (png_infop)m_end_info;
if( m_png_ptr && m_info_ptr && m_end_info && m_width && m_height )
{
if( setjmp( png_jmpbuf ( png_ptr ) ) == 0 )
{
int y;
if( img.depth() == CV_8U && m_bit_depth == 16 )
png_set_strip_16( png_ptr );
else if( !isBigEndian() )
png_set_swap( png_ptr );
if(img.channels() < 4)
{
/* observation: png_read_image() writes 400 bytes beyond
* end of data when reading a 400x118 color png
* "mpplus_sand.png". OpenCV crashes even with demo
* programs. Looking at the loaded image I'd say we get 4
* bytes per pixel instead of 3 bytes per pixel. Test
* indicate that it is a good idea to always ask for
* stripping alpha.. 18.11.2004 Axel Walthelm
*/
png_set_strip_alpha( png_ptr );
} else
png_set_tRNS_to_alpha( png_ptr );
if( m_color_type == PNG_COLOR_TYPE_PALETTE )
png_set_palette_to_rgb( png_ptr );
if( (m_color_type & PNG_COLOR_MASK_COLOR) == 0 && m_bit_depth < 8 )
#if (PNG_LIBPNG_VER_MAJOR*10000 + PNG_LIBPNG_VER_MINOR*100 + PNG_LIBPNG_VER_RELEASE >= 10209) || \
(PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR == 0 && PNG_LIBPNG_VER_RELEASE >= 18)
png_set_expand_gray_1_2_4_to_8( png_ptr );
#else
png_set_gray_1_2_4_to_8( png_ptr );
#endif
if( (m_color_type & PNG_COLOR_MASK_COLOR) && color )
png_set_bgr( png_ptr ); // convert RGB to BGR
else if( color )
png_set_gray_to_rgb( png_ptr ); // Gray->RGB
else
png_set_rgb_to_gray( png_ptr, 1, 0.299, 0.587 ); // RGB->Gray
png_set_interlace_handling( png_ptr );
png_read_update_info( png_ptr, info_ptr );
for( y = 0; y < m_height; y++ )
buffer[y] = img.data + y*img.step;
png_read_image( png_ptr, buffer );
png_read_end( png_ptr, end_info );
result = true;
}
}
close();
return result;
}
/////////////////////// PngEncoder ///////////////////
PngEncoder::PngEncoder()
{
m_description = "Portable Network Graphics files (*.png)";
m_buf_supported = true;
}
PngEncoder::~PngEncoder()
{
}
bool PngEncoder::isFormatSupported( int depth ) const
{
return depth == CV_8U || depth == CV_16U;
}
ImageEncoder PngEncoder::newEncoder() const
{
return makePtr<PngEncoder>();
}
void PngEncoder::writeDataToBuf(void* _png_ptr, uchar* src, size_t size)
{
if( size == 0 )
return;
png_structp png_ptr = (png_structp)_png_ptr;
PngEncoder* encoder = (PngEncoder*)(png_get_io_ptr(png_ptr));
CV_Assert( encoder && encoder->m_buf );
size_t cursz = encoder->m_buf->size();
encoder->m_buf->resize(cursz + size);
memcpy( &(*encoder->m_buf)[cursz], src, size );
}
void PngEncoder::flushBuf(void*)
{
}
bool PngEncoder::write( const Mat& img, const std::vector<int>& params )
{
png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
png_infop info_ptr = 0;
FILE * volatile f = 0;
int y, width = img.cols, height = img.rows;
int depth = img.depth(), channels = img.channels();
volatile bool result = false;
AutoBuffer<uchar*> buffer;
if( depth != CV_8U && depth != CV_16U )
return false;
if( png_ptr )
{
info_ptr = png_create_info_struct( png_ptr );
if( info_ptr )
{
if( setjmp( png_jmpbuf ( png_ptr ) ) == 0 )
{
if( m_buf )
{
png_set_write_fn(png_ptr, this,
(png_rw_ptr)writeDataToBuf, (png_flush_ptr)flushBuf);
}
else
{
f = fopen( m_filename.c_str(), "wb" );
if( f )
png_init_io( png_ptr, (png_FILE_p)f );
}
int compression_level = -1; // Invalid value to allow setting 0-9 as valid
int compression_strategy = IMWRITE_PNG_STRATEGY_RLE; // Default strategy
bool isBilevel = false;
for( size_t i = 0; i < params.size(); i += 2 )
{
if( params[i] == IMWRITE_PNG_COMPRESSION )
{
compression_strategy = IMWRITE_PNG_STRATEGY_DEFAULT; // Default strategy
compression_level = params[i+1];
compression_level = MIN(MAX(compression_level, 0), Z_BEST_COMPRESSION);
}
if( params[i] == IMWRITE_PNG_STRATEGY )
{
compression_strategy = params[i+1];
compression_strategy = MIN(MAX(compression_strategy, 0), Z_FIXED);
}
if( params[i] == IMWRITE_PNG_BILEVEL )
{
isBilevel = params[i+1] != 0;
}
}
if( m_buf || f )
{
if( compression_level >= 0 )
{
png_set_compression_level( png_ptr, compression_level );
}
else
{
// tune parameters for speed
// (see http://wiki.linuxquestions.org/wiki/Libpng)
png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_SUB);
png_set_compression_level(png_ptr, Z_BEST_SPEED);
}
png_set_compression_strategy(png_ptr, compression_strategy);
png_set_IHDR( png_ptr, info_ptr, width, height, depth == CV_8U ? isBilevel?1:8 : 16,
channels == 1 ? PNG_COLOR_TYPE_GRAY :
channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT );
png_write_info( png_ptr, info_ptr );
if (isBilevel)
png_set_packing(png_ptr);
png_set_bgr( png_ptr );
if( !isBigEndian() )
png_set_swap( png_ptr );
buffer.allocate(height);
for( y = 0; y < height; y++ )
buffer[y] = img.data + y*img.step;
png_write_image( png_ptr, buffer.data() );
png_write_end( png_ptr, info_ptr );
result = true;
}
}
}
}
png_destroy_write_struct( &png_ptr, &info_ptr );
if(f) fclose( (FILE*)f );
return result;
}
}
#endif
/* End of file. */

View File

@@ -0,0 +1,101 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_PNG_H_
#define _GRFMT_PNG_H_
#ifdef HAVE_PNG
#include "grfmt_base.hpp"
#include "bitstrm.hpp"
namespace cv
{
class PngDecoder CV_FINAL : public BaseImageDecoder
{
public:
PngDecoder();
virtual ~PngDecoder();
bool readData( Mat& img ) CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
void close();
ImageDecoder newDecoder() const CV_OVERRIDE;
protected:
static void readDataFromBuf(void* png_ptr, uchar* dst, size_t size);
int m_bit_depth;
void* m_png_ptr; // pointer to decompression structure
void* m_info_ptr; // pointer to image information structure
void* m_end_info; // pointer to one more image information structure
FILE* m_f;
int m_color_type;
size_t m_buf_pos;
};
class PngEncoder CV_FINAL : public BaseImageEncoder
{
public:
PngEncoder();
virtual ~PngEncoder();
bool isFormatSupported( int depth ) const CV_OVERRIDE;
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE;
protected:
static void writeDataToBuf(void* png_ptr, uchar* src, size_t size);
static void flushBuf(void* png_ptr);
};
}
#endif
#endif/*_GRFMT_PNG_H_*/

View File

@@ -0,0 +1,623 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "utils.hpp"
#include "grfmt_pxm.hpp"
#include <iostream>
#ifdef HAVE_IMGCODEC_PXM
namespace cv
{
///////////////////////// P?M reader //////////////////////////////
static int ReadNumber(RLByteStream& strm, int maxdigits = 0)
{
int code;
int64 val = 0;
int digits = 0;
code = strm.getByte();
while (!isdigit(code))
{
if (code == '#' )
{
do
{
code = strm.getByte();
}
while (code != '\n' && code != '\r');
code = strm.getByte();
}
else if (isspace(code))
{
while (isspace(code))
code = strm.getByte();
}
else
{
#if 1
CV_Error_(Error::StsError, ("PXM: Unexpected code in ReadNumber(): 0x%x (%d)", code, code));
#else
code = strm.getByte();
#endif
}
}
do
{
val = val*10 + (code - '0');
CV_Assert(val <= INT_MAX && "PXM: ReadNumber(): result is too large");
digits++;
if (maxdigits != 0 && digits >= maxdigits) break;
code = strm.getByte();
}
while (isdigit(code));
return (int)val;
}
PxMDecoder::PxMDecoder()
{
m_offset = -1;
m_buf_supported = true;
m_bpp = 0;
m_binary = false;
m_maxval = 0;
}
PxMDecoder::~PxMDecoder()
{
close();
}
size_t PxMDecoder::signatureLength() const
{
return 3;
}
bool PxMDecoder::checkSignature( const String& signature ) const
{
return signature.size() >= 3 && signature[0] == 'P' &&
'1' <= signature[1] && signature[1] <= '6' &&
isspace(signature[2]);
}
ImageDecoder PxMDecoder::newDecoder() const
{
return makePtr<PxMDecoder>();
}
void PxMDecoder::close()
{
m_strm.close();
}
bool PxMDecoder::readHeader()
{
bool result = false;
if( !m_buf.empty() )
{
if( !m_strm.open(m_buf) )
return false;
}
else if( !m_strm.open( m_filename ))
return false;
try
{
int code = m_strm.getByte();
if( code != 'P' )
throw RBS_BAD_HEADER;
code = m_strm.getByte();
switch( code )
{
case '1': case '4': m_bpp = 1; break;
case '2': case '5': m_bpp = 8; break;
case '3': case '6': m_bpp = 24; break;
default: throw RBS_BAD_HEADER;
}
m_binary = code >= '4';
m_type = m_bpp > 8 ? CV_8UC3 : CV_8UC1;
m_width = ReadNumber(m_strm);
m_height = ReadNumber(m_strm);
m_maxval = m_bpp == 1 ? 1 : ReadNumber(m_strm);
if( m_maxval > 65535 )
throw RBS_BAD_HEADER;
//if( m_maxval > 255 ) m_binary = false; nonsense
if( m_maxval > 255 )
m_type = CV_MAKETYPE(CV_16U, CV_MAT_CN(m_type));
if( m_width > 0 && m_height > 0 && m_maxval > 0 && m_maxval < (1 << 16))
{
m_offset = m_strm.getPos();
result = true;
}
}
catch (const cv::Exception&)
{
throw;
}
catch (...)
{
std::cerr << "PXM::readHeader(): unknown C++ exception" << std::endl << std::flush;
throw;
}
if( !result )
{
m_offset = -1;
m_width = m_height = -1;
m_strm.close();
}
return result;
}
bool PxMDecoder::readData( Mat& img )
{
bool color = img.channels() > 1;
uchar* data = img.ptr();
PaletteEntry palette[256];
bool result = false;
const int bit_depth = CV_ELEM_SIZE1(m_type)*8;
const int src_pitch = divUp(m_width*m_bpp*(bit_depth/8), 8);
int nch = CV_MAT_CN(m_type);
int width3 = m_width*nch;
if( m_offset < 0 || !m_strm.isOpened())
return false;
uchar gray_palette[256] = {0};
// create LUT for converting colors
if( bit_depth == 8 )
{
CV_Assert(m_maxval < 256 && m_maxval > 0);
for (int i = 0; i <= m_maxval; i++)
gray_palette[i] = (uchar)((i*255/m_maxval)^(m_bpp == 1 ? 255 : 0));
FillGrayPalette( palette, m_bpp==1 ? 1 : 8 , m_bpp == 1 );
}
try
{
m_strm.setPos( m_offset );
switch( m_bpp )
{
////////////////////////// 1 BPP /////////////////////////
case 1:
CV_Assert(CV_MAT_DEPTH(m_type) == CV_8U);
if( !m_binary )
{
AutoBuffer<uchar> _src(m_width);
uchar* src = _src.data();
for (int y = 0; y < m_height; y++, data += img.step)
{
for (int x = 0; x < m_width; x++)
src[x] = ReadNumber(m_strm, 1) != 0;
if( color )
FillColorRow8( data, src, m_width, palette );
else
FillGrayRow8( data, src, m_width, gray_palette );
}
}
else
{
AutoBuffer<uchar> _src(src_pitch);
uchar* src = _src.data();
for (int y = 0; y < m_height; y++, data += img.step)
{
m_strm.getBytes( src, src_pitch );
if( color )
FillColorRow1( data, src, m_width, palette );
else
FillGrayRow1( data, src, m_width, gray_palette );
}
}
result = true;
break;
////////////////////////// 8 BPP /////////////////////////
case 8:
case 24:
{
AutoBuffer<uchar> _src(std::max<size_t>(width3*2, src_pitch));
uchar* src = _src.data();
for (int y = 0; y < m_height; y++, data += img.step)
{
if( !m_binary )
{
for (int x = 0; x < width3; x++)
{
int code = ReadNumber(m_strm);
if( (unsigned)code > (unsigned)m_maxval ) code = m_maxval;
if( bit_depth == 8 )
src[x] = gray_palette[code];
else
((ushort *)src)[x] = (ushort)code;
}
}
else
{
m_strm.getBytes( src, src_pitch );
if( bit_depth == 16 && !isBigEndian() )
{
for (int x = 0; x < width3; x++)
{
uchar v = src[x * 2];
src[x * 2] = src[x * 2 + 1];
src[x * 2 + 1] = v;
}
}
}
if( img.depth() == CV_8U && bit_depth == 16 )
{
for (int x = 0; x < width3; x++)
{
int v = ((ushort *)src)[x];
src[x] = (uchar)(v >> 8);
}
}
if( m_bpp == 8 ) // image has one channel
{
if( color )
{
if( img.depth() == CV_8U ) {
uchar *d = data, *s = src, *end = src + m_width;
for( ; s < end; d += 3, s++)
d[0] = d[1] = d[2] = *s;
} else {
ushort *d = (ushort *)data, *s = (ushort *)src, *end = ((ushort *)src) + m_width;
for( ; s < end; s++, d += 3)
d[0] = d[1] = d[2] = *s;
}
}
else
memcpy(data, src, img.elemSize1()*m_width);
}
else
{
if( color )
{
if( img.depth() == CV_8U )
icvCvt_RGB2BGR_8u_C3R( src, 0, data, 0, Size(m_width,1) );
else
icvCvt_RGB2BGR_16u_C3R( (ushort *)src, 0, (ushort *)data, 0, Size(m_width,1) );
}
else if( img.depth() == CV_8U )
icvCvt_BGR2Gray_8u_C3C1R( src, 0, data, 0, Size(m_width,1), 2 );
else
icvCvt_BGRA2Gray_16u_CnC1R( (ushort *)src, 0, (ushort *)data, 0, Size(m_width,1), 3, 2 );
}
}
result = true;
break;
}
default:
CV_Error(Error::StsError, "m_bpp is not supported");
}
}
catch (const cv::Exception&)
{
throw;
}
catch (...)
{
std::cerr << "PXM::readData(): unknown exception" << std::endl << std::flush;
throw;
}
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////
PxMEncoder::PxMEncoder(PxMMode mode) :
mode_(mode)
{
switch (mode)
{
case PXM_TYPE_AUTO: m_description = "Portable image format - auto (*.pnm)"; break;
case PXM_TYPE_PBM: m_description = "Portable image format - monochrome (*.pbm)"; break;
case PXM_TYPE_PGM: m_description = "Portable image format - gray (*.pgm)"; break;
case PXM_TYPE_PPM: m_description = "Portable image format - color (*.ppm)"; break;
default:
CV_Error(Error::StsInternal, "");
}
m_buf_supported = true;
}
PxMEncoder::~PxMEncoder()
{
}
bool PxMEncoder::isFormatSupported(int depth) const
{
if (mode_ == PXM_TYPE_PBM)
return depth == CV_8U;
return depth == CV_8U || depth == CV_16U;
}
bool PxMEncoder::write(const Mat& img, const std::vector<int>& params)
{
bool isBinary = true;
int width = img.cols, height = img.rows;
int _channels = img.channels(), depth = (int)img.elemSize1()*8;
int channels = _channels > 1 ? 3 : 1;
int fileStep = width*(int)img.elemSize();
int x, y;
for( size_t i = 0; i < params.size(); i += 2 )
{
if( params[i] == IMWRITE_PXM_BINARY )
isBinary = params[i+1] != 0;
}
int mode = mode_;
if (mode == PXM_TYPE_AUTO)
{
mode = img.channels() == 1 ? PXM_TYPE_PGM : PXM_TYPE_PPM;
}
if (mode == PXM_TYPE_PGM && img.channels() > 1)
{
CV_Error(Error::StsBadArg, "Portable bitmap(.pgm) expects gray image");
}
if (mode == PXM_TYPE_PPM && img.channels() != 3)
{
CV_Error(Error::StsBadArg, "Portable bitmap(.ppm) expects BGR image");
}
if (mode == PXM_TYPE_PBM && img.type() != CV_8UC1)
{
CV_Error(Error::StsBadArg, "For portable bitmap(.pbm) type must be CV_8UC1");
}
WLByteStream strm;
if( m_buf )
{
if( !strm.open(*m_buf) )
return false;
int t = CV_MAKETYPE(img.depth(), channels);
m_buf->reserve( alignSize(256 + (isBinary ? fileStep*height :
((t == CV_8UC1 ? 4 : t == CV_8UC3 ? 4*3+2 :
t == CV_16UC1 ? 6 : 6*3+2)*width+1)*height), 256));
}
else if( !strm.open(m_filename) )
return false;
int lineLength;
int bufferSize = 128; // buffer that should fit a header
if( isBinary )
lineLength = width * (int)img.elemSize();
else
lineLength = (6 * channels + (channels > 1 ? 2 : 0)) * width + 32;
if( bufferSize < lineLength )
bufferSize = lineLength;
AutoBuffer<char> _buffer(bufferSize);
char* buffer = _buffer.data();
// write header;
const int code = ((mode == PXM_TYPE_PBM) ? 1 : (mode == PXM_TYPE_PGM) ? 2 : 3)
+ (isBinary ? 3 : 0);
const char* comment = "# Generated by OpenCV " CV_VERSION "\n";
int header_sz = sprintf(buffer, "P%c\n%s%d %d\n",
(char)('0' + code), comment,
width, height);
CV_Assert(header_sz > 0);
if (mode != PXM_TYPE_PBM)
{
int sz = sprintf(&buffer[header_sz], "%d\n", (1 << depth) - 1);
CV_Assert(sz > 0);
header_sz += sz;
}
strm.putBytes(buffer, header_sz);
for( y = 0; y < height; y++ )
{
const uchar* const data = img.ptr(y);
if( isBinary )
{
if (mode == PXM_TYPE_PBM)
{
char* ptr = buffer;
int bcount = 7;
char byte = 0;
for (x = 0; x < width; x++)
{
if (bcount == 0)
{
if (data[x] == 0)
byte = (byte) | 1;
*ptr++ = byte;
bcount = 7;
byte = 0;
}
else
{
if (data[x] == 0)
byte = (byte) | (1 << bcount);
bcount--;
}
}
if (bcount != 7)
{
*ptr++ = byte;
}
strm.putBytes(buffer, (int)(ptr - buffer));
continue;
}
if( _channels == 3 )
{
if( depth == 8 )
icvCvt_BGR2RGB_8u_C3R( (const uchar*)data, 0,
(uchar*)buffer, 0, Size(width,1) );
else
icvCvt_BGR2RGB_16u_C3R( (const ushort*)data, 0,
(ushort*)buffer, 0, Size(width,1) );
}
// swap endianness if necessary
if( depth == 16 && !isBigEndian() )
{
if( _channels == 1 )
memcpy( buffer, data, fileStep );
for( x = 0; x < width*channels*2; x += 2 )
{
uchar v = buffer[x];
buffer[x] = buffer[x + 1];
buffer[x + 1] = v;
}
}
strm.putBytes( (channels > 1 || depth > 8) ? buffer : (const char*)data, fileStep);
}
else
{
char* ptr = buffer;
if (mode == PXM_TYPE_PBM)
{
CV_Assert(channels == 1);
CV_Assert(depth == 8);
for (x = 0; x < width; x++)
{
ptr[0] = data[x] ? '0' : '1';
ptr += 1;
}
}
else
{
if( channels > 1 )
{
if( depth == 8 )
{
for( x = 0; x < width*channels; x += channels )
{
sprintf( ptr, "% 4d", data[x + 2] );
ptr += 4;
sprintf( ptr, "% 4d", data[x + 1] );
ptr += 4;
sprintf( ptr, "% 4d", data[x] );
ptr += 4;
*ptr++ = ' ';
*ptr++ = ' ';
}
}
else
{
for( x = 0; x < width*channels; x += channels )
{
sprintf( ptr, "% 6d", ((const ushort *)data)[x + 2] );
ptr += 6;
sprintf( ptr, "% 6d", ((const ushort *)data)[x + 1] );
ptr += 6;
sprintf( ptr, "% 6d", ((const ushort *)data)[x] );
ptr += 6;
*ptr++ = ' ';
*ptr++ = ' ';
}
}
}
else
{
if( depth == 8 )
{
for( x = 0; x < width; x++ )
{
sprintf( ptr, "% 4d", data[x] );
ptr += 4;
}
}
else
{
for( x = 0; x < width; x++ )
{
sprintf( ptr, "% 6d", ((const ushort *)data)[x] );
ptr += 6;
}
}
}
}
*ptr++ = '\n';
strm.putBytes( buffer, (int)(ptr - buffer) );
}
}
strm.close();
return true;
}
}
#endif // HAVE_IMGCODEC_PXM

View File

@@ -0,0 +1,108 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_PxM_H_
#define _GRFMT_PxM_H_
#include "grfmt_base.hpp"
#include "bitstrm.hpp"
#ifdef HAVE_IMGCODEC_PXM
namespace cv
{
enum PxMMode
{
PXM_TYPE_AUTO = 0, // "auto"
PXM_TYPE_PBM = 1, // monochrome format (single channel)
PXM_TYPE_PGM = 2, // gray format (single channel)
PXM_TYPE_PPM = 3 // color format
};
class PxMDecoder CV_FINAL : public BaseImageDecoder
{
public:
PxMDecoder();
virtual ~PxMDecoder() CV_OVERRIDE;
bool readData( Mat& img ) CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
void close();
size_t signatureLength() const CV_OVERRIDE;
bool checkSignature( const String& signature ) const CV_OVERRIDE;
ImageDecoder newDecoder() const CV_OVERRIDE;
protected:
RLByteStream m_strm;
PaletteEntry m_palette[256];
int m_bpp;
int m_offset;
bool m_binary;
int m_maxval;
};
class PxMEncoder CV_FINAL : public BaseImageEncoder
{
public:
PxMEncoder(PxMMode mode);
virtual ~PxMEncoder() CV_OVERRIDE;
bool isFormatSupported( int depth ) const CV_OVERRIDE;
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE
{
return makePtr<PxMEncoder>(mode_);
}
const PxMMode mode_;
};
}
#endif // HAVE_IMGCODEC_PXM
#endif/*_GRFMT_PxM_H_*/

View File

@@ -0,0 +1,433 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "grfmt_sunras.hpp"
#ifdef HAVE_IMGCODEC_SUNRASTER
namespace cv
{
static const char* fmtSignSunRas = "\x59\xA6\x6A\x95";
/************************ Sun Raster reader *****************************/
SunRasterDecoder::SunRasterDecoder()
{
m_offset = -1;
m_signature = fmtSignSunRas;
m_bpp = 0;
m_encoding = RAS_STANDARD;
m_maptype = RMT_NONE;
m_maplength = 0;
}
SunRasterDecoder::~SunRasterDecoder()
{
}
ImageDecoder SunRasterDecoder::newDecoder() const
{
return makePtr<SunRasterDecoder>();
}
void SunRasterDecoder::close()
{
m_strm.close();
}
bool SunRasterDecoder::readHeader()
{
bool result = false;
if( !m_strm.open( m_filename )) return false;
try
{
m_strm.skip( 4 );
m_width = m_strm.getDWord();
m_height = m_strm.getDWord();
m_bpp = m_strm.getDWord();
int palSize = (m_bpp > 0 && m_bpp <= 8) ? (3*(1 << m_bpp)) : 0;
m_strm.skip( 4 );
m_encoding = (SunRasType)m_strm.getDWord();
m_maptype = (SunRasMapType)m_strm.getDWord();
m_maplength = m_strm.getDWord();
if( m_width > 0 && m_height > 0 &&
(m_bpp == 1 || m_bpp == 8 || m_bpp == 24 || m_bpp == 32) &&
(m_encoding == RAS_OLD || m_encoding == RAS_STANDARD ||
(m_type == RAS_BYTE_ENCODED && m_bpp == 8) || m_type == RAS_FORMAT_RGB) &&
((m_maptype == RMT_NONE && m_maplength == 0) ||
(m_maptype == RMT_EQUAL_RGB && m_maplength <= palSize && m_maplength > 0 && m_bpp <= 8)))
{
memset( m_palette, 0, sizeof(m_palette));
if( m_maplength != 0 )
{
uchar buffer[256*3];
if( m_strm.getBytes( buffer, m_maplength ) == m_maplength )
{
int i;
palSize = m_maplength/3;
for( i = 0; i < palSize; i++ )
{
m_palette[i].b = buffer[i + 2*palSize];
m_palette[i].g = buffer[i + palSize];
m_palette[i].r = buffer[i];
m_palette[i].a = 0;
}
m_type = IsColorPalette( m_palette, m_bpp ) ? CV_8UC3 : CV_8UC1;
m_offset = m_strm.getPos();
CV_Assert(m_offset == 32 + m_maplength);
result = true;
}
}
else
{
m_type = m_bpp > 8 ? CV_8UC3 : CV_8UC1;
if( CV_MAT_CN(m_type) == 1 )
FillGrayPalette( m_palette, m_bpp );
m_offset = m_strm.getPos();
CV_Assert(m_offset == 32 + m_maplength);
result = true;
}
}
}
catch(...)
{
}
if( !result )
{
m_offset = -1;
m_width = m_height = -1;
m_strm.close();
}
return result;
}
bool SunRasterDecoder::readData( Mat& img )
{
bool color = img.channels() > 1;
uchar* data = img.ptr();
size_t step = img.step;
uchar gray_palette[256] = {0};
bool result = false;
int src_pitch = ((m_width*m_bpp + 7)/8 + 1) & -2;
int nch = color ? 3 : 1;
int width3 = m_width*nch;
int y;
if( m_offset < 0 || !m_strm.isOpened())
return false;
AutoBuffer<uchar> _src(src_pitch + 32);
uchar* src = _src.data();
if( !color && m_maptype == RMT_EQUAL_RGB )
CvtPaletteToGray( m_palette, gray_palette, 1 << m_bpp );
try
{
m_strm.setPos( m_offset );
switch( m_bpp )
{
/************************* 1 BPP ************************/
case 1:
if( m_type != RAS_BYTE_ENCODED )
{
for( y = 0; y < m_height; y++, data += step )
{
m_strm.getBytes( src, src_pitch );
if( color )
FillColorRow1( data, src, m_width, m_palette );
else
FillGrayRow1( data, src, m_width, gray_palette );
}
result = true;
}
else
{
uchar* line_end = src + (m_width*m_bpp + 7)/8;
uchar* tsrc = src;
y = 0;
for(;;)
{
int max_count = (int)(line_end - tsrc);
int code = 0, len = 0, len1 = 0;
do
{
code = m_strm.getByte();
if( code == 0x80 )
{
len = m_strm.getByte();
if( len != 0 ) break;
}
tsrc[len1] = (uchar)code;
}
while( ++len1 < max_count );
tsrc += len1;
if( len > 0 ) // encoded mode
{
++len;
code = m_strm.getByte();
if( len > line_end - tsrc )
{
CV_Error(Error::StsInternal, "");
goto bad_decoding_1bpp;
}
memset( tsrc, code, len );
tsrc += len;
}
if( tsrc >= line_end )
{
tsrc = src;
if( color )
FillColorRow1( data, src, m_width, m_palette );
else
FillGrayRow1( data, src, m_width, gray_palette );
data += step;
if( ++y >= m_height ) break;
}
}
result = true;
bad_decoding_1bpp:
;
}
break;
/************************* 8 BPP ************************/
case 8:
if( m_type != RAS_BYTE_ENCODED )
{
for( y = 0; y < m_height; y++, data += step )
{
m_strm.getBytes( src, src_pitch );
if( color )
FillColorRow8( data, src, m_width, m_palette );
else
FillGrayRow8( data, src, m_width, gray_palette );
}
result = true;
}
else // RLE-encoded
{
uchar* line_end = data + width3;
y = 0;
for(;;)
{
int max_count = (int)(line_end - data);
int code = 0, len = 0, len1;
uchar* tsrc = src;
do
{
code = m_strm.getByte();
if( code == 0x80 )
{
len = m_strm.getByte();
if( len != 0 ) break;
}
*tsrc++ = (uchar)code;
}
while( (max_count -= nch) > 0 );
len1 = (int)(tsrc - src);
if( len1 > 0 )
{
if( color )
FillColorRow8( data, src, len1, m_palette );
else
FillGrayRow8( data, src, len1, gray_palette );
data += len1*nch;
}
if( len > 0 ) // encoded mode
{
len = (len + 1)*nch;
code = m_strm.getByte();
if( color )
data = FillUniColor( data, line_end, validateToInt(step), width3,
y, m_height, len,
m_palette[code] );
else
data = FillUniGray( data, line_end, validateToInt(step), width3,
y, m_height, len,
gray_palette[code] );
if( y >= m_height )
break;
}
if( data == line_end )
{
if( m_strm.getByte() != 0 )
goto bad_decoding_end;
line_end += step;
data = line_end - width3;
if( ++y >= m_height ) break;
}
}
result = true;
bad_decoding_end:
;
}
break;
/************************* 24 BPP ************************/
case 24:
for( y = 0; y < m_height; y++, data += step )
{
m_strm.getBytes(src, src_pitch );
if( color )
{
if( m_type == RAS_FORMAT_RGB )
icvCvt_RGB2BGR_8u_C3R(src, 0, data, 0, Size(m_width,1) );
else
memcpy(data, src, std::min(step, (size_t)src_pitch));
}
else
{
icvCvt_BGR2Gray_8u_C3C1R(src, 0, data, 0, Size(m_width,1),
m_type == RAS_FORMAT_RGB ? 2 : 0 );
}
}
result = true;
break;
/************************* 32 BPP ************************/
case 32:
for( y = 0; y < m_height; y++, data += step )
{
/* hack: a0 b0 g0 r0 a1 b1 g1 r1 ... are written to src + 3,
so when we look at src + 4, we see b0 g0 r0 x b1 g1 g1 x ... */
m_strm.getBytes( src + 3, src_pitch );
if( color )
icvCvt_BGRA2BGR_8u_C4C3R( src + 4, 0, data, 0, Size(m_width,1),
m_type == RAS_FORMAT_RGB ? 2 : 0 );
else
icvCvt_BGRA2Gray_8u_C4C1R( src + 4, 0, data, 0, Size(m_width,1),
m_type == RAS_FORMAT_RGB ? 2 : 0 );
}
result = true;
break;
default:
CV_Error(Error::StsInternal, "");
}
}
catch( ... )
{
}
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////
SunRasterEncoder::SunRasterEncoder()
{
m_description = "Sun raster files (*.sr;*.ras)";
}
ImageEncoder SunRasterEncoder::newEncoder() const
{
return makePtr<SunRasterEncoder>();
}
SunRasterEncoder::~SunRasterEncoder()
{
}
bool SunRasterEncoder::write( const Mat& img, const std::vector<int>& )
{
bool result = false;
int y, width = img.cols, height = img.rows, channels = img.channels();
int fileStep = (width*channels + 1) & -2;
WMByteStream strm;
if( strm.open(m_filename) )
{
strm.putBytes( fmtSignSunRas, (int)strlen(fmtSignSunRas) );
strm.putDWord( width );
strm.putDWord( height );
strm.putDWord( channels*8 );
strm.putDWord( fileStep*height );
strm.putDWord( RAS_STANDARD );
strm.putDWord( RMT_NONE );
strm.putDWord( 0 );
for( y = 0; y < height; y++ )
strm.putBytes( img.ptr(y), fileStep );
strm.close();
result = true;
}
return result;
}
}
#endif // HAVE_IMGCODEC_SUNRASTER

View File

@@ -0,0 +1,109 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_SUNRAS_H_
#define _GRFMT_SUNRAS_H_
#include "grfmt_base.hpp"
#ifdef HAVE_IMGCODEC_SUNRASTER
namespace cv
{
enum SunRasType
{
RAS_OLD = 0,
RAS_STANDARD = 1,
RAS_BYTE_ENCODED = 2, /* RLE encoded */
RAS_FORMAT_RGB = 3 /* RGB instead of BGR */
};
enum SunRasMapType
{
RMT_NONE = 0, /* direct color encoding */
RMT_EQUAL_RGB = 1 /* paletted image */
};
// Sun Raster Reader
class SunRasterDecoder CV_FINAL : public BaseImageDecoder
{
public:
SunRasterDecoder();
virtual ~SunRasterDecoder() CV_OVERRIDE;
bool readData( Mat& img ) CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
void close();
ImageDecoder newDecoder() const CV_OVERRIDE;
protected:
RMByteStream m_strm;
PaletteEntry m_palette[256];
int m_bpp;
int m_offset;
SunRasType m_encoding;
SunRasMapType m_maptype;
int m_maplength;
};
class SunRasterEncoder CV_FINAL : public BaseImageEncoder
{
public:
SunRasterEncoder();
virtual ~SunRasterEncoder() CV_OVERRIDE;
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE;
};
}
#endif // HAVE_IMGCODEC_SUNRASTER
#endif/*_GRFMT_SUNRAS_H_*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,151 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_TIFF_H_
#define _GRFMT_TIFF_H_
#include "grfmt_base.hpp"
#ifdef HAVE_TIFF
namespace cv
{
// native simple TIFF codec
enum TiffCompression
{
TIFF_UNCOMP = 1,
TIFF_HUFFMAN = 2,
TIFF_PACKBITS = 32773
};
enum TiffByteOrder
{
TIFF_ORDER_II = 0x4949,
TIFF_ORDER_MM = 0x4d4d
};
enum TiffTag
{
TIFF_TAG_WIDTH = 256,
TIFF_TAG_HEIGHT = 257,
TIFF_TAG_BITS_PER_SAMPLE = 258,
TIFF_TAG_COMPRESSION = 259,
TIFF_TAG_PHOTOMETRIC = 262,
TIFF_TAG_STRIP_OFFSETS = 273,
TIFF_TAG_STRIP_COUNTS = 279,
TIFF_TAG_SAMPLES_PER_PIXEL = 277,
TIFF_TAG_ROWS_PER_STRIP = 278,
TIFF_TAG_PLANAR_CONFIG = 284,
TIFF_TAG_COLOR_MAP = 320
};
enum TiffFieldType
{
TIFF_TYPE_BYTE = 1,
TIFF_TYPE_SHORT = 3,
TIFF_TYPE_LONG = 4
};
// libtiff based TIFF codec
class TiffDecoder CV_FINAL : public BaseImageDecoder
{
public:
TiffDecoder();
virtual ~TiffDecoder() CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
bool readData( Mat& img ) CV_OVERRIDE;
void close();
bool nextPage() CV_OVERRIDE;
size_t signatureLength() const CV_OVERRIDE;
bool checkSignature( const String& signature ) const CV_OVERRIDE;
ImageDecoder newDecoder() const CV_OVERRIDE;
protected:
cv::Ptr<void> m_tif;
int normalizeChannelsNumber(int channels) const;
bool m_hdr;
size_t m_buf_pos;
private:
TiffDecoder(const TiffDecoder &); // copy disabled
TiffDecoder& operator=(const TiffDecoder &); // assign disabled
};
// ... and writer
class TiffEncoder CV_FINAL : public BaseImageEncoder
{
public:
TiffEncoder();
virtual ~TiffEncoder() CV_OVERRIDE;
bool isFormatSupported( int depth ) const CV_OVERRIDE;
bool write( const Mat& img, const std::vector<int>& params ) CV_OVERRIDE;
bool writemulti(const std::vector<Mat>& img_vec, const std::vector<int>& params) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE;
protected:
void writeTag( WLByteStream& strm, TiffTag tag,
TiffFieldType fieldType,
int count, int value );
bool writeLibTiff( const std::vector<Mat>& img_vec, const std::vector<int>& params );
bool write_32FC3_SGILOG(const Mat& img, void* tif);
private:
TiffEncoder(const TiffEncoder &); // copy disabled
TiffEncoder& operator=(const TiffEncoder &); // assign disabled
};
}
#endif // HAVE_TIFF
#endif/*_GRFMT_TIFF_H_*/

View File

@@ -0,0 +1,326 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifdef HAVE_WEBP
#include "precomp.hpp"
#include <webp/decode.h>
#include <webp/encode.h>
#include <stdio.h>
#include <limits.h>
#include "grfmt_webp.hpp"
#include "opencv2/imgproc.hpp"
#include <opencv2/core/utils/configuration.private.hpp>
namespace cv
{
// 64Mb limit to avoid memory DDOS
static size_t param_maxFileSize = utils::getConfigurationParameterSizeT("OPENCV_IMGCODECS_WEBP_MAX_FILE_SIZE", 64*1024*1024);
static const size_t WEBP_HEADER_SIZE = 32;
WebPDecoder::WebPDecoder()
{
m_buf_supported = true;
channels = 0;
fs_size = 0;
}
WebPDecoder::~WebPDecoder() {}
size_t WebPDecoder::signatureLength() const
{
return WEBP_HEADER_SIZE;
}
bool WebPDecoder::checkSignature(const String & signature) const
{
bool ret = false;
if(signature.size() >= WEBP_HEADER_SIZE)
{
WebPBitstreamFeatures features;
if(VP8_STATUS_OK == WebPGetFeatures((uint8_t *)signature.c_str(),
WEBP_HEADER_SIZE, &features))
{
ret = true;
}
}
return ret;
}
ImageDecoder WebPDecoder::newDecoder() const
{
return makePtr<WebPDecoder>();
}
bool WebPDecoder::readHeader()
{
uint8_t header[WEBP_HEADER_SIZE] = { 0 };
if (m_buf.empty())
{
fs.open(m_filename.c_str(), std::ios::binary);
fs.seekg(0, std::ios::end);
fs_size = safeCastToSizeT(fs.tellg(), "File is too large");
fs.seekg(0, std::ios::beg);
CV_Assert(fs && "File stream error");
CV_CheckGE(fs_size, WEBP_HEADER_SIZE, "File is too small");
CV_CheckLE(fs_size, param_maxFileSize, "File is too large. Increase OPENCV_IMGCODECS_WEBP_MAX_FILE_SIZE parameter if you want to process large files");
fs.read((char*)header, sizeof(header));
CV_Assert(fs && "Can't read WEBP_HEADER_SIZE bytes");
}
else
{
CV_CheckGE(m_buf.total(), WEBP_HEADER_SIZE, "Buffer is too small");
memcpy(header, m_buf.ptr(), sizeof(header));
data = m_buf;
}
WebPBitstreamFeatures features;
if (VP8_STATUS_OK == WebPGetFeatures(header, sizeof(header), &features))
{
m_width = features.width;
m_height = features.height;
if (features.has_alpha)
{
m_type = CV_8UC4;
channels = 4;
}
else
{
m_type = CV_8UC3;
channels = 3;
}
return true;
}
return false;
}
bool WebPDecoder::readData(Mat &img)
{
CV_CheckGE(m_width, 0, ""); CV_CheckGE(m_height, 0, "");
CV_CheckEQ(img.cols, m_width, "");
CV_CheckEQ(img.rows, m_height, "");
if (m_buf.empty())
{
fs.seekg(0, std::ios::beg); CV_Assert(fs && "File stream error");
data.create(1, validateToInt(fs_size), CV_8UC1);
fs.read((char*)data.ptr(), fs_size);
CV_Assert(fs && "Can't read file data");
fs.close();
}
CV_Assert(data.type() == CV_8UC1); CV_Assert(data.rows == 1);
{
Mat read_img;
CV_CheckType(img.type(), img.type() == CV_8UC1 || img.type() == CV_8UC3 || img.type() == CV_8UC4, "");
if (img.type() != m_type)
{
read_img.create(m_height, m_width, m_type);
}
else
{
read_img = img; // copy header
}
uchar* out_data = read_img.ptr();
size_t out_data_size = read_img.dataend - out_data;
uchar *res_ptr = NULL;
if (channels == 3)
{
CV_CheckTypeEQ(read_img.type(), CV_8UC3, "");
res_ptr = WebPDecodeBGRInto(data.ptr(), data.total(), out_data,
(int)out_data_size, (int)read_img.step);
}
else if (channels == 4)
{
CV_CheckTypeEQ(read_img.type(), CV_8UC4, "");
res_ptr = WebPDecodeBGRAInto(data.ptr(), data.total(), out_data,
(int)out_data_size, (int)read_img.step);
}
if (res_ptr != out_data)
return false;
if (read_img.data == img.data && img.type() == m_type)
{
// nothing
}
else if (img.type() == CV_8UC1)
{
cvtColor(read_img, img, COLOR_BGR2GRAY);
}
else if (img.type() == CV_8UC3 && m_type == CV_8UC4)
{
cvtColor(read_img, img, COLOR_BGRA2BGR);
}
else if (img.type() == CV_8UC4 && m_type == CV_8UC3)
{
cvtColor(read_img, img, COLOR_BGR2BGRA);
}
else
{
CV_Error(Error::StsInternal, "");
}
}
return true;
}
WebPEncoder::WebPEncoder()
{
m_description = "WebP files (*.webp)";
m_buf_supported = true;
}
WebPEncoder::~WebPEncoder() { }
ImageEncoder WebPEncoder::newEncoder() const
{
return makePtr<WebPEncoder>();
}
bool WebPEncoder::write(const Mat& img, const std::vector<int>& params)
{
CV_CheckDepthEQ(img.depth(), CV_8U, "WebP codec supports 8U images only");
const int width = img.cols, height = img.rows;
bool comp_lossless = true;
float quality = 100.0f;
if (params.size() > 1)
{
if (params[0] == CV_IMWRITE_WEBP_QUALITY)
{
comp_lossless = false;
quality = static_cast<float>(params[1]);
if (quality < 1.0f)
{
quality = 1.0f;
}
if (quality > 100.0f)
{
comp_lossless = true;
}
}
}
int channels = img.channels();
CV_Check(channels, channels == 1 || channels == 3 || channels == 4, "");
const Mat *image = &img;
Mat temp;
if (channels == 1)
{
cvtColor(*image, temp, COLOR_GRAY2BGR);
image = &temp;
channels = 3;
}
uint8_t *out = NULL;
size_t size = 0;
if (comp_lossless)
{
if (channels == 3)
{
size = WebPEncodeLosslessBGR(image->ptr(), width, height, (int)image->step, &out);
}
else if (channels == 4)
{
size = WebPEncodeLosslessBGRA(image->ptr(), width, height, (int)image->step, &out);
}
}
else
{
if (channels == 3)
{
size = WebPEncodeBGR(image->ptr(), width, height, (int)image->step, quality, &out);
}
else if (channels == 4)
{
size = WebPEncodeBGRA(image->ptr(), width, height, (int)image->step, quality, &out);
}
}
#if WEBP_DECODER_ABI_VERSION >= 0x0206
Ptr<uint8_t> out_cleaner(out, WebPFree);
#else
Ptr<uint8_t> out_cleaner(out, free);
#endif
CV_Assert(size > 0);
if (m_buf)
{
m_buf->resize(size);
memcpy(&(*m_buf)[0], out, size);
}
else
{
FILE *fd = fopen(m_filename.c_str(), "wb");
if (fd != NULL)
{
fwrite(out, size, sizeof(uint8_t), fd);
fclose(fd); fd = NULL;
}
}
return size > 0;
}
}
#endif

View File

@@ -0,0 +1,92 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMT_WEBP_H_
#define _GRFMT_WEBP_H_
#include "grfmt_base.hpp"
#ifdef HAVE_WEBP
#include <fstream>
namespace cv
{
class WebPDecoder CV_FINAL : public BaseImageDecoder
{
public:
WebPDecoder();
~WebPDecoder() CV_OVERRIDE;
bool readData( Mat& img ) CV_OVERRIDE;
bool readHeader() CV_OVERRIDE;
size_t signatureLength() const CV_OVERRIDE;
bool checkSignature( const String& signature) const CV_OVERRIDE;
ImageDecoder newDecoder() const CV_OVERRIDE;
protected:
std::ifstream fs;
size_t fs_size;
Mat data;
int channels;
};
class WebPEncoder CV_FINAL : public BaseImageEncoder
{
public:
WebPEncoder();
~WebPEncoder() CV_OVERRIDE;
bool write(const Mat& img, const std::vector<int>& params) CV_OVERRIDE;
ImageEncoder newEncoder() const CV_OVERRIDE;
};
}
#endif
#endif /* _GRFMT_WEBP_H_ */

View File

@@ -0,0 +1,61 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _GRFMTS_H_
#define _GRFMTS_H_
#include "grfmt_base.hpp"
#include "grfmt_bmp.hpp"
#include "grfmt_sunras.hpp"
#include "grfmt_jpeg.hpp"
#include "grfmt_pxm.hpp"
#include "grfmt_pfm.hpp"
#include "grfmt_tiff.hpp"
#include "grfmt_png.hpp"
#include "grfmt_jpeg2000.hpp"
#include "grfmt_exr.hpp"
#include "grfmt_webp.hpp"
#include "grfmt_hdr.hpp"
#include "grfmt_gdal.hpp"
#include "grfmt_gdcm.hpp"
#include "grfmt_pam.hpp"
#endif/*_GRFMTS_H_*/

View File

@@ -0,0 +1,130 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#import <UIKit/UIKit.h>
#import <Accelerate/Accelerate.h>
#import <AVFoundation/AVFoundation.h>
#import <ImageIO/ImageIO.h>
#include "opencv2/core.hpp"
#include "precomp.hpp"
CV_EXPORTS UIImage* MatToUIImage(const cv::Mat& image);
CV_EXPORTS void UIImageToMat(const UIImage* image, cv::Mat& m, bool alphaExist);
UIImage* MatToUIImage(const cv::Mat& image) {
NSData *data = [NSData dataWithBytes:image.data
length:image.step.p[0] * image.rows];
CGColorSpaceRef colorSpace;
if (image.elemSize() == 1) {
colorSpace = CGColorSpaceCreateDeviceGray();
} else {
colorSpace = CGColorSpaceCreateDeviceRGB();
}
CGDataProviderRef provider =
CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
// Preserve alpha transparency, if exists
bool alpha = image.channels() == 4;
CGBitmapInfo bitmapInfo = (alpha ? kCGImageAlphaLast : kCGImageAlphaNone) | kCGBitmapByteOrderDefault;
// Creating CGImage from cv::Mat
CGImageRef imageRef = CGImageCreate(image.cols,
image.rows,
8 * image.elemSize1(),
8 * image.elemSize(),
image.step.p[0],
colorSpace,
bitmapInfo,
provider,
NULL,
false,
kCGRenderingIntentDefault
);
// Getting UIImage from CGImage
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return finalImage;
}
void UIImageToMat(const UIImage* image,
cv::Mat& m, bool alphaExist) {
CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
CGFloat cols = CGImageGetWidth(image.CGImage), rows = CGImageGetHeight(image.CGImage);
CGContextRef contextRef;
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;
if (CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelMonochrome)
{
m.create(rows, cols, CV_8UC1); // 8 bits per component, 1 channel
bitmapInfo = kCGImageAlphaNone;
if (!alphaExist)
bitmapInfo = kCGImageAlphaNone;
else
m = cv::Scalar(0);
contextRef = CGBitmapContextCreate(m.data, m.cols, m.rows, 8,
m.step[0], colorSpace,
bitmapInfo);
}
else
{
m.create(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
if (!alphaExist)
bitmapInfo = kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrderDefault;
else
m = cv::Scalar(0);
contextRef = CGBitmapContextCreate(m.data, m.cols, m.rows, 8,
m.step[0], colorSpace,
bitmapInfo);
}
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows),
image.CGImage);
CGContextRelease(contextRef);
}

View File

@@ -0,0 +1,938 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
//
// Loading and saving images.
//
#include "precomp.hpp"
#include "grfmts.hpp"
#include "utils.hpp"
#include "exif.hpp"
#undef min
#undef max
#include <iostream>
#include <fstream>
#include <opencv2/core/utils/configuration.private.hpp>
/****************************************************************************************\
* Image Codecs *
\****************************************************************************************/
namespace cv {
static const size_t CV_IO_MAX_IMAGE_PARAMS = cv::utils::getConfigurationParameterSizeT("OPENCV_IO_MAX_IMAGE_PARAMS", 50);
static const size_t CV_IO_MAX_IMAGE_WIDTH = utils::getConfigurationParameterSizeT("OPENCV_IO_MAX_IMAGE_WIDTH", 1 << 20);
static const size_t CV_IO_MAX_IMAGE_HEIGHT = utils::getConfigurationParameterSizeT("OPENCV_IO_MAX_IMAGE_HEIGHT", 1 << 20);
static const size_t CV_IO_MAX_IMAGE_PIXELS = utils::getConfigurationParameterSizeT("OPENCV_IO_MAX_IMAGE_PIXELS", 1 << 30);
static Size validateInputImageSize(const Size& size)
{
CV_Assert(size.width > 0);
CV_Assert(static_cast<size_t>(size.width) <= CV_IO_MAX_IMAGE_WIDTH);
CV_Assert(size.height > 0);
CV_Assert(static_cast<size_t>(size.height) <= CV_IO_MAX_IMAGE_HEIGHT);
uint64 pixels = (uint64)size.width * (uint64)size.height;
CV_Assert(pixels <= CV_IO_MAX_IMAGE_PIXELS);
return size;
}
namespace {
class ByteStreamBuffer: public std::streambuf
{
public:
ByteStreamBuffer(char* base, size_t length)
{
setg(base, base, base + length);
}
protected:
virtual pos_type seekoff( off_type offset,
std::ios_base::seekdir dir,
std::ios_base::openmode ) CV_OVERRIDE
{
char* whence = eback();
if (dir == std::ios_base::cur)
{
whence = gptr();
}
else if (dir == std::ios_base::end)
{
whence = egptr();
}
char* to = whence + offset;
// check limits
if (to >= eback() && to <= egptr())
{
setg(eback(), to, egptr());
return gptr() - eback();
}
return -1;
}
};
}
/**
* @struct ImageCodecInitializer
*
* Container which stores the registered codecs to be used by OpenCV
*/
struct ImageCodecInitializer
{
/**
* Default Constructor for the ImageCodeInitializer
*/
ImageCodecInitializer()
{
/// BMP Support
decoders.push_back( makePtr<BmpDecoder>() );
encoders.push_back( makePtr<BmpEncoder>() );
#ifdef HAVE_IMGCODEC_HDR
decoders.push_back( makePtr<HdrDecoder>() );
encoders.push_back( makePtr<HdrEncoder>() );
#endif
#ifdef HAVE_JPEG
decoders.push_back( makePtr<JpegDecoder>() );
encoders.push_back( makePtr<JpegEncoder>() );
#endif
#ifdef HAVE_WEBP
decoders.push_back( makePtr<WebPDecoder>() );
encoders.push_back( makePtr<WebPEncoder>() );
#endif
#ifdef HAVE_IMGCODEC_SUNRASTER
decoders.push_back( makePtr<SunRasterDecoder>() );
encoders.push_back( makePtr<SunRasterEncoder>() );
#endif
#ifdef HAVE_IMGCODEC_PXM
decoders.push_back( makePtr<PxMDecoder>() );
encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_AUTO) );
encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_PBM) );
encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_PGM) );
encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_PPM) );
decoders.push_back( makePtr<PAMDecoder>() );
encoders.push_back( makePtr<PAMEncoder>() );
#endif
#ifdef HAVE_IMGCODEC_PFM
decoders.push_back( makePtr<PFMDecoder>() );
encoders.push_back( makePtr<PFMEncoder>() );
#endif
#ifdef HAVE_TIFF
decoders.push_back( makePtr<TiffDecoder>() );
encoders.push_back( makePtr<TiffEncoder>() );
#endif
#ifdef HAVE_PNG
decoders.push_back( makePtr<PngDecoder>() );
encoders.push_back( makePtr<PngEncoder>() );
#endif
#ifdef HAVE_GDCM
decoders.push_back( makePtr<DICOMDecoder>() );
#endif
#ifdef HAVE_JASPER
decoders.push_back( makePtr<Jpeg2KDecoder>() );
encoders.push_back( makePtr<Jpeg2KEncoder>() );
#endif
#ifdef HAVE_OPENEXR
decoders.push_back( makePtr<ExrDecoder>() );
encoders.push_back( makePtr<ExrEncoder>() );
#endif
#ifdef HAVE_GDAL
/// Attach the GDAL Decoder
decoders.push_back( makePtr<GdalDecoder>() );
#endif/*HAVE_GDAL*/
}
std::vector<ImageDecoder> decoders;
std::vector<ImageEncoder> encoders;
};
static ImageCodecInitializer codecs;
/**
* Find the decoders
*
* @param[in] filename File to search
*
* @return Image decoder to parse image file.
*/
static ImageDecoder findDecoder( const String& filename ) {
size_t i, maxlen = 0;
/// iterate through list of registered codecs
for( i = 0; i < codecs.decoders.size(); i++ )
{
size_t len = codecs.decoders[i]->signatureLength();
maxlen = std::max(maxlen, len);
}
/// Open the file
FILE* f= fopen( filename.c_str(), "rb" );
/// in the event of a failure, return an empty image decoder
if( !f )
return ImageDecoder();
// read the file signature
String signature(maxlen, ' ');
maxlen = fread( (void*)signature.c_str(), 1, maxlen, f );
fclose(f);
signature = signature.substr(0, maxlen);
/// compare signature against all decoders
for( i = 0; i < codecs.decoders.size(); i++ )
{
if( codecs.decoders[i]->checkSignature(signature) )
return codecs.decoders[i]->newDecoder();
}
/// If no decoder was found, return base type
return ImageDecoder();
}
static ImageDecoder findDecoder( const Mat& buf )
{
size_t i, maxlen = 0;
if( buf.rows*buf.cols < 1 || !buf.isContinuous() )
return ImageDecoder();
for( i = 0; i < codecs.decoders.size(); i++ )
{
size_t len = codecs.decoders[i]->signatureLength();
maxlen = std::max(maxlen, len);
}
String signature(maxlen, ' ');
size_t bufSize = buf.rows*buf.cols*buf.elemSize();
maxlen = std::min(maxlen, bufSize);
memcpy( (void*)signature.c_str(), buf.data, maxlen );
for( i = 0; i < codecs.decoders.size(); i++ )
{
if( codecs.decoders[i]->checkSignature(signature) )
return codecs.decoders[i]->newDecoder();
}
return ImageDecoder();
}
static ImageEncoder findEncoder( const String& _ext )
{
if( _ext.size() <= 1 )
return ImageEncoder();
const char* ext = strrchr( _ext.c_str(), '.' );
if( !ext )
return ImageEncoder();
int len = 0;
for( ext++; len < 128 && isalnum(ext[len]); len++ )
;
for( size_t i = 0; i < codecs.encoders.size(); i++ )
{
String description = codecs.encoders[i]->getDescription();
const char* descr = strchr( description.c_str(), '(' );
while( descr )
{
descr = strchr( descr + 1, '.' );
if( !descr )
break;
int j = 0;
for( descr++; j < len && isalnum(descr[j]) ; j++ )
{
int c1 = tolower(ext[j]);
int c2 = tolower(descr[j]);
if( c1 != c2 )
break;
}
if( j == len && !isalnum(descr[j]))
return codecs.encoders[i]->newEncoder();
descr += j;
}
}
return ImageEncoder();
}
static void ExifTransform(int orientation, Mat& img)
{
switch( orientation )
{
case IMAGE_ORIENTATION_TL: //0th row == visual top, 0th column == visual left-hand side
//do nothing, the image already has proper orientation
break;
case IMAGE_ORIENTATION_TR: //0th row == visual top, 0th column == visual right-hand side
flip(img, img, 1); //flip horizontally
break;
case IMAGE_ORIENTATION_BR: //0th row == visual bottom, 0th column == visual right-hand side
flip(img, img, -1);//flip both horizontally and vertically
break;
case IMAGE_ORIENTATION_BL: //0th row == visual bottom, 0th column == visual left-hand side
flip(img, img, 0); //flip vertically
break;
case IMAGE_ORIENTATION_LT: //0th row == visual left-hand side, 0th column == visual top
transpose(img, img);
break;
case IMAGE_ORIENTATION_RT: //0th row == visual right-hand side, 0th column == visual top
transpose(img, img);
flip(img, img, 1); //flip horizontally
break;
case IMAGE_ORIENTATION_RB: //0th row == visual right-hand side, 0th column == visual bottom
transpose(img, img);
flip(img, img, -1); //flip both horizontally and vertically
break;
case IMAGE_ORIENTATION_LB: //0th row == visual left-hand side, 0th column == visual bottom
transpose(img, img);
flip(img, img, 0); //flip vertically
break;
default:
//by default the image read has normal (JPEG_ORIENTATION_TL) orientation
break;
}
}
static void ApplyExifOrientation(const String& filename, Mat& img)
{
int orientation = IMAGE_ORIENTATION_TL;
if (filename.size() > 0)
{
std::ifstream stream( filename.c_str(), std::ios_base::in | std::ios_base::binary );
ExifReader reader( stream );
if( reader.parse() )
{
ExifEntry_t entry = reader.getTag( ORIENTATION );
if (entry.tag != INVALID_TAG)
{
orientation = entry.field_u16; //orientation is unsigned short, so check field_u16
}
}
stream.close();
}
ExifTransform(orientation, img);
}
static void ApplyExifOrientation(const Mat& buf, Mat& img)
{
int orientation = IMAGE_ORIENTATION_TL;
if( buf.isContinuous() )
{
ByteStreamBuffer bsb( reinterpret_cast<char*>(buf.data), buf.total() * buf.elemSize() );
std::istream stream( &bsb );
ExifReader reader( stream );
if( reader.parse() )
{
ExifEntry_t entry = reader.getTag( ORIENTATION );
if (entry.tag != INVALID_TAG)
{
orientation = entry.field_u16; //orientation is unsigned short, so check field_u16
}
}
}
ExifTransform(orientation, img);
}
/**
* Read an image into memory and return the information
*
* @param[in] filename File to load
* @param[in] flags Flags
* @param[in] hdrtype { LOAD_CVMAT=0,
* LOAD_IMAGE=1,
* LOAD_MAT=2
* }
* @param[in] mat Reference to C++ Mat object (If LOAD_MAT)
*
*/
static bool
imread_( const String& filename, int flags, Mat& mat )
{
/// Search for the relevant decoder to handle the imagery
ImageDecoder decoder;
#ifdef HAVE_GDAL
if(flags != IMREAD_UNCHANGED && (flags & IMREAD_LOAD_GDAL) == IMREAD_LOAD_GDAL ){
decoder = GdalDecoder().newDecoder();
}else{
#endif
decoder = findDecoder( filename );
#ifdef HAVE_GDAL
}
#endif
/// if no decoder was found, return nothing.
if( !decoder ){
return 0;
}
int scale_denom = 1;
if( flags > IMREAD_LOAD_GDAL )
{
if( flags & IMREAD_REDUCED_GRAYSCALE_2 )
scale_denom = 2;
else if( flags & IMREAD_REDUCED_GRAYSCALE_4 )
scale_denom = 4;
else if( flags & IMREAD_REDUCED_GRAYSCALE_8 )
scale_denom = 8;
}
/// set the scale_denom in the driver
decoder->setScale( scale_denom );
/// set the filename in the driver
decoder->setSource( filename );
try
{
// read the header to make sure it succeeds
if( !decoder->readHeader() )
return 0;
}
catch (const cv::Exception& e)
{
std::cerr << "imread_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;
return 0;
}
catch (...)
{
std::cerr << "imread_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;
return 0;
}
// established the required input image size
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
// grab the decoded type
int type = decoder->type();
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
{
if( (flags & IMREAD_ANYDEPTH) == 0 )
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if( (flags & IMREAD_COLOR) != 0 ||
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
}
mat.create( size.height, size.width, type );
// read the image data
bool success = false;
try
{
if (decoder->readData(mat))
success = true;
}
catch (const cv::Exception& e)
{
std::cerr << "imread_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;
}
catch (...)
{
std::cerr << "imread_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
}
if (!success)
{
mat.release();
return false;
}
if( decoder->setScale( scale_denom ) > 1 ) // if decoder is JpegDecoder then decoder->setScale always returns 1
{
resize( mat, mat, Size( size.width / scale_denom, size.height / scale_denom ), 0, 0, INTER_LINEAR_EXACT);
}
return true;
}
/**
* Read an image into memory and return the information
*
* @param[in] filename File to load
* @param[in] flags Flags
* @param[in] mats Reference to C++ vector<Mat> object to hold the images
*
*/
static bool
imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats)
{
/// Search for the relevant decoder to handle the imagery
ImageDecoder decoder;
#ifdef HAVE_GDAL
if (flags != IMREAD_UNCHANGED && (flags & IMREAD_LOAD_GDAL) == IMREAD_LOAD_GDAL){
decoder = GdalDecoder().newDecoder();
}
else{
#endif
decoder = findDecoder(filename);
#ifdef HAVE_GDAL
}
#endif
/// if no decoder was found, return nothing.
if (!decoder){
return 0;
}
/// set the filename in the driver
decoder->setSource(filename);
// read the header to make sure it succeeds
try
{
// read the header to make sure it succeeds
if( !decoder->readHeader() )
return 0;
}
catch (const cv::Exception& e)
{
std::cerr << "imreadmulti_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;
return 0;
}
catch (...)
{
std::cerr << "imreadmulti_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;
return 0;
}
for (;;)
{
// grab the decoded type
int type = decoder->type();
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
{
if ((flags & IMREAD_ANYDEPTH) == 0)
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if ((flags & CV_LOAD_IMAGE_COLOR) != 0 ||
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1))
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
}
// established the required input image size
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
// read the image data
Mat mat(size.height, size.width, type);
bool success = false;
try
{
if (decoder->readData(mat))
success = true;
}
catch (const cv::Exception& e)
{
std::cerr << "imreadmulti_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;
}
catch (...)
{
std::cerr << "imreadmulti_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
}
if (!success)
break;
// optionally rotate the data if EXIF' orientation flag says so
if( (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )
{
ApplyExifOrientation(filename, mat);
}
mats.push_back(mat);
if (!decoder->nextPage())
{
break;
}
}
return !mats.empty();
}
/**
* Read an image
*
* This function merely calls the actual implementation above and returns itself.
*
* @param[in] filename File to load
* @param[in] flags Flags you wish to set.
*/
Mat imread( const String& filename, int flags )
{
CV_TRACE_FUNCTION();
/// create the basic container
Mat img;
/// load the data
imread_( filename, flags, img );
/// optionally rotate the data if EXIF' orientation flag says so
if( !img.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )
{
ApplyExifOrientation(filename, img);
}
/// return a reference to the data
return img;
}
/**
* Read a multi-page image
*
* This function merely calls the actual implementation above and returns itself.
*
* @param[in] filename File to load
* @param[in] mats Reference to C++ vector<Mat> object to hold the images
* @param[in] flags Flags you wish to set.
*
*/
bool imreadmulti(const String& filename, std::vector<Mat>& mats, int flags)
{
CV_TRACE_FUNCTION();
return imreadmulti_(filename, flags, mats);
}
static bool imwrite_( const String& filename, const std::vector<Mat>& img_vec,
const std::vector<int>& params, bool flipv )
{
bool isMultiImg = img_vec.size() > 1;
std::vector<Mat> write_vec;
ImageEncoder encoder = findEncoder( filename );
if( !encoder )
CV_Error( Error::StsError, "could not find a writer for the specified extension" );
for (size_t page = 0; page < img_vec.size(); page++)
{
Mat image = img_vec[page];
CV_Assert(!image.empty());
CV_Assert( image.channels() == 1 || image.channels() == 3 || image.channels() == 4 );
Mat temp;
if( !encoder->isFormatSupported(image.depth()) )
{
CV_Assert( encoder->isFormatSupported(CV_8U) );
image.convertTo( temp, CV_8U );
image = temp;
}
if( flipv )
{
flip(image, temp, 0);
image = temp;
}
write_vec.push_back(image);
}
encoder->setDestination( filename );
CV_Assert(params.size() <= CV_IO_MAX_IMAGE_PARAMS*2);
bool code = false;
try
{
if (!isMultiImg)
code = encoder->write( write_vec[0], params );
else
code = encoder->writemulti( write_vec, params ); //to be implemented
}
catch (const cv::Exception& e)
{
std::cerr << "imwrite_('" << filename << "'): can't write data: " << e.what() << std::endl << std::flush;
}
catch (...)
{
std::cerr << "imwrite_('" << filename << "'): can't write data: unknown exception" << std::endl << std::flush;
}
// CV_Assert( code );
return code;
}
bool imwrite( const String& filename, InputArray _img,
const std::vector<int>& params )
{
CV_TRACE_FUNCTION();
CV_Assert(!_img.empty());
std::vector<Mat> img_vec;
if (_img.isMatVector() || _img.isUMatVector())
_img.getMatVector(img_vec);
else
img_vec.push_back(_img.getMat());
CV_Assert(!img_vec.empty());
return imwrite_(filename, img_vec, params, false);
}
static bool
imdecode_( const Mat& buf, int flags, Mat& mat )
{
CV_Assert(!buf.empty());
CV_Assert(buf.isContinuous());
CV_Assert(buf.checkVector(1, CV_8U) > 0);
Mat buf_row = buf.reshape(1, 1); // decoders expects single row, avoid issues with vector columns
String filename;
ImageDecoder decoder = findDecoder(buf_row);
if( !decoder )
return 0;
if( !decoder->setSource(buf_row) )
{
filename = tempfile();
FILE* f = fopen( filename.c_str(), "wb" );
if( !f )
return 0;
size_t bufSize = buf_row.total()*buf.elemSize();
if (fwrite(buf_row.ptr(), 1, bufSize, f) != bufSize)
{
fclose( f );
CV_Error( Error::StsError, "failed to write image data to temporary file" );
}
if( fclose(f) != 0 )
{
CV_Error( Error::StsError, "failed to write image data to temporary file" );
}
decoder->setSource(filename);
}
bool success = false;
try
{
if (decoder->readHeader())
success = true;
}
catch (const cv::Exception& e)
{
std::cerr << "imdecode_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;
}
catch (...)
{
std::cerr << "imdecode_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;
}
if (!success)
{
decoder.release();
if (!filename.empty())
{
if (0 != remove(filename.c_str()))
{
std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush;
}
}
return 0;
}
// established the required input image size
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
int type = decoder->type();
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
{
if( (flags & IMREAD_ANYDEPTH) == 0 )
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if( (flags & IMREAD_COLOR) != 0 ||
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
}
mat.create( size.height, size.width, type );
success = false;
try
{
if (decoder->readData(mat))
success = true;
}
catch (const cv::Exception& e)
{
std::cerr << "imdecode_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;
}
catch (...)
{
std::cerr << "imdecode_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
}
decoder.release();
if (!filename.empty())
{
if (0 != remove(filename.c_str()))
{
std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush;
}
}
if (!success)
{
mat.release();
return false;
}
return true;
}
Mat imdecode( InputArray _buf, int flags )
{
CV_TRACE_FUNCTION();
Mat buf = _buf.getMat(), img;
imdecode_( buf, flags, img );
/// optionally rotate the data if EXIF' orientation flag says so
if( !img.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )
{
ApplyExifOrientation(buf, img);
}
return img;
}
Mat imdecode( InputArray _buf, int flags, Mat* dst )
{
CV_TRACE_FUNCTION();
Mat buf = _buf.getMat(), img;
dst = dst ? dst : &img;
imdecode_( buf, flags, *dst );
/// optionally rotate the data if EXIF' orientation flag says so
if( !dst->empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )
{
ApplyExifOrientation(buf, *dst);
}
return *dst;
}
bool imencode( const String& ext, InputArray _image,
std::vector<uchar>& buf, const std::vector<int>& params )
{
CV_TRACE_FUNCTION();
Mat image = _image.getMat();
CV_Assert(!image.empty());
int channels = image.channels();
CV_Assert( channels == 1 || channels == 3 || channels == 4 );
ImageEncoder encoder = findEncoder( ext );
if( !encoder )
CV_Error( Error::StsError, "could not find encoder for the specified extension" );
if( !encoder->isFormatSupported(image.depth()) )
{
CV_Assert( encoder->isFormatSupported(CV_8U) );
Mat temp;
image.convertTo(temp, CV_8U);
image = temp;
}
bool code;
if( encoder->setDestination(buf) )
{
code = encoder->write(image, params);
encoder->throwOnEror();
CV_Assert( code );
}
else
{
String filename = tempfile();
code = encoder->setDestination(filename);
CV_Assert( code );
code = encoder->write(image, params);
encoder->throwOnEror();
CV_Assert( code );
FILE* f = fopen( filename.c_str(), "rb" );
CV_Assert(f != 0);
fseek( f, 0, SEEK_END );
long pos = ftell(f);
buf.resize((size_t)pos);
fseek( f, 0, SEEK_SET );
buf.resize(fread( &buf[0], 1, buf.size(), f ));
fclose(f);
remove(filename.c_str());
}
return code;
}
bool haveImageReader( const String& filename )
{
ImageDecoder decoder = cv::findDecoder(filename);
return !decoder.empty();
}
bool haveImageWriter( const String& filename )
{
cv::ImageEncoder encoder = cv::findEncoder(filename);
return !encoder.empty();
}
}
/* End of file. */

View File

@@ -0,0 +1,71 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __IMGCODECS_H_
#define __IMGCODECS_H_
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgcodecs/legacy/constants_c.h"
#include "opencv2/core/utility.hpp"
#include "opencv2/core/private.hpp"
#include "opencv2/imgproc.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#if defined _WIN32 || defined WINCE
#include <windows.h>
#undef small
#undef min
#undef max
#undef abs
#endif
#define __BEGIN__ __CV_BEGIN__
#define __END__ __CV_END__
#define EXIT __CV_EXIT__
#endif /* __IMGCODECS_H_ */

View File

@@ -0,0 +1,454 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "rgbe.hpp"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// This file contains code to read and write four byte rgbe file format
// developed by Greg Ward. It handles the conversions between rgbe and
// pixels consisting of floats. The data is assumed to be an array of floats.
// By default there are three floats per pixel in the order red, green, blue.
// (RGBE_DATA_??? values control this.) Only the minimal header reading and
// writing is implemented. Each routine does error checking and will return
// a status value as defined below. This code is intended as a skeleton so
// feel free to modify it to suit your needs.
// Some opencv specific changes have been added:
// inline define specified, error handler uses CV_Error,
// defines changed to work in bgr color space.
//
// posted to http://www.graphics.cornell.edu/~bjw/
// written by Bruce Walter (bjw@graphics.cornell.edu) 5/26/95
// based on code written by Greg Ward
#define INLINE inline
/* offsets to red, green, and blue components in a data (float) pixel */
#define RGBE_DATA_RED 2
#define RGBE_DATA_GREEN 1
#define RGBE_DATA_BLUE 0
/* number of floats per pixel */
#define RGBE_DATA_SIZE 3
enum rgbe_error_codes {
rgbe_read_error,
rgbe_write_error,
rgbe_format_error,
rgbe_memory_error
};
/* default error routine. change this to change error handling */
static int rgbe_error(int rgbe_error_code, const char *msg)
{
switch (rgbe_error_code) {
case rgbe_read_error:
CV_Error(cv::Error::StsError, "RGBE read error");
break;
case rgbe_write_error:
CV_Error(cv::Error::StsError, "RGBE write error");
break;
case rgbe_format_error:
CV_Error(cv::Error::StsError, cv::String("RGBE bad file format: ") +
cv::String(msg));
break;
default:
case rgbe_memory_error:
CV_Error(cv::Error::StsError, cv::String("RGBE error: \n") +
cv::String(msg));
}
}
/* standard conversion from float pixels to rgbe pixels */
/* note: you can remove the "inline"s if your compiler complains about it */
static INLINE void
float2rgbe(unsigned char rgbe[4], float red, float green, float blue)
{
float v;
int e;
v = red;
if (green > v) v = green;
if (blue > v) v = blue;
if (v < 1e-32) {
rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
}
else {
v = static_cast<float>(frexp(v,&e) * 256.0/v);
rgbe[0] = (unsigned char) (red * v);
rgbe[1] = (unsigned char) (green * v);
rgbe[2] = (unsigned char) (blue * v);
rgbe[3] = (unsigned char) (e + 128);
}
}
/* standard conversion from rgbe to float pixels */
/* note: Ward uses ldexp(col+0.5,exp-(128+8)). However we wanted pixels */
/* in the range [0,1] to map back into the range [0,1]. */
static INLINE void
rgbe2float(float *red, float *green, float *blue, unsigned char rgbe[4])
{
float f;
if (rgbe[3]) { /*nonzero pixel*/
f = static_cast<float>(ldexp(1.0,rgbe[3]-(int)(128+8)));
*red = rgbe[0] * f;
*green = rgbe[1] * f;
*blue = rgbe[2] * f;
}
else
*red = *green = *blue = 0.0;
}
/* default minimal header. modify if you want more information in header */
int RGBE_WriteHeader(FILE *fp, int width, int height, rgbe_header_info *info)
{
const char *programtype = "RADIANCE";
if (info && (info->valid & RGBE_VALID_PROGRAMTYPE))
programtype = info->programtype;
if (fprintf(fp,"#?%s\n",programtype) < 0)
return rgbe_error(rgbe_write_error,NULL);
/* The #? is to identify file type, the programtype is optional. */
if (info && (info->valid & RGBE_VALID_GAMMA)) {
if (fprintf(fp,"GAMMA=%g\n",info->gamma) < 0)
return rgbe_error(rgbe_write_error,NULL);
}
if (info && (info->valid & RGBE_VALID_EXPOSURE)) {
if (fprintf(fp,"EXPOSURE=%g\n",info->exposure) < 0)
return rgbe_error(rgbe_write_error,NULL);
}
if (fprintf(fp,"FORMAT=32-bit_rle_rgbe\n\n") < 0)
return rgbe_error(rgbe_write_error,NULL);
if (fprintf(fp, "-Y %d +X %d\n", height, width) < 0)
return rgbe_error(rgbe_write_error,NULL);
return RGBE_RETURN_SUCCESS;
}
/* minimal header reading. modify if you want to parse more information */
int RGBE_ReadHeader(FILE *fp, int *width, int *height, rgbe_header_info *info)
{
char buf[128];
float tempf;
int i;
if (info) {
info->valid = 0;
info->programtype[0] = 0;
info->gamma = info->exposure = 1.0;
}
// 1. read first line
if (fgets(buf,sizeof(buf)/sizeof(buf[0]),fp) == NULL)
return rgbe_error(rgbe_read_error,NULL);
if ((buf[0] != '#')||(buf[1] != '?')) {
/* if you want to require the magic token then uncomment the next line */
/*return rgbe_error(rgbe_format_error,"bad initial token"); */
}
else if (info) {
info->valid |= RGBE_VALID_PROGRAMTYPE;
for(i=0;i<static_cast<int>(sizeof(info->programtype)-1);i++) {
if ((buf[i+2] == 0) || isspace(buf[i+2]))
break;
info->programtype[i] = buf[i+2];
}
info->programtype[i] = 0;
}
// 2. reading other header lines
bool hasFormat = false;
for(;;) {
if (fgets(buf,sizeof(buf)/sizeof(buf[0]),fp) == 0)
return rgbe_error(rgbe_read_error,NULL);
if (buf[0] == '\n') // end of the header
break;
else if (buf[0] == '#') // comment
continue;
else if (strcmp(buf,"FORMAT=32-bit_rle_rgbe\n") == 0)
hasFormat = true;
else if (info && (sscanf(buf,"GAMMA=%g",&tempf) == 1)) {
info->gamma = tempf;
info->valid |= RGBE_VALID_GAMMA;
}
else if (info && (sscanf(buf,"EXPOSURE=%g",&tempf) == 1)) {
info->exposure = tempf;
info->valid |= RGBE_VALID_EXPOSURE;
}
}
if (strcmp(buf,"\n") != 0)
return rgbe_error(rgbe_format_error,
"missing blank line after FORMAT specifier");
if (!hasFormat)
return rgbe_error(rgbe_format_error, "missing FORMAT specifier");
// 3. reading resolution string
if (fgets(buf,sizeof(buf)/sizeof(buf[0]),fp) == 0)
return rgbe_error(rgbe_read_error,NULL);
if (sscanf(buf,"-Y %d +X %d",height,width) < 2)
return rgbe_error(rgbe_format_error,"missing image size specifier");
return RGBE_RETURN_SUCCESS;
}
/* simple write routine that does not use run length encoding */
/* These routines can be made faster by allocating a larger buffer and
fread-ing and fwrite-ing the data in larger chunks */
int RGBE_WritePixels(FILE *fp, float *data, int numpixels)
{
unsigned char rgbe[4];
while (numpixels-- > 0) {
float2rgbe(rgbe,data[RGBE_DATA_RED],
data[RGBE_DATA_GREEN],data[RGBE_DATA_BLUE]);
data += RGBE_DATA_SIZE;
if (fwrite(rgbe, sizeof(rgbe), 1, fp) < 1)
return rgbe_error(rgbe_write_error,NULL);
}
return RGBE_RETURN_SUCCESS;
}
/* simple read routine. will not correctly handle run length encoding */
int RGBE_ReadPixels(FILE *fp, float *data, int numpixels)
{
unsigned char rgbe[4];
while(numpixels-- > 0) {
if (fread(rgbe, sizeof(rgbe), 1, fp) < 1)
return rgbe_error(rgbe_read_error,NULL);
rgbe2float(&data[RGBE_DATA_RED],&data[RGBE_DATA_GREEN],
&data[RGBE_DATA_BLUE],rgbe);
data += RGBE_DATA_SIZE;
}
return RGBE_RETURN_SUCCESS;
}
/* The code below is only needed for the run-length encoded files. */
/* Run length encoding adds considerable complexity but does */
/* save some space. For each scanline, each channel (r,g,b,e) is */
/* encoded separately for better compression. */
static int RGBE_WriteBytes_RLE(FILE *fp, unsigned char *data, int numbytes)
{
#define MINRUNLENGTH 4
int cur, beg_run, run_count, old_run_count, nonrun_count;
unsigned char buf[2];
cur = 0;
while(cur < numbytes) {
beg_run = cur;
/* find next run of length at least 4 if one exists */
run_count = old_run_count = 0;
while((run_count < MINRUNLENGTH) && (beg_run < numbytes)) {
beg_run += run_count;
old_run_count = run_count;
run_count = 1;
while( (beg_run + run_count < numbytes) && (run_count < 127)
&& (data[beg_run] == data[beg_run + run_count]))
run_count++;
}
/* if data before next big run is a short run then write it as such */
if ((old_run_count > 1)&&(old_run_count == beg_run - cur)) {
buf[0] = static_cast<unsigned char>(128 + old_run_count); /*write short run*/
buf[1] = data[cur];
if (fwrite(buf,sizeof(buf[0])*2,1,fp) < 1)
return rgbe_error(rgbe_write_error,NULL);
cur = beg_run;
}
/* write out bytes until we reach the start of the next run */
while(cur < beg_run) {
nonrun_count = beg_run - cur;
if (nonrun_count > 128)
nonrun_count = 128;
buf[0] = static_cast<unsigned char>(nonrun_count);
if (fwrite(buf,sizeof(buf[0]),1,fp) < 1)
return rgbe_error(rgbe_write_error,NULL);
if (fwrite(&data[cur],sizeof(data[0])*nonrun_count,1,fp) < 1)
return rgbe_error(rgbe_write_error,NULL);
cur += nonrun_count;
}
/* write out next run if one was found */
if (run_count >= MINRUNLENGTH) {
buf[0] = static_cast<unsigned char>(128 + run_count);
buf[1] = data[beg_run];
if (fwrite(buf,sizeof(buf[0])*2,1,fp) < 1)
return rgbe_error(rgbe_write_error,NULL);
cur += run_count;
}
}
return RGBE_RETURN_SUCCESS;
#undef MINRUNLENGTH
}
int RGBE_WritePixels_RLE(FILE *fp, float *data, int scanline_width,
int num_scanlines)
{
unsigned char rgbe[4];
unsigned char *buffer;
int i, err;
if ((scanline_width < 8)||(scanline_width > 0x7fff))
/* run length encoding is not allowed so write flat*/
return RGBE_WritePixels(fp,data,scanline_width*num_scanlines);
buffer = (unsigned char *)malloc(sizeof(unsigned char)*4*scanline_width);
if (buffer == NULL)
/* no buffer space so write flat */
return RGBE_WritePixels(fp,data,scanline_width*num_scanlines);
while(num_scanlines-- > 0) {
rgbe[0] = 2;
rgbe[1] = 2;
rgbe[2] = static_cast<unsigned char>(scanline_width >> 8);
rgbe[3] = scanline_width & 0xFF;
if (fwrite(rgbe, sizeof(rgbe), 1, fp) < 1) {
free(buffer);
return rgbe_error(rgbe_write_error,NULL);
}
for(i=0;i<scanline_width;i++) {
float2rgbe(rgbe,data[RGBE_DATA_RED],
data[RGBE_DATA_GREEN],data[RGBE_DATA_BLUE]);
buffer[i] = rgbe[0];
buffer[i+scanline_width] = rgbe[1];
buffer[i+2*scanline_width] = rgbe[2];
buffer[i+3*scanline_width] = rgbe[3];
data += RGBE_DATA_SIZE;
}
/* write out each of the four channels separately run length encoded */
/* first red, then green, then blue, then exponent */
for(i=0;i<4;i++) {
if ((err = RGBE_WriteBytes_RLE(fp,&buffer[i*scanline_width],
scanline_width)) != RGBE_RETURN_SUCCESS) {
free(buffer);
return err;
}
}
}
free(buffer);
return RGBE_RETURN_SUCCESS;
}
int RGBE_ReadPixels_RLE(FILE *fp, float *data, int scanline_width,
int num_scanlines)
{
unsigned char rgbe[4], *scanline_buffer, *ptr, *ptr_end;
int i, count;
unsigned char buf[2];
if ((scanline_width < 8)||(scanline_width > 0x7fff))
/* run length encoding is not allowed so read flat*/
return RGBE_ReadPixels(fp,data,scanline_width*num_scanlines);
scanline_buffer = NULL;
/* read in each successive scanline */
while(num_scanlines > 0) {
if (fread(rgbe,sizeof(rgbe),1,fp) < 1) {
free(scanline_buffer);
return rgbe_error(rgbe_read_error,NULL);
}
if ((rgbe[0] != 2)||(rgbe[1] != 2)||(rgbe[2] & 0x80)) {
/* this file is not run length encoded */
rgbe2float(&data[RGBE_DATA_RED],&data[RGBE_DATA_GREEN],&data[RGBE_DATA_BLUE],rgbe);
data += RGBE_DATA_SIZE;
free(scanline_buffer);
return RGBE_ReadPixels(fp,data,scanline_width*num_scanlines-1);
}
if ((((int)rgbe[2])<<8 | rgbe[3]) != scanline_width) {
free(scanline_buffer);
return rgbe_error(rgbe_format_error,"wrong scanline width");
}
if (scanline_buffer == NULL)
scanline_buffer = (unsigned char *)
malloc(sizeof(unsigned char)*4*scanline_width);
if (scanline_buffer == NULL)
return rgbe_error(rgbe_memory_error,"unable to allocate buffer space");
ptr = &scanline_buffer[0];
/* read each of the four channels for the scanline into the buffer */
for(i=0;i<4;i++) {
ptr_end = &scanline_buffer[(i+1)*scanline_width];
while(ptr < ptr_end) {
if (fread(buf,sizeof(buf[0])*2,1,fp) < 1) {
free(scanline_buffer);
return rgbe_error(rgbe_read_error,NULL);
}
if (buf[0] > 128) {
/* a run of the same value */
count = buf[0]-128;
if ((count == 0)||(count > ptr_end - ptr)) {
free(scanline_buffer);
return rgbe_error(rgbe_format_error,"bad scanline data");
}
while(count-- > 0)
*ptr++ = buf[1];
}
else {
/* a non-run */
count = buf[0];
if ((count == 0)||(count > ptr_end - ptr)) {
free(scanline_buffer);
return rgbe_error(rgbe_format_error,"bad scanline data");
}
*ptr++ = buf[1];
if (--count > 0) {
if (fread(ptr,sizeof(*ptr)*count,1,fp) < 1) {
free(scanline_buffer);
return rgbe_error(rgbe_read_error,NULL);
}
ptr += count;
}
}
}
}
/* now convert data from buffer into floats */
for(i=0;i<scanline_width;i++) {
rgbe[0] = scanline_buffer[i];
rgbe[1] = scanline_buffer[i+scanline_width];
rgbe[2] = scanline_buffer[i+2*scanline_width];
rgbe[3] = scanline_buffer[i+3*scanline_width];
rgbe2float(&data[RGBE_DATA_RED],&data[RGBE_DATA_GREEN],
&data[RGBE_DATA_BLUE],rgbe);
data += RGBE_DATA_SIZE;
}
num_scanlines--;
}
free(scanline_buffer);
return RGBE_RETURN_SUCCESS;
}

View File

@@ -0,0 +1,89 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _RGBE_HDR_H_
#define _RGBE_HDR_H_
// posted to http://www.graphics.cornell.edu/~bjw/
// written by Bruce Walter (bjw@graphics.cornell.edu) 5/26/95
// based on code written by Greg Ward
#include <stdio.h>
typedef struct {
int valid; /* indicate which fields are valid */
char programtype[16]; /* listed at beginning of file to identify it
* after "#?". defaults to "RGBE" */
float gamma; /* image has already been gamma corrected with
* given gamma. defaults to 1.0 (no correction) */
float exposure; /* a value of 1.0 in an image corresponds to
* <exposure> watts/steradian/m^2.
* defaults to 1.0 */
} rgbe_header_info;
/* flags indicating which fields in an rgbe_header_info are valid */
#define RGBE_VALID_PROGRAMTYPE 0x01
#define RGBE_VALID_GAMMA 0x02
#define RGBE_VALID_EXPOSURE 0x04
/* return codes for rgbe routines */
#define RGBE_RETURN_SUCCESS 0
#define RGBE_RETURN_FAILURE -1
/* read or write headers */
/* you may set rgbe_header_info to null if you want to */
int RGBE_WriteHeader(FILE *fp, int width, int height, rgbe_header_info *info);
int RGBE_ReadHeader(FILE *fp, int *width, int *height, rgbe_header_info *info);
/* read or write pixels */
/* can read or write pixels in chunks of any size including single pixels*/
int RGBE_WritePixels(FILE *fp, float *data, int numpixels);
int RGBE_ReadPixels(FILE *fp, float *data, int numpixels);
/* read or write run length encoded files */
/* must be called to read or write whole scanlines */
int RGBE_WritePixels_RLE(FILE *fp, float *data, int scanline_width,
int num_scanlines);
int RGBE_ReadPixels_RLE(FILE *fp, float *data, int scanline_width,
int num_scanlines);
#endif/*_RGBE_HDR_H_*/

View File

@@ -0,0 +1,609 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "utils.hpp"
namespace cv {
int validateToInt(size_t sz)
{
int valueInt = (int)sz;
CV_Assert((size_t)valueInt == sz);
return valueInt;
}
#define SCALE 14
#define cR (int)(0.299*(1 << SCALE) + 0.5)
#define cG (int)(0.587*(1 << SCALE) + 0.5)
#define cB ((1 << SCALE) - cR - cG)
void icvCvt_BGR2Gray_8u_C3C1R( const uchar* rgb, int rgb_step,
uchar* gray, int gray_step,
Size size, int _swap_rb )
{
int i;
for( ; size.height--; gray += gray_step )
{
short cRGB0 = cR;
short cRGB2 = cB;
if (_swap_rb) std::swap(cRGB0, cRGB2);
for( i = 0; i < size.width; i++, rgb += 3 )
{
int t = descale( rgb[0]*cRGB0 + rgb[1]*cG + rgb[2]*cRGB2, SCALE );
gray[i] = (uchar)t;
}
rgb += rgb_step - size.width*3;
}
}
void icvCvt_BGRA2Gray_16u_CnC1R( const ushort* rgb, int rgb_step,
ushort* gray, int gray_step,
Size size, int ncn, int _swap_rb )
{
int i;
for( ; size.height--; gray += gray_step )
{
short cRGB0 = cR;
short cRGB2 = cB;
if (_swap_rb) std::swap(cRGB0, cRGB2);
for( i = 0; i < size.width; i++, rgb += ncn )
{
int t = descale( rgb[0]*cRGB0 + rgb[1]*cG + rgb[2]*cRGB2, SCALE );
gray[i] = (ushort)t;
}
rgb += rgb_step - size.width*ncn;
}
}
void icvCvt_BGRA2Gray_8u_C4C1R( const uchar* rgba, int rgba_step,
uchar* gray, int gray_step,
Size size, int _swap_rb )
{
int i;
for( ; size.height--; gray += gray_step )
{
short cRGB0 = cR;
short cRGB2 = cB;
if (_swap_rb) std::swap(cRGB0, cRGB2);
for( i = 0; i < size.width; i++, rgba += 4 )
{
int t = descale( rgba[0]*cRGB0 + rgba[1]*cG + rgba[2]*cRGB2, SCALE );
gray[i] = (uchar)t;
}
rgba += rgba_step - size.width*4;
}
}
void icvCvt_Gray2BGR_8u_C1C3R( const uchar* gray, int gray_step,
uchar* bgr, int bgr_step, Size size )
{
int i;
for( ; size.height--; gray += gray_step )
{
for( i = 0; i < size.width; i++, bgr += 3 )
{
bgr[0] = bgr[1] = bgr[2] = gray[i];
}
bgr += bgr_step - size.width*3;
}
}
void icvCvt_Gray2BGR_16u_C1C3R( const ushort* gray, int gray_step,
ushort* bgr, int bgr_step, Size size )
{
int i;
for( ; size.height--; gray += gray_step/sizeof(gray[0]) )
{
for( i = 0; i < size.width; i++, bgr += 3 )
{
bgr[0] = bgr[1] = bgr[2] = gray[i];
}
bgr += bgr_step/sizeof(bgr[0]) - size.width*3;
}
}
void icvCvt_BGRA2BGR_8u_C4C3R( const uchar* bgra, int bgra_step,
uchar* bgr, int bgr_step,
Size size, int _swap_rb )
{
int i;
int swap_rb = _swap_rb ? 2 : 0;
for( ; size.height--; )
{
for( i = 0; i < size.width; i++, bgr += 3, bgra += 4 )
{
uchar t0 = bgra[swap_rb], t1 = bgra[1];
bgr[0] = t0; bgr[1] = t1;
t0 = bgra[swap_rb^2]; bgr[2] = t0;
}
bgr += bgr_step - size.width*3;
bgra += bgra_step - size.width*4;
}
}
void icvCvt_BGRA2BGR_16u_C4C3R( const ushort* bgra, int bgra_step,
ushort* bgr, int bgr_step,
Size size, int _swap_rb )
{
int i;
int swap_rb = _swap_rb ? 2 : 0;
for( ; size.height--; )
{
for( i = 0; i < size.width; i++, bgr += 3, bgra += 4 )
{
ushort t0 = bgra[swap_rb], t1 = bgra[1];
bgr[0] = t0; bgr[1] = t1;
t0 = bgra[swap_rb^2]; bgr[2] = t0;
}
bgr += bgr_step/sizeof(bgr[0]) - size.width*3;
bgra += bgra_step/sizeof(bgra[0]) - size.width*4;
}
}
void icvCvt_BGRA2RGBA_8u_C4R( const uchar* bgra, int bgra_step,
uchar* rgba, int rgba_step, Size size )
{
int i;
for( ; size.height--; )
{
for( i = 0; i < size.width; i++, bgra += 4, rgba += 4 )
{
uchar t0 = bgra[0], t1 = bgra[1];
uchar t2 = bgra[2], t3 = bgra[3];
rgba[0] = t2; rgba[1] = t1;
rgba[2] = t0; rgba[3] = t3;
}
bgra += bgra_step - size.width*4;
rgba += rgba_step - size.width*4;
}
}
void icvCvt_BGRA2RGBA_16u_C4R( const ushort* bgra, int bgra_step,
ushort* rgba, int rgba_step, Size size )
{
int i;
for( ; size.height--; )
{
for( i = 0; i < size.width; i++, bgra += 4, rgba += 4 )
{
ushort t0 = bgra[0], t1 = bgra[1];
ushort t2 = bgra[2], t3 = bgra[3];
rgba[0] = t2; rgba[1] = t1;
rgba[2] = t0; rgba[3] = t3;
}
bgra += bgra_step/sizeof(bgra[0]) - size.width*4;
rgba += rgba_step/sizeof(rgba[0]) - size.width*4;
}
}
void icvCvt_BGR2RGB_8u_C3R( const uchar* bgr, int bgr_step,
uchar* rgb, int rgb_step, Size size )
{
int i;
for( ; size.height--; )
{
for( i = 0; i < size.width; i++, bgr += 3, rgb += 3 )
{
uchar t0 = bgr[0], t1 = bgr[1], t2 = bgr[2];
rgb[2] = t0; rgb[1] = t1; rgb[0] = t2;
}
bgr += bgr_step - size.width*3;
rgb += rgb_step - size.width*3;
}
}
void icvCvt_BGR2RGB_16u_C3R( const ushort* bgr, int bgr_step,
ushort* rgb, int rgb_step, Size size )
{
int i;
for( ; size.height--; )
{
for( i = 0; i < size.width; i++, bgr += 3, rgb += 3 )
{
ushort t0 = bgr[0], t1 = bgr[1], t2 = bgr[2];
rgb[2] = t0; rgb[1] = t1; rgb[0] = t2;
}
bgr += bgr_step - size.width*3;
rgb += rgb_step - size.width*3;
}
}
typedef unsigned short ushort;
void icvCvt_BGR5552Gray_8u_C2C1R( const uchar* bgr555, int bgr555_step,
uchar* gray, int gray_step, Size size )
{
int i;
for( ; size.height--; gray += gray_step, bgr555 += bgr555_step )
{
for( i = 0; i < size.width; i++ )
{
int t = descale( ((((ushort*)bgr555)[i] << 3) & 0xf8)*cB +
((((ushort*)bgr555)[i] >> 2) & 0xf8)*cG +
((((ushort*)bgr555)[i] >> 7) & 0xf8)*cR, SCALE );
gray[i] = (uchar)t;
}
}
}
void icvCvt_BGR5652Gray_8u_C2C1R( const uchar* bgr565, int bgr565_step,
uchar* gray, int gray_step, Size size )
{
int i;
for( ; size.height--; gray += gray_step, bgr565 += bgr565_step )
{
for( i = 0; i < size.width; i++ )
{
int t = descale( ((((ushort*)bgr565)[i] << 3) & 0xf8)*cB +
((((ushort*)bgr565)[i] >> 3) & 0xfc)*cG +
((((ushort*)bgr565)[i] >> 8) & 0xf8)*cR, SCALE );
gray[i] = (uchar)t;
}
}
}
void icvCvt_BGR5552BGR_8u_C2C3R( const uchar* bgr555, int bgr555_step,
uchar* bgr, int bgr_step, Size size )
{
int i;
for( ; size.height--; bgr555 += bgr555_step )
{
for( i = 0; i < size.width; i++, bgr += 3 )
{
int t0 = (((ushort*)bgr555)[i] << 3) & 0xf8;
int t1 = (((ushort*)bgr555)[i] >> 2) & 0xf8;
int t2 = (((ushort*)bgr555)[i] >> 7) & 0xf8;
bgr[0] = (uchar)t0; bgr[1] = (uchar)t1; bgr[2] = (uchar)t2;
}
bgr += bgr_step - size.width*3;
}
}
void icvCvt_BGR5652BGR_8u_C2C3R( const uchar* bgr565, int bgr565_step,
uchar* bgr, int bgr_step, Size size )
{
int i;
for( ; size.height--; bgr565 += bgr565_step )
{
for( i = 0; i < size.width; i++, bgr += 3 )
{
int t0 = (((ushort*)bgr565)[i] << 3) & 0xf8;
int t1 = (((ushort*)bgr565)[i] >> 3) & 0xfc;
int t2 = (((ushort*)bgr565)[i] >> 8) & 0xf8;
bgr[0] = (uchar)t0; bgr[1] = (uchar)t1; bgr[2] = (uchar)t2;
}
bgr += bgr_step - size.width*3;
}
}
void icvCvt_CMYK2BGR_8u_C4C3R( const uchar* cmyk, int cmyk_step,
uchar* bgr, int bgr_step, Size size )
{
int i;
for( ; size.height--; )
{
for( i = 0; i < size.width; i++, bgr += 3, cmyk += 4 )
{
int c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
c = k - ((255 - c)*k>>8);
m = k - ((255 - m)*k>>8);
y = k - ((255 - y)*k>>8);
bgr[2] = (uchar)c; bgr[1] = (uchar)m; bgr[0] = (uchar)y;
}
bgr += bgr_step - size.width*3;
cmyk += cmyk_step - size.width*4;
}
}
void icvCvt_CMYK2Gray_8u_C4C1R( const uchar* cmyk, int cmyk_step,
uchar* gray, int gray_step, Size size )
{
int i;
for( ; size.height--; )
{
for( i = 0; i < size.width; i++, cmyk += 4 )
{
int c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
c = k - ((255 - c)*k>>8);
m = k - ((255 - m)*k>>8);
y = k - ((255 - y)*k>>8);
int t = descale( y*cB + m*cG + c*cR, SCALE );
gray[i] = (uchar)t;
}
gray += gray_step;
cmyk += cmyk_step - size.width*4;
}
}
void CvtPaletteToGray( const PaletteEntry* palette, uchar* grayPalette, int entries )
{
int i;
for( i = 0; i < entries; i++ )
{
icvCvt_BGR2Gray_8u_C3C1R( (uchar*)(palette + i), 0, grayPalette + i, 0, Size(1,1) );
}
}
void FillGrayPalette( PaletteEntry* palette, int bpp, bool negative )
{
int i, length = 1 << bpp;
int xor_mask = negative ? 255 : 0;
for( i = 0; i < length; i++ )
{
int val = (i * 255/(length - 1)) ^ xor_mask;
palette[i].b = palette[i].g = palette[i].r = (uchar)val;
palette[i].a = 0;
}
}
bool IsColorPalette( PaletteEntry* palette, int bpp )
{
int i, length = 1 << bpp;
for( i = 0; i < length; i++ )
{
if( palette[i].b != palette[i].g ||
palette[i].b != palette[i].r )
return true;
}
return false;
}
uchar* FillUniColor( uchar* data, uchar*& line_end,
int step, int width3,
int& y, int height,
int count3, PaletteEntry clr )
{
do
{
uchar* end = data + count3;
if( end > line_end )
end = line_end;
count3 -= (int)(end - data);
for( ; data < end; data += 3 )
{
WRITE_PIX( data, clr );
}
if( data >= line_end )
{
line_end += step;
data = line_end - width3;
if( ++y >= height ) break;
}
}
while( count3 > 0 );
return data;
}
uchar* FillUniGray( uchar* data, uchar*& line_end,
int step, int width,
int& y, int height,
int count, uchar clr )
{
do
{
uchar* end = data + count;
if( end > line_end )
end = line_end;
count -= (int)(end - data);
for( ; data < end; data++ )
{
*data = clr;
}
if( data >= line_end )
{
line_end += step;
data = line_end - width;
if( ++y >= height ) break;
}
}
while( count > 0 );
return data;
}
uchar* FillColorRow8( uchar* data, uchar* indices, int len, PaletteEntry* palette )
{
uchar* end = data + len*3;
while( (data += 3) < end )
{
*((PaletteEntry*)(data-3)) = palette[*indices++];
}
PaletteEntry clr = palette[indices[0]];
WRITE_PIX( data - 3, clr );
return data;
}
uchar* FillGrayRow8( uchar* data, uchar* indices, int len, uchar* palette )
{
int i;
for( i = 0; i < len; i++ )
{
data[i] = palette[indices[i]];
}
return data + len;
}
uchar* FillColorRow4( uchar* data, uchar* indices, int len, PaletteEntry* palette )
{
uchar* end = data + len*3;
while( (data += 6) < end )
{
int idx = *indices++;
*((PaletteEntry*)(data-6)) = palette[idx >> 4];
*((PaletteEntry*)(data-3)) = palette[idx & 15];
}
int idx = indices[0];
PaletteEntry clr = palette[idx >> 4];
WRITE_PIX( data - 6, clr );
if( data == end )
{
clr = palette[idx & 15];
WRITE_PIX( data - 3, clr );
}
return end;
}
uchar* FillGrayRow4( uchar* data, uchar* indices, int len, uchar* palette )
{
uchar* end = data + len;
while( (data += 2) < end )
{
int idx = *indices++;
data[-2] = palette[idx >> 4];
data[-1] = palette[idx & 15];
}
int idx = indices[0];
uchar clr = palette[idx >> 4];
data[-2] = clr;
if( data == end )
{
clr = palette[idx & 15];
data[-1] = clr;
}
return end;
}
uchar* FillColorRow1( uchar* data, uchar* indices, int len, PaletteEntry* palette )
{
uchar* end = data + len*3;
const PaletteEntry p0 = palette[0], p1 = palette[1];
while( (data += 24) < end )
{
int idx = *indices++;
*((PaletteEntry*)(data - 24)) = (idx & 128) ? p1 : p0;
*((PaletteEntry*)(data - 21)) = (idx & 64) ? p1 : p0;
*((PaletteEntry*)(data - 18)) = (idx & 32) ? p1 : p0;
*((PaletteEntry*)(data - 15)) = (idx & 16) ? p1 : p0;
*((PaletteEntry*)(data - 12)) = (idx & 8) ? p1 : p0;
*((PaletteEntry*)(data - 9)) = (idx & 4) ? p1 : p0;
*((PaletteEntry*)(data - 6)) = (idx & 2) ? p1 : p0;
*((PaletteEntry*)(data - 3)) = (idx & 1) ? p1 : p0;
}
int idx = indices[0];
for( data -= 24; data < end; data += 3, idx += idx )
{
const PaletteEntry clr = (idx & 128) ? p1 : p0;
WRITE_PIX( data, clr );
}
return data;
}
uchar* FillGrayRow1( uchar* data, uchar* indices, int len, uchar* palette )
{
uchar* end = data + len;
const uchar p0 = palette[0], p1 = palette[1];
while( (data += 8) < end )
{
int idx = *indices++;
*((uchar*)(data - 8)) = (idx & 128) ? p1 : p0;
*((uchar*)(data - 7)) = (idx & 64) ? p1 : p0;
*((uchar*)(data - 6)) = (idx & 32) ? p1 : p0;
*((uchar*)(data - 5)) = (idx & 16) ? p1 : p0;
*((uchar*)(data - 4)) = (idx & 8) ? p1 : p0;
*((uchar*)(data - 3)) = (idx & 4) ? p1 : p0;
*((uchar*)(data - 2)) = (idx & 2) ? p1 : p0;
*((uchar*)(data - 1)) = (idx & 1) ? p1 : p0;
}
int idx = indices[0];
for( data -= 8; data < end; data++, idx += idx )
{
data[0] = (idx & 128) ? p1 : p0;
}
return data;
}
} // namespace

View File

@@ -0,0 +1,143 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef _UTILS_H_
#define _UTILS_H_
namespace cv {
int validateToInt(size_t step);
template <typename _Tp> static inline
size_t safeCastToSizeT(const _Tp v_origin, const char* msg)
{
const size_t value_cast = (size_t)v_origin;
if ((_Tp)value_cast != v_origin)
CV_Error(cv::Error::StsError, msg ? msg : "Can't cast value into size_t");
return value_cast;
}
struct PaletteEntry
{
unsigned char b, g, r, a;
};
#define WRITE_PIX( ptr, clr ) \
(((uchar*)(ptr))[0] = (clr).b, \
((uchar*)(ptr))[1] = (clr).g, \
((uchar*)(ptr))[2] = (clr).r)
#define descale(x,n) (((x) + (1 << ((n)-1))) >> (n))
#define saturate(x) (uchar)(((x) & ~255) == 0 ? (x) : ~((x)>>31))
void icvCvt_BGR2Gray_8u_C3C1R( const uchar* bgr, int bgr_step,
uchar* gray, int gray_step,
Size size, int swap_rb=0 );
void icvCvt_BGRA2Gray_8u_C4C1R( const uchar* bgra, int bgra_step,
uchar* gray, int gray_step,
Size size, int swap_rb=0 );
void icvCvt_BGRA2Gray_16u_CnC1R( const ushort* bgra, int bgra_step,
ushort* gray, int gray_step,
Size size, int ncn, int swap_rb=0 );
void icvCvt_Gray2BGR_8u_C1C3R( const uchar* gray, int gray_step,
uchar* bgr, int bgr_step, Size size );
void icvCvt_Gray2BGR_16u_C1C3R( const ushort* gray, int gray_step,
ushort* bgr, int bgr_step, Size size );
void icvCvt_BGRA2BGR_8u_C4C3R( const uchar* bgra, int bgra_step,
uchar* bgr, int bgr_step,
Size size, int swap_rb=0 );
void icvCvt_BGRA2BGR_16u_C4C3R( const ushort* bgra, int bgra_step,
ushort* bgr, int bgr_step,
Size size, int _swap_rb );
void icvCvt_BGR2RGB_8u_C3R( const uchar* bgr, int bgr_step,
uchar* rgb, int rgb_step, Size size );
#define icvCvt_RGB2BGR_8u_C3R icvCvt_BGR2RGB_8u_C3R
void icvCvt_BGR2RGB_16u_C3R( const ushort* bgr, int bgr_step,
ushort* rgb, int rgb_step, Size size );
#define icvCvt_RGB2BGR_16u_C3R icvCvt_BGR2RGB_16u_C3R
void icvCvt_BGRA2RGBA_8u_C4R( const uchar* bgra, int bgra_step,
uchar* rgba, int rgba_step, Size size );
#define icvCvt_RGBA2BGRA_8u_C4R icvCvt_BGRA2RGBA_8u_C4R
void icvCvt_BGRA2RGBA_16u_C4R( const ushort* bgra, int bgra_step,
ushort* rgba, int rgba_step, Size size );
#define icvCvt_RGBA2BGRA_16u_C4R icvCvt_BGRA2RGBA_16u_C4R
void icvCvt_BGR5552Gray_8u_C2C1R( const uchar* bgr555, int bgr555_step,
uchar* gray, int gray_step, Size size );
void icvCvt_BGR5652Gray_8u_C2C1R( const uchar* bgr565, int bgr565_step,
uchar* gray, int gray_step, Size size );
void icvCvt_BGR5552BGR_8u_C2C3R( const uchar* bgr555, int bgr555_step,
uchar* bgr, int bgr_step, Size size );
void icvCvt_BGR5652BGR_8u_C2C3R( const uchar* bgr565, int bgr565_step,
uchar* bgr, int bgr_step, Size size );
void icvCvt_CMYK2BGR_8u_C4C3R( const uchar* cmyk, int cmyk_step,
uchar* bgr, int bgr_step, Size size );
void icvCvt_CMYK2Gray_8u_C4C1R( const uchar* ycck, int ycck_step,
uchar* gray, int gray_step, Size size );
void FillGrayPalette( PaletteEntry* palette, int bpp, bool negative = false );
bool IsColorPalette( PaletteEntry* palette, int bpp );
void CvtPaletteToGray( const PaletteEntry* palette, uchar* grayPalette, int entries );
uchar* FillUniColor( uchar* data, uchar*& line_end, int step, int width3,
int& y, int height, int count3, PaletteEntry clr );
uchar* FillUniGray( uchar* data, uchar*& line_end, int step, int width3,
int& y, int height, int count3, uchar clr );
uchar* FillColorRow8( uchar* data, uchar* indices, int len, PaletteEntry* palette );
uchar* FillGrayRow8( uchar* data, uchar* indices, int len, uchar* palette );
uchar* FillColorRow4( uchar* data, uchar* indices, int len, PaletteEntry* palette );
uchar* FillGrayRow4( uchar* data, uchar* indices, int len, uchar* palette );
uchar* FillColorRow1( uchar* data, uchar* indices, int len, PaletteEntry* palette );
uchar* FillGrayRow1( uchar* data, uchar* indices, int len, uchar* palette );
CV_INLINE bool isBigEndian( void )
{
return (((const int*)"\0\x1\x2\x3\x4\x5\x6\x7")[0] & 255) != 0;
}
} // namespace
#endif/*_UTILS_H_*/

View File

@@ -0,0 +1,117 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
//#define GENERATE_DATA
namespace opencv_test { namespace {
TEST(Imgcodecs_EXR, readWrite_32FC1)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filenameInput = root + "readwrite/test32FC1.exr";
const string filenameOutput = cv::tempfile(".exr");
#ifndef GENERATE_DATA
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
#else
const Size sz(64, 32);
Mat img(sz, CV_32FC1, Scalar(0.5, 0.1, 1));
img(Rect(10, 5, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 0, 0));
ASSERT_TRUE(cv::imwrite(filenameInput, img));
#endif
ASSERT_FALSE(img.empty());
ASSERT_EQ(CV_32FC1,img.type());
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
ASSERT_EQ(img2.type(), img.type());
ASSERT_EQ(img2.size(), img.size());
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
EXPECT_EQ(0, remove(filenameOutput.c_str()));
}
TEST(Imgcodecs_EXR, readWrite_32FC3)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filenameInput = root + "readwrite/test32FC3.exr";
const string filenameOutput = cv::tempfile(".exr");
#ifndef GENERATE_DATA
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
#else
const Size sz(64, 32);
Mat img(sz, CV_32FC3, Scalar(0.5, 0.1, 1));
img(Rect(10, 5, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 0, 0));
ASSERT_TRUE(cv::imwrite(filenameInput, img));
#endif
ASSERT_FALSE(img.empty());
ASSERT_EQ(CV_32FC3, img.type());
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
ASSERT_EQ(img2.type(), img.type());
ASSERT_EQ(img2.size(), img.size());
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
EXPECT_EQ(0, remove(filenameOutput.c_str()));
}
TEST(Imgcodecs_EXR, readWrite_32FC1_half)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filenameInput = root + "readwrite/test32FC1_half.exr";
const string filenameOutput = cv::tempfile(".exr");
std::vector<int> params;
params.push_back(IMWRITE_EXR_TYPE);
params.push_back(IMWRITE_EXR_TYPE_HALF);
#ifndef GENERATE_DATA
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
#else
const Size sz(64, 32);
Mat img(sz, CV_32FC1, Scalar(0.5, 0.1, 1));
img(Rect(10, 5, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 0, 0));
ASSERT_TRUE(cv::imwrite(filenameInput, img, params));
#endif
ASSERT_FALSE(img.empty());
ASSERT_EQ(CV_32FC1,img.type());
ASSERT_TRUE(cv::imwrite(filenameOutput, img, params));
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
ASSERT_EQ(img2.type(), img.type());
ASSERT_EQ(img2.size(), img.size());
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
EXPECT_EQ(0, remove(filenameOutput.c_str()));
}
TEST(Imgcodecs_EXR, readWrite_32FC3_half)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filenameInput = root + "readwrite/test32FC3_half.exr";
const string filenameOutput = cv::tempfile(".exr");
std::vector<int> params;
params.push_back(IMWRITE_EXR_TYPE);
params.push_back(IMWRITE_EXR_TYPE_HALF);
#ifndef GENERATE_DATA
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
#else
const Size sz(64, 32);
Mat img(sz, CV_32FC3, Scalar(0.5, 0.1, 1));
img(Rect(10, 5, sz.width - 30, sz.height - 20)).setTo(Scalar(1, 0, 0));
ASSERT_TRUE(cv::imwrite(filenameInput, img, params));
#endif
ASSERT_FALSE(img.empty());
ASSERT_EQ(CV_32FC3, img.type());
ASSERT_TRUE(cv::imwrite(filenameOutput, img, params));
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
ASSERT_EQ(img2.type(), img.type());
ASSERT_EQ(img2.size(), img.size());
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
EXPECT_EQ(0, remove(filenameOutput.c_str()));
}
}} // namespace

View File

@@ -0,0 +1,394 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
namespace opencv_test { namespace {
typedef tuple<string, int> File_Mode;
typedef testing::TestWithParam<File_Mode> Imgcodecs_FileMode;
TEST_P(Imgcodecs_FileMode, regression)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filename = root + get<0>(GetParam());
const int mode = get<1>(GetParam());
const Mat single = imread(filename, mode);
ASSERT_FALSE(single.empty());
vector<Mat> pages;
ASSERT_TRUE(imreadmulti(filename, pages, mode));
ASSERT_FALSE(pages.empty());
const Mat page = pages[0];
ASSERT_FALSE(page.empty());
EXPECT_EQ(page.channels(), single.channels());
EXPECT_EQ(page.depth(), single.depth());
EXPECT_EQ(page.size().height, single.size().height);
EXPECT_EQ(page.size().width, single.size().width);
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), page, single);
}
const string all_images[] =
{
#if defined(HAVE_JASPER) && defined(OPENCV_IMGCODECS_ENABLE_JASPER_TESTS)
"readwrite/Rome.jp2",
"readwrite/Bretagne2.jp2",
"readwrite/Bretagne2.jp2",
"readwrite/Grey.jp2",
"readwrite/Grey.jp2",
#endif
#ifdef HAVE_GDCM
"readwrite/int16-mono1.dcm",
"readwrite/uint8-mono2.dcm",
"readwrite/uint16-mono2.dcm",
"readwrite/uint8-rgb.dcm",
#endif
"readwrite/color_palette_alpha.png",
"readwrite/multipage.tif",
"readwrite/ordinary.bmp",
"readwrite/rle8.bmp",
"readwrite/test_1_c1.jpg",
#ifdef HAVE_IMGCODEC_HDR
"readwrite/rle.hdr"
#endif
};
const int basic_modes[] =
{
IMREAD_UNCHANGED,
IMREAD_GRAYSCALE,
IMREAD_COLOR,
IMREAD_ANYDEPTH,
IMREAD_ANYCOLOR
};
INSTANTIATE_TEST_CASE_P(All, Imgcodecs_FileMode,
testing::Combine(
testing::ValuesIn(all_images),
testing::ValuesIn(basic_modes)));
// GDAL does not support "hdr", "dcm" and have problems with "jp2"
struct notForGDAL {
bool operator()(const string &name) const {
const string &ext = name.substr(name.size() - 3, 3);
return ext == "hdr" || ext == "dcm" || ext == "jp2" ||
name.find("rle8.bmp") != std::string::npos;
}
};
inline vector<string> gdal_images()
{
vector<string> res;
std::back_insert_iterator< vector<string> > it(res);
std::remove_copy_if(all_images, all_images + sizeof(all_images)/sizeof(all_images[0]), it, notForGDAL());
return res;
}
INSTANTIATE_TEST_CASE_P(GDAL, Imgcodecs_FileMode,
testing::Combine(
testing::ValuesIn(gdal_images()),
testing::Values(IMREAD_LOAD_GDAL)));
//==================================================================================================
typedef tuple<string, Size> Ext_Size;
typedef testing::TestWithParam<Ext_Size> Imgcodecs_ExtSize;
TEST_P(Imgcodecs_ExtSize, write_imageseq)
{
const string ext = get<0>(GetParam());
const Size size = get<1>(GetParam());
const Point2i center = Point2i(size.width / 2, size.height / 2);
const int radius = std::min(size.height, size.width / 4);
for (int cn = 1; cn <= 4; cn++)
{
SCOPED_TRACE(format("channels %d", cn));
std::vector<int> parameters;
if (cn == 2)
continue;
if (cn == 4 && ext != ".tiff")
continue;
if (cn > 1 && (ext == ".pbm" || ext == ".pgm"))
continue;
if (cn != 3 && ext == ".ppm")
continue;
string filename = cv::tempfile(format("%d%s", cn, ext.c_str()).c_str());
Mat img_gt(size, CV_MAKETYPE(CV_8U, cn), Scalar::all(0));
circle(img_gt, center, radius, Scalar::all(255));
#if 1
if (ext == ".pbm" || ext == ".pgm" || ext == ".ppm")
{
parameters.push_back(IMWRITE_PXM_BINARY);
parameters.push_back(0);
}
#endif
ASSERT_TRUE(imwrite(filename, img_gt, parameters));
Mat img = imread(filename, IMREAD_UNCHANGED);
ASSERT_FALSE(img.empty());
EXPECT_EQ(img.size(), img.size());
EXPECT_EQ(img.type(), img.type());
EXPECT_EQ(cn, img.channels());
if (ext == ".jpg")
{
// JPEG format does not provide 100% accuracy
// using fuzzy image comparison
double n = cvtest::norm(img, img_gt, NORM_L1);
double expected = 0.07 * img.size().area();
EXPECT_LT(n, expected);
EXPECT_PRED_FORMAT2(cvtest::MatComparator(10, 0), img, img_gt);
}
else if (ext == ".pfm")
{
img_gt.convertTo(img_gt, CV_MAKETYPE(CV_32F, img.channels()));
double n = cvtest::norm(img, img_gt, NORM_L2);
EXPECT_LT(n, 1.);
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img, img_gt);
}
else
{
double n = cvtest::norm(img, img_gt, NORM_L2);
EXPECT_LT(n, 1.);
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img, img_gt);
}
#if 0
imshow("loaded", img);
waitKey(0);
#else
EXPECT_EQ(0, remove(filename.c_str()));
#endif
}
}
const string all_exts[] =
{
#ifdef HAVE_PNG
".png",
#endif
#ifdef HAVE_TIFF
".tiff",
#endif
#ifdef HAVE_JPEG
".jpg",
#endif
".bmp",
#ifdef HAVE_IMGCODEC_PXM
".pam",
".ppm",
".pgm",
".pbm",
".pnm",
#endif
#ifdef HAVE_IMGCODEC_PFM
".pfm",
#endif
};
vector<Size> all_sizes()
{
vector<Size> res;
for (int k = 1; k <= 5; ++k)
res.push_back(Size(640 * k, 480 * k));
return res;
}
INSTANTIATE_TEST_CASE_P(All, Imgcodecs_ExtSize,
testing::Combine(
testing::ValuesIn(all_exts),
testing::ValuesIn(all_sizes())));
#ifdef HAVE_IMGCODEC_PXM
typedef testing::TestWithParam<bool> Imgcodecs_pbm;
TEST_P(Imgcodecs_pbm, write_read)
{
bool binary = GetParam();
const String ext = "pbm";
const string full_name = cv::tempfile(ext.c_str());
Size size(640, 480);
const Point2i center = Point2i(size.width / 2, size.height / 2);
const int radius = std::min(size.height, size.width / 4);
Mat image(size, CV_8UC1, Scalar::all(0));
circle(image, center, radius, Scalar::all(255));
vector<int> pbm_params;
pbm_params.push_back(IMWRITE_PXM_BINARY);
pbm_params.push_back(binary);
imwrite( full_name, image, pbm_params );
Mat loaded = imread(full_name, IMREAD_UNCHANGED);
ASSERT_FALSE(loaded.empty());
EXPECT_EQ(0, cvtest::norm(loaded, image, NORM_INF));
FILE *f = fopen(full_name.c_str(), "rb");
ASSERT_TRUE(f != NULL);
ASSERT_EQ('P', getc(f));
ASSERT_EQ('1' + (binary ? 3 : 0), getc(f));
fclose(f);
EXPECT_EQ(0, remove(full_name.c_str()));
}
INSTANTIATE_TEST_CASE_P(All, Imgcodecs_pbm, testing::Bool());
#endif
//==================================================================================================
TEST(Imgcodecs_Bmp, read_rle8)
{
const string root = cvtest::TS::ptr()->get_data_path();
Mat rle = imread(root + "readwrite/rle8.bmp");
ASSERT_FALSE(rle.empty());
Mat ord = imread(root + "readwrite/ordinary.bmp");
ASSERT_FALSE(ord.empty());
EXPECT_LE(cvtest::norm(rle, ord, NORM_L2), 1.e-10);
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), rle, ord);
}
#ifdef HAVE_IMGCODEC_HDR
TEST(Imgcodecs_Hdr, regression)
{
string folder = string(cvtest::TS::ptr()->get_data_path()) + "/readwrite/";
string name_rle = folder + "rle.hdr";
string name_no_rle = folder + "no_rle.hdr";
Mat img_rle = imread(name_rle, -1);
ASSERT_FALSE(img_rle.empty()) << "Could not open " << name_rle;
Mat img_no_rle = imread(name_no_rle, -1);
ASSERT_FALSE(img_no_rle.empty()) << "Could not open " << name_no_rle;
double min = 0.0, max = 1.0;
minMaxLoc(abs(img_rle - img_no_rle), &min, &max);
ASSERT_FALSE(max > DBL_EPSILON);
string tmp_file_name = tempfile(".hdr");
vector<int>param(1);
for(int i = 0; i < 2; i++) {
param[0] = i;
imwrite(tmp_file_name, img_rle, param);
Mat written_img = imread(tmp_file_name, -1);
ASSERT_FALSE(written_img.empty()) << "Could not open " << tmp_file_name;
minMaxLoc(abs(img_rle - written_img), &min, &max);
ASSERT_FALSE(max > DBL_EPSILON);
}
remove(tmp_file_name.c_str());
}
#endif
#ifdef HAVE_IMGCODEC_PXM
TEST(Imgcodecs_Pam, read_write)
{
string folder = string(cvtest::TS::ptr()->get_data_path()) + "readwrite/";
string filepath = folder + "lena.pam";
cv::Mat img = cv::imread(filepath);
ASSERT_FALSE(img.empty());
std::vector<int> params;
params.push_back(IMWRITE_PAM_TUPLETYPE);
params.push_back(IMWRITE_PAM_FORMAT_RGB);
string writefile = cv::tempfile(".pam");
EXPECT_NO_THROW(cv::imwrite(writefile, img, params));
cv::Mat reread = cv::imread(writefile);
string writefile_no_param = cv::tempfile(".pam");
EXPECT_NO_THROW(cv::imwrite(writefile_no_param, img));
cv::Mat reread_no_param = cv::imread(writefile_no_param);
EXPECT_EQ(0, cvtest::norm(reread, reread_no_param, NORM_INF));
EXPECT_EQ(0, cvtest::norm(img, reread, NORM_INF));
remove(writefile.c_str());
remove(writefile_no_param.c_str());
}
#endif
#ifdef HAVE_IMGCODEC_PFM
TEST(Imgcodecs_Pfm, read_write)
{
Mat img = imread(findDataFile("readwrite/lena.pam"));
ASSERT_FALSE(img.empty());
img.convertTo(img, CV_32F, 1/255.0f);
std::vector<int> params;
string writefile = cv::tempfile(".pfm");
EXPECT_NO_THROW(cv::imwrite(writefile, img, params));
cv::Mat reread = cv::imread(writefile, IMREAD_UNCHANGED);
string writefile_no_param = cv::tempfile(".pfm");
EXPECT_NO_THROW(cv::imwrite(writefile_no_param, img));
cv::Mat reread_no_param = cv::imread(writefile_no_param, IMREAD_UNCHANGED);
EXPECT_EQ(0, cvtest::norm(reread, reread_no_param, NORM_INF));
EXPECT_EQ(0, cvtest::norm(img, reread, NORM_INF));
EXPECT_EQ(0, remove(writefile.c_str()));
EXPECT_EQ(0, remove(writefile_no_param.c_str()));
}
#endif
TEST(Imgcodecs, write_parameter_type)
{
cv::Mat m(10, 10, CV_8UC1, cv::Scalar::all(0));
cv::Mat1b m_type = cv::Mat1b::zeros(10, 10);
string tmp_file = cv::tempfile(".bmp");
EXPECT_NO_THROW(cv::imwrite(tmp_file, cv::Mat(m * 2))) << "* Failed with cv::Mat";
EXPECT_NO_THROW(cv::imwrite(tmp_file, m * 2)) << "* Failed with cv::MatExpr";
EXPECT_NO_THROW(cv::imwrite(tmp_file, m_type)) << "* Failed with cv::Mat_";
EXPECT_NO_THROW(cv::imwrite(tmp_file, m_type * 2)) << "* Failed with cv::MatExpr(Mat_)";
cv::Matx<uchar, 10, 10> matx;
EXPECT_NO_THROW(cv::imwrite(tmp_file, matx)) << "* Failed with cv::Matx";
EXPECT_EQ(0, remove(tmp_file.c_str()));
}
}} // namespace
#ifdef HAVE_OPENEXR
#include "test_exr.impl.hpp"
#endif

View File

@@ -0,0 +1,183 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "test_precomp.hpp"
namespace opencv_test { namespace {
#ifdef HAVE_JPEG
/**
* Test for check whether reading exif orientation tag was processed successfully or not
* The test info is the set of 8 images named testExifRotate_{1 to 8}.jpg
* The test image is the square 10x10 points divided by four sub-squares:
* (R corresponds to Red, G to Green, B to Blue, W to white)
* --------- ---------
* | R | G | | G | R |
* |-------| - (tag 1) |-------| - (tag 2)
* | B | W | | W | B |
* --------- ---------
*
* --------- ---------
* | W | B | | B | W |
* |-------| - (tag 3) |-------| - (tag 4)
* | G | R | | R | G |
* --------- ---------
*
* --------- ---------
* | R | B | | G | W |
* |-------| - (tag 5) |-------| - (tag 6)
* | G | W | | R | B |
* --------- ---------
*
* --------- ---------
* | W | G | | B | R |
* |-------| - (tag 7) |-------| - (tag 8)
* | B | R | | W | G |
* --------- ---------
*
*
* Every image contains exif field with orientation tag (0x112)
* After reading each image the corresponding matrix must be read as
* ---------
* | R | G |
* |-------|
* | B | W |
* ---------
*
*/
typedef testing::TestWithParam<string> Imgcodecs_Jpeg_Exif;
TEST_P(Imgcodecs_Jpeg_Exif, exif_orientation)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filename = root + GetParam();
const int colorThresholdHigh = 250;
const int colorThresholdLow = 5;
Mat m_img = imread(filename);
ASSERT_FALSE(m_img.empty());
Vec3b vec;
//Checking the first quadrant (with supposed red)
vec = m_img.at<Vec3b>(2, 2); //some point inside the square
EXPECT_LE(vec.val[0], colorThresholdLow);
EXPECT_LE(vec.val[1], colorThresholdLow);
EXPECT_GE(vec.val[2], colorThresholdHigh);
//Checking the second quadrant (with supposed green)
vec = m_img.at<Vec3b>(2, 7); //some point inside the square
EXPECT_LE(vec.val[0], colorThresholdLow);
EXPECT_GE(vec.val[1], colorThresholdHigh);
EXPECT_LE(vec.val[2], colorThresholdLow);
//Checking the third quadrant (with supposed blue)
vec = m_img.at<Vec3b>(7, 2); //some point inside the square
EXPECT_GE(vec.val[0], colorThresholdHigh);
EXPECT_LE(vec.val[1], colorThresholdLow);
EXPECT_LE(vec.val[2], colorThresholdLow);
}
const string exif_files[] =
{
"readwrite/testExifOrientation_1.jpg",
"readwrite/testExifOrientation_2.jpg",
"readwrite/testExifOrientation_3.jpg",
"readwrite/testExifOrientation_4.jpg",
"readwrite/testExifOrientation_5.jpg",
"readwrite/testExifOrientation_6.jpg",
"readwrite/testExifOrientation_7.jpg",
"readwrite/testExifOrientation_8.jpg"
};
INSTANTIATE_TEST_CASE_P(ExifFiles, Imgcodecs_Jpeg_Exif,
testing::ValuesIn(exif_files));
//==================================================================================================
TEST(Imgcodecs_Jpeg, encode_empty)
{
cv::Mat img;
std::vector<uchar> jpegImg;
ASSERT_THROW(cv::imencode(".jpg", img, jpegImg), cv::Exception);
}
TEST(Imgcodecs_Jpeg, encode_decode_progressive_jpeg)
{
cvtest::TS& ts = *cvtest::TS::ptr();
string input = string(ts.get_data_path()) + "../cv/shared/lena.png";
cv::Mat img = cv::imread(input);
ASSERT_FALSE(img.empty());
std::vector<int> params;
params.push_back(IMWRITE_JPEG_PROGRESSIVE);
params.push_back(1);
string output_progressive = cv::tempfile(".jpg");
EXPECT_NO_THROW(cv::imwrite(output_progressive, img, params));
cv::Mat img_jpg_progressive = cv::imread(output_progressive);
string output_normal = cv::tempfile(".jpg");
EXPECT_NO_THROW(cv::imwrite(output_normal, img));
cv::Mat img_jpg_normal = cv::imread(output_normal);
EXPECT_EQ(0, cvtest::norm(img_jpg_progressive, img_jpg_normal, NORM_INF));
EXPECT_EQ(0, remove(output_progressive.c_str()));
EXPECT_EQ(0, remove(output_normal.c_str()));
}
TEST(Imgcodecs_Jpeg, encode_decode_optimize_jpeg)
{
cvtest::TS& ts = *cvtest::TS::ptr();
string input = string(ts.get_data_path()) + "../cv/shared/lena.png";
cv::Mat img = cv::imread(input);
ASSERT_FALSE(img.empty());
std::vector<int> params;
params.push_back(IMWRITE_JPEG_OPTIMIZE);
params.push_back(1);
string output_optimized = cv::tempfile(".jpg");
EXPECT_NO_THROW(cv::imwrite(output_optimized, img, params));
cv::Mat img_jpg_optimized = cv::imread(output_optimized);
string output_normal = cv::tempfile(".jpg");
EXPECT_NO_THROW(cv::imwrite(output_normal, img));
cv::Mat img_jpg_normal = cv::imread(output_normal);
EXPECT_EQ(0, cvtest::norm(img_jpg_optimized, img_jpg_normal, NORM_INF));
EXPECT_EQ(0, remove(output_optimized.c_str()));
EXPECT_EQ(0, remove(output_normal.c_str()));
}
TEST(Imgcodecs_Jpeg, encode_decode_rst_jpeg)
{
cvtest::TS& ts = *cvtest::TS::ptr();
string input = string(ts.get_data_path()) + "../cv/shared/lena.png";
cv::Mat img = cv::imread(input);
ASSERT_FALSE(img.empty());
std::vector<int> params;
params.push_back(IMWRITE_JPEG_RST_INTERVAL);
params.push_back(1);
string output_rst = cv::tempfile(".jpg");
EXPECT_NO_THROW(cv::imwrite(output_rst, img, params));
cv::Mat img_jpg_rst = cv::imread(output_rst);
string output_normal = cv::tempfile(".jpg");
EXPECT_NO_THROW(cv::imwrite(output_normal, img));
cv::Mat img_jpg_normal = cv::imread(output_normal);
EXPECT_EQ(0, cvtest::norm(img_jpg_rst, img_jpg_normal, NORM_INF));
EXPECT_EQ(0, remove(output_rst.c_str()));
EXPECT_EQ(0, remove(output_normal.c_str()));
}
#endif // HAVE_JPEG
}} // namespace

View File

@@ -0,0 +1,10 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "test_precomp.hpp"
#if defined(HAVE_HPX)
#include <hpx/hpx_main.hpp>
#endif
CV_TEST_MAIN("highgui")

View File

@@ -0,0 +1,98 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "test_precomp.hpp"
namespace opencv_test { namespace {
#ifdef HAVE_PNG
TEST(Imgcodecs_Png, write_big)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filename = root + "readwrite/read.png";
const string dst_file = cv::tempfile(".png");
Mat img;
ASSERT_NO_THROW(img = imread(filename));
ASSERT_FALSE(img.empty());
EXPECT_EQ(13043, img.cols);
EXPECT_EQ(13917, img.rows);
ASSERT_NO_THROW(imwrite(dst_file, img));
EXPECT_EQ(0, remove(dst_file.c_str()));
}
TEST(Imgcodecs_Png, encode)
{
vector<uchar> buff;
Mat img_gt = Mat::zeros(1000, 1000, CV_8U);
vector<int> param;
param.push_back(IMWRITE_PNG_COMPRESSION);
param.push_back(3); //default(3) 0-9.
EXPECT_NO_THROW(imencode(".png", img_gt, buff, param));
Mat img;
EXPECT_NO_THROW(img = imdecode(buff, IMREAD_ANYDEPTH)); // hang
EXPECT_FALSE(img.empty());
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img, img_gt);
}
TEST(Imgcodecs_Png, regression_ImreadVSCvtColor)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string imgName = root + "../cv/shared/lena.png";
Mat original_image = imread(imgName);
Mat gray_by_codec = imread(imgName, IMREAD_GRAYSCALE);
Mat gray_by_cvt;
cvtColor(original_image, gray_by_cvt, COLOR_BGR2GRAY);
Mat diff;
absdiff(gray_by_codec, gray_by_cvt, diff);
EXPECT_LT(cvtest::mean(diff)[0], 1.);
EXPECT_PRED_FORMAT2(cvtest::MatComparator(10, 0), gray_by_codec, gray_by_cvt);
}
// Test OpenCV issue 3075 is solved
TEST(Imgcodecs_Png, read_color_palette_with_alpha)
{
const string root = cvtest::TS::ptr()->get_data_path();
Mat img;
// First Test : Read PNG with alpha, imread flag -1
img = imread(root + "readwrite/color_palette_alpha.png", IMREAD_UNCHANGED);
ASSERT_FALSE(img.empty());
ASSERT_TRUE(img.channels() == 4);
// pixel is red in BGRA
EXPECT_EQ(img.at<Vec4b>(0, 0), Vec4b(0, 0, 255, 255));
EXPECT_EQ(img.at<Vec4b>(0, 1), Vec4b(0, 0, 255, 255));
// Second Test : Read PNG without alpha, imread flag -1
img = imread(root + "readwrite/color_palette_no_alpha.png", IMREAD_UNCHANGED);
ASSERT_FALSE(img.empty());
ASSERT_TRUE(img.channels() == 3);
// pixel is red in BGR
EXPECT_EQ(img.at<Vec3b>(0, 0), Vec3b(0, 0, 255));
EXPECT_EQ(img.at<Vec3b>(0, 1), Vec3b(0, 0, 255));
// Third Test : Read PNG with alpha, imread flag 1
img = imread(root + "readwrite/color_palette_alpha.png", IMREAD_COLOR);
ASSERT_FALSE(img.empty());
ASSERT_TRUE(img.channels() == 3);
// pixel is red in BGR
EXPECT_EQ(img.at<Vec3b>(0, 0), Vec3b(0, 0, 255));
EXPECT_EQ(img.at<Vec3b>(0, 1), Vec3b(0, 0, 255));
// Fourth Test : Read PNG without alpha, imread flag 1
img = imread(root + "readwrite/color_palette_no_alpha.png", IMREAD_COLOR);
ASSERT_FALSE(img.empty());
ASSERT_TRUE(img.channels() == 3);
// pixel is red in BGR
EXPECT_EQ(img.at<Vec3b>(0, 0), Vec3b(0, 0, 255));
EXPECT_EQ(img.at<Vec3b>(0, 1), Vec3b(0, 0, 255));
}
#endif // HAVE_PNG
}} // namespace

View File

@@ -0,0 +1,11 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#ifndef __OPENCV_TEST_PRECOMP_HPP__
#define __OPENCV_TEST_PRECOMP_HPP__
#include "opencv2/ts.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#endif

View File

@@ -0,0 +1,155 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "test_precomp.hpp"
namespace opencv_test { namespace {
TEST(Imgcodecs_Image, read_write_bmp)
{
const size_t IMAGE_COUNT = 10;
const double thresDbell = 32;
for (size_t i = 0; i < IMAGE_COUNT; ++i)
{
stringstream s; s << i;
const string digit = s.str();
const string src_name = TS::ptr()->get_data_path() + "../python/images/QCIF_0" + digit + ".bmp";
const string dst_name = cv::tempfile((digit + ".bmp").c_str());
Mat image = imread(src_name);
ASSERT_FALSE(image.empty());
resize(image, image, Size(968, 757), 0.0, 0.0, INTER_CUBIC);
imwrite(dst_name, image);
Mat loaded = imread(dst_name);
ASSERT_FALSE(loaded.empty());
double psnr = cvtest::PSNR(loaded, image);
EXPECT_GT(psnr, thresDbell);
vector<uchar> from_file;
FILE *f = fopen(dst_name.c_str(), "rb");
fseek(f, 0, SEEK_END);
long len = ftell(f);
from_file.resize((size_t)len);
fseek(f, 0, SEEK_SET);
from_file.resize(fread(&from_file[0], 1, from_file.size(), f));
fclose(f);
vector<uchar> buf;
imencode(".bmp", image, buf);
ASSERT_EQ(buf, from_file);
Mat buf_loaded = imdecode(Mat(buf), 1);
ASSERT_FALSE(buf_loaded.empty());
psnr = cvtest::PSNR(buf_loaded, image);
EXPECT_GT(psnr, thresDbell);
EXPECT_EQ(0, remove(dst_name.c_str()));
}
}
//==================================================================================================
typedef string Ext;
typedef testing::TestWithParam<Ext> Imgcodecs_Image;
TEST_P(Imgcodecs_Image, read_write)
{
const string ext = this->GetParam();
const string full_name = cv::tempfile(ext.c_str());
const string _name = TS::ptr()->get_data_path() + "../cv/shared/baboon.png";
const double thresDbell = 32;
Mat image = imread(_name);
image.convertTo(image, CV_8UC3);
ASSERT_FALSE(image.empty());
imwrite(full_name, image);
Mat loaded = imread(full_name);
ASSERT_FALSE(loaded.empty());
double psnr = cvtest::PSNR(loaded, image);
EXPECT_GT(psnr, thresDbell);
vector<uchar> from_file;
FILE *f = fopen(full_name.c_str(), "rb");
fseek(f, 0, SEEK_END);
long len = ftell(f);
from_file.resize((size_t)len);
fseek(f, 0, SEEK_SET);
from_file.resize(fread(&from_file[0], 1, from_file.size(), f));
fclose(f);
vector<uchar> buf;
imencode("." + ext, image, buf);
ASSERT_EQ(buf, from_file);
Mat buf_loaded = imdecode(Mat(buf), 1);
ASSERT_FALSE(buf_loaded.empty());
psnr = cvtest::PSNR(buf_loaded, image);
EXPECT_GT(psnr, thresDbell);
EXPECT_EQ(0, remove(full_name.c_str()));
}
const string exts[] = {
#ifdef HAVE_PNG
"png",
#endif
#ifdef HAVE_TIFF
"tiff",
#endif
#ifdef HAVE_JPEG
"jpg",
#endif
#if defined(HAVE_JASPER) && defined(OPENCV_IMGCODECS_ENABLE_JASPER_TESTS)
"jp2",
#endif
#if 0 /*defined HAVE_OPENEXR && !defined __APPLE__*/
"exr",
#endif
"bmp",
#ifdef HAVE_IMGCODEC_PXM
"ppm",
#endif
#ifdef HAVE_IMGCODEC_SUNRASTER
"ras",
#endif
};
INSTANTIATE_TEST_CASE_P(imgcodecs, Imgcodecs_Image, testing::ValuesIn(exts));
TEST(Imgcodecs_Image, regression_9376)
{
String path = findDataFile("readwrite/regression_9376.bmp");
Mat m = imread(path);
ASSERT_FALSE(m.empty());
EXPECT_EQ(32, m.cols);
EXPECT_EQ(32, m.rows);
}
//==================================================================================================
TEST(Imgcodecs_Image, write_umat)
{
const string src_name = TS::ptr()->get_data_path() + "../python/images/baboon.bmp";
const string dst_name = cv::tempfile(".bmp");
Mat image1 = imread(src_name);
ASSERT_FALSE(image1.empty());
UMat image1_umat = image1.getUMat(ACCESS_RW);
imwrite(dst_name, image1_umat);
Mat image2 = imread(dst_name);
ASSERT_FALSE(image2.empty());
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), image1, image2);
EXPECT_EQ(0, remove(dst_name.c_str()));
}
}} // namespace

View File

@@ -0,0 +1,338 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "test_precomp.hpp"
namespace opencv_test { namespace {
#ifdef HAVE_TIFF
// these defines are used to resolve conflict between tiff.h and opencv2/core/types_c.h
#define uint64 uint64_hack_
#define int64 int64_hack_
#include "tiff.h"
#ifdef __ANDROID__
// Test disabled as it uses a lot of memory.
// It is killed with SIGKILL by out of memory killer.
TEST(Imgcodecs_Tiff, DISABLED_decode_tile16384x16384)
#else
TEST(Imgcodecs_Tiff, decode_tile16384x16384)
#endif
{
// see issue #2161
cv::Mat big(16384, 16384, CV_8UC1, cv::Scalar::all(0));
string file3 = cv::tempfile(".tiff");
string file4 = cv::tempfile(".tiff");
std::vector<int> params;
params.push_back(TIFFTAG_ROWSPERSTRIP);
params.push_back(big.rows);
EXPECT_NO_THROW(cv::imwrite(file4, big, params));
EXPECT_NO_THROW(cv::imwrite(file3, big.colRange(0, big.cols - 1), params));
big.release();
try
{
cv::imread(file3, IMREAD_UNCHANGED);
EXPECT_NO_THROW(cv::imread(file4, IMREAD_UNCHANGED));
}
catch(const std::bad_alloc&)
{
// not enough memory
}
EXPECT_EQ(0, remove(file3.c_str()));
EXPECT_EQ(0, remove(file4.c_str()));
}
TEST(Imgcodecs_Tiff, write_read_16bit_big_little_endian)
{
// see issue #2601 "16-bit Grayscale TIFF Load Failures Due to Buffer Underflow and Endianness"
// Setup data for two minimal 16-bit grayscale TIFF files in both endian formats
uchar tiff_sample_data[2][86] = { {
// Little endian
0x49, 0x49, 0x2a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xad, 0xde, 0xef, 0xbe, 0x06, 0x00, 0x00, 0x01,
0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01,
0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x17, 0x01, 0x04, 0x00, 0x01, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x00 }, {
// Big endian
0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x0c, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x06, 0x01, 0x00,
0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x00,
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10,
0x00, 0x00, 0x01, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x11,
0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x01, 0x17, 0x00, 0x04, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x04 }
};
// Test imread() for both a little endian TIFF and big endian TIFF
for (int i = 0; i < 2; i++)
{
string filename = cv::tempfile(".tiff");
// Write sample TIFF file
FILE* fp = fopen(filename.c_str(), "wb");
ASSERT_TRUE(fp != NULL);
ASSERT_EQ((size_t)1, fwrite(tiff_sample_data[i], 86, 1, fp));
fclose(fp);
Mat img = imread(filename, IMREAD_UNCHANGED);
EXPECT_EQ(1, img.rows);
EXPECT_EQ(2, img.cols);
EXPECT_EQ(CV_16U, img.type());
EXPECT_EQ(sizeof(ushort), img.elemSize());
EXPECT_EQ(1, img.channels());
EXPECT_EQ(0xDEAD, img.at<ushort>(0,0));
EXPECT_EQ(0xBEEF, img.at<ushort>(0,1));
EXPECT_EQ(0, remove(filename.c_str()));
}
}
TEST(Imgcodecs_Tiff, decode_tile_remainder)
{
/* see issue #3472 - dealing with tiled images where the tile size is
* not a multiple of image size.
* The tiled images were created with 'convert' from ImageMagick,
* using the command 'convert <input> -define tiff:tile-geometry=128x128 -depth [8|16] <output>
* Note that the conversion to 16 bits expands the range from 0-255 to 0-255*255,
* so the test converts back but rounding errors cause small differences.
*/
const string root = cvtest::TS::ptr()->get_data_path();
cv::Mat img = imread(root + "readwrite/non_tiled.tif",-1);
ASSERT_FALSE(img.empty());
ASSERT_TRUE(img.channels() == 3);
cv::Mat tiled8 = imread(root + "readwrite/tiled_8.tif", -1);
ASSERT_FALSE(tiled8.empty());
ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), img, tiled8);
cv::Mat tiled16 = imread(root + "readwrite/tiled_16.tif", -1);
ASSERT_FALSE(tiled16.empty());
ASSERT_TRUE(tiled16.elemSize() == 6);
tiled16.convertTo(tiled8, CV_8UC3, 1./256.);
ASSERT_PRED_FORMAT2(cvtest::MatComparator(2, 0), img, tiled8);
// What about 32, 64 bit?
}
TEST(Imgcodecs_Tiff, decode_infinite_rowsperstrip)
{
const uchar sample_data[142] = {
0x49, 0x49, 0x2a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x56, 0x54,
0x56, 0x5a, 0x59, 0x55, 0x5a, 0x00, 0x0a, 0x00, 0x00, 0x01,
0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00,
0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x03, 0x01, 0x03, 0x00, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01,
0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x15, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x16, 0x01, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0x17, 0x01, 0x04, 0x00, 0x01, 0x00,
0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x03, 0x00,
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
const string filename = cv::tempfile(".tiff");
std::ofstream outfile(filename.c_str(), std::ofstream::binary);
outfile.write(reinterpret_cast<const char *>(sample_data), sizeof sample_data);
outfile.close();
EXPECT_NO_THROW(cv::imread(filename, IMREAD_UNCHANGED));
EXPECT_EQ(0, remove(filename.c_str()));
}
TEST(Imgcodecs_Tiff, readWrite_32FC1)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filenameInput = root + "readwrite/test32FC1.tiff";
const string filenameOutput = cv::tempfile(".tiff");
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
ASSERT_FALSE(img.empty());
ASSERT_EQ(CV_32FC1,img.type());
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
ASSERT_EQ(img2.type(), img.type());
ASSERT_EQ(img2.size(), img.size());
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
EXPECT_EQ(0, remove(filenameOutput.c_str()));
}
TEST(Imgcodecs_Tiff, readWrite_64FC1)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filenameInput = root + "readwrite/test64FC1.tiff";
const string filenameOutput = cv::tempfile(".tiff");
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
ASSERT_FALSE(img.empty());
ASSERT_EQ(CV_64FC1, img.type());
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
ASSERT_EQ(img2.type(), img.type());
ASSERT_EQ(img2.size(), img.size());
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
EXPECT_EQ(0, remove(filenameOutput.c_str()));
}
TEST(Imgcodecs_Tiff, readWrite_32FC3_SGILOG)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filenameInput = root + "readwrite/test32FC3_sgilog.tiff";
const string filenameOutput = cv::tempfile(".tiff");
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
ASSERT_FALSE(img.empty());
ASSERT_EQ(CV_32FC3, img.type());
ASSERT_TRUE(cv::imwrite(filenameOutput, img));
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
ASSERT_EQ(img2.type(), img.type());
ASSERT_EQ(img2.size(), img.size());
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 0.01);
EXPECT_EQ(0, remove(filenameOutput.c_str()));
}
TEST(Imgcodecs_Tiff, readWrite_32FC3_RAW)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filenameInput = root + "readwrite/test32FC3_raw.tiff";
const string filenameOutput = cv::tempfile(".tiff");
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
ASSERT_FALSE(img.empty());
ASSERT_EQ(CV_32FC3, img.type());
std::vector<int> params;
params.push_back(IMWRITE_TIFF_COMPRESSION);
params.push_back(1/*COMPRESSION_NONE*/);
ASSERT_TRUE(cv::imwrite(filenameOutput, img, params));
const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED);
ASSERT_EQ(img2.type(), img.type());
ASSERT_EQ(img2.size(), img.size());
EXPECT_LE(cvtest::norm(img, img2, NORM_INF | NORM_RELATIVE), 1e-3);
EXPECT_EQ(0, remove(filenameOutput.c_str()));
}
//==================================================================================================
typedef testing::TestWithParam<int> Imgcodecs_Tiff_Modes;
TEST_P(Imgcodecs_Tiff_Modes, decode_multipage)
{
const int mode = GetParam();
const string root = cvtest::TS::ptr()->get_data_path();
const string filename = root + "readwrite/multipage.tif";
const string page_files[] = {
"readwrite/multipage_p1.tif",
"readwrite/multipage_p2.tif",
"readwrite/multipage_p3.tif",
"readwrite/multipage_p4.tif",
"readwrite/multipage_p5.tif",
"readwrite/multipage_p6.tif"
};
const size_t page_count = sizeof(page_files)/sizeof(page_files[0]);
vector<Mat> pages;
bool res = imreadmulti(filename, pages, mode);
ASSERT_TRUE(res == true);
ASSERT_EQ(page_count, pages.size());
for (size_t i = 0; i < page_count; i++)
{
const Mat page = imread(root + page_files[i], mode);
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), page, pages[i]);
}
}
const int all_modes[] =
{
IMREAD_UNCHANGED,
IMREAD_GRAYSCALE,
IMREAD_COLOR,
IMREAD_ANYDEPTH,
IMREAD_ANYCOLOR
};
INSTANTIATE_TEST_CASE_P(AllModes, Imgcodecs_Tiff_Modes, testing::ValuesIn(all_modes));
//==================================================================================================
TEST(Imgcodecs_Tiff_Modes, write_multipage)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filename = root + "readwrite/multipage.tif";
const string page_files[] = {
"readwrite/multipage_p1.tif",
"readwrite/multipage_p2.tif",
"readwrite/multipage_p3.tif",
"readwrite/multipage_p4.tif",
"readwrite/multipage_p5.tif",
"readwrite/multipage_p6.tif"
};
const size_t page_count = sizeof(page_files) / sizeof(page_files[0]);
vector<Mat> pages;
for (size_t i = 0; i < page_count; i++)
{
const Mat page = imread(root + page_files[i]);
pages.push_back(page);
}
string tmp_filename = cv::tempfile(".tiff");
bool res = imwrite(tmp_filename, pages);
ASSERT_TRUE(res);
vector<Mat> read_pages;
imreadmulti(tmp_filename, read_pages);
for (size_t i = 0; i < page_count; i++)
{
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), read_pages[i], pages[i]);
}
}
//==================================================================================================
TEST(Imgcodecs_Tiff, imdecode_no_exception_temporary_file_removed)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string filename = root + "../cv/shared/lena.png";
cv::Mat img = cv::imread(filename);
ASSERT_FALSE(img.empty());
std::vector<uchar> buf;
EXPECT_NO_THROW(cv::imencode(".tiff", img, buf));
EXPECT_NO_THROW(cv::imdecode(buf, IMREAD_UNCHANGED));
}
TEST(Imgcodecs_Tiff, decode_black_and_write_image_pr12989)
{
const string filename = cvtest::findDataFile("readwrite/bitsperpixel1.tiff");
cv::Mat img;
ASSERT_NO_THROW(img = cv::imread(filename, IMREAD_GRAYSCALE));
ASSERT_FALSE(img.empty());
EXPECT_EQ(64, img.cols);
EXPECT_EQ(64, img.rows);
EXPECT_EQ(CV_8UC1, img.type()) << cv::typeToString(img.type());
// Check for 0/255 values only: 267 + 3829 = 64*64
EXPECT_EQ(267, countNonZero(img == 0));
EXPECT_EQ(3829, countNonZero(img == 255));
}
TEST(Imgcodecs_Tiff, decode_black_and_write_image_pr12989_default)
{
const string filename = cvtest::findDataFile("readwrite/bitsperpixel1.tiff");
cv::Mat img;
ASSERT_NO_THROW(img = cv::imread(filename)); // by default image type is CV_8UC3
ASSERT_FALSE(img.empty());
EXPECT_EQ(64, img.cols);
EXPECT_EQ(64, img.rows);
EXPECT_EQ(CV_8UC3, img.type()) << cv::typeToString(img.type());
}
#endif
}} // namespace

View File

@@ -0,0 +1,114 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "test_precomp.hpp"
namespace opencv_test { namespace {
#ifdef HAVE_WEBP
TEST(Imgcodecs_WebP, encode_decode_lossless_webp)
{
const string root = cvtest::TS::ptr()->get_data_path();
string filename = root + "../cv/shared/lena.png";
cv::Mat img = cv::imread(filename);
ASSERT_FALSE(img.empty());
string output = cv::tempfile(".webp");
EXPECT_NO_THROW(cv::imwrite(output, img)); // lossless
cv::Mat img_webp = cv::imread(output);
std::vector<unsigned char> buf;
FILE * wfile = NULL;
wfile = fopen(output.c_str(), "rb");
if (wfile != NULL)
{
fseek(wfile, 0, SEEK_END);
size_t wfile_size = ftell(wfile);
fseek(wfile, 0, SEEK_SET);
buf.resize(wfile_size);
size_t data_size = fread(&buf[0], 1, wfile_size, wfile);
if(wfile)
{
fclose(wfile);
}
if (data_size != wfile_size)
{
EXPECT_TRUE(false);
}
}
EXPECT_EQ(0, remove(output.c_str()));
cv::Mat decode = cv::imdecode(buf, IMREAD_COLOR);
ASSERT_FALSE(decode.empty());
EXPECT_TRUE(cvtest::norm(decode, img_webp, NORM_INF) == 0);
ASSERT_FALSE(img_webp.empty());
EXPECT_TRUE(cvtest::norm(img, img_webp, NORM_INF) == 0);
}
TEST(Imgcodecs_WebP, encode_decode_lossy_webp)
{
const string root = cvtest::TS::ptr()->get_data_path();
std::string input = root + "../cv/shared/lena.png";
cv::Mat img = cv::imread(input);
ASSERT_FALSE(img.empty());
for(int q = 100; q>=0; q-=20)
{
std::vector<int> params;
params.push_back(IMWRITE_WEBP_QUALITY);
params.push_back(q);
string output = cv::tempfile(".webp");
EXPECT_NO_THROW(cv::imwrite(output, img, params));
cv::Mat img_webp = cv::imread(output);
EXPECT_EQ(0, remove(output.c_str()));
EXPECT_FALSE(img_webp.empty());
EXPECT_EQ(3, img_webp.channels());
EXPECT_EQ(512, img_webp.cols);
EXPECT_EQ(512, img_webp.rows);
}
}
TEST(Imgcodecs_WebP, encode_decode_with_alpha_webp)
{
const string root = cvtest::TS::ptr()->get_data_path();
std::string input = root + "../cv/shared/lena.png";
cv::Mat img = cv::imread(input);
ASSERT_FALSE(img.empty());
std::vector<cv::Mat> imgs;
cv::split(img, imgs);
imgs.push_back(cv::Mat(imgs[0]));
imgs[imgs.size() - 1] = cv::Scalar::all(128);
cv::merge(imgs, img);
string output = cv::tempfile(".webp");
EXPECT_NO_THROW(cv::imwrite(output, img));
cv::Mat img_webp = cv::imread(output, IMREAD_UNCHANGED);
cv::Mat img_webp_bgr = cv::imread(output); // IMREAD_COLOR by default
EXPECT_EQ(0, remove(output.c_str()));
EXPECT_FALSE(img_webp.empty());
EXPECT_EQ(4, img_webp.channels());
EXPECT_EQ(512, img_webp.cols);
EXPECT_EQ(512, img_webp.rows);
EXPECT_FALSE(img_webp_bgr.empty());
EXPECT_EQ(3, img_webp_bgr.channels());
EXPECT_EQ(512, img_webp_bgr.cols);
EXPECT_EQ(512, img_webp_bgr.rows);
}
#endif // HAVE_WEBP
}} // namespace