Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (525)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (594)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Mipmap (gamma corrected)  (Read 4032 times)
0 Members and 1 Guest are viewing this topic.
Offline Riven
« League of Dukes »

« JGO Overlord »


Medals: 833
Projects: 4
Exp: 16 years


Hand over your head.


« Posted 2009-08-02 17:13:28 »

High constrast regions become 'darker' when scaling down. Use this (slow) code to fixy fixy.

vs.

vs.

Have fun.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
   public static BufferedImage mipmapGammaCorrected(BufferedImage src, int level)
   {
      if (level < 1)
      {
         throw new IllegalArgumentException();
      }

      for (int i = 0; i < level; i++)
      {
         BufferedImage tmp = mipmapGammaCorrected(src);
         if (i != 0)
            src.flush(); // do not flush argument
         src = tmp;
      }
      return src;
   }

   public static BufferedImage mipmapGammaCorrected(BufferedImage src)
   {
      int wSrc = src.getWidth();
      int hSrc = src.getHeight();

      if (wSrc % 2 != 0 || hSrc % 2 != 0)
      {
         throw new IllegalStateException("dimensions must be multiple of 2");
      }

      int wDst = wSrc / 2;
      int hDst = hSrc / 2;

      int[] argbFull = src.getRGB(0, 0, wSrc, hSrc, null, 0, wSrc);

      int type = BufferedImage.TYPE_INT_RGB;
      if (src.getAlphaRaster() != null)
      {
         type = BufferedImage.TYPE_INT_ARGB;

         // merge alpha into RGB values
         int[] alphaFull = src.getAlphaRaster().getPixels(0, 0, wSrc, hSrc, (int[]) null);
         for (int i = 0; i < alphaFull.length; i++)
         {
            argbFull[i] = (alphaFull[i] << 24) | (argbFull[i] & 0x00FFFFFF);
         }
      }

      BufferedImage half = new BufferedImage(wDst, hDst, type);

      int[] argbHalf = new int[argbFull.length >>> 2];

      for (int y = 0; y < hDst; y++)
      {
         for (int x = 0; x < wDst; x++)
         {
            int p0 = argbFull[((y << 1) | 0) * wSrc + ((x << 1) | 0)];
            int p1 = argbFull[((y << 1) | 1) * wSrc + ((x << 1) | 0)];
            int p2 = argbFull[((y << 1) | 1) * wSrc + ((x << 1) | 1)];
            int p3 = argbFull[((y << 1) | 0) * wSrc + ((x << 1) | 1)];

            int a = gammaCorrectedAverage(p0, p1, p2, p3, 24);
            int r = gammaCorrectedAverage(p0, p1, p2, p3, 16);
            int g = gammaCorrectedAverage(p0, p1, p2, p3, 8);
            int b = gammaCorrectedAverage(p0, p1, p2, p3, 0);

            argbHalf[y * wDst + x] = (a << 24) | (r << 16) | (g << 8) | (b << 0);
         }
      }

      half.setRGB(0, 0, wDst, hDst, argbHalf, 0, wDst);
      if (type == BufferedImage.TYPE_INT_ARGB)
      {
         // extract alpha from ARGB values
         int[] alpha = new int[argbHalf.length];
         for (int i = 0; i < alpha.length; i++)
            alpha[i] = (argbHalf[i] >> 24) & 0xFF;
         half.getAlphaRaster().setPixels(0, 0, wDst, hDst, alpha);
      }

      return half;
   }

   static int gammaCorrectedAverage(int a, int b, int c, int d, int shift)
   {
      float x = ((a >> shift) & 0xFF) / 255.0f;
      float y = ((b >> shift) & 0xFF) / 255.0f;
      float z = ((c >> shift) & 0xFF) / 255.0f;
      float w = ((d >> shift) & 0xFF) / 255.0f;

      float e = x * x + y * y + z * z + w * w;
      e = (float) Math.sqrt(e * 0.25f);
      return (int) (e * 255.0f);
   }

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline SwampChicken
« Reply #1 - Posted 2009-08-13 07:28:44 »

Could you possibly attach two larger pics so we can see what the differences actually look like?
Offline Riven
« League of Dukes »

« JGO Overlord »


Medals: 833
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #2 - Posted 2009-08-13 11:42:29 »

Uh... do you see the text is much brighter against the blue background?

You don't see that effect too clearly in the larger images, so there wouldn't be any point in showing them.

It's all about the quality in the smaller/smallest mipmap levels.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Spasi
« Reply #3 - Posted 2009-08-13 13:50:28 »

I implemented a shader version of this a few years ago, it improves texture quality by a huge margin, especially in a gamma-correct rendering environment (most HDR renderers). You don't even have to use mipmaps to notice it, just compare a shaded surface with a texture in your engine side-by-side with the same texture in your favorite image editor, it won't be what the artist created under non-gamma-correct rendering. It's the same thing with mipmaps, any kind of action on the non-linear values of the original image will distort the colors.

My implementation did an initial conversion to linear space on a floating-point texture, then did the downscale in fp precision with a bicubic filter, then converted back to gamma-space. It was nearly instant too, even with large textures, GPU acceleration owns. Wink
Edit: I also used x^2.2 instead of x^2, since 2.2 is the value used by most monitors and image editing software. x^2 is a very decent approximation though, I use it in the fast path of my renderer, since you can then use inversesqrt instead of pow for the gamma correction.

Anyway, I'd post the code but it's kinda buried deep in my tool code, so if anyone wants code-snippets or help with implementing something similar, feel free to contact me. But Riven's implementation is great for most use-cases, as always. Wink
Offline i30817

Junior Devvie





« Reply #4 - Posted 2009-08-24 19:20:34 »

Anything for better quality thumbnails. As long as it is fast. Is the effect noticeable on larger thumbs?
Offline Riven
« League of Dukes »

« JGO Overlord »


Medals: 833
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #5 - Posted 2009-08-24 19:36:03 »

Anything for better quality thumbnails. As long as it is fast. Is the effect noticeable on larger thumbs?

Answer:
You don't see that effect too clearly in the larger images, so there wouldn't be any point in showing them.

Ah, also, the CPU version (my version) is extremely slow.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline i30817

Junior Devvie





« Reply #6 - Posted 2009-08-27 19:39:27 »

Ah, well. Ok.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

toopeicgaming1999 (71 views)
2014-11-26 15:22:04

toopeicgaming1999 (60 views)
2014-11-26 15:20:36

toopeicgaming1999 (14 views)
2014-11-26 15:20:08

SHC (27 views)
2014-11-25 12:00:59

SHC (25 views)
2014-11-25 11:53:45

Norakomi (31 views)
2014-11-25 11:26:43

Gibbo3771 (25 views)
2014-11-24 19:59:16

trollwarrior1 (38 views)
2014-11-22 12:13:56

xFryIx (77 views)
2014-11-13 12:34:49

digdugdiggy (55 views)
2014-11-12 21:11:50
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!