typedef std::function<void(int error)> ResultCallback;
/**
- * @brief Implements useful image utils. Self removed.
+ * @brief Implements useful image utils.
*/
class ImageData
{
public:
/**
- * @brief Create image data.
- * @param[in] origPath Image path
- * @param[in] destPath Destination path of cropped image.
- * @param[in] callback Callback that is called when image is cropped.
+ @param[in] path Image path
*/
- ImageData(const char *origPath, const char *destPath, ResultCallback callback);
+ explicit ImageData(std::string path);
~ImageData();
/**
*/
bool initialize();
+ /**
+ * @brief Export image to file.
+ * @param[in] destPath Destination path of image.
+ * @return true if success.
+ */
+ bool exportToFile(const char *destPath);
+
+ /**
+ * @brief Resize image.
+ * @param[in] width Width of resized image
+ * @param[in] height Height of resized image
+ * @param[in] callback Callback that is called when image is resized.
+ * @return true if success.
+ */
+ bool resize(unsigned long width, unsigned long height, ResultCallback callback);
+
/**
* @brief Crop image.
* @param[in] width Width of cropped image
* @param[in] height Height of cropped image
+ * @param[in] callback Callback that is called when image is cropped.
* @return true if success.
*/
- bool crop(int width, int height);
+ bool crop(unsigned long width, unsigned long height, ResultCallback callback);
private:
- bool decode();
- bool encode();
- void createJpegFile(unsigned char *jpegBuffer);
+ double getResizeRatio(int width, int height);
+ void createPacket(unsigned char *buffer, unsigned long long bufferSize);
+ void createJpegFile(const char *destPath, unsigned char *jpegBuffer, unsigned long long bufferSize);
image_util_rotation_e getRotation();
- void onCropFinished(media_packet_h *dst, int error);
-
- unsigned char *m_Buffer;
- unsigned long long m_BufferSize;
+ void clear();
+ void onFinished(media_packet_h *dst, int error);
- unsigned long m_OrigWidth;
- unsigned long m_OrigHeight;
- unsigned long m_DestWidth;
- unsigned long m_DestHeight;
+ std::string m_Path;
- std::string m_OrigPath;
- std::string m_DestPath;
+ unsigned long m_Width;
+ unsigned long m_Height;
ExifData *m_ExifData;
- media_format_h m_Fmt;
media_packet_h m_Packet;
- ResultCallback m_OnCropped;
+ ResultCallback m_OnResult;
};
}
const unsigned int EXIF_HEADER_LEN = sizeof(EXIF_HEADER);
const unsigned int JPEG_HEADER_OFFSET = 20;
-ImageData::ImageData(const char *origPath, const char *destPath, ResultCallback callback)
- : m_Buffer(nullptr),
- m_BufferSize(0),
- m_OrigWidth(0),
- m_OrigHeight(0),
- m_DestWidth(0),
- m_DestHeight(0),
- m_OrigPath(origPath),
- m_DestPath(destPath),
+ImageData::ImageData(std::string path)
+ : m_Path(std::move(path)),
+ m_Width(0),
+ m_Height(0),
m_ExifData(nullptr),
- m_Fmt(nullptr),
- m_Packet(nullptr),
- m_OnCropped(std::move(callback))
+ m_Packet(nullptr)
{
}
ImageData::~ImageData()
{
- exif_data_unref(m_ExifData);
- media_packet_destroy(m_Packet);
+ clear();
}
bool ImageData::initialize()
{
- bool isSuccess = decode();
- if (!isSuccess || m_Buffer == nullptr) {
- free(m_Buffer);
- m_Buffer = nullptr;
- return false;
- }
+ unsigned char *buffer = nullptr;
+ unsigned long long bufferSize = 0;
- media_format_create(&m_Fmt);
- media_format_set_video_mime(m_Fmt, MEDIA_FORMAT_RGBA);
- media_format_set_video_width(m_Fmt, m_OrigWidth);
- media_format_set_video_height(m_Fmt, m_OrigHeight);
+ m_ExifData = exif_data_new_from_file(m_Path.c_str());
- void *srcPtr = nullptr;
- media_packet_create_alloc(m_Fmt, nullptr, nullptr, &m_Packet);
- media_packet_get_buffer_data_ptr(m_Packet, &srcPtr);
- memcpy(srcPtr, m_Buffer, m_BufferSize);
- free(m_Buffer);
- m_Buffer = nullptr;
- media_format_unref(m_Fmt);
+ image_util_decode_h decoder = nullptr;
+ image_util_decode_create(&decoder);
+ image_util_decode_set_input_path(decoder, m_Path.c_str());
+ image_util_decode_set_colorspace(decoder, IMAGE_UTIL_COLORSPACE_RGBA8888);
+ image_util_decode_set_output_buffer(decoder, &buffer);
+ int err = image_util_decode_run(decoder, &m_Width, &m_Height, &bufferSize);
- return true;
+ WARN_IF_ERR(err, "image_util_decode_run() failed.");
+ image_util_decode_destroy(decoder);
+
+ bool isSuccess = (buffer && err == IMAGE_UTIL_ERROR_NONE);
+ if (isSuccess) {
+ createPacket(buffer, bufferSize);
+ } else {
+ clear();
+ }
+ free(buffer);
+
+ return isSuccess;
}
-bool ImageData::crop(int width, int height)
+bool ImageData::exportToFile(const char *destPath)
{
- m_DestWidth = width;
- m_DestHeight = height;
+ unsigned char *buffer = nullptr;
+ unsigned long long bufferSize = 0;
+ media_packet_get_buffer_data_ptr(m_Packet, (void **)&buffer);
+ media_packet_get_buffer_size(m_Packet, (uint64_t *)&bufferSize);
+
+ unsigned char *jpegBuffer = nullptr;
+ image_util_encode_h encoder = nullptr;
+
+ image_util_encode_create(IMAGE_UTIL_JPEG, &encoder);
+ image_util_encode_set_resolution(encoder, m_Width, m_Height);
+ image_util_encode_set_colorspace(encoder, IMAGE_UTIL_COLORSPACE_RGBA8888);
+ image_util_encode_set_quality(encoder, 100);
+ image_util_encode_set_input_buffer(encoder, buffer);
+ image_util_encode_set_output_buffer(encoder, &jpegBuffer);
+ int err = image_util_encode_run(encoder, nullptr);
+ WARN_IF_ERR(err, "image_util_encode_run() failed.");
+ image_util_encode_destroy(encoder);
+
+ if (err == IMAGE_UTIL_ERROR_NONE) {
+ createJpegFile(destPath, jpegBuffer, bufferSize);
+ }
+ free(jpegBuffer);
+
+ return err == IMAGE_UTIL_ERROR_NONE;
+}
+
+bool ImageData::resize(unsigned long width, unsigned long height, ResultCallback callback)
+{
+ if (callback == nullptr) {
+ return false;
+ }
image_util_rotation_e rotation = getRotation();
+
if (rotation == IMAGE_UTIL_ROTATION_90 || rotation == IMAGE_UTIL_ROTATION_270) {
- std::swap(m_DestWidth, m_DestHeight);
+ std::swap(width, height);
}
- if (m_OrigWidth < m_DestWidth || m_OrigHeight < m_DestHeight) {
+ if (m_Width < width || m_Height < height) {
return false;
}
+ m_OnResult = std::move(callback);
- transformation_h handle;
+ double ratio = getResizeRatio(width, height);
+
+ transformation_h handle = nullptr;
image_util_transform_create(&handle);
image_util_transform_set_hardware_acceleration(handle, true);
- image_util_transform_set_crop_area(handle,
- (m_OrigWidth - m_DestWidth) / 2, (m_OrigHeight - m_DestHeight) / 2,
- (m_OrigWidth + m_DestWidth) / 2, (m_OrigHeight + m_DestHeight) / 2);
- int err = image_util_transform_run(handle, m_Packet, makeCallbackWithLastParam(&ImageData::onCropFinished), this);
- WARN_IF_ERR(err, "image_util_transform_run() failed.");
-
+ image_util_transform_set_resolution(handle, m_Width * ratio, m_Height * ratio);
+ int err = image_util_transform_run(handle, m_Packet, makeCallbackWithLastParam(&ImageData::onFinished), this);
+ if (err != IMAGE_UTIL_ERROR_NONE) {
+ m_OnResult = nullptr;
+ ERR("image_util_transform_run() failed.");
+ return false;
+ }
return true;
}
-bool ImageData::decode()
+bool ImageData::crop(unsigned long width, unsigned long height, ResultCallback callback)
{
- m_ExifData = exif_data_new_from_file(m_OrigPath.c_str());
+ if (callback == nullptr) {
+ return false;
+ }
+ image_util_rotation_e rotation = getRotation();
+ if (rotation == IMAGE_UTIL_ROTATION_90 || rotation == IMAGE_UTIL_ROTATION_270) {
+ std::swap(width, height);
+ }
- image_util_decode_h decoder = nullptr;
- image_util_decode_create(&decoder);
- image_util_decode_set_input_path(decoder, m_OrigPath.c_str());
- image_util_decode_set_colorspace(decoder, IMAGE_UTIL_COLORSPACE_RGBA8888);
- image_util_decode_set_output_buffer(decoder, &m_Buffer);
- int err = image_util_decode_run(decoder, &m_OrigWidth, &m_OrigHeight, &m_BufferSize);
- WARN_IF_ERR(err, "image_util_decode_run() failed.");
- image_util_decode_destroy(decoder);
+ if (m_Width < width || m_Height < height) {
+ return false;
+ }
- return err == IMAGE_UTIL_ERROR_NONE;
+ m_OnResult = std::move(callback);
+ transformation_h handle = nullptr;
+ image_util_transform_create(&handle);
+ image_util_transform_set_hardware_acceleration(handle, true);
+ image_util_transform_set_crop_area(handle,
+ (m_Width - width) / 2, (m_Height - height) / 2,
+ (m_Width + width) / 2, (m_Height + height) / 2);
+ int err = image_util_transform_run(handle, m_Packet, makeCallbackWithLastParam(&ImageData::onFinished), this);
+ if (err != IMAGE_UTIL_ERROR_NONE) {
+ m_OnResult = nullptr;
+ ERR("image_util_transform_run() failed.");
+ return false;
+ }
+ return true;
}
-bool ImageData::encode()
+double ImageData::getResizeRatio(int width, int height)
{
- unsigned char *jpegBuffer = nullptr;
- image_util_encode_h encoder = nullptr;
+ double widthRatio = width / (double)m_Width;
+ double heightRatio = height / (double)m_Height;
+ return std::max(heightRatio, widthRatio);
+}
- image_util_encode_create(IMAGE_UTIL_JPEG, &encoder);
- image_util_encode_set_resolution(encoder, m_DestWidth, m_DestHeight);
- image_util_encode_set_colorspace(encoder, IMAGE_UTIL_COLORSPACE_RGBA8888);
- image_util_encode_set_quality(encoder, 100);
- image_util_encode_set_input_buffer(encoder, m_Buffer);
- image_util_encode_set_output_buffer(encoder, &jpegBuffer);
- int err = image_util_encode_run(encoder, nullptr);
- WARN_IF_ERR(err, "image_util_encode_run() failed.");
- image_util_encode_destroy(encoder);
+void ImageData::createPacket(unsigned char *buffer, unsigned long long bufferSize)
+{
+ media_format_h fmt = nullptr;
+ media_format_create(&fmt);
+ media_format_set_video_mime(fmt, MEDIA_FORMAT_RGBA);
+ media_format_set_video_width(fmt, m_Width);
+ media_format_set_video_height(fmt, m_Height);
- if (err == IMAGE_UTIL_ERROR_NONE) {
- createJpegFile(jpegBuffer);
- }
- free(jpegBuffer);
+ void *srcPtr = nullptr;
+ media_packet_create_alloc(fmt, nullptr, nullptr, &m_Packet);
+ media_packet_get_buffer_data_ptr(m_Packet, &srcPtr);
+ memcpy(srcPtr, buffer, bufferSize);
- return err == IMAGE_UTIL_ERROR_NONE;
+ media_format_unref(fmt);
}
-void ImageData::createJpegFile(unsigned char *jpegBuffer)
+void ImageData::createJpegFile(const char *destPath, unsigned char *jpegBuffer, unsigned long long bufferSize)
{
unsigned char *exifBuff = nullptr;
unsigned int exifBuffLen = 0;
exif_data_save_data(m_ExifData, &exifBuff, &exifBuffLen);
std::ofstream outputFile;
- outputFile.open(m_DestPath.c_str());
+ outputFile.open(destPath);
if(outputFile.is_open()) {
if (exifBuff) {
outputFile.write((char *) EXIF_HEADER, EXIF_HEADER_LEN);
outputFile.put((exifBuffLen + 2) >> 8);
outputFile.put((exifBuffLen + 2) & 0xff);
outputFile.write((char *) exifBuff, exifBuffLen);
- outputFile.write((char *) jpegBuffer + JPEG_HEADER_OFFSET, m_BufferSize - JPEG_HEADER_OFFSET);
+ outputFile.write((char *) jpegBuffer + JPEG_HEADER_OFFSET, bufferSize - JPEG_HEADER_OFFSET);
} else {
- outputFile.write((char *)jpegBuffer, m_BufferSize);
+ outputFile.write((char *)jpegBuffer, bufferSize);
}
outputFile.close();
}
return rotation;
}
-void ImageData::onCropFinished(media_packet_h *dst, int error)
+void ImageData::clear()
{
- if (error == IMAGE_UTIL_ERROR_NONE) {
- media_packet_get_buffer_data_ptr(*dst, (void **)&m_Buffer);
- encode();
+ if (m_ExifData) {
+ exif_data_unref(m_ExifData);
+ m_ExifData = nullptr;
}
- if (m_OnCropped) {
- m_OnCropped(error);
+ if (m_Packet) {
+ media_packet_destroy(m_Packet);
+ m_Packet = nullptr;
+ }
+}
+
+void ImageData::onFinished(media_packet_h *dst, int error)
+{
+ if (error == IMAGE_UTIL_ERROR_NONE) {
+ media_packet_destroy(m_Packet);
+ m_Packet = *dst;
+
+ media_format_h fmt = nullptr;
+ media_packet_get_format(m_Packet, &fmt);
+ media_format_get_video_info(fmt, nullptr, (int *)&m_Width, (int *)&m_Height, nullptr, nullptr);
}
- delete this;
+
+ ResultCallback callback = m_OnResult;
+ m_OnResult = nullptr;
+ callback(error);
}