Skip to content

Commit 849e572

Browse files
committed
RGB565 improvements
1 parent 248e89c commit 849e572

File tree

8 files changed

+97
-101
lines changed

8 files changed

+97
-101
lines changed

app/src/main/java/com/radzivon/bartoshyk/avif/MainActivity.kt

Lines changed: 28 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -45,86 +45,26 @@ class MainActivity : AppCompatActivity() {
4545
// assert(HeifCoder().isAvif(buffer))
4646
val size = HeifCoder().getSize(buffer)!!
4747
assert(size != null)
48-
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
49-
// val time = measureTimeMillis {
50-
//// val bitmap = HeifCoder().decodeSampled(
51-
//// buffer,
52-
//// size.width / 2,
53-
//// size.height / 2,
54-
//// PreferredColorConfig.HARDWARE
55-
//// )
56-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
57-
val bitmap = HeifCoder().decodeSampled(
58-
buffer,
59-
350,
60-
600,
61-
PreferredColorConfig.HARDWARE,
62-
ScaleMode.FIT
63-
)
64-
bitmap.recycle()
65-
}
66-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
67-
val bitmap = HeifCoder().decodeSampled(
68-
buffer,
69-
350,
70-
600,
71-
PreferredColorConfig.HARDWARE,
72-
ScaleMode.FIT
73-
)
74-
bitmap.recycle()
75-
}
76-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
77-
val bitmap = HeifCoder().decodeSampled(
78-
buffer,
79-
350,
80-
600,
81-
PreferredColorConfig.HARDWARE,
82-
ScaleMode.FIT
83-
)
84-
bitmap.recycle()
85-
}
86-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
87-
val bitmap = HeifCoder().decodeSampled(
88-
buffer,
89-
350,
90-
600,
91-
PreferredColorConfig.HARDWARE,
92-
ScaleMode.FIT
93-
)
94-
bitmap.recycle()
95-
}
96-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
97-
val bitmap = HeifCoder().decodeSampled(
98-
buffer,
99-
350,
100-
600,
101-
PreferredColorConfig.HARDWARE,
102-
ScaleMode.FIT
103-
)
104-
bitmap.recycle()
105-
}
106-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
107-
val bitmap = HeifCoder().decodeSampled(
108-
buffer,
109-
350,
110-
600,
111-
PreferredColorConfig.HARDWARE,
112-
ScaleMode.FIT
113-
)
114-
bitmap.recycle()
115-
}
116-
//// val opts = BitmapFactory.Options()
117-
//// opts.inMutable = true
118-
//// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
119-
//// opts.inPreferredConfig = Bitmap.Config.RGBA_F16
120-
//// }
121-
// binding.imageView.setImageBitmap(bitmap)
122-
// }
123-
// Log.i("MainActivity AVIF ", "Done in ${time}")
124-
//// val encoded = HeifCoder().encodeAvif(bitmap)
125-
//// val decodedSample = HeifCoder().decode(encoded)
126-
//// binding.imageView.setImageBitmap(bitmap)
48+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
49+
val time = measureTimeMillis {
50+
val bitmap = HeifCoder().decodeSampled(
51+
buffer,
52+
size.width / 2,
53+
size.height / 2,
54+
PreferredColorConfig.RGB_565
55+
)
56+
// val opts = BitmapFactory.Options()
57+
// opts.inMutable = true
58+
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
59+
// opts.inPreferredConfig = Bitmap.Config.RGBA_F16
12760
// }
61+
binding.imageView.setImageBitmap(bitmap)
62+
}
63+
Log.i("MainActivity AVIF ", "Done in ${time}")
64+
// val encoded = HeifCoder().encodeAvif(bitmap)
65+
// val decodedSample = HeifCoder().decode(encoded)
66+
// binding.imageView.setImageBitmap(bitmap)
67+
}
12868

12969
//https://wh.aimuse.online/creatives/IMUSE_03617fe2db82a584166_27/TT_a9d21ff1061d785347935fef/68f06252.avif
13070
//https://wh.aimuse.online/preset/federico-beccari.avif
@@ -135,12 +75,15 @@ class MainActivity : AppCompatActivity() {
13575
// .skipMemoryCache(true)
13676
// .into(binding.imageView)
13777

138-
binding.imageView.load("https://wh.aimuse.online/creatives/IMUSE_03617fe2db82a584166_27/TT_a9d21ff1061d785347935fef/68f06252.avif",
139-
imageLoader = ImageLoader.Builder(this)
140-
.components {
141-
add(HeifDecoder.Factory())
142-
}
143-
.build())
78+
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
79+
// binding.imageView.load("https://wh.aimuse.online/preset/federico-beccari.avif",
80+
// imageLoader = ImageLoader.Builder(this)
81+
// .components {
82+
// add(HeifDecoder.Factory())
83+
// }
84+
// .bitmapConfig(Bitmap.Config.HARDWARE)
85+
// .build())
86+
// }
14487

14588
// binding.imageView.setImageBitmap(bitmap)
14689
// binding.imageView.setImageBitmap(cc16)

app/src/main/res/layout/activity_main.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919
<ImageView
2020
android:id="@+id/imageView"
21-
android:layout_width="wrap_content"
22-
android:layout_height="wrap_content"
21+
android:layout_width="320dp"
22+
android:layout_height="320dp"
2323
android:scaleType="fitCenter"
2424
app:layout_constraintBottom_toBottomOf="parent"
2525
app:layout_constraintEnd_toEndOf="parent"

avif-coder/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ android {
8181
sourceCompatibility = JavaVersion.VERSION_17
8282
targetCompatibility = JavaVersion.VERSION_17
8383
}
84+
8485
kotlinOptions {
8586
jvmTarget = JavaVersion.VERSION_17.toString()
8687
}

avif-coder/src/main/cpp/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ list(APPEND EXTRA_LIBS cpufeatures)
4848

4949
include(CheckCXXCompilerFlag)
5050
if (ANDROID_ABI STREQUAL arm64-v8a)
51-
set_target_properties(coder PROPERTIES COMPILE_FLAGS -mfpu=neon)
5251
add_definitions("-DHAVE_NEON=1")
5352
endif ()
5453

avif-coder/src/main/cpp/JniBitmap.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,17 @@ createBitmap(JNIEnv *env, std::shared_ptr<uint8_t> &data, std::string &colorConf
4444
return static_cast<jobject>(nullptr);
4545
}
4646

47-
coder::CopyUnalignedRGBA(reinterpret_cast<const uint8_t *>(data.get()), stride,
48-
reinterpret_cast<uint8_t *>(addr), (int) info.stride, (int) info.width,
49-
(int) info.height, use16Floats ? 2 : 1);
47+
if (colorConfig == "RGB_565") {
48+
coder::CopyUnalignedRGB565(reinterpret_cast<const uint8_t *>(data.get()), stride,
49+
reinterpret_cast<uint8_t *>(addr), (int) info.stride,
50+
(int) info.width,
51+
(int) info.height);
52+
} else {
53+
coder::CopyUnalignedRGBA(reinterpret_cast<const uint8_t *>(data.get()), stride,
54+
reinterpret_cast<uint8_t *>(addr), (int) info.stride,
55+
(int) info.width,
56+
(int) info.height, use16Floats ? 2 : 1);
57+
}
5058

5159
if (AndroidBitmap_unlockPixels(env, bitmapObj) != 0) {
5260
throwPixelsException(env);

avif-coder/src/main/cpp/imagebits/CopyUnalignedRGBA.cpp

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313

1414
HWY_BEFORE_NAMESPACE();
1515

16-
namespace coder {
17-
namespace HWY_NAMESPACE {
16+
namespace coder::HWY_NAMESPACE {
1817

1918
using hwy::HWY_NAMESPACE::ScalableTag;
2019
using hwy::HWY_NAMESPACE::Store;
@@ -96,14 +95,47 @@ namespace coder {
9695
}
9796
}
9897

98+
void CopyUnalignedRGB565Row(const uint16_t *HWY_RESTRICT src, uint16_t *HWY_RESTRICT dst,
99+
int width) {
100+
int x = 0;
101+
const ScalableTag<uint16_t> du;
102+
using VU = Vec<decltype(du)>;
103+
int pixels = du.MaxLanes();
104+
for (x = 0; x + pixels < width; x += pixels) {
105+
VU pixel = Load(du, src);
106+
Store(pixel, du, dst);
107+
108+
src += pixels;
109+
dst += pixels;
110+
}
111+
112+
for (; x < width; ++x) {
113+
auto p1 = src[0];
114+
dst[0] = p1;
115+
src += 1;
116+
dst += 1;
117+
}
118+
}
119+
120+
void
121+
CopyUnalignedRGB565(const uint8_t *HWY_RESTRICT src, int srcStride, uint8_t *HWY_RESTRICT dst,
122+
int dstStride, int width,
123+
int height) {
124+
for (int y = 0; y < height; y++) {
125+
CopyUnalignedRGB565Row(reinterpret_cast<const uint16_t *>(src + (y * srcStride)),
126+
reinterpret_cast<uint16_t *>(dst + (y * dstStride)),
127+
width);
128+
}
129+
}
130+
99131
}
100-
}
101132

102133
HWY_AFTER_NAMESPACE();
103134

104135
#if HWY_ONCE
105136
namespace coder {
106137
HWY_EXPORT(CopyUnalignedRGBA);
138+
HWY_EXPORT(CopyUnalignedRGB565);
107139

108140
HWY_DLLEXPORT void
109141
CopyUnalignedRGBA(const uint8_t *HWY_RESTRICT src, int srcStride, uint8_t *HWY_RESTRICT dst,
@@ -113,5 +145,12 @@ namespace coder {
113145
HWY_DYNAMIC_DISPATCH(CopyUnalignedRGBA)(src, srcStride, dst, dstStride, width, height,
114146
pixelSize);
115147
}
148+
149+
HWY_DLLEXPORT void
150+
CopyUnalignedRGB565(const uint8_t *HWY_RESTRICT src, int srcStride, uint8_t *HWY_RESTRICT dst,
151+
int dstStride, int width,
152+
int height) {
153+
HWY_DYNAMIC_DISPATCH(CopyUnalignedRGB565)(src, srcStride, dst, dstStride, width, height);
154+
}
116155
}
117156
#endif

avif-coder/src/main/cpp/imagebits/CopyUnalignedRGBA.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ namespace coder {
1313
int dstStride, int width,
1414
int height,
1515
int pixelSize);
16+
17+
void
18+
CopyUnalignedRGB565(const uint8_t *__restrict__ src, int srcStride, uint8_t *__restrict__ dst,
19+
int dstStride, int width,
20+
int height);
1621
}
1722

1823
#endif //AVIF_COPYUNALIGNEDRGBA_H

avif-coder/src/main/cpp/imagebits/Rgb565.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "Rgb565.h"
66
#include "ThreadPool.hpp"
77
#include "HalfFloats.h"
8+
#include <algorithm>
89

910
#undef HWY_TARGET_INCLUDE
1011
#define HWY_TARGET_INCLUDE "imagebits/Rgb565.cpp"
@@ -39,7 +40,7 @@ namespace coder::HWY_NAMESPACE {
3940
using hwy::float16_t;
4041

4142
void
42-
Rgba8ToF16HWYRow(const uint8_t *source, uint16_t *destination, int width) {
43+
Rgba8To565HWYRow(const uint8_t *source, uint16_t *destination, int width) {
4344
const FixedTag<uint16_t, 8> du16;
4445
const FixedTag<uint8_t, 8> du8x8;
4546
using VU16 = Vec<decltype(du16)>;
@@ -62,7 +63,7 @@ namespace coder::HWY_NAMESPACE {
6263

6364
auto rdu16Vec = ShiftLeft<11>(ShiftRight<3>(PromoteTo(rdu16, ru8Row)));
6465
auto gdu16Vec = ShiftLeft<5>(ShiftRight<2>(PromoteTo(rdu16, gu8Row)));
65-
auto bdu16Vec = ShiftRight<5>(PromoteTo(rdu16, bu8Row));
66+
auto bdu16Vec = ShiftRight<3>(PromoteTo(rdu16, bu8Row));
6667

6768
auto result = Or(Or(rdu16Vec, gdu16Vec), bdu16Vec);
6869
Store(result, du16, dst);
@@ -95,7 +96,7 @@ namespace coder::HWY_NAMESPACE {
9596
auto mDst = reinterpret_cast<uint8_t *>(dst);
9697

9798
for (int y = 0; y < height; ++y) {
98-
auto r = pool.enqueue(Rgba8ToF16HWYRow,
99+
auto r = pool.enqueue(Rgba8To565HWYRow,
99100
reinterpret_cast<const uint8_t *>(mSrc),
100101
reinterpret_cast<uint16_t *>(mDst), width);
101102
results.push_back(std::move(r));
@@ -168,7 +169,7 @@ namespace coder::HWY_NAMESPACE {
168169

169170
auto rdu16Vec = ShiftLeft<11>(ShiftRight<3>(PromoteTo(rdu16, r16Row)));
170171
auto gdu16Vec = ShiftLeft<5>(ShiftRight<2>(PromoteTo(rdu16, g16Row)));
171-
auto bdu16Vec = ShiftRight<5>(PromoteTo(rdu16, b16Row));
172+
auto bdu16Vec = ShiftRight<3>(PromoteTo(rdu16, b16Row));
172173

173174
auto result = Or(Or(rdu16Vec, gdu16Vec), bdu16Vec);
174175
Store(result, du16, dst);
@@ -178,9 +179,9 @@ namespace coder::HWY_NAMESPACE {
178179
}
179180

180181
for (; x < width; ++x) {
181-
uint16_t red565 = (src[0] >> 3) << 11;
182-
uint16_t green565 = (src[1] >> 2) << 5;
183-
uint16_t blue565 = src[2] >> 3;
182+
uint16_t red565 = ((uint16_t )roundf(half_to_float(src[0]) * maxColors) >> 3) << 11;
183+
uint16_t green565 = ((uint16_t )roundf(half_to_float(src[1]) * maxColors) >> 2) << 5;
184+
uint16_t blue565 = (uint16_t )roundf(half_to_float(src[2]) * maxColors) >> 3;
184185

185186
auto result = static_cast<uint16_t>(red565 | green565 | blue565);
186187
dst[0] = result;

0 commit comments

Comments
 (0)