Skip to content

Commit aa1c44f

Browse files
committed
Fix accuracy loss when generating mipmap (#7)
1 parent 96335b5 commit aa1c44f

File tree

7 files changed

+150
-14
lines changed

7 files changed

+150
-14
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
## [Unreleased]
2+
### Fixed
3+
- Fix accuracy loss when generating mipmap (#7)
24

35
## [0.1.2] - 2022-02-17
46
### Fixed

Runtime/ImageImporter.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -294,15 +294,15 @@ static void FilterMipmapRGB24(ref FilterMipmapJob job, int outputIndex) {
294294
var inputX = min(mad(2, outputX, offsetX), job.inputDimensions.x - 1);
295295
var inputY = min(mad(2, outputY, offsetY), job.inputDimensions.y - 1);
296296
var inputIndex = mad(job.inputDimensions.x, inputY, inputX);
297-
outputColor.x += (uint)job.inputMipmap[mad(3, inputIndex, 0)] >> 2;
298-
outputColor.y += (uint)job.inputMipmap[mad(3, inputIndex, 1)] >> 2;
299-
outputColor.z += (uint)job.inputMipmap[mad(3, inputIndex, 2)] >> 2;
297+
outputColor.x += (uint)job.inputMipmap[mad(3, inputIndex, 0)];
298+
outputColor.y += (uint)job.inputMipmap[mad(3, inputIndex, 1)];
299+
outputColor.z += (uint)job.inputMipmap[mad(3, inputIndex, 2)];
300300
}
301301
}
302302

303-
job.outputMipmap[mad(3, outputIndex, 0)] = (byte)outputColor.x;
304-
job.outputMipmap[mad(3, outputIndex, 1)] = (byte)outputColor.y;
305-
job.outputMipmap[mad(3, outputIndex, 2)] = (byte)outputColor.z;
303+
job.outputMipmap[mad(3, outputIndex, 0)] = (byte)(outputColor.x >> 2);
304+
job.outputMipmap[mad(3, outputIndex, 1)] = (byte)(outputColor.y >> 2);
305+
job.outputMipmap[mad(3, outputIndex, 2)] = (byte)(outputColor.z >> 2);
306306
}
307307

308308
[BurstCompile(CompileSynchronously = true)]
@@ -316,17 +316,17 @@ static void FilterMipmapRGBA32(ref FilterMipmapJob job, int outputIndex) {
316316
var inputX = min(mad(2, outputX, offsetX), job.inputDimensions.x - 1);
317317
var inputY = min(mad(2, outputY, offsetY), job.inputDimensions.y - 1);
318318
var inputIndex = mad(job.inputDimensions.x, inputY, inputX);
319-
outputColor.x += (uint)job.inputMipmap[mad(4, inputIndex, 0)] >> 2;
320-
outputColor.y += (uint)job.inputMipmap[mad(4, inputIndex, 1)] >> 2;
321-
outputColor.z += (uint)job.inputMipmap[mad(4, inputIndex, 2)] >> 2;
322-
outputColor.w += (uint)job.inputMipmap[mad(4, inputIndex, 3)] >> 2;
319+
outputColor.x += (uint)job.inputMipmap[mad(4, inputIndex, 0)];
320+
outputColor.y += (uint)job.inputMipmap[mad(4, inputIndex, 1)];
321+
outputColor.z += (uint)job.inputMipmap[mad(4, inputIndex, 2)];
322+
outputColor.w += (uint)job.inputMipmap[mad(4, inputIndex, 3)];
323323
}
324324
}
325325

326-
job.outputMipmap[mad(4, outputIndex, 0)] = (byte)outputColor.x;
327-
job.outputMipmap[mad(4, outputIndex, 1)] = (byte)outputColor.y;
328-
job.outputMipmap[mad(4, outputIndex, 2)] = (byte)outputColor.z;
329-
job.outputMipmap[mad(4, outputIndex, 3)] = (byte)outputColor.w;
326+
job.outputMipmap[mad(4, outputIndex, 0)] = (byte)(outputColor.x >> 2);
327+
job.outputMipmap[mad(4, outputIndex, 1)] = (byte)(outputColor.y >> 2);
328+
job.outputMipmap[mad(4, outputIndex, 2)] = (byte)(outputColor.z >> 2);
329+
job.outputMipmap[mad(4, outputIndex, 3)] = (byte)(outputColor.w >> 2);
330330
}
331331

332332
[ReadOnly]

Tests.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "AsyncImageLoader.Tests",
3+
"references": [
4+
"AsyncImageLoader.Runtime"
5+
],
6+
"optionalUnityReferences": [
7+
"TestAssemblies"
8+
],
9+
"includePlatforms": [],
10+
"excludePlatforms": []
11+
}

Tests/AsyncImageLoader.Tests.asmdef.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tests/TestMipmap.cs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
using NUnit.Framework;
2+
using UnityEngine;
3+
using UnityEngine.TestTools;
4+
5+
public class TestMipmap {
6+
[Test]
7+
public void TestPNGImage() {
8+
var data = new byte[] {
9+
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
10+
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x08, 0x06, 0x00, 0x00, 0x00, 0x72, 0xB6, 0x0D,
11+
0x24, 0x00, 0x00, 0x00, 0x1B, 0x49, 0x44, 0x41, 0x54, 0x08, 0xD7, 0x63, 0x60, 0xF8, 0xCF, 0xD0,
12+
0xC0, 0xC0, 0xF0, 0xDF, 0x81, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x33, 0x30, 0xEC, 0x07, 0x00,
13+
0x43, 0x18, 0x08, 0x79, 0xEB, 0xE3, 0x55, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44,
14+
0xAE, 0x42, 0x60, 0x82
15+
};
16+
17+
var texture = AsyncImageLoader.CreateFromImage(data);
18+
var mipmapLevel0 = texture.GetPixelData<int>(0);
19+
var mipmapLevel1 = texture.GetPixelData<int>(1);
20+
21+
Assert.That(texture.format, Is.EqualTo(TextureFormat.RGBA32));
22+
Assert.That(texture.width, Is.EqualTo(2));
23+
Assert.That(texture.height, Is.EqualTo(2));
24+
Assert.That(texture.mipmapCount, Is.EqualTo(2));
25+
26+
Assert.That(mipmapLevel0.Length, Is.EqualTo(4));
27+
Assert.That(mipmapLevel0[0], Is.EqualTo(unchecked((int)0xFF_FF_FF_FF)));
28+
Assert.That(mipmapLevel0[1], Is.EqualTo(unchecked((int)0xBF_00_00_FF)));
29+
Assert.That(mipmapLevel0[2], Is.EqualTo(unchecked((int)0x80_00_FF_00)));
30+
Assert.That(mipmapLevel0[3], Is.EqualTo(unchecked((int)0x40_FF_00_00)));
31+
32+
Assert.That(mipmapLevel1.Length, Is.EqualTo(1));
33+
Assert.That(mipmapLevel1[0], Is.EqualTo(unchecked((int)0x9F_7F_7F_7F)));
34+
}
35+
36+
[Test]
37+
public void TestJPEGImage() {
38+
var data = new byte[] {
39+
0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x01, 0x2C,
40+
0x01, 0x2C, 0x00, 0x00, 0xFF, 0xDB, 0x00, 0x43, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
41+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
42+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
43+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
44+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xDB, 0x00, 0x43, 0x01, 0x01, 0x01,
45+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
46+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
47+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
48+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xC9,
49+
0x00, 0x11, 0x08, 0x00, 0x02, 0x00, 0x02, 0x03, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11,
50+
0x01, 0xFF, 0xCC, 0x00, 0x0A, 0x00, 0x10, 0x10, 0x05, 0x01, 0x10, 0x11, 0x05, 0xFF, 0xDA, 0x00,
51+
0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0xED, 0x83, 0x1F,
52+
0x33, 0xBE, 0xF8, 0x94, 0x15, 0x70, 0xB2, 0xBB, 0x79, 0x32, 0xF4, 0x33, 0x76, 0x95, 0xE5, 0x72,
53+
0x12, 0x80, 0xC7, 0xBB, 0xD4, 0xFB, 0xA3, 0x62, 0x4D, 0xF7, 0x60, 0x15, 0xAF, 0x52, 0x24, 0xCD,
54+
0xD2, 0xBF, 0xC1, 0x1C, 0xF3, 0x9A, 0x08, 0x87, 0xEE, 0x86, 0xB1, 0xD7, 0xE2, 0xC8, 0x9D, 0x24,
55+
0x55, 0xC1, 0x6D, 0xFF, 0x00, 0x4F, 0x49, 0x19, 0x7B, 0x42, 0xB3, 0x28, 0xB9, 0xB6, 0x05, 0x0E,
56+
0x5F, 0xCF, 0x84, 0x92, 0x6C, 0xB5, 0x54, 0x89, 0xBF, 0xFE, 0xE0, 0x0F, 0x33, 0x5E, 0x63, 0xB3,
57+
0x89, 0xEB, 0x11, 0x5A, 0x95, 0xD5, 0x09, 0x39, 0x2C, 0xB6, 0x04, 0x72, 0x3D, 0xF4, 0x9B, 0xB4,
58+
0x58, 0x49, 0x64, 0x46, 0x1D, 0x65, 0x60, 0x14, 0xBD, 0x04, 0x5C, 0xA4, 0xF0, 0x82, 0xAF, 0x10,
59+
0xC8, 0xFD, 0x60, 0x8E, 0x9C, 0x55, 0x8C, 0xA4, 0xFF, 0x00, 0x3C, 0xAE, 0x16, 0xBB, 0x53, 0xC2,
60+
0x59, 0x82, 0xDD, 0xAD, 0x3F, 0x7D, 0x68, 0x04, 0x6D, 0x7E, 0xD3, 0x6B, 0xA9, 0xA2, 0x01, 0x7F,
61+
0x6E, 0xA9, 0xBE, 0xE9, 0x3E, 0xB6, 0x24, 0x9E, 0xAB, 0xAD, 0xD8, 0xE7, 0x60, 0x64, 0x73, 0xC3,
62+
0x8F, 0xDC, 0xDC, 0xC2, 0x2F, 0x35, 0xF1, 0xEB, 0x2F, 0xA2, 0x75, 0x61, 0x01, 0xDF, 0x11, 0xF4,
63+
0xD0, 0xC1, 0x62, 0x5A, 0x28, 0x22, 0xEC, 0x05, 0x2A, 0x41, 0x14, 0xC2, 0xA0, 0x4D, 0xB7, 0x9F,
64+
0x3C, 0xF5, 0xD8, 0x90, 0xF1, 0x6F, 0x87, 0x09, 0xBE, 0xA9, 0xFD, 0x44, 0xBD, 0x59, 0x0C, 0x8B,
65+
0x03, 0xF8, 0xB1, 0x0E, 0x07, 0x73, 0x3C, 0x82, 0xDA, 0x09, 0x83, 0x35, 0x03, 0x90, 0x3E, 0xBC,
66+
0x65, 0x4B, 0x44, 0xAF, 0x2C, 0x80, 0xFF, 0xD9
67+
};
68+
69+
var texture = AsyncImageLoader.CreateFromImage(data);
70+
var mipmapLevel0 = texture.GetPixelData<byte>(0);
71+
var mipmapLevel1 = texture.GetPixelData<byte>(1);
72+
73+
Assert.That(texture.format, Is.EqualTo(TextureFormat.RGB24));
74+
Assert.That(texture.width, Is.EqualTo(2));
75+
Assert.That(texture.height, Is.EqualTo(2));
76+
Assert.That(texture.mipmapCount, Is.EqualTo(2));
77+
78+
Assert.That(mipmapLevel0.Length, Is.EqualTo(3 * 4));
79+
Assert.That(mipmapLevel0[0], Is.EqualTo(0XF7));
80+
Assert.That(mipmapLevel0[1], Is.EqualTo(0XFF));
81+
Assert.That(mipmapLevel0[2], Is.EqualTo(0XFF));
82+
Assert.That(mipmapLevel0[3], Is.EqualTo(0XF7));
83+
Assert.That(mipmapLevel0[4], Is.EqualTo(0X07));
84+
Assert.That(mipmapLevel0[5], Is.EqualTo(0X08));
85+
Assert.That(mipmapLevel0[6], Is.EqualTo(0X00));
86+
Assert.That(mipmapLevel0[7], Is.EqualTo(0XFF));
87+
Assert.That(mipmapLevel0[8], Is.EqualTo(0X00));
88+
Assert.That(mipmapLevel0[9], Is.EqualTo(0X00));
89+
Assert.That(mipmapLevel0[10], Is.EqualTo(0X08));
90+
Assert.That(mipmapLevel0[11], Is.EqualTo(0XFF));
91+
92+
Assert.That(mipmapLevel1.Length, Is.EqualTo(3));
93+
Assert.That(mipmapLevel1[0], Is.EqualTo(0x7B));
94+
Assert.That(mipmapLevel1[1], Is.EqualTo(0x83));
95+
Assert.That(mipmapLevel1[2], Is.EqualTo(0x81));
96+
}
97+
}

Tests/TestMipmap.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)