Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/lvandeve/lodepng.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLode <lvandeve@gmail.com>2020-01-20 02:27:52 +0300
committerLode <lvandeve@gmail.com>2020-01-20 02:27:52 +0300
commit5a0dba103893e6b8084be13945a826663917d00a (patch)
tree8e26875e91495d26a4882e8dfac8ce6641995061
parent2febfe0d105822575328759dd950c8a24b0ad6b3 (diff)
fix get-filtertype utility for 1-pixel wide or high interlaced images
-rw-r--r--lodepng_unittest.cpp19
-rw-r--r--lodepng_util.cpp24
2 files changed, 34 insertions, 9 deletions
diff --git a/lodepng_unittest.cpp b/lodepng_unittest.cpp
index 90c8323..4a21e29 100644
--- a/lodepng_unittest.cpp
+++ b/lodepng_unittest.cpp
@@ -679,6 +679,24 @@ void doCodecTestNoLZ77(Image& image) {
doCodecTestWithEncState(image, state);
}
+void testGetFilterTypes() {
+ std::cout << "testGetFilterTypes" << std::endl;
+ // Test that getFilterTypes works on the special case of 1-pixel wide interlaced image
+ std::string png64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAAHCAIAAAExKYBVAAAAHUlEQVR4ASXHAQoAAAjCwPX/R9tK4ZBN4EHKcPcLXCgGAQa0TV8AAAAASUVORK5CYII=";
+ std::vector<unsigned char> png;
+ fromBase64(png, png64);
+ std::vector<unsigned char> types;
+ lodepng::getFilterTypes(types, png);
+ ASSERT_EQUALS(7, types.size());
+ ASSERT_EQUALS(1, types[0]);
+ ASSERT_EQUALS(1, types[1]);
+ ASSERT_EQUALS(1, types[2]);
+ ASSERT_EQUALS(0, types[3]);
+ ASSERT_EQUALS(1, types[4]);
+ ASSERT_EQUALS(1, types[5]);
+ ASSERT_EQUALS(1, types[6]);
+}
+
//Test LodePNG encoding and decoding the encoded result, using the C++ interface, with interlace
void doCodecTestInterlaced(Image& image) {
std::vector<unsigned char> encoded;
@@ -3663,6 +3681,7 @@ void doMain() {
//lodepng_util
testChunkUtil();
+ testGetFilterTypes();
std::cout << "\ntest successful" << std::endl;
}
diff --git a/lodepng_util.cpp b/lodepng_util.cpp
index 5c5d876..899a49d 100644
--- a/lodepng_util.cpp
+++ b/lodepng_util.cpp
@@ -198,8 +198,7 @@ unsigned getFilterTypesInterlaced(std::vector<std::vector<unsigned char> >& filt
for(size_t j = 0; j < 7; j++) {
unsigned w2 = (w - ADAM7_IX[j] + ADAM7_DX[j] - 1) / ADAM7_DX[j];
unsigned h2 = (h - ADAM7_IY[j] + ADAM7_DY[j] - 1) / ADAM7_DY[j];
- if(ADAM7_IX[j] >= w) w2 = 0;
- if(ADAM7_IY[j] >= h) h2 = 0;
+ if(ADAM7_IX[j] >= w || ADAM7_IY[j] >= h) continue;
size_t linebytes = 1 + lodepng_get_raw_size(w2, 1, &state.info_png.color);
for(size_t i = 0; i < h2; i++) {
filterTypes[j].push_back(data[pos]);
@@ -219,17 +218,24 @@ unsigned getFilterTypes(std::vector<unsigned char>& filterTypes, const std::vect
if(passes.size() == 1) {
filterTypes.swap(passes[0]);
} else {
+ // Simplify interlaced filter types to get a single filter value per scanline:
+ // put pass 6 and 7 alternating in the one vector, these filters
+ // correspond to the closest to what it would be for non-interlaced
+ // image. If the image is only 1 pixel wide, pass 6 doesn't exist so the
+ // alternative values column0 are used. The shift values are to match
+ // the y position in the interlaced sub-images.
+ // NOTE: the values 0-6 match Adam7's passes 1-7.
+ const unsigned column0[8] = {0, 6, 4, 6, 2, 6, 4, 6};
+ const unsigned column1[8] = {5, 6, 5, 6, 5, 6, 5, 6};
+ const unsigned shift0[8] = {3, 1, 2, 1, 3, 1, 2, 1};
+ const unsigned shift1[8] = {1, 1, 1, 1, 1, 1, 1, 1};
lodepng::State state;
unsigned w, h;
lodepng_inspect(&w, &h, &state, &png[0], png.size());
- /*
- Interlaced. Simplify it: put pass 6 and 7 alternating in the one vector so
- that one filter per scanline of the uninterlaced image is given, with that
- filter corresponding the closest to what it would be for non-interlaced
- image.
- */
+ const unsigned* column = w > 1 ? column1 : column0;
+ const unsigned* shift = w > 1 ? shift1 : shift0;
for(size_t i = 0; i < h; i++) {
- filterTypes.push_back(i % 2 == 0 ? passes[5][i / 2] : passes[6][i / 2]);
+ filterTypes.push_back(passes[column[i & 7u]][i >> shift[i & 7u]]);
}
}
return 0; /* OK */