|
@@ -1,39 +1,59 @@
|
|
|
-#include <libpng16/png.h>
|
|
|
-
|
|
|
#include "images/PNGReader.h"
|
|
|
-#include "utils/Logger.h"
|
|
|
-#include "utils/StringBuffer.h"
|
|
|
|
|
|
-PNGReader::PNGReader(const char* path)
|
|
|
- : path(path), width(0), height(0), channels(0), bitDepth(0), rowBytes(0),
|
|
|
- file(fopen(path, "r")), read(nullptr), info(nullptr),
|
|
|
- rowPointers(nullptr) {
|
|
|
+PNGReader::PNGReader()
|
|
|
+ : path(""), width(0), height(0), channels(0), bitDepth(0), rowBytes(0),
|
|
|
+ file(nullptr), read(nullptr), info(nullptr), rowPointers(nullptr) {
|
|
|
+}
|
|
|
+
|
|
|
+PNGReader::~PNGReader() {
|
|
|
+ if(file != nullptr) {
|
|
|
+ fclose(file);
|
|
|
+ }
|
|
|
+ if(rowPointers != nullptr) {
|
|
|
+ png_free(read, rowPointers);
|
|
|
+ }
|
|
|
+ png_destroy_read_struct(&read, &info, nullptr);
|
|
|
+}
|
|
|
+
|
|
|
+Error PNGReader::load(const char* path) {
|
|
|
+ if(file != nullptr) {
|
|
|
+ Error error = {"file '"};
|
|
|
+ error.message.append(path).append("' is alreaded loaded");
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+ PNGReader::path = path;
|
|
|
+ file = fopen(path, "r");
|
|
|
if(file == nullptr) {
|
|
|
- LOG_WARNING(StringBuffer<100>("file '")
|
|
|
- .append(path)
|
|
|
- .append("' cannot be read: ")
|
|
|
- .append(static_cast<const char*>(strerror(errno))));
|
|
|
- return;
|
|
|
+ Error error = {"file '"};
|
|
|
+ error.message.append(path)
|
|
|
+ .append("' cannot be read: ")
|
|
|
+ .append(static_cast<const char*>(strerror(errno)));
|
|
|
+ return error;
|
|
|
}
|
|
|
- if(checkSignature()) {
|
|
|
- return;
|
|
|
+ png_byte buffer[8];
|
|
|
+ if(fread(buffer, sizeof(png_byte), 8, file) != 8) {
|
|
|
+ Error error = {"cannot read signature of file '"};
|
|
|
+ error.message.append(path).append("'");
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+ if(png_sig_cmp(buffer, 0, 8)) {
|
|
|
+ Error error = {"file '"};
|
|
|
+ error.message.append(path).append("' is not a png");
|
|
|
+ return error;
|
|
|
}
|
|
|
read = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr,
|
|
|
nullptr);
|
|
|
if(read == nullptr) {
|
|
|
- LOG_WARNING("cannot create png read data structure");
|
|
|
- return;
|
|
|
+ return {"cannot create png read data structure"};
|
|
|
}
|
|
|
info = png_create_info_struct(read);
|
|
|
if(info == nullptr) {
|
|
|
- LOG_WARNING("cannot create png info structure");
|
|
|
- return;
|
|
|
+ return {"cannot create png info structure"};
|
|
|
}
|
|
|
if(setjmp(png_jmpbuf(read))) {
|
|
|
- LOG_WARNING(StringBuffer<100>("png file '")
|
|
|
- .append(path)
|
|
|
- .append("' has used error callback"));
|
|
|
- return;
|
|
|
+ Error error = {"png file '"};
|
|
|
+ error.message.append(path).append("' has used error callback");
|
|
|
+ return error;
|
|
|
}
|
|
|
png_init_io(read, file);
|
|
|
png_set_sig_bytes(read, 8);
|
|
@@ -49,16 +69,27 @@ PNGReader::PNGReader(const char* path)
|
|
|
png_set_strip_16(read);
|
|
|
}
|
|
|
rowBytes = png_get_rowbytes(read, info);
|
|
|
-}
|
|
|
|
|
|
-PNGReader::~PNGReader() {
|
|
|
- if(file != nullptr) {
|
|
|
- fclose(file);
|
|
|
- }
|
|
|
- if(rowPointers != nullptr) {
|
|
|
- png_free(read, rowPointers);
|
|
|
+ if(channels < 1 || channels > 4) {
|
|
|
+ Error error = {"'"};
|
|
|
+ error.message.append(path)
|
|
|
+ .append("' has unsupported number of channels: ")
|
|
|
+ .append(channels);
|
|
|
+ return error;
|
|
|
+ } else if(width < 1 || width > 2048 || height < 1 || height > 2048) {
|
|
|
+ Error error = {"width and height of '"};
|
|
|
+ error.message.append(path).append("' are too big");
|
|
|
+ return error;
|
|
|
+ } else if(bitDepth != 8 && bitDepth != 16) {
|
|
|
+ Error error = {"bit depth of '"};
|
|
|
+ error.message.append(path).append("' is neither 8 or 16");
|
|
|
+ return error;
|
|
|
+ } else if(getBufferSize() != (rowBytes * height * 8 / bitDepth)) {
|
|
|
+ Error error = {"'"};
|
|
|
+ error.message.append(path).append("' needs an unexpected buffer size");
|
|
|
+ return error;
|
|
|
}
|
|
|
- png_destroy_read_struct(&read, &info, nullptr);
|
|
|
+ return {};
|
|
|
}
|
|
|
|
|
|
int PNGReader::getWidth() const {
|
|
@@ -77,53 +108,11 @@ int PNGReader::getBufferSize() const {
|
|
|
return width * height * channels;
|
|
|
}
|
|
|
|
|
|
-bool PNGReader::hasError() const {
|
|
|
- if(channels < 1 || channels > 4) {
|
|
|
- LOG_WARNING(StringBuffer<100>("'")
|
|
|
- .append(path)
|
|
|
- .append("' has unsupported number of channels: ")
|
|
|
- .append(channels));
|
|
|
- return true;
|
|
|
- } else if(width < 1 || width > 2048 || height < 1 || height > 2048) {
|
|
|
- LOG_WARNING(StringBuffer<100>("width and height of '")
|
|
|
- .append(path)
|
|
|
- .append("' are too big"));
|
|
|
- return true;
|
|
|
- } else if(bitDepth != 8 && bitDepth != 16) {
|
|
|
- LOG_WARNING(StringBuffer<100>("bit depth of '")
|
|
|
- .append(path)
|
|
|
- .append("' is neither 8 or 16"));
|
|
|
- return true;
|
|
|
- } else if(getBufferSize() != (rowBytes * height * 8 / bitDepth)) {
|
|
|
- LOG_WARNING(StringBuffer<100>("'").append(path).append(
|
|
|
- "' needs an unexpected buffer size"));
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-bool PNGReader::checkSignature() {
|
|
|
- png_byte buffer[8];
|
|
|
- if(fread(buffer, sizeof(png_byte), 8, file) != 8) {
|
|
|
- LOG_WARNING(StringBuffer<100>("cannot read signature of file '")
|
|
|
- .append(path)
|
|
|
- .append("'"));
|
|
|
- return true;
|
|
|
- }
|
|
|
- if(png_sig_cmp(buffer, 0, 8)) {
|
|
|
- LOG_WARNING(
|
|
|
- StringBuffer<100>("file '").append(path).append("' is not a png"));
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-bool PNGReader::readData(ColorChannel* buffer) {
|
|
|
+Error PNGReader::readData(ColorChannel* buffer) {
|
|
|
if(setjmp(png_jmpbuf(read))) {
|
|
|
- LOG_WARNING(StringBuffer<100>("png file '")
|
|
|
- .append(path)
|
|
|
- .append("' has used error callback"));
|
|
|
- return true;
|
|
|
+ Error error = {"png file '"};
|
|
|
+ error.message.append(path).append("' has used error callback");
|
|
|
+ return error;
|
|
|
}
|
|
|
rowPointers = static_cast<ColorChannel**>(
|
|
|
png_malloc(read, height * sizeof(ColorChannel*)));
|
|
@@ -132,5 +121,5 @@ bool PNGReader::readData(ColorChannel* buffer) {
|
|
|
}
|
|
|
png_set_rows(read, info, reinterpret_cast<png_bytepp>(rowPointers));
|
|
|
png_read_image(read, reinterpret_cast<png_bytepp>(rowPointers));
|
|
|
- return false;
|
|
|
+ return {};
|
|
|
}
|