opj_dwt_encode_1_real(): avoid many bound comparisons, similarly to decoding side
authorEven Rouault <even.rouault@spatialys.com>
Wed, 20 May 2020 09:36:05 +0000 (11:36 +0200)
committerEven Rouault <even.rouault@spatialys.com>
Wed, 20 May 2020 18:31:28 +0000 (20:31 +0200)
src/lib/openjp2/dwt.c

index bdc91cf5585e51a1d968ccdf7bb6fcca610cb1d2..a825f0136082c8b94194228aa2ee80ca847950dd 100644 (file)
@@ -1040,59 +1040,77 @@ static void opj_idwt53_v(const opj_dwt_t *dwt,
 #endif
 }
 
+static void opj_dwt_encode_step1(OPJ_FLOAT32* fw,
+                                 OPJ_UINT32 start,
+                                 OPJ_UINT32 end,
+                                 const OPJ_FLOAT32 c)
+{
+    OPJ_UINT32 i;
+    for (i = start; i < end; ++i) {
+        fw[i * 2] *= c;
+    }
+}
+static void opj_dwt_encode_step2(OPJ_FLOAT32* fl, OPJ_FLOAT32* fw,
+                                 OPJ_UINT32 start,
+                                 OPJ_UINT32 end,
+                                 OPJ_UINT32 m,
+                                 OPJ_FLOAT32 c)
+{
+    OPJ_UINT32 i;
+    OPJ_UINT32 imax = opj_uint_min(end, m);
+    if (start > 0) {
+        fw += 2 * start;
+        fl = fw - 2;
+    }
+    for (i = start; i < imax; ++i) {
+        fw[-1] += (fl[0] + fw[0]) * c;
+        fl = fw;
+        fw += 2;
+    }
+    if (m < end) {
+        assert(m + 1 == end);
+        fw[-1] += (2 * fl[0]) * c;
+    }
+}
 
-/* <summary>                             */
-/* Forward 9-7 wavelet transform in 1-D. */
-/* </summary>                            */
 static void opj_dwt_encode_1_real(void *aIn, OPJ_INT32 dn, OPJ_INT32 sn,
                                   OPJ_INT32 cas)
 {
-    OPJ_INT32 i;
-    OPJ_FLOAT32* a = (OPJ_FLOAT32*)aIn;
-
-    if (!cas) {
-        if ((dn > 0) || (sn > 1)) { /* NEW :  CASE ONE ELEMENT */
-            for (i = 0; i < dn; i++) {
-                OPJ_D(i) += opj_dwt_alpha * (OPJ_S_(i) + OPJ_S_(i + 1));
-            }
-            for (i = 0; i < sn; i++) {
-                OPJ_S(i) += opj_dwt_beta * (OPJ_D_(i - 1) + OPJ_D_(i));
-            }
-            for (i = 0; i < dn; i++) {
-                OPJ_D(i) += opj_dwt_gamma * (OPJ_S_(i) + OPJ_S_(i + 1));
-            }
-            for (i = 0; i < sn; i++) {
-                OPJ_S(i) += opj_dwt_delta * (OPJ_D_(i - 1) + OPJ_D_(i));
-            }
-            for (i = 0; i < dn; i++) {
-                OPJ_D(i) = opj_K / 2 * OPJ_D(i);
-            }
-            for (i = 0; i < sn; i++) {
-                OPJ_S(i) = opj_c13318 / 2 * OPJ_S(i);
-            }
+    OPJ_FLOAT32* w = (OPJ_FLOAT32*)aIn;
+    OPJ_INT32 a, b;
+    if (cas == 0) {
+        if (!((dn > 0) || (sn > 1))) {
+            return;
         }
+        a = 0;
+        b = 1;
     } else {
-        if ((sn > 0) || (dn > 1)) { /* NEW :  CASE ONE ELEMENT */
-            for (i = 0; i < dn; i++) {
-                OPJ_S(i) += opj_dwt_alpha * (OPJ_DD_(i) + OPJ_DD_(i - 1));
-            }
-            for (i = 0; i < sn; i++) {
-                OPJ_D(i) += opj_dwt_beta * (OPJ_SS_(i) + OPJ_SS_(i + 1));
-            }
-            for (i = 0; i < dn; i++) {
-                OPJ_S(i) += opj_dwt_gamma * (OPJ_DD_(i) + OPJ_DD_(i - 1));
-            }
-            for (i = 0; i < sn; i++) {
-                OPJ_D(i) += opj_dwt_delta * (OPJ_SS_(i) + OPJ_SS_(i + 1));
-            }
-            for (i = 0; i < dn; i++) {
-                OPJ_S(i) = opj_K / 2 * OPJ_S(i);
-            }
-            for (i = 0; i < sn; i++) {
-                OPJ_D(i) = opj_c13318 / 2 * OPJ_D(i);
-            }
+        if (!((sn > 0) || (dn > 1))) {
+            return;
         }
+        a = 1;
+        b = 0;
     }
+    opj_dwt_encode_step2(w + a, w + b + 1,
+                         0, (OPJ_UINT32)dn,
+                         (OPJ_UINT32)opj_int_min(dn, sn - b),
+                         opj_dwt_alpha);
+    opj_dwt_encode_step2(w + b, w + a + 1,
+                         0, (OPJ_UINT32)sn,
+                         (OPJ_UINT32)opj_int_min(sn, dn - a),
+                         opj_dwt_beta);
+    opj_dwt_encode_step2(w + a, w + b + 1,
+                         0, (OPJ_UINT32)dn,
+                         (OPJ_UINT32)opj_int_min(dn, sn - b),
+                         opj_dwt_gamma);
+    opj_dwt_encode_step2(w + b, w + a + 1,
+                         0, (OPJ_UINT32)sn,
+                         (OPJ_UINT32)opj_int_min(sn, dn - a),
+                         opj_dwt_delta);
+    opj_dwt_encode_step1(w + b, 0, (OPJ_UINT32)dn,
+                         opj_K / 2);
+    opj_dwt_encode_step1(w + a, 0, (OPJ_UINT32)sn,
+                         opj_c13318 / 2);
 }
 
 static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps,