浏览代码

LibGfx: Move PNG header and paeth_predictor function to a shared header

Karol Kosek 3 年之前
父节点
当前提交
98a90d79de
共有 3 个文件被更改,包括 28 次插入27 次删除
  1. 10 25
      Userland/Libraries/LibGfx/PNGLoader.cpp
  2. 17 0
      Userland/Libraries/LibGfx/PNGShared.h
  3. 1 2
      Userland/Libraries/LibGfx/PNGWriter.cpp

+ 10 - 25
Userland/Libraries/LibGfx/PNGLoader.cpp

@@ -20,8 +20,6 @@
 
 namespace Gfx {
 
-static constexpr Array<u8, 8> png_header = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 };
-
 struct PNG_IHDR {
     NetworkOrdered<u32> width;
     NetworkOrdered<u32> height;
@@ -166,19 +164,6 @@ private:
 
 static bool process_chunk(Streamer&, PNGLoadingContext& context);
 
-ALWAYS_INLINE static u8 paeth_predictor(int a, int b, int c)
-{
-    int p = a + b - c;
-    int pa = abs(p - a);
-    int pb = abs(p - b);
-    int pc = abs(p - c);
-    if (pa <= pb && pa <= pc)
-        return a;
-    if (pb <= pc)
-        return b;
-    return c;
-}
-
 union [[gnu::packed]] Pixel {
     ARGB32 rgba { 0 };
     u8 v[4];
@@ -264,11 +249,11 @@ ALWAYS_INLINE static void unfilter_impl(Gfx::Bitmap& bitmap, int y, void const*
                 a = pixels[i - 1];
                 c = pixels_y_minus_1[i - 1];
             }
-            x.v[0] += paeth_predictor(a.v[0], b.v[0], c.v[0]);
-            x.v[1] += paeth_predictor(a.v[1], b.v[1], c.v[1]);
-            x.v[2] += paeth_predictor(a.v[2], b.v[2], c.v[2]);
+            x.v[0] += PNG::paeth_predictor(a.v[0], b.v[0], c.v[0]);
+            x.v[1] += PNG::paeth_predictor(a.v[1], b.v[1], c.v[1]);
+            x.v[2] += PNG::paeth_predictor(a.v[2], b.v[2], c.v[2]);
             if constexpr (has_alpha)
-                x.v[3] += paeth_predictor(a.v[3], b.v[3], c.v[3]);
+                x.v[3] += PNG::paeth_predictor(a.v[3], b.v[3], c.v[3]);
         }
     }
 }
@@ -513,13 +498,13 @@ static bool decode_png_header(PNGLoadingContext& context)
     if (context.state >= PNGLoadingContext::HeaderDecoded)
         return true;
 
-    if (!context.data || context.data_size < sizeof(png_header)) {
+    if (!context.data || context.data_size < sizeof(PNG::header)) {
         dbgln_if(PNG_DEBUG, "Missing PNG header");
         context.state = PNGLoadingContext::State::Error;
         return false;
     }
 
-    if (memcmp(context.data, png_header.span().data(), sizeof(png_header)) != 0) {
+    if (memcmp(context.data, PNG::header.span().data(), sizeof(PNG::header)) != 0) {
         dbgln_if(PNG_DEBUG, "Invalid PNG header");
         context.state = PNGLoadingContext::State::Error;
         return false;
@@ -539,8 +524,8 @@ static bool decode_png_size(PNGLoadingContext& context)
             return false;
     }
 
-    u8 const* data_ptr = context.data + sizeof(png_header);
-    size_t data_remaining = context.data_size - sizeof(png_header);
+    u8 const* data_ptr = context.data + sizeof(PNG::header);
+    size_t data_remaining = context.data_size - sizeof(PNG::header);
 
     Streamer streamer(data_ptr, data_remaining);
     while (!streamer.at_end()) {
@@ -567,8 +552,8 @@ static bool decode_png_chunks(PNGLoadingContext& context)
             return false;
     }
 
-    u8 const* data_ptr = context.data + sizeof(png_header);
-    int data_remaining = context.data_size - sizeof(png_header);
+    u8 const* data_ptr = context.data + sizeof(PNG::header);
+    int data_remaining = context.data_size - sizeof(PNG::header);
 
     context.compressed_data.ensure_capacity(context.data_size);
 

+ 17 - 0
Userland/Libraries/LibGfx/PNGShared.h

@@ -8,6 +8,9 @@
 
 namespace Gfx::PNG {
 
+// https://www.w3.org/TR/PNG/#5PNG-file-signature
+static constexpr Array<u8, 8> header = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 };
+
 // https://www.w3.org/TR/PNG/#6Colour-values
 enum class ColorType : u8 {
     Greyscale = 0,
@@ -26,4 +29,18 @@ enum class FilterType : u8 {
     Paeth,
 };
 
+// https://www.w3.org/TR/PNG/#9Filter-type-4-Paeth
+ALWAYS_INLINE u8 paeth_predictor(u8 a, u8 b, u8 c)
+{
+    int p = a + b - c;
+    int pa = abs(p - a);
+    int pb = abs(p - b);
+    int pc = abs(p - c);
+    if (pa <= pb && pa <= pc)
+        return a;
+    if (pb <= pc)
+        return b;
+    return c;
+}
+
 };

+ 1 - 2
Userland/Libraries/LibGfx/PNGWriter.cpp

@@ -112,8 +112,7 @@ void PNGWriter::add_chunk(PNGChunk& png_chunk)
 
 void PNGWriter::add_png_header()
 {
-    const u8 png_header[8] = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 };
-    m_data.append(png_header, sizeof(png_header));
+    m_data.append(PNG::header.data(), PNG::header.size());
 }
 
 void PNGWriter::add_IHDR_chunk(u32 width, u32 height, u8 bit_depth, PNG::ColorType color_type, u8 compression_method, u8 filter_method, u8 interlace_method)