Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

About overblurring #10

Open
ilyakurdyukov opened this issue Jul 12, 2020 · 2 comments
Open

About overblurring #10

ilyakurdyukov opened this issue Jul 12, 2020 · 2 comments

Comments

@ilyakurdyukov
Copy link

As the author of a similar project, I also encountered this effect, but found a method to prevent overblurring. I tried to apply same method to jpeg2png.

In compute.c, made changes to clamp_dct_c function:

// clamp the DCT values to interval that quantizes to our jpg
POSSIBLY_UNUSED static void clamp_dct_c(struct coef *coef, float *boxed, unsigned blocks) {
        for(unsigned i = 0; i < blocks; i++) {
                float mul = 1;
#if 1 // here's the fix
                float m0 = 0, m1 = 0;
                for (unsigned j = 1; j < 64; j++) {
                        float a0 = coef->data[i*64+j] * (int)coef->quant_table[j];
                        m0 += boxed[i*64+j] * a0;
                        m1 += a0 * a0;
                }
                if (m1 > m0) mul = MIN(m1 / m0, 1.1f);
#endif
                for(unsigned j = 0; j < 64; j++) {
                        float min = (coef->data[i*64+j] - 0.5f) * coef->quant_table[j];
                        float max = (coef->data[i*64+j] + 0.5f) * coef->quant_table[j];
                        float val = boxed[i*64+j] * mul;
                        boxed[i*64+j] = CLAMP(val, min, max);
                }
        }
}

And replaced the line
POSSIBLY_SIMD(clamp_dct)(coef, boxed, blocks);
with
clamp_dct_c(coef, boxed, blocks);

The resulting images become sharper, but in some places appeared side effects like sharp dots, and some gradients split into borders. I tried to limit this with MIN(m1 / m0, 1.1f) (I don't have this limit in my project, works without it), side effects become less visible but remain.

So my attempt to fix this problem added a few new ones.
Maybe someone will find a way to improve this fix, or another method to aid with overblurring.

@ilyakurdyukov
Copy link
Author

Second attempt:

--- compute-orig.c	2016-01-31 06:42:13.000000000 +0600
+++ compute.c	2020-07-12 17:52:23.634530193 +0700
@@ -331,7 +331,7 @@
 }
 
 // compute projection of data onto the feasible set defined by our jpg
-static void compute_projection(unsigned w, unsigned h, struct aux *aux, struct coef *coef) {
+static void compute_projection(unsigned w, unsigned h, struct aux *aux, struct coef *coef, float mul_limit) {
         unsigned blocks = (coef->h / 8) * (coef->w / 8);
         float *subsampled;
         float *boxed = aux->temp[0];
@@ -378,6 +378,25 @@
 
         POSSIBLY_SIMD(clamp_dct)(coef, boxed, blocks);
 
+        // second attempt to prevent overblurring
+        if(mul_limit > 1.0f)
+        for(unsigned i = 0; i < blocks; i++) {
+                float m0 = 0, m1 = 0, mul = 1;
+                for(unsigned j = 1; j < 64; j++) {
+                        float a0 = coef->data[i*64+j] * (int)coef->quant_table[j];
+                        m0 += boxed[i*64+j] * a0;
+                        m1 += a0 * a0;
+                }
+                if(m1 <= m0) continue;
+                mul = MIN(m1 / m0, mul_limit);
+                for(unsigned j = 1; j < 64; j++) {
+                        float min = (coef->data[i*64+j] - 0.5f) * coef->quant_table[j];
+                        float max = (coef->data[i*64+j] + 0.5f) * coef->quant_table[j];
+                        float val = boxed[i*64+j] * mul;
+                        boxed[i*64+j] = CLAMP(val, min, max);
+                }
+        }
+
         memcpy(aux->cos, boxed, coef->w * coef->h * sizeof(float)); // save a copy of the DCT values for step_prob
 
         for(unsigned i = 0; i < blocks; i++) {
@@ -444,7 +463,7 @@
                 // project back onto feasible set
                 OPENMP(parallel for schedule(dynamic))
                 for(unsigned c = 0; c < nchannel; c++) {
-                        compute_projection(w, h, &auxs[c], &coefs[c]);
+                        compute_projection(w, h, &auxs[c], &coefs[c], (float)(i + 1) / iterations * 0.2f + 0.9f);
                 }
                 if(pb) {
                         OPENMP(critical(progressbar))

Reduced side effects, the quality now seems acceptable.
You can adjust the sharpness by experimenting with the constants * 0.2f + 0.9f in the code.
Results looks a little over sharpened with the current values.

@zvezdochiot
Copy link

zvezdochiot commented Jul 12, 2020

@ilyakurdyukov say:

You can adjust the sharpness by experimenting with the constants * 0.2f + 0.9f in the code.

It is less bad to make constants as ext. command line options.

PS: ❓ Maybe add 'Issues' of you fork?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants