Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7f7bf1316 | ||
|
|
a72fca3dfb | ||
|
|
c5e7a6e8f9 | ||
|
|
80a20f25b9 | ||
|
|
500163fe1a | ||
|
|
513886eff4 | ||
|
|
0093db9986 | ||
|
|
50c6111773 | ||
|
|
3a05649c71 | ||
|
|
9d25376e1f | ||
|
|
89935b5639 | ||
|
|
e095627aee | ||
|
|
b61e46e956 | ||
|
|
76459c5dd2 | ||
|
|
7ad67a3dbd | ||
|
|
577b49ac19 | ||
|
|
182e3a0d40 | ||
|
|
6d140aaa9d | ||
|
|
17248d3a82 | ||
|
|
ec80e7a189 | ||
|
|
493eeadf1b | ||
|
|
7a0fab29bc | ||
|
|
5f7e40f258 | ||
|
|
0bf6b8d827 | ||
|
|
4c6ccab051 | ||
|
|
00377f15b9 | ||
|
|
96b50eb5aa | ||
|
|
acdf681d40 | ||
|
|
b92cf9746b | ||
|
|
d0dfbaaae0 | ||
|
|
0c656e617b | ||
|
|
148b1a6344 | ||
|
|
1fe0b079cd | ||
|
|
87505aa989 | ||
|
|
3d7a71647e | ||
|
|
c9d2f698b6 | ||
|
|
233adbddae | ||
|
|
6900d8a8c9 | ||
|
|
640f75d8d9 | ||
|
|
4381eb8c3d | ||
|
|
3026b16d70 |
No files matched your search
+3
-9
@@ -1,15 +1,9 @@
|
||||
[submodule "native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo"]
|
||||
path = native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo
|
||||
url = https://github.com/Ehviewer-Overhauled/libjpeg-turbo
|
||||
[submodule "native/src/main/jni/image/giflib/giflib"]
|
||||
path = native/src/main/jni/image/giflib/giflib
|
||||
url = https://github.com/Ehviewer-Overhauled/giflib
|
||||
[submodule "native/src/main/jni/image/libpng/libpng"]
|
||||
path = native/src/main/jni/image/libpng/libpng
|
||||
url = https://github.com/Ehviewer-Overhauled/libpng
|
||||
[submodule "native/src/main/jni/libarchive"]
|
||||
path = native/src/main/jni/libarchive
|
||||
url = https://github.com/Ehviewer-Overhauled/libarchive
|
||||
[submodule "native/src/main/jni/liblzma"]
|
||||
path = native/src/main/jni/liblzma
|
||||
url = https://github.com/Ehviewer-Overhauled/xz
|
||||
[submodule "native/src/main/jni/nettle/nettle"]
|
||||
path = native/src/main/jni/nettle/nettle
|
||||
url = https://github.com/Ehviewer-Overhauled/nettle
|
||||
@@ -21,30 +21,29 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Description
|
||||
这是一个 E-Hentai Android 平台的浏览器
|
||||
# Description
|
||||
|
||||
致力于轻量化与良好性能表现的 EhViewer 分支
|
||||
|
||||
已针对性适配 Material Design 3 及其动态取色系统
|
||||
|
||||
动态配色仅供 Android 12 及以上平台使用!
|
||||
|
||||
EhViewer fork dedicated to lightweight and high-performance
|
||||
|
||||
An E-Hentai Application for Android.
|
||||
with Material Design 3 and Dynamic Color Support
|
||||
|
||||
with Material Design 3 and Dynamic Color Support.
|
||||
|
||||
Dynamic Color only support Android S and above!
|
||||
|
||||
## Download
|
||||
# Download
|
||||
|
||||
[Github 下载](https://github.com/Ehviewer-Overhauled/Ehviewer/releases)
|
||||
|
||||
## Screenshot
|
||||
[CI 版本下载(需登录)](https://github.com/Ehviewer-Overhauled/Ehviewer/actions/workflows/ci.yml)
|
||||
|
||||
# Screenshot
|
||||
|
||||

|
||||

|
||||
|
||||
## Thanks
|
||||
# Thanks
|
||||
|
||||
本项目受到了诸多开源项目的帮助
|
||||
|
||||
@@ -52,6 +51,7 @@ Here is the libraries
|
||||
|
||||
- [AOSP](http://source.android.com/)
|
||||
- [android-advancedrecyclerview](https://github.com/h6ah4i/android-advancedrecyclerview)
|
||||
- [material-components-android](https://github.com/material-components/material-components-android)
|
||||
- [material-design-icons](https://github.com/google/material-design-icons)
|
||||
- [Apache Commons Lang](https://commons.apache.org/proper/commons-lang/)
|
||||
- [apng](http://apng.sourceforge.net/)
|
||||
@@ -67,7 +67,7 @@ Here is the libraries
|
||||
- [XZ Utils](https://tukaani.org/xz/)
|
||||
|
||||
|
||||
## License
|
||||
# License
|
||||
|
||||
Copyright 2014-2019 Hippo Seven
|
||||
Copyright 2020-2022 NekoInverter
|
||||
@@ -78,5 +78,3 @@ Here is the libraries
|
||||
EhViewer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with EhViewer. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fasuka-mio%2FEhviewer?ref=badge_large)
|
||||
+3
-3
@@ -32,10 +32,10 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "moe.tarsin.ehviewer"
|
||||
minSdkVersion 26
|
||||
minSdkVersion 31
|
||||
targetSdkVersion 33
|
||||
versionCode 114531
|
||||
versionName "1.7.28.4"
|
||||
versionCode 180000
|
||||
versionName "1.8.0.0"
|
||||
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
|
||||
}
|
||||
|
||||
|
||||
@@ -120,35 +120,21 @@
|
||||
<data android:mimeType="application/x-7z-compressed" />
|
||||
<data android:mimeType="application/x-rar-compressed" />
|
||||
<data android:mimeType="application/x-zip-compressed" />
|
||||
</intent-filter>
|
||||
<data android:mimeType="application/x-tar" />
|
||||
<data android:mimeType="application/x-xz" />
|
||||
<data android:mimeType="application/gzip" />
|
||||
<data android:mimeType="application/x-cbz" />
|
||||
<data android:mimeType="application/x-cbr" />
|
||||
<data android:mimeType="application/x-cbt" />
|
||||
<data android:mimeType="application/x-cb7" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="file" />
|
||||
<data android:scheme="content" />
|
||||
<data android:host="*" />
|
||||
<data android:pathPattern=".*\\.7z" />
|
||||
<data android:pathPattern=".*\\.rar" />
|
||||
<data android:pathPattern=".*\\.zip" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="file" />
|
||||
<data android:scheme="content" />
|
||||
<data android:host="*" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:pathPattern=".*\\.7z" />
|
||||
<data android:pathPattern=".*\\.rar" />
|
||||
<data android:pathPattern=".*\\.zip" />
|
||||
<!-- untested -->
|
||||
<data android:mimeType="application/vnd.comicbook+zip" />
|
||||
<data android:mimeType="application/vnd.comicbook-rar" />
|
||||
<data android:mimeType="application/x-compressed-tar" />
|
||||
<data android:mimeType="application/x-bzip-compressed-tar" />
|
||||
<data android:mimeType="application/x-lzma-compressed-tar" />
|
||||
<data android:mimeType="application/x-xz-compressed-tar" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ class EditTextDialogBuilder constructor(
|
||||
return mDialog as AlertDialog
|
||||
}
|
||||
|
||||
override fun onEditorAction(v: TextView, actionId: Int, event: KeyEvent): Boolean {
|
||||
override fun onEditorAction(v: TextView?, p1: Int, event: KeyEvent?): Boolean {
|
||||
return if (mDialog != null) {
|
||||
val button = mDialog!!.getButton(DialogInterface.BUTTON_POSITIVE)
|
||||
button?.performClick()
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.hippo.ehviewer;
|
||||
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@@ -23,7 +25,9 @@ import com.hippo.conaco.ValueHelper;
|
||||
import com.hippo.image.ImageBitmap;
|
||||
import com.hippo.streampipe.InputStreamPipe;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ImageBitmapHelper implements ValueHelper<ImageBitmap> {
|
||||
|
||||
@@ -34,7 +38,8 @@ public class ImageBitmapHelper implements ValueHelper<ImageBitmap> {
|
||||
public ImageBitmap decode(@NonNull InputStreamPipe isPipe) {
|
||||
try {
|
||||
isPipe.obtain();
|
||||
return ImageBitmap.decode(isPipe.open());
|
||||
FileInputStream is = (FileInputStream) isPipe.open();
|
||||
return ImageBitmap.decode(is.getFD());
|
||||
} catch (OutOfMemoryError | IOException e) {
|
||||
return null;
|
||||
} finally {
|
||||
|
||||
@@ -41,6 +41,7 @@ import com.hippo.yorozuya.NumberUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
public class Settings {
|
||||
|
||||
@@ -271,6 +272,11 @@ public class Settings {
|
||||
private static final int DEFAULT_DOWNLOAD_DELAY = 0;
|
||||
private static final String KEY_REQUEST_NEWS = "request_news";
|
||||
private static final boolean DEFAULT_REQUEST_NEWS = true;
|
||||
|
||||
|
||||
private static final String KEY_ARCHIVE_PASSWDS = "archive_passwds";
|
||||
|
||||
|
||||
private static Context sContext;
|
||||
private static SharedPreferences sSettingsPre;
|
||||
private static EhConfig sEhConfig;
|
||||
@@ -384,6 +390,21 @@ public class Settings {
|
||||
sSettingsPre.edit().putString(key, value).apply();
|
||||
}
|
||||
|
||||
public static Set<String> getStringSet(String key) {
|
||||
return sSettingsPre.getStringSet(key, null);
|
||||
}
|
||||
|
||||
public static void putStringToStringSet(String key, String value) {
|
||||
Set<String> set = getStringSet(key);
|
||||
if (set == null)
|
||||
set = Set.of(value);
|
||||
else if (set.contains(value))
|
||||
return;
|
||||
else
|
||||
set.add(value);
|
||||
sSettingsPre.edit().putStringSet(key, set).apply();
|
||||
}
|
||||
|
||||
public static int getIntFromStr(String key, int defValue) {
|
||||
try {
|
||||
return NumberUtils.parseIntSafely(sSettingsPre.getString(key, Integer.toString(defValue)), defValue);
|
||||
@@ -1139,4 +1160,12 @@ public class Settings {
|
||||
public static void putClipboardTextHashCode(int value) {
|
||||
putInt(KEY_CLIPBOARD_TEXT_HASH_CODE, value);
|
||||
}
|
||||
|
||||
public static Set<String> getArchivePasswds() {
|
||||
return getStringSet(KEY_ARCHIVE_PASSWDS);
|
||||
}
|
||||
|
||||
public static void putPasswdToArchivePasswds(String value) {
|
||||
putStringToStringSet(KEY_ARCHIVE_PASSWDS, value);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package com.hippo.ehviewer.gallery;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -26,26 +27,33 @@ import androidx.annotation.Nullable;
|
||||
import com.hippo.UriArchiveAccessor;
|
||||
import com.hippo.ehviewer.GetText;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.glgallery.GalleryPageView;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.yorozuya.thread.PVLock;
|
||||
import com.hippo.yorozuya.thread.PriorityThread;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
|
||||
private static final AtomicInteger sIdGenerator = new AtomicInteger();
|
||||
public static Handler showPasswd;
|
||||
public static String passwd;
|
||||
public static PVLock pv = new PVLock(0);
|
||||
private final UriArchiveAccessor archiveAccessor;
|
||||
private final Stack<Integer> requests = new Stack<>();
|
||||
private final AtomicInteger extractingIndex = new AtomicInteger(GalleryPageView.INVALID_INDEX);
|
||||
private final LinkedHashMap<Integer, InputStream> streams = new LinkedHashMap<>();
|
||||
private final LinkedHashMap<Integer, Long> streams = new LinkedHashMap<>();
|
||||
private final AtomicInteger decodingIndex = new AtomicInteger(GalleryPageView.INVALID_INDEX);
|
||||
private Thread archiveThread;
|
||||
private Thread decodeThread;
|
||||
@@ -56,7 +64,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
UriArchiveAccessor archiveAccessor1;
|
||||
try {
|
||||
archiveAccessor1 = new UriArchiveAccessor(context, uri);
|
||||
} catch (FileNotFoundException e) {
|
||||
} catch (Exception e) {
|
||||
archiveAccessor1 = null;
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -90,6 +98,11 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
decodeThread.interrupt();
|
||||
decodeThread = null;
|
||||
}
|
||||
try {
|
||||
archiveAccessor.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,9 +172,27 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
}
|
||||
|
||||
private class ArchiveTask implements Runnable {
|
||||
private void waitPasswd() throws InterruptedException {
|
||||
showPasswd.sendEmptyMessage(0);
|
||||
pv.p();
|
||||
}
|
||||
|
||||
private void notifyError() {
|
||||
showPasswd.sendEmptyMessage(1);
|
||||
}
|
||||
|
||||
private void notifyDismiss() {
|
||||
showPasswd.sendEmptyMessage(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
size = archiveAccessor.open();
|
||||
try {
|
||||
size = archiveAccessor.open();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
size = 0;
|
||||
}
|
||||
if (size <= 0) {
|
||||
size = STATE_ERROR;
|
||||
error = GetText.getString(R.string.error_reading_failed);
|
||||
@@ -171,6 +202,34 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
// Update size and notify changed
|
||||
notifyDataChanged();
|
||||
|
||||
if (archiveAccessor.needPassword()) {
|
||||
boolean need_request = true;
|
||||
Set<String> set = Settings.getArchivePasswds();
|
||||
if (set != null) {
|
||||
for (String passwd : set) {
|
||||
if (archiveAccessor.providePassword(passwd)) {
|
||||
need_request = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!Thread.currentThread().isInterrupted() && need_request) {
|
||||
try {
|
||||
waitPasswd();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (!archiveAccessor.providePassword(passwd))
|
||||
notifyError();
|
||||
else {
|
||||
Settings.putPasswdToArchivePasswds(passwd);
|
||||
notifyDismiss();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
int index;
|
||||
synchronized (requests) {
|
||||
@@ -194,17 +253,18 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
Pipe pipe = new Pipe(4096 * 16);
|
||||
|
||||
synchronized (streams) {
|
||||
if (streams.get(index) != null) {
|
||||
continue;
|
||||
}
|
||||
streams.put(index, pipe.getInputStream());
|
||||
streams.notify();
|
||||
}
|
||||
|
||||
archiveAccessor.extractTargetIndexToOutputStream(index, pipe.getOutputStream());
|
||||
long addr = archiveAccessor.extracttoOutputStream(index);
|
||||
|
||||
synchronized (streams) {
|
||||
streams.put(index, addr);
|
||||
streams.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,7 +274,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
public void run() {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
int index;
|
||||
InputStream stream;
|
||||
Long addr;
|
||||
synchronized (streams) {
|
||||
if (streams.isEmpty()) {
|
||||
try {
|
||||
@@ -226,16 +286,16 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
Iterator<Map.Entry<Integer, InputStream>> iterator = streams.entrySet().iterator();
|
||||
Map.Entry<Integer, InputStream> entry = iterator.next();
|
||||
Iterator<Map.Entry<Integer, Long>> iterator = streams.entrySet().iterator();
|
||||
Map.Entry<Integer, Long> entry = iterator.next();
|
||||
iterator.remove();
|
||||
index = entry.getKey();
|
||||
stream = entry.getValue();
|
||||
addr = entry.getValue();
|
||||
decodingIndex.lazySet(index);
|
||||
}
|
||||
|
||||
try {
|
||||
Image image = Image.decode(stream, true);
|
||||
Image image = Image.decodeAddr(addr, true);
|
||||
if (image != null) {
|
||||
notifyPageSucceed(index, image);
|
||||
} else {
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.hippo.yorozuya.IOUtils;
|
||||
import com.hippo.yorozuya.StringUtils;
|
||||
import com.hippo.yorozuya.thread.PriorityThread;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@@ -258,7 +259,7 @@ public class DirGalleryProvider extends GalleryProvider2 implements Runnable {
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = files[index].openInputStream();
|
||||
Image image = Image.decode(is, true);
|
||||
Image image = Image.decode(((FileInputStream)is).getFD(), true);
|
||||
mDecodingIndex.lazySet(GalleryPageView.INVALID_INDEX);
|
||||
if (image != null) {
|
||||
notifyPageSucceed(index, image);
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.gallery;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
class Pipe {
|
||||
|
||||
private final int capacity;
|
||||
private final byte[] buffer;
|
||||
|
||||
private int head = 0;
|
||||
private int tail = 0;
|
||||
private boolean full = false;
|
||||
|
||||
private boolean inClosed = false;
|
||||
private boolean outClosed = false;
|
||||
|
||||
private final InputStream inputStream = new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
synchronized (Pipe.this) {
|
||||
byte[] bytes = new byte[1];
|
||||
if (read(bytes, 0, 1) != -1) {
|
||||
return bytes[0];
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(@NonNull byte[] b, int off, int len) throws IOException {
|
||||
synchronized (Pipe.this) {
|
||||
for (; ; ) {
|
||||
if (inClosed) {
|
||||
throw new IOException("The InputStream is closed");
|
||||
}
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (head == tail && !full) {
|
||||
if (outClosed) {
|
||||
// No bytes available and the OutputStream is closed. So it's the end.
|
||||
return -1;
|
||||
} else {
|
||||
// Wait for OutputStream write bytes
|
||||
try {
|
||||
Pipe.this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("The thread interrupted", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int read = Math.min(len, (head < tail ? tail : capacity) - head);
|
||||
System.arraycopy(buffer, head, b, off, read);
|
||||
head += read;
|
||||
if (head == capacity) {
|
||||
head = 0;
|
||||
}
|
||||
full = false;
|
||||
Pipe.this.notifyAll();
|
||||
return read;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
synchronized (Pipe.this) {
|
||||
inClosed = true;
|
||||
Pipe.this.notifyAll();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final OutputStream outputStream = new OutputStream() {
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
synchronized (Pipe.this) {
|
||||
byte[] bytes = new byte[]{(byte) b};
|
||||
write(bytes, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NonNull byte[] b, int off, int len) throws IOException {
|
||||
synchronized (Pipe.this) {
|
||||
while (len != 0) {
|
||||
if (head == tail && full) {
|
||||
// The buffer is full, wait for InputStream read bytes
|
||||
try {
|
||||
Pipe.this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("The thread interrupted", e);
|
||||
}
|
||||
} else {
|
||||
int write = Math.min(len, (head <= tail ? capacity : head) - tail);
|
||||
System.arraycopy(b, off, buffer, tail, write);
|
||||
off += write;
|
||||
len -= write;
|
||||
tail += write;
|
||||
if (tail == capacity) {
|
||||
tail = 0;
|
||||
}
|
||||
if (head == tail) {
|
||||
full = true;
|
||||
}
|
||||
Pipe.this.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
synchronized (Pipe.this) {
|
||||
outClosed = true;
|
||||
Pipe.this.notifyAll();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Pipe(int capacity) {
|
||||
this.capacity = capacity;
|
||||
this.buffer = new byte[capacity];
|
||||
}
|
||||
|
||||
InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
OutputStream getOutputStream() {
|
||||
return outputStream;
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,27 @@ class VersionPreference @JvmOverloads constructor(
|
||||
override fun onPrepareDialogBuilder(builder: AlertDialog.Builder) {
|
||||
super.onPrepareDialogBuilder(builder)
|
||||
builder.setTitle(R.string.show_library_version)
|
||||
builder.setMessage(Native.getlibarchiveVersion() + "\nlzma(xz-utils) " + Native.getliblzmaVersion() + "\nzlib " + Native.getzlibVersion() + "\nlibjpeg-turbo " + Native.getlibjpeg_turboVersion())
|
||||
val info = NativeLibInfo().addLib(Native.getlibarchiveVersion())
|
||||
.addLib("lzma(xz-utils)", Native.getliblzmaVersion())
|
||||
.addLib("zlib", Native.getzlibVersion())
|
||||
.addLib(Native.getnettleVersion())
|
||||
builder.setMessage(info.getMessage())
|
||||
}
|
||||
|
||||
inner class NativeLibInfo {
|
||||
private var message: String = ""
|
||||
fun addLib(libname:String, libversion:String): NativeLibInfo {
|
||||
message = "$message$libname $libversion\n"
|
||||
return this
|
||||
}
|
||||
|
||||
fun getMessage(): String {
|
||||
return message;
|
||||
}
|
||||
|
||||
fun addLib(msg: String): NativeLibInfo {
|
||||
message = "$message$msg\n"
|
||||
return this
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@ import com.hippo.yorozuya.thread.PriorityThread;
|
||||
import com.hippo.yorozuya.thread.PriorityThreadFactory;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@@ -1096,33 +1097,6 @@ public final class SpiderQueen implements Runnable {
|
||||
void onGetImageFailure(int index, String error);
|
||||
}
|
||||
|
||||
private static class AutoCloseInputStream extends InputStream {
|
||||
|
||||
private final InputStreamPipe mPipe;
|
||||
private final InputStream mIs;
|
||||
|
||||
public AutoCloseInputStream(InputStreamPipe pipe, InputStream is) {
|
||||
mPipe = pipe;
|
||||
mIs = is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return mIs.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(@NonNull byte[] buffer, int byteOffset, int byteCount) throws IOException {
|
||||
return mIs.read(buffer, byteOffset, byteCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
mPipe.close();
|
||||
mPipe.release();
|
||||
}
|
||||
}
|
||||
|
||||
private class SpiderWorker implements Runnable {
|
||||
|
||||
private final long mGid;
|
||||
@@ -1693,7 +1667,7 @@ public final class SpiderQueen implements Runnable {
|
||||
|
||||
pipe.obtain();
|
||||
try {
|
||||
is = new AutoCloseInputStream(pipe, pipe.open());
|
||||
is = pipe.open();
|
||||
} catch (IOException e) {
|
||||
// Can't open pipe
|
||||
error = GetText.getString(R.string.error_reading_failed);
|
||||
@@ -1703,7 +1677,18 @@ public final class SpiderQueen implements Runnable {
|
||||
}
|
||||
|
||||
if (is != null) {
|
||||
image = Image.decode(is, true);
|
||||
try {
|
||||
image = Image.decode(((FileInputStream)is).getFD(), true);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
image = null;
|
||||
} finally {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (image == null) {
|
||||
error = GetText.getString(R.string.error_decoding_failed);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.provider.MediaStore;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
@@ -67,6 +69,7 @@ import androidx.core.view.WindowInsetsControllerCompat;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.materialswitch.MaterialSwitch;
|
||||
import com.hippo.app.EditTextDialogBuilder;
|
||||
import com.hippo.ehviewer.AppConfig;
|
||||
import com.hippo.ehviewer.BuildConfig;
|
||||
import com.hippo.ehviewer.R;
|
||||
@@ -103,6 +106,7 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import rikka.core.res.ConfigurationKt;
|
||||
import rikka.core.res.ResourcesKt;
|
||||
@@ -314,10 +318,19 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
onRestore(savedInstanceState);
|
||||
}
|
||||
|
||||
builder = new EditTextDialogBuilder(this, null, getString(R.string.archive_passwd));
|
||||
builder.setTitle(getString(R.string.archive_need_passwd));
|
||||
builder.setPositiveButton(getString(android.R.string.ok), null);
|
||||
dialog = builder.create();
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
|
||||
if (mGalleryProvider == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
ArchiveGalleryProvider.showPasswd = new ShowPasswdDialogHandler(this);
|
||||
|
||||
mGalleryProvider.start();
|
||||
|
||||
// Get start page
|
||||
@@ -1293,7 +1306,69 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
}
|
||||
}
|
||||
|
||||
private EditTextDialogBuilder builder;
|
||||
|
||||
private boolean dialogShown = false;
|
||||
|
||||
private AlertDialog dialog;
|
||||
|
||||
private void showPasswdDialog() {
|
||||
if (!dialogShown) {
|
||||
dialogShown = true;
|
||||
dialog.show();
|
||||
if (dialog.getButton(AlertDialog.BUTTON_POSITIVE) != null) {
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(v -> {
|
||||
GalleryActivity.this.onProvidePasswd();
|
||||
});
|
||||
}
|
||||
dialog.setOnCancelListener(v -> finish());
|
||||
}
|
||||
}
|
||||
|
||||
private void onProvidePasswd() {
|
||||
String passwd = builder.getText();
|
||||
if (passwd.isEmpty())
|
||||
builder.setError(getString(R.string.passwd_cannot_be_empty));
|
||||
else {
|
||||
ArchiveGalleryProvider.passwd = passwd;
|
||||
ArchiveGalleryProvider.pv.v();
|
||||
}
|
||||
}
|
||||
|
||||
private void onPasswdWrong() {
|
||||
builder.setError(getString(R.string.passwd_wrong));
|
||||
}
|
||||
|
||||
private void onPasswdCorrect() {
|
||||
dialog.dismiss();
|
||||
}
|
||||
|
||||
private static class ShowPasswdDialogHandler extends Handler {
|
||||
|
||||
//弱引用持有HandlerActivity , GC 回收时会被回收掉
|
||||
private final WeakReference<GalleryActivity> weakReference;
|
||||
|
||||
public ShowPasswdDialogHandler(GalleryActivity activity) {
|
||||
this.weakReference = new WeakReference(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
GalleryActivity activity = weakReference.get();
|
||||
super.handleMessage(msg);
|
||||
if (null != activity) {
|
||||
switch (msg.what) {
|
||||
case 0:
|
||||
activity.showPasswdDialog();
|
||||
break;
|
||||
case 1:
|
||||
activity.onPasswdWrong();
|
||||
break;
|
||||
case 2:
|
||||
activity.onPasswdCorrect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.yorozuya.NumberUtils;
|
||||
|
||||
public class AdvanceSearchTable extends LinearLayout {
|
||||
|
||||
public static final int SNAME = 0x1;
|
||||
public static final int STAGS = 0x2;
|
||||
public static final int SDESC = 0x4;
|
||||
public static final int STORR = 0x8;
|
||||
public static final int STO = 0x10;
|
||||
public static final int SDT1 = 0x20;
|
||||
public static final int SDT2 = 0x40;
|
||||
public static final int SH = 0x80;
|
||||
public static final int SFL = 0x100;
|
||||
public static final int SFU = 0x200;
|
||||
public static final int SFT = 0x400;
|
||||
private static final String STATE_KEY_SUPER = "super";
|
||||
private static final String STATE_KEY_ADVANCE_SEARCH = "advance_search";
|
||||
private static final String STATE_KEY_MIN_RATING = "min_rating";
|
||||
private static final String STATE_KEY_PAGE_FROM = "page_from";
|
||||
private static final String STATE_KEY_PAGE_TO = "page_to";
|
||||
private CheckBox mSname;
|
||||
private CheckBox mStags;
|
||||
private CheckBox mSdesc;
|
||||
private CheckBox mStorr;
|
||||
private CheckBox mSto;
|
||||
private CheckBox mSdt1;
|
||||
private CheckBox mSdt2;
|
||||
private CheckBox mSh;
|
||||
private CheckBox mSr;
|
||||
private Spinner mMinRating;
|
||||
private CheckBox mSp;
|
||||
private EditText mSpf;
|
||||
private EditText mSpt;
|
||||
private CheckBox mSfl;
|
||||
private CheckBox mSfu;
|
||||
private CheckBox mSft;
|
||||
|
||||
public AdvanceSearchTable(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public AdvanceSearchTable(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public void init(Context context) {
|
||||
setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
inflater.inflate(R.layout.widget_advance_search_table, this);
|
||||
|
||||
ViewGroup row0 = (ViewGroup) getChildAt(0);
|
||||
mSname = (CheckBox) row0.getChildAt(0);
|
||||
mStags = (CheckBox) row0.getChildAt(1);
|
||||
|
||||
ViewGroup row1 = (ViewGroup) getChildAt(1);
|
||||
mSdesc = (CheckBox) row1.getChildAt(0);
|
||||
mStorr = (CheckBox) row1.getChildAt(1);
|
||||
|
||||
ViewGroup row2 = (ViewGroup) getChildAt(2);
|
||||
mSto = (CheckBox) row2.getChildAt(0);
|
||||
mSdt1 = (CheckBox) row2.getChildAt(1);
|
||||
|
||||
ViewGroup row3 = (ViewGroup) getChildAt(3);
|
||||
mSdt2 = (CheckBox) row3.getChildAt(0);
|
||||
mSh = (CheckBox) row3.getChildAt(1);
|
||||
|
||||
ViewGroup row4 = (ViewGroup) getChildAt(4);
|
||||
mSr = (CheckBox) row4.getChildAt(0);
|
||||
mMinRating = (Spinner) row4.getChildAt(1);
|
||||
|
||||
ViewGroup row5 = (ViewGroup) getChildAt(5);
|
||||
mSp = (CheckBox) row5.getChildAt(0);
|
||||
mSpf = (EditText) row5.getChildAt(1);
|
||||
mSpt = (EditText) row5.getChildAt(3);
|
||||
|
||||
ViewGroup row7 = (ViewGroup) getChildAt(7);
|
||||
mSfl = (CheckBox) row7.getChildAt(0);
|
||||
mSfu = (CheckBox) row7.getChildAt(1);
|
||||
mSft = (CheckBox) row7.getChildAt(2);
|
||||
|
||||
// Avoid java.lang.IllegalStateException: focus search returned a view that wasn't able to take focus!
|
||||
mSpt.setOnEditorActionListener((v, actionId, event) -> {
|
||||
View nextView = v.focusSearch(View.FOCUS_DOWN);
|
||||
if (nextView != null) {
|
||||
nextView.requestFocus(View.FOCUS_DOWN);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public int getAdvanceSearch() {
|
||||
int advanceSearch = 0;
|
||||
if (mSname.isChecked()) advanceSearch |= SNAME;
|
||||
if (mStags.isChecked()) advanceSearch |= STAGS;
|
||||
if (mSdesc.isChecked()) advanceSearch |= SDESC;
|
||||
if (mStorr.isChecked()) advanceSearch |= STORR;
|
||||
if (mSto.isChecked()) advanceSearch |= STO;
|
||||
if (mSdt1.isChecked()) advanceSearch |= SDT1;
|
||||
if (mSdt2.isChecked()) advanceSearch |= SDT2;
|
||||
if (mSh.isChecked()) advanceSearch |= SH;
|
||||
if (mSfl.isChecked()) advanceSearch |= SFL;
|
||||
if (mSfu.isChecked()) advanceSearch |= SFU;
|
||||
if (mSft.isChecked()) advanceSearch |= SFT;
|
||||
return advanceSearch;
|
||||
}
|
||||
|
||||
public void setAdvanceSearch(int advanceSearch) {
|
||||
mSname.setChecked(NumberUtils.int2boolean(advanceSearch & SNAME));
|
||||
mStags.setChecked(NumberUtils.int2boolean(advanceSearch & STAGS));
|
||||
mSdesc.setChecked(NumberUtils.int2boolean(advanceSearch & SDESC));
|
||||
mStorr.setChecked(NumberUtils.int2boolean(advanceSearch & STORR));
|
||||
mSto.setChecked(NumberUtils.int2boolean(advanceSearch & STO));
|
||||
mSdt1.setChecked(NumberUtils.int2boolean(advanceSearch & SDT1));
|
||||
mSdt2.setChecked(NumberUtils.int2boolean(advanceSearch & SDT2));
|
||||
mSh.setChecked(NumberUtils.int2boolean(advanceSearch & SH));
|
||||
mSfl.setChecked(NumberUtils.int2boolean(advanceSearch & SFL));
|
||||
mSfu.setChecked(NumberUtils.int2boolean(advanceSearch & SFU));
|
||||
mSft.setChecked(NumberUtils.int2boolean(advanceSearch & SFT));
|
||||
}
|
||||
|
||||
public int getMinRating() {
|
||||
int position = mMinRating.getSelectedItemPosition();
|
||||
if (mSr.isChecked() && position >= 0) {
|
||||
return position + 2;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void setMinRating(int minRating) {
|
||||
if (minRating >= 2 && minRating <= 5) {
|
||||
mSr.setChecked(true);
|
||||
mMinRating.setSelection(minRating - 2);
|
||||
} else {
|
||||
mSr.setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
public int getPageFrom() {
|
||||
if (mSp.isChecked()) {
|
||||
return NumberUtils.parseIntSafely(mSpf.getText().toString(), -1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void setPageFrom(int pageFrom) {
|
||||
if (pageFrom > 0) {
|
||||
mSpf.setText(Integer.toString(pageFrom));
|
||||
mSp.setChecked(true);
|
||||
} else {
|
||||
mSp.setChecked(false);
|
||||
mSpf.setText(null);
|
||||
}
|
||||
}
|
||||
|
||||
public int getPageTo() {
|
||||
if (mSp.isChecked()) {
|
||||
return NumberUtils.parseIntSafely(mSpt.getText().toString(), -1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void setPageTo(int pageTo) {
|
||||
if (pageTo > 0) {
|
||||
mSpt.setText(Integer.toString(pageTo));
|
||||
mSp.setChecked(true);
|
||||
} else {
|
||||
mSp.setChecked(false);
|
||||
mSpt.setText(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
final Bundle state = new Bundle();
|
||||
state.putParcelable(STATE_KEY_SUPER, super.onSaveInstanceState());
|
||||
state.putInt(STATE_KEY_ADVANCE_SEARCH, getAdvanceSearch());
|
||||
state.putInt(STATE_KEY_MIN_RATING, getMinRating());
|
||||
state.putInt(STATE_KEY_PAGE_FROM, getPageFrom());
|
||||
state.putInt(STATE_KEY_PAGE_TO, getPageTo());
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(Parcelable state) {
|
||||
if (state instanceof Bundle) {
|
||||
final Bundle savedState = (Bundle) state;
|
||||
super.onRestoreInstanceState(savedState.getParcelable(STATE_KEY_SUPER));
|
||||
setAdvanceSearch(savedState.getInt(STATE_KEY_ADVANCE_SEARCH));
|
||||
setMinRating(savedState.getInt(STATE_KEY_MIN_RATING));
|
||||
setPageFrom(savedState.getInt(STATE_KEY_PAGE_FROM));
|
||||
setPageTo(savedState.getInt(STATE_KEY_PAGE_TO));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.hippo.ehviewer.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.KeyEvent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.yorozuya.NumberUtils
|
||||
|
||||
class AdvanceSearchTable @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null
|
||||
) : LinearLayout(context, attrs) {
|
||||
private var mSname: CheckBox
|
||||
private var mStags: CheckBox
|
||||
private var mSdesc: CheckBox
|
||||
private var mStorr: CheckBox
|
||||
private var mSto: CheckBox
|
||||
private var mSdt1: CheckBox
|
||||
private var mSdt2: CheckBox
|
||||
private var mSh: CheckBox
|
||||
private var mSr: CheckBox
|
||||
private var mMinRating: TextInputLayout
|
||||
private var mSp: CheckBox
|
||||
private var mSpf: EditText
|
||||
private var mSpt: EditText
|
||||
private var mSfl: CheckBox
|
||||
private var mSfu: CheckBox
|
||||
private var mSft: CheckBox
|
||||
private val mArray: Array<String> = context.resources.getStringArray(R.array.search_min_rating)
|
||||
|
||||
init {
|
||||
orientation = VERTICAL
|
||||
val inflater = LayoutInflater.from(context)
|
||||
inflater.inflate(R.layout.widget_advance_search_table, this)
|
||||
val row0 = getChildAt(0) as ViewGroup
|
||||
mSname = row0.getChildAt(0) as CheckBox
|
||||
mStags = row0.getChildAt(1) as CheckBox
|
||||
val row1 = getChildAt(1) as ViewGroup
|
||||
mSdesc = row1.getChildAt(0) as CheckBox
|
||||
mStorr = row1.getChildAt(1) as CheckBox
|
||||
val row2 = getChildAt(2) as ViewGroup
|
||||
mSto = row2.getChildAt(0) as CheckBox
|
||||
mSdt1 = row2.getChildAt(1) as CheckBox
|
||||
val row3 = getChildAt(3) as ViewGroup
|
||||
mSdt2 = row3.getChildAt(0) as CheckBox
|
||||
mSh = row3.getChildAt(1) as CheckBox
|
||||
val row4 = getChildAt(4) as ViewGroup
|
||||
mSr = row4.getChildAt(0) as CheckBox
|
||||
mMinRating = row4.getChildAt(1) as TextInputLayout
|
||||
val row5 = getChildAt(5) as ViewGroup
|
||||
mSp = row5.getChildAt(0) as CheckBox
|
||||
mSpf = row5.getChildAt(1) as EditText
|
||||
mSpt = row5.getChildAt(3) as EditText
|
||||
val row7 = getChildAt(7) as ViewGroup
|
||||
mSfl = row7.getChildAt(0) as CheckBox
|
||||
mSfu = row7.getChildAt(1) as CheckBox
|
||||
mSft = row7.getChildAt(2) as CheckBox
|
||||
|
||||
mSpt.setOnEditorActionListener { v: TextView, _: Int, _: KeyEvent? ->
|
||||
val nextView = v.focusSearch(
|
||||
FOCUS_DOWN
|
||||
)
|
||||
nextView?.requestFocus(FOCUS_DOWN)
|
||||
true
|
||||
}
|
||||
|
||||
mMinRating.isEnabled = mSr.isChecked
|
||||
mSr.setOnCheckedChangeListener { _: CompoundButton, isChecked: Boolean ->
|
||||
mMinRating.isEnabled = isChecked
|
||||
}
|
||||
|
||||
mSpt.isEnabled = mSp.isChecked
|
||||
mSpf.isEnabled = mSp.isChecked
|
||||
mSp.setOnCheckedChangeListener { _: CompoundButton, isChecked: Boolean ->
|
||||
mSpt.isEnabled = isChecked
|
||||
mSpf.isEnabled = isChecked
|
||||
}
|
||||
}
|
||||
|
||||
var advanceSearch: Int
|
||||
get() {
|
||||
var advanceSearch = 0
|
||||
if (mSname.isChecked) advanceSearch = advanceSearch or SNAME
|
||||
if (mStags.isChecked) advanceSearch = advanceSearch or STAGS
|
||||
if (mSdesc.isChecked) advanceSearch = advanceSearch or SDESC
|
||||
if (mStorr.isChecked) advanceSearch = advanceSearch or STORR
|
||||
if (mSto.isChecked) advanceSearch = advanceSearch or STO
|
||||
if (mSdt1.isChecked) advanceSearch = advanceSearch or SDT1
|
||||
if (mSdt2.isChecked) advanceSearch = advanceSearch or SDT2
|
||||
if (mSh.isChecked) advanceSearch = advanceSearch or SH
|
||||
if (mSfl.isChecked) advanceSearch = advanceSearch or SFL
|
||||
if (mSfu.isChecked) advanceSearch = advanceSearch or SFU
|
||||
if (mSft.isChecked) advanceSearch = advanceSearch or SFT
|
||||
return advanceSearch
|
||||
}
|
||||
set(advanceSearch) {
|
||||
mSname.isChecked =
|
||||
NumberUtils.int2boolean(advanceSearch and SNAME)
|
||||
mStags.isChecked =
|
||||
NumberUtils.int2boolean(advanceSearch and STAGS)
|
||||
mSdesc.isChecked =
|
||||
NumberUtils.int2boolean(advanceSearch and SDESC)
|
||||
mStorr.isChecked = NumberUtils.int2boolean(advanceSearch and STORR)
|
||||
mSto.isChecked = NumberUtils.int2boolean(advanceSearch and STO)
|
||||
mSdt1.isChecked = NumberUtils.int2boolean(advanceSearch and SDT1)
|
||||
mSdt2.isChecked = NumberUtils.int2boolean(advanceSearch and SDT2)
|
||||
mSh.isChecked = NumberUtils.int2boolean(advanceSearch and SH)
|
||||
mSfl.isChecked = NumberUtils.int2boolean(advanceSearch and SFL)
|
||||
mSfu.isChecked = NumberUtils.int2boolean(advanceSearch and SFU)
|
||||
mSft.isChecked = NumberUtils.int2boolean(advanceSearch and SFT)
|
||||
}
|
||||
var minRating: Int
|
||||
get() {
|
||||
val position = mArray.indexOf(mMinRating.editText!!.text.toString())
|
||||
return if (mSr.isChecked && position >= 0) {
|
||||
position + 2
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
}
|
||||
set(minRating) {
|
||||
if (minRating in 2..5) {
|
||||
mSr.isChecked = true
|
||||
(mMinRating.editText!! as AutoCompleteTextView).setText(
|
||||
mArray[minRating - 2],
|
||||
false
|
||||
)
|
||||
} else {
|
||||
mSr.isChecked = false
|
||||
}
|
||||
}
|
||||
var pageFrom: Int
|
||||
get() = if (mSp.isChecked) {
|
||||
NumberUtils.parseIntSafely(mSpf.text.toString(), -1)
|
||||
} else -1
|
||||
set(pageFrom) {
|
||||
if (pageFrom > 0) {
|
||||
mSpf.setText(pageFrom.toString())
|
||||
mSp.isChecked = true
|
||||
} else {
|
||||
mSp.isChecked = false
|
||||
mSpf.text = null
|
||||
}
|
||||
}
|
||||
var pageTo: Int
|
||||
get() = if (mSp.isChecked) {
|
||||
NumberUtils.parseIntSafely(mSpt.text.toString(), -1)
|
||||
} else -1
|
||||
set(pageTo) {
|
||||
if (pageTo > 0) {
|
||||
mSpt.setText(pageTo.toString())
|
||||
mSp.isChecked = true
|
||||
} else {
|
||||
mSp.isChecked = false
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SNAME = 0x1
|
||||
const val STAGS = 0x2
|
||||
const val SDESC = 0x4
|
||||
const val STORR = 0x8
|
||||
const val STO = 0x10
|
||||
const val SDT1 = 0x20
|
||||
const val SDT2 = 0x40
|
||||
const val SH = 0x80
|
||||
const val SFL = 0x100
|
||||
const val SFU = 0x200
|
||||
const val SFT = 0x400
|
||||
}
|
||||
}
|
||||
@@ -245,7 +245,7 @@ public abstract class GalleryProvider {
|
||||
}
|
||||
|
||||
public void add(Integer key, ImageWrapper value) {
|
||||
if (value.getFormat() != Image.FORMAT_GIF && value.obtain()) {
|
||||
if (value.getFormat() != Image.FORMAT_ANIMATED && value.obtain()) {
|
||||
put(key, value);
|
||||
}
|
||||
}
|
||||
@@ -253,7 +253,7 @@ public abstract class GalleryProvider {
|
||||
@Override
|
||||
protected int sizeOf(Integer key, ImageWrapper value) {
|
||||
int size = value.getWidth() * value.getHeight() * 4;
|
||||
if (value.getFormat() == Image.FORMAT_GIF) {
|
||||
if (value.getFormat() == Image.FORMAT_ANIMATED) {
|
||||
size *= 5;
|
||||
}
|
||||
return size;
|
||||
|
||||
@@ -153,12 +153,6 @@ public class ImageTexture implements Texture, Animatable {
|
||||
}
|
||||
|
||||
mTiles = list.toArray(new Tile[list.size()]);
|
||||
|
||||
if (!mImage.isCompleted()) {
|
||||
Runnable runnable = new AnimateRunnable();
|
||||
mAnimateRunnable = runnable;
|
||||
sThreadExecutor.execute(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
private static Tile obtainSmallTile() {
|
||||
@@ -239,7 +233,7 @@ public class ImageTexture implements Texture, Animatable {
|
||||
}
|
||||
|
||||
boolean end = mReleased.get() || mImage.isImageRecycled() || mNeedRelease.get() ||
|
||||
(mImage.isCompleted() && mImage.getFrameCount() <= 1) || mRunning.get();
|
||||
(mImage.getFormat() == 0) || mRunning.get();
|
||||
|
||||
synchronized (mImage) {
|
||||
mImageBusy = false;
|
||||
@@ -597,25 +591,11 @@ public class ImageTexture implements Texture, Animatable {
|
||||
mImageBusy = true;
|
||||
}
|
||||
|
||||
if (!mImage.isCompleted()) {
|
||||
try {
|
||||
sPVLock.p();
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore
|
||||
}
|
||||
if (!mNeedRelease.get()) {
|
||||
mImage.complete();
|
||||
}
|
||||
sPVLock.v();
|
||||
}
|
||||
|
||||
int frameCount = mImage.getFrameCount();
|
||||
|
||||
synchronized (mImage) {
|
||||
// Release image
|
||||
mImageBusy = false;
|
||||
// Check need release, frameCount <= 1
|
||||
if (mNeedRelease.get() || frameCount <= 1) {
|
||||
if (mNeedRelease.get() || mImage.getFormat() == 0) {
|
||||
mAnimateRunnable = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -122,22 +122,6 @@ public class ImageWrapper {
|
||||
return mCut.height();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Image#complete()
|
||||
*/
|
||||
public boolean complete() {
|
||||
synchronized (mImage) {
|
||||
return mImage.complete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Image#isCompleted()
|
||||
*/
|
||||
public boolean isCompleted() {
|
||||
return mImage.isCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Image#render(int, int, Bitmap, int, int, int, int, boolean, int)
|
||||
*/
|
||||
@@ -168,13 +152,6 @@ public class ImageWrapper {
|
||||
return mImage.getDelay();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Image#getFrameCount()
|
||||
*/
|
||||
public int getFrameCount() {
|
||||
return mImage.getFrameCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Image#isOpaque()
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 hathlife
|
||||
~
|
||||
~ This file is part of EhViewer
|
||||
~
|
||||
~ EhViewer is free software: you can redistribute it and/or
|
||||
~ modify it under the terms of the GNU General Public License as
|
||||
~ published by the Free Software Foundation, either version 3 of the
|
||||
~ License, or (at your option) any later version.
|
||||
~
|
||||
~ EhViewer is distributed in the hope that it will be useful, but
|
||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License along with EhViewer.
|
||||
~ If not, see <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/actions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/keyline_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/newerVersion"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="@string/newer_version_avaliable"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingLeft="@dimen/keyline_margin"
|
||||
android:paddingRight="@dimen/keyline_margin">
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/rate"
|
||||
android:layout_width="484dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatRatingBar
|
||||
android:id="@+id/rating"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginLeft="0dp"
|
||||
android:layout_marginTop="0dp"
|
||||
|
||||
android:isIndicator="true"
|
||||
android:theme="@style/RatingBarTheme" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/rating_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginLeft="0dp"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/actions_scroll_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:clipToPadding="false"
|
||||
android:paddingLeft="36dp"
|
||||
android:paddingRight="@dimen/keyline_margin"
|
||||
android:scrollbars="none">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:divider="@drawable/spacer_keyline"
|
||||
android:orientation="horizontal"
|
||||
android:showDividers="middle">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/heart_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:nextFocusUp="@+id/download">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/heart"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/favorited"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/heart_outline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/not_favorited"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/share"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:drawablePadding="4dp"
|
||||
android:focusable="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:nextFocusUp="@+id/download"
|
||||
android:text="@string/share"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/torrent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:drawablePadding="4dp"
|
||||
android:focusable="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:nextFocusUp="@+id/download"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/archive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:drawablePadding="4dp"
|
||||
android:focusable="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:nextFocusUp="@+id/download"
|
||||
android:text="@string/archive"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/similar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:drawablePadding="4dp"
|
||||
android:focusable="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:nextFocusUp="@+id/download"
|
||||
android:text="@string/similar_gallery"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/search_cover"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:drawablePadding="4dp"
|
||||
android:focusable="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:nextFocusRight="@+id/search_cover"
|
||||
android:nextFocusUp="@+id/download"
|
||||
android:text="@string/search_cover"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,263 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 hathlife
|
||||
~
|
||||
~ This file is part of EhViewer
|
||||
~
|
||||
~ EhViewer is free software: you can redistribute it and/or
|
||||
~ modify it under the terms of the GNU General Public License as
|
||||
~ published by the Free Software Foundation, either version 3 of the
|
||||
~ License, or (at your option) any later version.
|
||||
~
|
||||
~ EhViewer is distributed in the hope that it will be useful, but
|
||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License along with EhViewer.
|
||||
~ If not, see <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:id="@+id/color_bg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:elevation="4dp"
|
||||
app:fitsSystemWindowsInsets="top" />
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="28dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.Material3.HeadlineSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/keyline_margin"
|
||||
android:layout_marginRight="@dimen/keyline_margin"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="5" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/Widget.Material3.CardView.Elevated"
|
||||
android:layout_width="540dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/keyline_margin"
|
||||
android:layout_marginTop="@dimen/keyline_margin"
|
||||
android:layout_marginRight="@dimen/keyline_margin"
|
||||
android:layout_marginBottom="@dimen/keyline_margin"
|
||||
app:fitsSystemWindowsInsets="top">
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/header_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/thumb_card"
|
||||
style="@style/Widget.Material3.CardView.Filled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.hippo.widget.LoadImageView
|
||||
android:id="@+id/thumb"
|
||||
android:layout_width="256dp"
|
||||
android:layout_height="@dimen/gallery_detail_thumb_height" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/info"
|
||||
style="@style/Widget.Material3.CardView.Filled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="@dimen/keyline_margin"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:nextFocusRight="@+id/read"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/language"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="left"
|
||||
android:singleLine="true"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/size"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:gravity="right"
|
||||
android:singleLine="true"
|
||||
app:layout_constraintBaseline_toBaselineOf="@id/language"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toEndOf="@id/language" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/favoredTimes"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="left"
|
||||
android:singleLine="true"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/language" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pages"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:gravity="right"
|
||||
android:singleLine="true"
|
||||
app:layout_constraintBaseline_toBaselineOf="@id/favoredTimes"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toEndOf="@id/favoredTimes" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/posted"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="left"
|
||||
android:singleLine="true"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/favoredTimes" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/uploader"
|
||||
style="@style/Widget.Material3.Chip.Assist"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/keyline_margin"
|
||||
android:ellipsize="end"
|
||||
android:nextFocusRight="@+id/read"
|
||||
android:nextFocusDown="@+id/rate"
|
||||
android:singleLine="true"
|
||||
android:textAllCaps="true"
|
||||
app:chipIcon="@drawable/file_upload_black_24dp"
|
||||
app:ensureMinTouchTargetSize="true"
|
||||
app:layout_constraintBottom_toBottomOf="@id/thumb_card"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/category"
|
||||
style="@style/Widget.Material3.Chip.Assist"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/keyline_margin"
|
||||
android:ellipsize="end"
|
||||
android:nextFocusRight="@+id/read"
|
||||
android:singleLine="true"
|
||||
android:textAllCaps="true"
|
||||
app:chipIcon="@drawable/ic_baseline_label_24"
|
||||
app:ensureMinTouchTargetSize="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/uploader"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/action_card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/keyline_margin"
|
||||
android:layout_marginRight="@dimen/keyline_margin"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@+id/read"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:insetLeft="40dp"
|
||||
android:insetRight="40dp"
|
||||
android:insetTop="16dp"
|
||||
android:text="@string/read">
|
||||
|
||||
<requestFocus />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:id="@+id/download"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:nextFocusDown="@+id/torrent"
|
||||
android:focusable="true"
|
||||
android:insetLeft="40dp"
|
||||
android:insetTop="16dp"
|
||||
android:insetRight="40dp" />
|
||||
|
||||
|
||||
<android.widget.Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -1,17 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 hathlife
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~ This file is part of EhViewer
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~ EhViewer is free software: you can redistribute it and/or
|
||||
~ modify it under the terms of the GNU General Public License as
|
||||
~ published by the Free Software Foundation, either version 3 of the
|
||||
~ License, or (at your option) any later version.
|
||||
~
|
||||
~ EhViewer is distributed in the hope that it will be useful, but
|
||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License along with EhViewer.
|
||||
~ If not, see <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 hathlife
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~ This file is part of EhViewer
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~ EhViewer is free software: you can redistribute it and/or
|
||||
~ modify it under the terms of the GNU General Public License as
|
||||
~ published by the Free Software Foundation, either version 3 of the
|
||||
~ License, or (at your option) any later version.
|
||||
~
|
||||
~ EhViewer is distributed in the hope that it will be useful, but
|
||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License along with EhViewer.
|
||||
~ If not, see <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
@@ -36,7 +39,7 @@
|
||||
|
||||
<ImageView
|
||||
android:layout_width="257dp"
|
||||
android:layout_height="518dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:padding="@dimen/keyline_margin"
|
||||
app:srcCompat="@mipmap/ic_launcher" />
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 hathlife
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~ This file is part of EhViewer
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~ EhViewer is free software: you can redistribute it and/or
|
||||
~ modify it under the terms of the GNU General Public License as
|
||||
~ published by the Free Software Foundation, either version 3 of the
|
||||
~ License, or (at your option) any later version.
|
||||
~
|
||||
~ EhViewer is distributed in the hope that it will be useful, but
|
||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License along with EhViewer.
|
||||
~ If not, see <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 hathlife
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~ This file is part of EhViewer
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~ EhViewer is free software: you can redistribute it and/or
|
||||
~ modify it under the terms of the GNU General Public License as
|
||||
~ published by the Free Software Foundation, either version 3 of the
|
||||
~ License, or (at your option) any later version.
|
||||
~
|
||||
~ EhViewer is distributed in the hope that it will be useful, but
|
||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License along with EhViewer.
|
||||
~ If not, see <https://www.gnu.org/licenses/>.
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
@@ -64,16 +64,18 @@
|
||||
android:layout_marginBottom="@dimen/keyline_margin"
|
||||
app:fitsSystemWindowsInsets="top">
|
||||
|
||||
<RelativeLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/header_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/thumb_card"
|
||||
style="@style/Widget.Material3.CardView.Elevated"
|
||||
style="@style/Widget.Material3.CardView.Filled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.hippo.widget.LoadImageView
|
||||
android:id="@+id/thumb"
|
||||
@@ -87,12 +89,13 @@
|
||||
style="@style/Widget.Material3.CardView.Filled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="@dimen/keyline_margin"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="wrap_content"
|
||||
@@ -101,6 +104,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/language"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
@@ -110,6 +114,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/size"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
@@ -123,6 +128,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/favoredTimes"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
@@ -133,6 +139,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pages"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
@@ -146,6 +153,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/posted"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
@@ -165,30 +173,31 @@
|
||||
style="@style/Widget.Material3.Chip.Assist"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@id/thumb_card"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="@dimen/keyline_margin"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAllCaps="true"
|
||||
app:chipIcon="@drawable/file_upload_black_24dp"
|
||||
app:ensureMinTouchTargetSize="true" />
|
||||
app:ensureMinTouchTargetSize="true"
|
||||
app:layout_constraintBottom_toBottomOf="@id/thumb_card"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/category"
|
||||
style="@style/Widget.Material3.Chip.Assist"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/uploader"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="@dimen/keyline_margin"
|
||||
app:chipSpacingHorizontal="8dp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAllCaps="true"
|
||||
app:chipIcon="@drawable/ic_baseline_label_24"
|
||||
app:ensureMinTouchTargetSize="true" />
|
||||
app:ensureMinTouchTargetSize="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/uploader"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
@@ -205,19 +214,17 @@
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
<android.widget.Space
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/read"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
|
||||
@@ -95,27 +95,30 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:gravity="bottom"
|
||||
android:orientation="vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/sign_in"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/sign_in" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/register"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/register" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/sign_in"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/sign_in" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -139,13 +140,22 @@
|
||||
android:minHeight="0dp"
|
||||
android:text="@string/search_sr" />
|
||||
|
||||
<Spinner
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="@dimen/advance_search_table_item_margin"
|
||||
android:layout_marginStart="@dimen/advance_search_table_item_margin"
|
||||
android:layout_weight="1"
|
||||
android:entries="@array/search_min_rating" />
|
||||
android:hint="@string/search_sr">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none"
|
||||
app:simpleItems="@array/search_min_rating" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -764,4 +764,9 @@
|
||||
<string name="settings_privacy_require_unlock">需要解锁</string>
|
||||
<string name="proxy_type_name">代理类型</string>
|
||||
<string name="filter_label">屏蔽项类型</string>
|
||||
|
||||
<string name="archive_passwd">归档文件密码</string>
|
||||
<string name="archive_need_passwd">归档文件需要密码</string>
|
||||
<string name="passwd_wrong">密码错误</string>
|
||||
<string name="passwd_cannot_be_empty">密码不能为空</string>
|
||||
</resources>
|
||||
@@ -828,4 +828,9 @@
|
||||
<string name="settings_privacy_require_unlock">Require Unlock</string>
|
||||
<string name="proxy_type_name">Proxy Type</string>
|
||||
<string name="filter_label">Blocker Type</string>
|
||||
|
||||
<string name="archive_passwd">password</string>
|
||||
<string name="archive_need_passwd">Archive need password</string>
|
||||
<string name="passwd_wrong">Password Wrong</string>
|
||||
<string name="passwd_cannot_be_empty">Password can\'t be empty</string>
|
||||
</resources>
|
||||
+1
-1
@@ -9,7 +9,7 @@ android {
|
||||
ndkVersion "25.0.8775105"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 26
|
||||
minSdkVersion 31
|
||||
targetSdkVersion 33
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
|
||||
|
||||
@@ -28,9 +28,7 @@ public class Native {
|
||||
|
||||
public static native String getliblzmaVersion();
|
||||
|
||||
public static native String getlibzstdVersion();
|
||||
|
||||
public static native String getlibjpeg_turboVersion();
|
||||
|
||||
public static native String getzlibVersion();
|
||||
|
||||
public static native String getnettleVersion();
|
||||
}
|
||||
@@ -21,106 +21,44 @@ package com.hippo;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
import android.system.OsConstants;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class UriArchiveAccessor implements AutoCloseable {
|
||||
public static int OPEN_OK = 1;
|
||||
public static int OPEN_ERR = 2;
|
||||
private final OsReadableFile osf;
|
||||
public class UriArchiveAccessor {
|
||||
ParcelFileDescriptor pfd;
|
||||
FileDescriptor fd;
|
||||
long archiveAddr;
|
||||
Context ctx;
|
||||
Uri uri;
|
||||
|
||||
public UriArchiveAccessor(Context ctx, Uri uri) throws FileNotFoundException {
|
||||
osf = new OsReadableFile(ctx, uri);
|
||||
public UriArchiveAccessor(Context ctx, Uri uri) {
|
||||
this.ctx = ctx;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public int open() {
|
||||
return openArchive(osf);
|
||||
public int open() throws Exception {
|
||||
pfd = ctx.getContentResolver().openFileDescriptor(uri, "r");
|
||||
fd = pfd.getFileDescriptor();
|
||||
archiveAddr = Os.mmap(0, pfd.getStatSize(), OsConstants.PROT_READ, OsConstants.MAP_PRIVATE, fd, 0);
|
||||
return openArchive(archiveAddr, pfd.getStatSize());
|
||||
}
|
||||
|
||||
public void extractTargetIndexToOutputStream(int index, OutputStream os) {
|
||||
extracttoOutputStream(index, os);
|
||||
}
|
||||
private native int openArchive(long addr, long size);
|
||||
|
||||
private native int openArchive(OsReadableFile osf);
|
||||
public native long extracttoOutputStream(int index);
|
||||
|
||||
private native void extracttoOutputStream(int index, OutputStream os);
|
||||
public native boolean needPassword();
|
||||
|
||||
public native boolean providePassword(String str);
|
||||
|
||||
private native void closeArchive();
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close() throws Exception {
|
||||
closeArchive();
|
||||
osf.close();
|
||||
}
|
||||
|
||||
static class OsReadableFile {
|
||||
ParcelFileDescriptor pfd;
|
||||
FileDescriptor fd;
|
||||
|
||||
public OsReadableFile(Context ctx, Uri uri) throws FileNotFoundException {
|
||||
pfd = ctx.getContentResolver().openFileDescriptor(uri, "r");
|
||||
fd = pfd.getFileDescriptor();
|
||||
}
|
||||
|
||||
public int read(byte[] b, int off, int len) throws IOException, ErrnoException {
|
||||
return Os.read(fd, b, off, len);
|
||||
}
|
||||
|
||||
public int read(byte[] b) throws IOException, ErrnoException {
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
public long length() throws IOException, ErrnoException {
|
||||
return Os.fstat(fd).st_size;
|
||||
}
|
||||
|
||||
public long seek(long pos, int whence) throws IOException, ErrnoException {
|
||||
try {
|
||||
return Os.lseek(fd, pos, whence);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return -30;
|
||||
}
|
||||
}
|
||||
|
||||
public void rewind() throws IOException, ErrnoException {
|
||||
Os.lseek(fd, 0, OsConstants.SEEK_SET);
|
||||
}
|
||||
|
||||
public long skip(long n) throws IOException, ErrnoException {
|
||||
long pos;
|
||||
long len;
|
||||
long newpos;
|
||||
|
||||
if (n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
pos = Os.lseek(fd, 0L, OsConstants.SEEK_CUR);
|
||||
len = length();
|
||||
newpos = pos + n;
|
||||
if (newpos > len) {
|
||||
newpos = len;
|
||||
}
|
||||
seek(newpos, OsConstants.SEEK_SET);
|
||||
|
||||
/* return the actual number of bytes skipped */
|
||||
return newpos - pos;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
pfd.close();
|
||||
try {
|
||||
Os.close(fd);
|
||||
} catch (ErrnoException e) {
|
||||
throw new IOException("An ErrnoException occurs", e);
|
||||
}
|
||||
}
|
||||
Os.munmap(archiveAddr, pfd.getStatSize());
|
||||
Os.close(fd);
|
||||
pfd.close();
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.graphics.Bitmap;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -28,31 +29,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* The {@code Image} is a image which stored pixel data in native heap
|
||||
*/
|
||||
public final class Image {
|
||||
public static final int FORMAT_NORMAL = 0;
|
||||
|
||||
/**
|
||||
* Unknown image format
|
||||
*/
|
||||
public static final int FORMAT_UNKNOWN = -1;
|
||||
|
||||
/**
|
||||
* Plain image format, for {@code Image} from {@link #create(Bitmap)}
|
||||
*/
|
||||
public static final int FORMAT_PLAIN = 0;
|
||||
|
||||
/**
|
||||
* JPEG image format
|
||||
*/
|
||||
public static final int FORMAT_JPEG = 1;
|
||||
|
||||
/**
|
||||
* PNG image format
|
||||
*/
|
||||
public static final int FORMAT_PNG = 2;
|
||||
|
||||
/**
|
||||
* GIF image format
|
||||
*/
|
||||
public static final int FORMAT_GIF = 3;
|
||||
public static final int FORMAT_ANIMATED = 1;
|
||||
|
||||
private static final AtomicInteger sImageCount = new AtomicInteger();
|
||||
private final int mFormat;
|
||||
@@ -74,11 +53,24 @@ public final class Image {
|
||||
* Decode image from {@code InputStream}
|
||||
*/
|
||||
@Nullable
|
||||
public static Image decode(InputStream is, boolean partially) {
|
||||
if (!(is instanceof BufferedInputStream)) {
|
||||
is = new BufferedInputStream(is);
|
||||
}
|
||||
return nativeDecode(is, partially);
|
||||
public static Image decode(FileDescriptor fd, boolean partially) {
|
||||
return nativeDecode(fd, partially);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode image from {@code InputStream}
|
||||
*/
|
||||
@Nullable
|
||||
public static Image decode(Integer fd, boolean partially) {
|
||||
return nativeDecodeFdInt(fd, partially);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode image from {@code InputStream}
|
||||
*/
|
||||
@Nullable
|
||||
public static Image decodeAddr(Long addr, boolean partially) {
|
||||
return nativeDecodeAddr(addr, partially);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,31 +89,16 @@ public final class Image {
|
||||
return sImageCount.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all supported image formats, exclude {@link #FORMAT_PLAIN}
|
||||
*/
|
||||
public static int[] getSupportedImageFormats() {
|
||||
return nativeGetSupportedImageFormats();
|
||||
}
|
||||
private static native Image nativeDecode(FileDescriptor fd, boolean partially);
|
||||
|
||||
/**
|
||||
* Return decoder description of the image format,
|
||||
* {@code null} for invalid image format.
|
||||
*/
|
||||
public static String getDecoderDescription(int format) {
|
||||
return nativeGetDecoderDescription(format);
|
||||
}
|
||||
private static native Image nativeDecodeFdInt(int fd, boolean partially);
|
||||
|
||||
private static native Image nativeDecode(InputStream is, boolean partially);
|
||||
private static native Image nativeDecodeAddr(long addr, boolean partially);
|
||||
|
||||
private static native Image nativeCreate(Bitmap bitmap);
|
||||
|
||||
private static native int nativeGetByteCount(long nativePtr, int format);
|
||||
|
||||
private static native boolean nativeComplete(long nativePtr, int format);
|
||||
|
||||
private static native boolean nativeIsCompleted(long nativePtr, int format);
|
||||
|
||||
private static native void nativeRender(long nativePtr, int format,
|
||||
int srcX, int srcY, Bitmap dst, int dstX, int dstY,
|
||||
int width, int height, boolean fillBlank, int defaultColor);
|
||||
@@ -133,8 +110,6 @@ public final class Image {
|
||||
|
||||
private static native int nativeGetDelay(long nativePtr, int format);
|
||||
|
||||
private static native int nativeFrameCount(long nativePtr, int format);
|
||||
|
||||
private static native boolean nativeIsOpaque(long nativePtr, int format);
|
||||
|
||||
private static native boolean nativeIsGray(long nativePtr, int format, int error);
|
||||
@@ -143,10 +118,6 @@ public final class Image {
|
||||
|
||||
private static native void nativeRecycle(long nativePtr, int format);
|
||||
|
||||
private static native int[] nativeGetSupportedImageFormats();
|
||||
|
||||
private static native String nativeGetDecoderDescription(int format);
|
||||
|
||||
/**
|
||||
* Return the format of the image
|
||||
*/
|
||||
@@ -186,22 +157,6 @@ public final class Image {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the image decoding
|
||||
*/
|
||||
public boolean complete() {
|
||||
checkRecycled();
|
||||
return nativeComplete(mNativePtr, mFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the image decoding completed
|
||||
*/
|
||||
public boolean isCompleted() {
|
||||
checkRecycled();
|
||||
return nativeIsCompleted(mNativePtr, mFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the image to {@code Bitmap}
|
||||
*/
|
||||
@@ -239,14 +194,6 @@ public final class Image {
|
||||
return delay <= 10 ? 100 : delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return frame count. 1 for non-animation image
|
||||
*/
|
||||
public int getFrameCount() {
|
||||
checkRecycled();
|
||||
return nativeFrameCount(mNativePtr, mFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return is the image opaque
|
||||
*/
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.os.Looper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Iterator;
|
||||
@@ -45,7 +46,6 @@ public final class ImageBitmap implements Animatable, Runnable {
|
||||
private final int mFormat;
|
||||
private final boolean mIsOpaque;
|
||||
private final int mByteCount;
|
||||
private final int mFrameCount;
|
||||
private final Set<WeakReference<Callback>> mCallbackSet = new LinkedHashSet<>();
|
||||
@Nullable
|
||||
private Image mImage;
|
||||
@@ -61,9 +61,8 @@ public final class ImageBitmap implements Animatable, Runnable {
|
||||
mFormat = image.getFormat();
|
||||
mIsOpaque = image.isOpaque();
|
||||
mByteCount = image.getByteCount();
|
||||
mFrameCount = image.getFrameCount();
|
||||
|
||||
if (mFrameCount > 1) {
|
||||
if (mFormat == 1) {
|
||||
// For animated image, save image object
|
||||
mImage = image;
|
||||
} else {
|
||||
@@ -73,19 +72,18 @@ public final class ImageBitmap implements Animatable, Runnable {
|
||||
}
|
||||
|
||||
private ImageBitmap(@NonNull Bitmap bitmap) {
|
||||
mFormat = Image.FORMAT_PLAIN;
|
||||
mFormat = Image.FORMAT_NORMAL;
|
||||
mBitmap = bitmap;
|
||||
mIsOpaque = !bitmap.hasAlpha();
|
||||
mByteCount = bitmap.getRowBytes() * bitmap.getHeight();
|
||||
mFrameCount = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode {@code InputStream}, then create image.
|
||||
*/
|
||||
@Nullable
|
||||
public static ImageBitmap decode(@NonNull InputStream is) {
|
||||
Image image = Image.decode(is, false);
|
||||
public static ImageBitmap decode(@NonNull FileDescriptor fd) {
|
||||
Image image = Image.decode(fd, false);
|
||||
if (image != null) {
|
||||
return create(image);
|
||||
} else {
|
||||
@@ -237,13 +235,6 @@ public final class ImageBitmap implements Animatable, Runnable {
|
||||
return mImage != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return image frame count
|
||||
*/
|
||||
public int getFrameCount() {
|
||||
return mFrameCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw image to canvas
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,20 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Oz -fvisibility=hidden -fvisibility-inlines
|
||||
-mllvm -polly-detect-profitability-min-per-loop-insts=40 \
|
||||
-mllvm -polly-invariant-load-hoisting")
|
||||
|
||||
# Build GNUTLS libnettle
|
||||
add_subdirectory(nettle)
|
||||
|
||||
# Configure libnettle support for libarchive
|
||||
include_directories(nettle)
|
||||
include_directories(.)
|
||||
set(HAVE_LIBNETTLE 1)
|
||||
set(HAVE_NETTLE_AES_H 1)
|
||||
set(HAVE_NETTLE_HMAC_H 1)
|
||||
set(HAVE_NETTLE_MD5_H 1)
|
||||
set(HAVE_NETTLE_PBKDF2_H 1)
|
||||
set(HAVE_NETTLE_RIPEMD160_H 1)
|
||||
set(HAVE_NETTLE_SHA_H 1)
|
||||
|
||||
# Build liblzma
|
||||
add_subdirectory(liblzma)
|
||||
|
||||
@@ -24,6 +38,9 @@ SET(HAVE_LZMA_STREAM_ENCODER_MT 1)
|
||||
SET(HAVE_LZMADEC_H 1)
|
||||
SET(HAVE_LIBLZMADEC 1)
|
||||
|
||||
# Configure libarchive link's static lib
|
||||
SET(LIBARCHIVE_CUSTOM_LIBS "liblzma" "nettle")
|
||||
|
||||
# Build libarchive
|
||||
add_subdirectory(libarchive)
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#include <android/log.h>
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define LOG_TAG "libarchive_wrapper"
|
||||
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG ,__VA_ARGS__)
|
||||
@@ -32,38 +35,13 @@
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG ,__VA_ARGS__)
|
||||
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG ,__VA_ARGS__)
|
||||
|
||||
#define BLOCK_SIZE 4096 * 16
|
||||
|
||||
static JNIEnv *env;
|
||||
static jobject file;
|
||||
static jmethodID readID;
|
||||
static jmethodID seekID;
|
||||
static jmethodID skipID;
|
||||
static jmethodID rewindID;
|
||||
static void* read_buffer;
|
||||
static jbyteArray jbr;
|
||||
|
||||
static int cur_index = 0; // Current entry we haven't read any data from it yet
|
||||
static struct archive* arc;
|
||||
|
||||
static void JNI_prepare_environment(JNIEnv* jniEnv, jobject OsReadablefile)
|
||||
{
|
||||
env = jniEnv;
|
||||
file = (*env)->NewGlobalRef(env, OsReadablefile);
|
||||
readID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, OsReadablefile), "read", "([B)I");
|
||||
seekID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, OsReadablefile), "seek", "(JI)J");
|
||||
skipID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, OsReadablefile), "skip", "(J)J");
|
||||
rewindID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, OsReadablefile), "rewind", "()V");
|
||||
jbr = (*env)->NewGlobalRef(env, (*env)->NewByteArray(env, BLOCK_SIZE));
|
||||
read_buffer = malloc(BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static void JNI_destroy_environment()
|
||||
{
|
||||
(*env)->DeleteGlobalRef(env, file);
|
||||
(*env)->DeleteGlobalRef(env, jbr);
|
||||
free(read_buffer);
|
||||
}
|
||||
static struct archive *arc = NULL;
|
||||
static bool need_encrypt = false;
|
||||
static char *passwd = NULL;
|
||||
static void *archiveAddr = NULL;
|
||||
static jlong archiveSize = 0;
|
||||
|
||||
static int filename_is_playable_file(const char *name) {
|
||||
const char *dotptr = strrchr(name, '.');
|
||||
@@ -94,99 +72,123 @@ static long archive_list_all_entries() {
|
||||
return count;
|
||||
}
|
||||
|
||||
ssize_t ins_read(struct archive *a, void *client_data_ptr, const void **buff) {
|
||||
int32_t r = (*env)->CallIntMethod(env, file, readID, jbr);
|
||||
(*env)->GetByteArrayRegion(env, jbr, 0, r, read_buffer);
|
||||
*buff = read_buffer;
|
||||
return r;
|
||||
static void archive_release() {
|
||||
if (arc) {
|
||||
archive_read_close(arc);
|
||||
archive_read_free(arc);
|
||||
arc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int ins_close(struct archive *a, void *client_data) {
|
||||
(*env)->CallVoidMethod(env, file, rewindID);
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
la_int64_t ins_seek(struct archive *a, void *client_data, la_int64_t offset, int whence) {
|
||||
jlong ret = (*env)->CallLongMethod(env, file, seekID, offset, whence);
|
||||
return ret;
|
||||
}
|
||||
|
||||
la_int64_t ins_skip(struct archive *a, void *client_data, la_int64_t request) {
|
||||
jlong ret = (*env)->CallLongMethod(env, file, skipID, request);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void archive_create() {
|
||||
static int archive_alloc() {
|
||||
archive_release();
|
||||
arc = archive_read_new();
|
||||
archive_read_set_seek_callback(arc, ins_seek);
|
||||
archive_read_set_skip_callback(arc, ins_skip);
|
||||
archive_read_support_format_all(arc);
|
||||
archive_read_support_filter_all(arc);
|
||||
if (passwd)
|
||||
archive_read_add_passphrase(arc, passwd);
|
||||
return archive_read_open_memory(arc, archiveAddr, archiveSize);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jobject osf) {
|
||||
JNI_prepare_environment(_, osf);
|
||||
archive_create();
|
||||
long r = archive_read_open(arc, arc, NULL, ins_read, ins_close);
|
||||
Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jlong addr, jlong size) {
|
||||
archiveAddr = (void *) addr;
|
||||
archiveSize = size;
|
||||
env = _;
|
||||
madvise(archiveAddr, archiveSize, MADV_SEQUENTIAL | MADV_WILLNEED);
|
||||
long r = archive_alloc();
|
||||
if (r) {
|
||||
r = 0;
|
||||
LOGE("%s%s", "Archive open failed:", archive_error_string(arc));
|
||||
} else {
|
||||
r = archive_list_all_entries();
|
||||
LOGI("%s%ld%s", "Found ", r, " image entries in archive");
|
||||
|
||||
// We must read through the file|vm then we can know whether it is encrypted
|
||||
int encryptRet = archive_read_has_encrypted_entries(arc);
|
||||
switch (encryptRet) {
|
||||
case 1: // At lease 1 encrypted entry
|
||||
need_encrypt = true;
|
||||
break;
|
||||
case 0: // format supports but no encrypted entry found
|
||||
case ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW: // Sometimes we might not read through whole file|vm, but it means so far we haven't meet any encrypted entry yet
|
||||
default:
|
||||
need_encrypt = false;
|
||||
}
|
||||
LOGI("%s%d", "archive_read_has_encrypted_entries returns ", encryptRet);
|
||||
}
|
||||
archive_read_close(arc);
|
||||
archive_read_free(arc);
|
||||
arc = NULL;
|
||||
archive_release();
|
||||
return r;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *_, jobject thiz, jint index, jobject os) {
|
||||
typedef struct Memarea {
|
||||
void* buffer;
|
||||
long size;
|
||||
} Memarea;
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *_, jobject thiz, jint index) {
|
||||
struct archive_entry *entry;
|
||||
size_t size;
|
||||
int ret;
|
||||
la_int64_t offset;
|
||||
const void* buff;
|
||||
if (!arc || index < cur_index) {
|
||||
if (arc)
|
||||
archive_read_close(arc);
|
||||
archive_read_free(arc);
|
||||
archive_create();
|
||||
archive_read_open(arc, arc, NULL, ins_read, ins_close);
|
||||
archive_alloc();
|
||||
cur_index = 0;
|
||||
}
|
||||
jmethodID writeID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, os), "write", "([B)V");
|
||||
jmethodID flushID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, os), "flush", "()V");
|
||||
jmethodID closeID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, os), "close", "()V");
|
||||
Memarea* memarea = malloc(sizeof(Memarea));
|
||||
while (archive_read_next_header(arc, &entry) == ARCHIVE_OK) {
|
||||
if (!filename_is_playable_file(archive_entry_pathname(entry)))
|
||||
continue;
|
||||
if (cur_index++ == index) {
|
||||
memarea->size = archive_entry_size(entry);
|
||||
memarea->buffer = malloc(memarea->size);
|
||||
for (;;) {
|
||||
ret = archive_read_data_block(arc, &buff, &size, &offset);
|
||||
if (ret == ARCHIVE_EOF)
|
||||
break;
|
||||
if (ret != ARCHIVE_OK) {
|
||||
ret = archive_read_data(arc, memarea->buffer, memarea->size);
|
||||
if (ret < 0) {
|
||||
LOGE("%s%s", "Archive read failed:", archive_error_string(arc));
|
||||
break;
|
||||
}
|
||||
(*env)->SetByteArrayRegion(env, jbr, 0, (int)size, buff);
|
||||
(*env)->CallVoidMethod(env, os, writeID, jbr);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
(*env)->CallVoidMethod(env, os, flushID);
|
||||
(*env)->CallVoidMethod(env, os, closeID);
|
||||
return (jlong) memarea;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_closeArchive(JNIEnv *jniEnv, jobject thiz) {
|
||||
if (arc) {
|
||||
archive_read_close(arc);
|
||||
archive_read_free(arc);
|
||||
archive_release();
|
||||
free(passwd);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_needPassword(JNIEnv *_, jobject thiz) {
|
||||
return need_encrypt;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_providePassword(JNIEnv *_, jobject thiz, jstring str) {
|
||||
struct archive_entry *entry;
|
||||
jboolean ret = true;
|
||||
int len = (*env)->GetStringUTFLength(env, str);
|
||||
if (passwd)
|
||||
free(passwd);
|
||||
passwd = calloc(len, sizeof(char));
|
||||
strcpy(passwd, (*env)->GetStringUTFChars(env, str, NULL));
|
||||
LOGI("%s%s", "Passwd is ", passwd);
|
||||
archive_alloc();
|
||||
while (archive_read_next_header(arc, &entry) == ARCHIVE_OK) {
|
||||
if (!filename_is_playable_file(archive_entry_pathname(entry)))
|
||||
continue;
|
||||
if (!archive_entry_is_encrypted(entry))
|
||||
continue;
|
||||
void *tmpBuf = malloc(4096);
|
||||
if (archive_read_data(arc, tmpBuf, 4096) < ARCHIVE_OK) {
|
||||
LOGE("%s%s", "Archive read failed:", archive_error_string(arc));
|
||||
ret = false;
|
||||
}
|
||||
free(tmpBuf);
|
||||
break;
|
||||
}
|
||||
JNI_destroy_environment();
|
||||
}
|
||||
archive_release();
|
||||
return ret;
|
||||
}
|
||||
@@ -13,9 +13,24 @@
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(image C)
|
||||
|
||||
add_subdirectory(image)
|
||||
add_subdirectory(stream)
|
||||
add_subdirectory(libjpeg-turbo)
|
||||
add_subdirectory(libpng)
|
||||
add_subdirectory(giflib)
|
||||
set(IMAGE_SOURCES
|
||||
image.c
|
||||
image_utils.c
|
||||
filter/clahe.c
|
||||
filter/gray.c
|
||||
java_wrapper.c
|
||||
)
|
||||
set(IMAGE_INCLUDES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
set(IMAGE_LIBRARIES
|
||||
log
|
||||
jnigraphics
|
||||
GLESv2
|
||||
)
|
||||
|
||||
add_library(image STATIC ${IMAGE_SOURCES})
|
||||
target_include_directories(image PRIVATE ${IMAGE_INCLUDES})
|
||||
target_link_libraries(image PRIVATE ${IMAGE_LIBRARIES})
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright 2018 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "clahe.h"
|
||||
#include "pixel.h"
|
||||
#include "../utils.h"
|
||||
#include "../log.h"
|
||||
|
||||
#define TILE_BLOCK 8
|
||||
#define LIMIT_MULTIPLE 4
|
||||
#define CL_MAX_LOOP_NUMBER 4
|
||||
|
||||
static BYTE clamp(int t) {
|
||||
t = t > 255 ? 255 : t;
|
||||
t = t < 0 ? 0 : t;
|
||||
return (BYTE) t;
|
||||
}
|
||||
|
||||
void IMAGE_clahe(void *data, int width, int height, bool to_gray) {
|
||||
if (width < TILE_BLOCK || height < TILE_BLOCK) {
|
||||
return;
|
||||
}
|
||||
|
||||
PIXEL *pixels = data;
|
||||
|
||||
if (to_gray) {
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
PIXEL *p = pixels + i;
|
||||
int t1 = (int) (p->c1 * 0.299f + p->c2 * 0.587f + p->c3 * 0.114f);
|
||||
p->c1 = clamp(t1);
|
||||
}
|
||||
} else {
|
||||
// RGBA to YUVA
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
PIXEL *p = pixels + i;
|
||||
int t1 = (int) (p->c1 * 0.299f + p->c2 * 0.587f + p->c3 * 0.114f);
|
||||
int t2 = (int) (p->c1 * -0.169f + p->c2 * -0.331f + p->c3 * 0.5f + 128);
|
||||
int t3 = (int) (p->c1 * 0.5f + p->c2 * -0.419f + p->c3 * -0.081f + 128);
|
||||
p->c1 = clamp(t1);
|
||||
p->c2 = clamp(t2);
|
||||
p->c3 = clamp(t3);
|
||||
}
|
||||
}
|
||||
|
||||
int tile_width = width / TILE_BLOCK;
|
||||
int tile_height = height / TILE_BLOCK;
|
||||
int histogram[TILE_BLOCK * TILE_BLOCK][256] = {0};
|
||||
float accumulation[TILE_BLOCK * TILE_BLOCK][256] = {0.0f};
|
||||
|
||||
// Build histogram and accumulation
|
||||
for (int i = 0; i < TILE_BLOCK; i++) {
|
||||
for (int j = 0; j < TILE_BLOCK; j++) {
|
||||
int x_start = tile_width * i;
|
||||
int x_end = i == TILE_BLOCK - 1 ? width : x_start + tile_width;
|
||||
int y_start = tile_height * j;
|
||||
int y_end = j == TILE_BLOCK - 1 ? height : y_start + tile_height;
|
||||
int tile_size = (x_end - x_start) * (y_end - y_start);
|
||||
int tile_index = i + TILE_BLOCK * j;
|
||||
|
||||
// Count
|
||||
for (int x = x_start; x < x_end; x++) {
|
||||
for (int y = y_start; y < y_end; y++) {
|
||||
PIXEL *p = pixels + x + y * width;
|
||||
histogram[tile_index][p->c1] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// CL
|
||||
int limit = tile_size * LIMIT_MULTIPLE / 256;
|
||||
for (int m = 0; m < CL_MAX_LOOP_NUMBER; m++) {
|
||||
int steal = 0;
|
||||
for (int n = 0; n < 256; n++) {
|
||||
if (histogram[tile_index][n] > limit) {
|
||||
steal += histogram[tile_index][n] - limit;
|
||||
histogram[tile_index][n] = limit;
|
||||
}
|
||||
}
|
||||
int bonus = steal / 256;
|
||||
if (bonus == 0 && steal != 0 && m == 0) {
|
||||
bonus = 1;
|
||||
}
|
||||
if (bonus == 0) {
|
||||
break;
|
||||
}
|
||||
for (int n = 0; n < 256; n++) {
|
||||
histogram[tile_index][n] += bonus;
|
||||
}
|
||||
}
|
||||
|
||||
// accumulation
|
||||
for (int n = 0; n < 256; n++) {
|
||||
accumulation[tile_index][n] = (float) histogram[tile_index][n] / tile_size;
|
||||
if (n != 0) {
|
||||
accumulation[tile_index][n] += accumulation[tile_index][n - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Interpolation
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
PIXEL *p = pixels + x + y * width;
|
||||
// top-left corner
|
||||
if (x <= tile_width / 2 && y <= tile_height / 2) {
|
||||
p->c1 = clamp((int) (accumulation[0][p->c1] * 255));
|
||||
continue;
|
||||
}
|
||||
// top-right corner
|
||||
if (x > width - tile_width / 2 && y <= tile_height / 2) {
|
||||
p->c1 = clamp((int) (accumulation[TILE_BLOCK - 1][p->c1] * 255));
|
||||
continue;
|
||||
}
|
||||
// bottom-left corner
|
||||
if (x <= tile_width / 2 && y > height - tile_height / 2) {
|
||||
p->c1 = clamp((int) (accumulation[TILE_BLOCK * (TILE_BLOCK - 1)][p->c1] * 255));
|
||||
continue;
|
||||
}
|
||||
// bottom-right corner
|
||||
if (x > width - tile_width / 2 && y > height - tile_height / 2) {
|
||||
p->c1 = clamp((int) (accumulation[TILE_BLOCK * TILE_BLOCK - 1][p->c1] * 255));
|
||||
continue;
|
||||
}
|
||||
|
||||
int tile_x_index = (x - tile_width / 2) / tile_width;
|
||||
int tile_y_index = (y - tile_height / 2) / tile_height;
|
||||
int tile_index1 = tile_x_index + TILE_BLOCK * tile_y_index;
|
||||
int tile_index2 = tile_index1 + 1;
|
||||
float u = (float) (x - (tile_x_index * tile_width + tile_width / 2)) / tile_width;
|
||||
// top side and bottom side
|
||||
if (y <= tile_height / 2 || y > height - tile_height / 2) {
|
||||
p->c1 = clamp((int) (255 * (accumulation[tile_index1][p->c1] * (1 - u) +
|
||||
accumulation[tile_index2][p->c1] * u)));
|
||||
continue;
|
||||
}
|
||||
|
||||
int tile_index3 = tile_index1 + TILE_BLOCK;
|
||||
float v = (float) (y - (tile_y_index * tile_height + tile_height / 2)) / tile_height;
|
||||
// left side and right side
|
||||
if (x <= tile_width / 2 || x > width - tile_width / 2) {
|
||||
p->c1 = clamp((int) (255 * (accumulation[tile_index1][p->c1] * (1 - v) +
|
||||
accumulation[tile_index3][p->c1] * v)));
|
||||
continue;
|
||||
}
|
||||
|
||||
int tile_index4 = tile_index2 + TILE_BLOCK;
|
||||
p->c1 = clamp((int) (255 * (
|
||||
accumulation[tile_index1][p->c1] * (1 - u) * (1 - v)
|
||||
+ accumulation[tile_index2][p->c1] * u * (1 - v)
|
||||
+ accumulation[tile_index3][p->c1] * (1 - u) * v
|
||||
+ accumulation[tile_index4][p->c1] * u * v)));
|
||||
}
|
||||
}
|
||||
|
||||
if (to_gray) {
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
PIXEL *p = pixels + i;
|
||||
p->c2 = p->c1;
|
||||
p->c3 = p->c1;
|
||||
}
|
||||
} else {
|
||||
// YUVA to RGBA
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
PIXEL *p = pixels + i;
|
||||
int t1 = (int) (p->c1 + (p->c2 - 128) * -0.00093f + (p->c3 - 128) * 1.401687f);
|
||||
int t2 = (int) (p->c1 + (p->c2 - 128) * -0.3437f + (p->c3 - 128) * -0.71417f);
|
||||
int t3 = (int) (p->c1 + (p->c2 - 128) * 1.77216f + (p->c3 - 128) * 0.00099f);
|
||||
p->c1 = clamp(t1);
|
||||
p->c2 = clamp(t2);
|
||||
p->c3 = clamp(t3);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -19,6 +19,6 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
void IMAGE_clahe(void* data, int width, int height, bool to_gray);
|
||||
void IMAGE_clahe(void *data, int width, int height, bool to_gray);
|
||||
|
||||
#endif //IMAGE_CLAHE_H
|
||||
+12
-12
@@ -17,20 +17,20 @@
|
||||
#include "gray.h"
|
||||
#include "pixel.h"
|
||||
|
||||
bool IMAGE_is_gray(void* data, int width, int height, int error) {
|
||||
PIXEL* p = data;
|
||||
bool IMAGE_is_gray(void *data, int width, int height, int error) {
|
||||
PIXEL *p = data;
|
||||
|
||||
for (int i = 0, n = width * height; i < n; i++, p++) {
|
||||
int e1 = p->c1 - p->c2;
|
||||
int e2 = p->c1 - p->c3;
|
||||
int e3 = p->c2 - p->c3;
|
||||
for (int i = 0, n = width * height; i < n; i++, p++) {
|
||||
int e1 = p->c1 - p->c2;
|
||||
int e2 = p->c1 - p->c3;
|
||||
int e3 = p->c2 - p->c3;
|
||||
|
||||
if (e1 > error || e1 < -error
|
||||
|| e2 > error || e2 < -error
|
||||
|| e3 > error || e3 < -error) {
|
||||
return false;
|
||||
if (e1 > error || e1 < -error
|
||||
|| e2 > error || e2 < -error
|
||||
|| e3 > error || e3 < -error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
+1
-1
@@ -19,6 +19,6 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool IMAGE_is_gray(void* data, int width, int height, int error);
|
||||
bool IMAGE_is_gray(void *data, int width, int height, int error);
|
||||
|
||||
#endif //IMAGE_GRAY_H
|
||||
+5
-6
@@ -19,12 +19,11 @@
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE c1;
|
||||
BYTE c2;
|
||||
BYTE c3;
|
||||
BYTE c4;
|
||||
typedef struct {
|
||||
BYTE c1;
|
||||
BYTE c2;
|
||||
BYTE c3;
|
||||
BYTE c4;
|
||||
} PIXEL;
|
||||
|
||||
#endif //IMAGE_PIXEL_H
|
||||
@@ -1,27 +0,0 @@
|
||||
# Copyright 2018 Hippo Seven
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(gif C)
|
||||
|
||||
set(GIFLIB_SOURCES
|
||||
giflib/dgif_lib.c
|
||||
giflib/gif_hash.c
|
||||
giflib/gifalloc.c
|
||||
giflib/openbsd-reallocarray.c
|
||||
)
|
||||
set(GIFLIB_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/giflib)
|
||||
|
||||
add_library(gif STATIC ${GIFLIB_SOURCES})
|
||||
target_include_directories(gif PUBLIC ${GIFLIB_INCLUDES})
|
||||
Submodule native/src/main/jni/image/giflib/giflib deleted from df82ff4380.
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#include <android/data_space.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "image.h"
|
||||
#include "image_utils.h"
|
||||
#include "filter/clahe.h"
|
||||
#include "filter/gray.h"
|
||||
#include "log.h"
|
||||
|
||||
void decodeCommon(IMAGE *image) {
|
||||
AImageDecoder *decoder = image->decoder;
|
||||
AImageDecoder_setDataSpace(decoder, ADATASPACE_SRGB);
|
||||
AImageDecoder_setAndroidBitmapFormat(decoder, ANDROID_BITMAP_FORMAT_RGBA_8888);
|
||||
const AImageDecoderHeaderInfo *headerInfo = AImageDecoder_getHeaderInfo(decoder);
|
||||
image->height = AImageDecoderHeaderInfo_getHeight(headerInfo);
|
||||
image->width = AImageDecoderHeaderInfo_getWidth(headerInfo);
|
||||
image->alpha =
|
||||
AImageDecoderHeaderInfo_getAlphaFlags(headerInfo) == ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
|
||||
image->stride = AImageDecoder_getMinimumStride(decoder);
|
||||
image->bufferLen = image->height * image->stride;
|
||||
image->buffer = malloc(image->bufferLen);
|
||||
if (image->isAnimated) {
|
||||
AImageDecoder_setInternallyHandleDisposePrevious(decoder, false);
|
||||
image->frameInfo = AImageDecoderFrameInfo_create();
|
||||
AImageDecoder_getFrameInfo(decoder, image->frameInfo);
|
||||
}
|
||||
AImageDecoder_decodeImage(decoder, image->buffer, image->stride, image->bufferLen);
|
||||
}
|
||||
|
||||
IMAGE *createFromFd(JNIEnv *env, int fd, bool partially, int *format) {
|
||||
AImageDecoder *decoder;
|
||||
int r = AImageDecoder_createFromFd(fd, &decoder);
|
||||
LOGD("%s%d", "Create ImageDecoder with ret ", r);
|
||||
if (r)
|
||||
return NULL;
|
||||
IMAGE *image = calloc(1, sizeof(IMAGE));
|
||||
image->isAnimated = *format = AImageDecoder_isAnimated(decoder);
|
||||
image->decoder = decoder;
|
||||
decodeCommon(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
IMAGE *createFromAddr(JNIEnv *env, void *addr, long size, bool partially, int *format) {
|
||||
AImageDecoder *decoder;
|
||||
int r = AImageDecoder_createFromBuffer((const void *) addr, size, &decoder);
|
||||
LOGD("%s%d", "Create ImageDecoder with ret ", r);
|
||||
if (r)
|
||||
return NULL;
|
||||
IMAGE *image = calloc(1, sizeof(IMAGE));
|
||||
image->isAnimated = *format = AImageDecoder_isAnimated(decoder);
|
||||
image->decoder = decoder;
|
||||
image->srcBuffer = addr;
|
||||
decodeCommon(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
void *create(int32_t width, int32_t height, const void *data) {
|
||||
IMAGE *plain = NULL;
|
||||
void *buffer = NULL;
|
||||
size_t length;
|
||||
|
||||
plain = malloc(sizeof(IMAGE));
|
||||
if (plain == NULL) {
|
||||
WTF_OM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
length = (size_t) (width * height * 4);
|
||||
|
||||
buffer = malloc(length);
|
||||
if (buffer == NULL) {
|
||||
WTF_OM;
|
||||
free(plain);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(buffer, data, length);
|
||||
|
||||
plain->width = width;
|
||||
plain->height = height;
|
||||
plain->buffer = buffer;
|
||||
plain->bufferLen = length;
|
||||
plain->decoder = NULL;
|
||||
|
||||
return plain;
|
||||
}
|
||||
|
||||
int get_width(IMAGE *image, int format) {
|
||||
return image->width;
|
||||
}
|
||||
|
||||
int get_height(IMAGE *image, int format) {
|
||||
return image->height;
|
||||
}
|
||||
|
||||
int get_byte_count(IMAGE *image, int format) {
|
||||
return image->bufferLen;
|
||||
}
|
||||
|
||||
void render(IMAGE *image, int format, int src_x, int src_y,
|
||||
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color) {
|
||||
copy_pixels(image->buffer, image->width, image->height, src_x, src_y, dst, dst_w, dst_h, dst_x,
|
||||
dst_y, width, height, fill_blank, default_color);
|
||||
}
|
||||
|
||||
void advance(IMAGE *image, int format) {
|
||||
if (format) {
|
||||
AImageDecoder_advanceFrame(image->decoder);
|
||||
if (AImageDecoder_decodeImage(image->decoder, image->buffer, image->stride,
|
||||
image->bufferLen) == ANDROID_IMAGE_DECODER_FINISHED) {
|
||||
AImageDecoder_rewind(image->decoder);
|
||||
AImageDecoder_decodeImage(image->decoder, image->buffer, image->stride,
|
||||
image->bufferLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int get_delay(IMAGE *image, int format) {
|
||||
if (format)
|
||||
return AImageDecoderFrameInfo_getDuration(image->frameInfo) / 1000000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool is_opaque(IMAGE *image, int format) {
|
||||
return image->alpha;
|
||||
}
|
||||
|
||||
static void get_image_data(IMAGE *image, int format, void **pixel, int *width, int *height) {
|
||||
*pixel = image->buffer;
|
||||
*width = image->width;
|
||||
*height = image->height;
|
||||
}
|
||||
|
||||
bool is_gray(IMAGE *image, int format, int error) {
|
||||
void *pixel = NULL;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
get_image_data(image, format, &pixel, &width, &height);
|
||||
|
||||
if (pixel == NULL || width == 0 || height == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IMAGE_is_gray(pixel, width, height, error);
|
||||
}
|
||||
|
||||
void clahe(IMAGE *image, int format, bool to_gray) {
|
||||
void *pixel = NULL;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
get_image_data(image, format, &pixel, &width, &height);
|
||||
|
||||
if (pixel == NULL || width == 0 || height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
IMAGE_clahe(pixel, width, height, to_gray);
|
||||
}
|
||||
|
||||
void recycle(JNIEnv *env, IMAGE *image, int format) {
|
||||
free(image->buffer);
|
||||
image->buffer = NULL;
|
||||
AImageDecoderFrameInfo_delete(image->frameInfo);
|
||||
AImageDecoder_delete(image->decoder);
|
||||
free(image->srcBuffer);
|
||||
free(image);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#ifndef IMAGE_IMAGE_H
|
||||
#define IMAGE_IMAGE_H
|
||||
|
||||
#include <android/imagedecoder.h>
|
||||
#include <stdbool.h>
|
||||
#include <jni.h>
|
||||
|
||||
typedef struct {
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
void *buffer;
|
||||
int bufferLen;
|
||||
AImageDecoder *decoder;
|
||||
void *srcBuffer;
|
||||
size_t stride;
|
||||
bool isAnimated;
|
||||
AImageDecoderFrameInfo *frameInfo;
|
||||
bool alpha;
|
||||
} IMAGE;
|
||||
|
||||
IMAGE *createFromFd(JNIEnv *env, int fd, bool partially, int *format);
|
||||
|
||||
IMAGE *createFromAddr(JNIEnv *env, void *addr, long size, bool partially, int *format);
|
||||
|
||||
void *create(int32_t width, int32_t height, const void *data);
|
||||
|
||||
int get_width(IMAGE *image, int format);
|
||||
|
||||
int get_height(IMAGE *image, int format);
|
||||
|
||||
int get_byte_count(IMAGE *image, int format);
|
||||
|
||||
void render(IMAGE *image, int format, int src_x, int src_y,
|
||||
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color);
|
||||
|
||||
void advance(IMAGE *image, int format);
|
||||
|
||||
int get_delay(IMAGE *image, int format);
|
||||
|
||||
bool is_opaque(IMAGE *image, int format);
|
||||
|
||||
bool is_gray(IMAGE *image, int format, int error);
|
||||
|
||||
void clahe(IMAGE *image, int format, bool to_gray);
|
||||
|
||||
void recycle(JNIEnv *env, IMAGE *image, int format);
|
||||
|
||||
#endif //IMAGE_IMAGE_H
|
||||
@@ -1,60 +0,0 @@
|
||||
# Copyright 2015 Hippo Seven
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
SUPPORT_FORMAT := plain jpeg png gif
|
||||
|
||||
LOCAL_MODULE := image
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../stream
|
||||
LOCAL_SRC_FILES := \
|
||||
image.c \
|
||||
image_utils.c \
|
||||
java_wrapper.c
|
||||
LOCAL_LDLIBS := -llog -ljnigraphics -lGLESv2
|
||||
LOCAL_STATIC_LIBRARIES := stream
|
||||
|
||||
ifeq ($(filter plain, $(SUPPORT_FORMAT)), plain)
|
||||
LOCAL_SRC_FILES += image_plain.c
|
||||
else
|
||||
LOCAL_CFLAGS += -DIMAGE_NOT_SUPPORT_PLAIN
|
||||
endif
|
||||
|
||||
ifeq ($(filter jpeg, $(SUPPORT_FORMAT)), jpeg)
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libjpeg-turbo
|
||||
LOCAL_SRC_FILES += image_jpeg.c
|
||||
LOCAL_STATIC_LIBRARIES += jpeg-turbo
|
||||
else
|
||||
LOCAL_CFLAGS += -DIMAGE_NOT_SUPPORT_JPEG
|
||||
endif
|
||||
|
||||
ifeq ($(filter png, $(SUPPORT_FORMAT)), png)
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libpng
|
||||
LOCAL_SRC_FILES += image_png.c
|
||||
LOCAL_STATIC_LIBRARIES += png
|
||||
else
|
||||
LOCAL_CFLAGS += -DIMAGE_NOT_SUPPORT_PNG
|
||||
endif
|
||||
|
||||
ifeq ($(filter gif, $(SUPPORT_FORMAT)), gif)
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../giflib
|
||||
LOCAL_SRC_FILES += image_gif.c
|
||||
LOCAL_STATIC_LIBRARIES += gif
|
||||
else
|
||||
LOCAL_CFLAGS += -DIMAGE_NOT_SUPPORT_GIF
|
||||
endif
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
@@ -1,44 +0,0 @@
|
||||
# Copyright 2018 Hippo Seven
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(image C)
|
||||
|
||||
set(IMAGE_SOURCES
|
||||
image.c
|
||||
image_utils.c
|
||||
image_plain.c
|
||||
image_jpeg.c
|
||||
image_png.c
|
||||
image_gif.c
|
||||
filter/clahe.c
|
||||
filter/gray.c
|
||||
java_wrapper.c
|
||||
)
|
||||
set(IMAGE_INCLUDES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
set(IMAGE_LIBRARIES
|
||||
log
|
||||
jnigraphics
|
||||
GLESv2
|
||||
stream
|
||||
jpeg
|
||||
png
|
||||
gif
|
||||
)
|
||||
|
||||
add_library(image STATIC ${IMAGE_SOURCES})
|
||||
target_include_directories(image PRIVATE ${IMAGE_INCLUDES})
|
||||
target_link_libraries(image PRIVATE ${IMAGE_LIBRARIES})
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#ifndef IMAGE_CONFIG_H
|
||||
#define IMAGE_CONFIG_H
|
||||
|
||||
#ifndef IMAGE_NOT_SUPPORT_PLAIN
|
||||
#define IMAGE_SUPPORT_PLAIN
|
||||
#endif
|
||||
#ifndef IMAGE_NOT_SUPPORT_JPEG
|
||||
#define IMAGE_SUPPORT_JPEG
|
||||
#endif
|
||||
#ifndef IMAGE_NOT_SUPPORT_PNG
|
||||
#define IMAGE_SUPPORT_PNG
|
||||
#endif
|
||||
#ifndef IMAGE_NOT_SUPPORT_GIF
|
||||
#define IMAGE_SUPPORT_GIF
|
||||
#endif
|
||||
|
||||
#endif //IMAGE_CONFIG_H
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "clahe.h"
|
||||
#include "pixel.h"
|
||||
#include "../../utils.h"
|
||||
#include "../../log.h"
|
||||
|
||||
#define TILE_BLOCK 8
|
||||
#define LIMIT_MULTIPLE 4
|
||||
#define CL_MAX_LOOP_NUMBER 4
|
||||
|
||||
static BYTE clamp(int t) {
|
||||
t = t > 255 ? 255 : t;
|
||||
t = t < 0 ? 0 : t;
|
||||
return (BYTE) t;
|
||||
}
|
||||
|
||||
void IMAGE_clahe(void* data, int width, int height, bool to_gray) {
|
||||
if (width < TILE_BLOCK || height < TILE_BLOCK) {
|
||||
return;
|
||||
}
|
||||
|
||||
PIXEL* pixels = data;
|
||||
|
||||
if (to_gray) {
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
PIXEL* p = pixels + i;
|
||||
int t1 = (int) (p->c1 * 0.299f + p->c2 * 0.587f + p->c3 * 0.114f);
|
||||
p->c1 = clamp(t1);
|
||||
}
|
||||
} else {
|
||||
// RGBA to YUVA
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
PIXEL* p = pixels + i;
|
||||
int t1 = (int) (p->c1 * 0.299f + p->c2 * 0.587f + p->c3 * 0.114f);
|
||||
int t2 = (int) (p->c1 * -0.169f + p->c2 * -0.331f + p->c3 * 0.5f + 128);
|
||||
int t3 = (int) (p->c1 * 0.5f + p->c2 * -0.419f + p->c3 * -0.081f + 128);
|
||||
p->c1 = clamp(t1);
|
||||
p->c2 = clamp(t2);
|
||||
p->c3 = clamp(t3);
|
||||
}
|
||||
}
|
||||
|
||||
int tile_width = width / TILE_BLOCK;
|
||||
int tile_height = height / TILE_BLOCK;
|
||||
int histogram[TILE_BLOCK * TILE_BLOCK][256] = {0};
|
||||
float accumulation[TILE_BLOCK * TILE_BLOCK][256] = {0.0f};
|
||||
|
||||
// Build histogram and accumulation
|
||||
for (int i = 0; i < TILE_BLOCK; i++) {
|
||||
for (int j = 0; j < TILE_BLOCK; j++) {
|
||||
int x_start = tile_width * i;
|
||||
int x_end = i == TILE_BLOCK - 1 ? width : x_start + tile_width;
|
||||
int y_start = tile_height * j;
|
||||
int y_end = j == TILE_BLOCK - 1 ? height : y_start + tile_height;
|
||||
int tile_size = (x_end - x_start) * (y_end - y_start);
|
||||
int tile_index = i + TILE_BLOCK * j;
|
||||
|
||||
// Count
|
||||
for(int x = x_start; x < x_end; x++) {
|
||||
for(int y = y_start; y < y_end ; y++) {
|
||||
PIXEL* p = pixels + x + y * width;
|
||||
histogram[tile_index][p->c1] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// CL
|
||||
int limit = tile_size * LIMIT_MULTIPLE / 256;
|
||||
for (int m = 0; m < CL_MAX_LOOP_NUMBER; m++) {
|
||||
int steal = 0;
|
||||
for (int n = 0; n < 256; n++) {
|
||||
if (histogram[tile_index][n] > limit) {
|
||||
steal += histogram[tile_index][n] - limit;
|
||||
histogram[tile_index][n] = limit;
|
||||
}
|
||||
}
|
||||
int bonus = steal / 256;
|
||||
if (bonus == 0 && steal != 0 && m == 0) {
|
||||
bonus = 1;
|
||||
}
|
||||
if (bonus == 0) {
|
||||
break;
|
||||
}
|
||||
for (int n = 0; n < 256; n++) {
|
||||
histogram[tile_index][n] += bonus;
|
||||
}
|
||||
}
|
||||
|
||||
// accumulation
|
||||
for (int n = 0; n < 256; n++) {
|
||||
accumulation[tile_index][n] = (float) histogram[tile_index][n] / tile_size;
|
||||
if (n != 0) {
|
||||
accumulation[tile_index][n] += accumulation[tile_index][n - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Interpolation
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
PIXEL* p = pixels + x + y * width;
|
||||
// top-left corner
|
||||
if (x <= tile_width / 2 && y <= tile_height / 2) {
|
||||
p->c1 = clamp((int) (accumulation[0][p->c1] * 255));
|
||||
continue;
|
||||
}
|
||||
// top-right corner
|
||||
if (x > width - tile_width / 2 && y <= tile_height / 2) {
|
||||
p->c1 = clamp((int) (accumulation[TILE_BLOCK - 1][p->c1] * 255));
|
||||
continue;
|
||||
}
|
||||
// bottom-left corner
|
||||
if (x <= tile_width / 2 && y > height - tile_height / 2) {
|
||||
p->c1 = clamp((int) (accumulation[TILE_BLOCK * (TILE_BLOCK - 1)][p->c1] * 255));
|
||||
continue;
|
||||
}
|
||||
// bottom-right corner
|
||||
if (x > width - tile_width / 2 && y > height - tile_height / 2) {
|
||||
p->c1 = clamp((int) (accumulation[TILE_BLOCK * TILE_BLOCK - 1][p->c1] * 255));
|
||||
continue;
|
||||
}
|
||||
|
||||
int tile_x_index = (x - tile_width / 2) / tile_width;
|
||||
int tile_y_index = (y - tile_height / 2) / tile_height;
|
||||
int tile_index1 = tile_x_index + TILE_BLOCK * tile_y_index;
|
||||
int tile_index2 = tile_index1 + 1;
|
||||
float u = (float) (x - (tile_x_index * tile_width + tile_width / 2)) / tile_width;
|
||||
// top side and bottom side
|
||||
if (y <= tile_height / 2 || y > height - tile_height / 2) {
|
||||
p->c1 = clamp((int) (255 * (accumulation[tile_index1][p->c1] * (1 - u) + accumulation[tile_index2][p->c1] * u)));
|
||||
continue;
|
||||
}
|
||||
|
||||
int tile_index3 = tile_index1 + TILE_BLOCK;
|
||||
float v = (float) (y - (tile_y_index * tile_height + tile_height / 2)) / tile_height;
|
||||
// left side and right side
|
||||
if (x <= tile_width / 2 || x > width - tile_width / 2) {
|
||||
p->c1 = clamp((int) (255 * (accumulation[tile_index1][p->c1] * (1 - v) + accumulation[tile_index3][p->c1] * v)));
|
||||
continue;
|
||||
}
|
||||
|
||||
int tile_index4 = tile_index2 + TILE_BLOCK;
|
||||
p->c1 = clamp((int) (255 * (
|
||||
accumulation[tile_index1][p->c1] * (1 - u) * (1 - v)
|
||||
+ accumulation[tile_index2][p->c1] * u * (1 - v)
|
||||
+ accumulation[tile_index3][p->c1] * (1 - u) * v
|
||||
+ accumulation[tile_index4][p->c1] * u * v)));
|
||||
}
|
||||
}
|
||||
|
||||
if (to_gray) {
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
PIXEL* p = pixels + i;
|
||||
p->c2 = p->c1;
|
||||
p->c3 = p->c1;
|
||||
}
|
||||
} else {
|
||||
// YUVA to RGBA
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
PIXEL* p = pixels + i;
|
||||
int t1 = (int) (p->c1 + (p->c2 - 128) * -0.00093f + (p->c3 - 128) * 1.401687f);
|
||||
int t2 = (int) (p->c1 + (p->c2 - 128) * -0.3437f + (p->c3 - 128) * -0.71417f);
|
||||
int t3 = (int) (p->c1 + (p->c2 - 128) * 1.77216f + (p->c3 - 128) * 0.00099f);
|
||||
p->c1 = clamp(t1);
|
||||
p->c2 = clamp(t2);
|
||||
p->c3 = clamp(t3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,532 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#include "image.h"
|
||||
#include "image_plain.h"
|
||||
#include "image_jpeg.h"
|
||||
#include "image_png.h"
|
||||
#include "image_gif.h"
|
||||
#include "filter/clahe.h"
|
||||
#include "filter/gray.h"
|
||||
#include "../log.h"
|
||||
|
||||
static int get_format(JNIEnv* env, InputStream* stream)
|
||||
{
|
||||
unsigned char temp[2];
|
||||
int read = read_input_stream(env, stream, temp, 0, 2);
|
||||
|
||||
if (read == 2) {
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
if (temp[0] == IMAGE_JPEG_MAGIC_NUMBER_0 && temp[1] == IMAGE_JPEG_MAGIC_NUMBER_1) {
|
||||
return IMAGE_FORMAT_JPEG;
|
||||
}
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
if (temp[0] == IMAGE_PNG_MAGIC_NUMBER_0 && temp[1] == IMAGE_PNG_MAGIC_NUMBER_1) {
|
||||
return IMAGE_FORMAT_PNG;
|
||||
}
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
if (temp[0] == IMAGE_GIF_MAGIC_NUMBER_0 && temp[1] == IMAGE_GIF_MAGIC_NUMBER_1) {
|
||||
return IMAGE_FORMAT_GIF;
|
||||
}
|
||||
#endif
|
||||
LOGE(MSG("Can't recognize the two magic number: %d, %d"), temp[0], temp[1]);
|
||||
} else {
|
||||
LOGE(MSG("Can't read two magic number from stream"));
|
||||
}
|
||||
|
||||
return IMAGE_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
void* decode(JNIEnv* env, InputStream* stream, bool partially, int* format)
|
||||
{
|
||||
unsigned char magic_numbers[2];
|
||||
PatchHeadInputStream* patch_head_input_stream;
|
||||
|
||||
*format = get_format(env, stream);
|
||||
|
||||
switch (*format) {
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
magic_numbers[0] = IMAGE_JPEG_MAGIC_NUMBER_0;
|
||||
magic_numbers[1] = IMAGE_JPEG_MAGIC_NUMBER_1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
magic_numbers[0] = IMAGE_PNG_MAGIC_NUMBER_0;
|
||||
magic_numbers[1] = IMAGE_PNG_MAGIC_NUMBER_1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
magic_numbers[0] = IMAGE_GIF_MAGIC_NUMBER_0;
|
||||
magic_numbers[1] = IMAGE_GIF_MAGIC_NUMBER_1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), *format);
|
||||
destroy_input_stream(env, &stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
patch_head_input_stream = create_patch_head_input_stream(stream, magic_numbers, 2);
|
||||
if (patch_head_input_stream == NULL){
|
||||
WTF_OM;
|
||||
destroy_input_stream(env, &stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (*format) {
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
return JPEG_decode(env, patch_head_input_stream, partially);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
return PNG_decode(env, patch_head_input_stream, partially);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
return GIF_decode(env, patch_head_input_stream, partially);
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), *format);
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void* create(unsigned int width, unsigned int height, const void* data)
|
||||
{
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
return PLAIN_create(width, height, data);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool complete(JNIEnv* env, void* image, int format)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN:
|
||||
return PLAIN_complete((PLAIN*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
return JPEG_complete((JPEG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
return PNG_complete(env, (PNG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
return GIF_complete(env, (GIF*) image);
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), format);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_completed(void* image, int format)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN:
|
||||
return PLAIN_is_completed((PLAIN*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
return JPEG_is_completed((JPEG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
return PNG_is_completed((PNG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
return GIF_is_completed((GIF*) image);
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), format);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int get_width(void* image, int format)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN:
|
||||
return PLAIN_get_width((PLAIN*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
return JPEG_get_width((JPEG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
return PNG_get_width((PNG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
return GIF_get_width((GIF*) image);
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), format);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int get_height(void* image, int format)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN:
|
||||
return PLAIN_get_height((PLAIN*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
return JPEG_get_height((JPEG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
return PNG_get_height((PNG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
return GIF_get_height((GIF*) image);
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), format);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int get_byte_count(void* image, int format)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN:
|
||||
return PLAIN_get_byte_count((PLAIN*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
return JPEG_get_byte_count((JPEG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
return PNG_get_byte_count((PNG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
return GIF_get_byte_count((GIF*) image);
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), format);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void render(void* image, int format, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN:
|
||||
PLAIN_render((PLAIN*) image, src_x, src_y,
|
||||
dst, dst_w, dst_h, dst_x, dst_y,
|
||||
width, height, fill_blank, default_color);
|
||||
break;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
JPEG_render((JPEG*) image, src_x, src_y,
|
||||
dst, dst_w, dst_h, dst_x, dst_y,
|
||||
width, height, fill_blank, default_color);
|
||||
break;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
PNG_render((PNG*) image, src_x, src_y,
|
||||
dst, dst_w, dst_h, dst_x, dst_y,
|
||||
width, height, fill_blank, default_color);
|
||||
break;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
GIF_render((GIF*) image, src_x, src_y,
|
||||
dst, dst_w, dst_h, dst_x, dst_y,
|
||||
width, height, fill_blank, default_color);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), format);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void advance(void* image, int format)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN:
|
||||
PLAIN_advance((PLAIN*) image);
|
||||
break;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
JPEG_advance((JPEG*) image);
|
||||
break;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
PNG_advance((PNG*) image);
|
||||
break;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
GIF_advance((GIF*) image);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), format);
|
||||
}
|
||||
}
|
||||
|
||||
int get_delay(void* image, int format)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN:
|
||||
return PLAIN_get_delay((PLAIN*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
return JPEG_get_delay((JPEG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
return PNG_get_delay((PNG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
return GIF_get_delay((GIF*) image);
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), format);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int get_frame_count(void* image, int format)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN:
|
||||
return PLAIN_get_frame_count((PLAIN*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
return JPEG_get_frame_count((JPEG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
return PNG_get_frame_count((PNG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
return GIF_get_frame_count((GIF*) image);
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), format);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_opaque(void* image, int format)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN:
|
||||
return PLAIN_is_opaque((PLAIN*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
return JPEG_is_opaque((JPEG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
return PNG_is_opaque((PNG*) image);
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
return GIF_is_opaque((GIF*) image);
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), format);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void get_image_data(void* image, int format, void** pixel, int* width, int* height) {
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN: {
|
||||
PLAIN* plain = (PLAIN*) image;
|
||||
*pixel = PLAIN_get_pixels(plain);
|
||||
*width = PLAIN_get_width(plain);
|
||||
*height = PLAIN_get_height(plain);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG: {
|
||||
JPEG* jpeg = (JPEG*) image;
|
||||
*pixel = JPEG_get_pixels(jpeg);
|
||||
*width = JPEG_get_width(jpeg);
|
||||
*height = JPEG_get_height(jpeg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG: {
|
||||
PNG* png = (PNG*) image;
|
||||
*pixel = PNG_get_pixels(png);
|
||||
*width = PNG_get_width(png);
|
||||
*height = PNG_get_height(png);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF: {
|
||||
GIF* gif = (GIF*) image;
|
||||
*pixel = GIF_get_pixels(gif);
|
||||
*width = GIF_get_width(gif);
|
||||
*height = GIF_get_height(gif);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
*pixel = NULL;
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_gray(void* image, int format, int error)
|
||||
{
|
||||
void* pixel = NULL;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
get_image_data(image, format, &pixel, &width, &height);
|
||||
|
||||
if (pixel == NULL || width == 0 || height == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IMAGE_is_gray(pixel, width, height, error);
|
||||
}
|
||||
|
||||
void clahe(void* image, int format, bool to_gray)
|
||||
{
|
||||
void* pixel = NULL;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
get_image_data(image, format, &pixel, &width, &height);
|
||||
|
||||
if (pixel == NULL || width == 0 || height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
IMAGE_clahe(pixel, width, height, to_gray);
|
||||
}
|
||||
|
||||
void recycle(JNIEnv *env, void* image, int format)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
case IMAGE_FORMAT_PLAIN:
|
||||
PLAIN_recycle((PLAIN*) image);
|
||||
break;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
JPEG_recycle((JPEG*) image);
|
||||
break;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
PNG_recycle(env, (PNG*) image);
|
||||
break;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
GIF_recycle(env, (GIF*) image);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
LOGE(MSG("Can't detect format %d"), format);
|
||||
}
|
||||
}
|
||||
|
||||
int get_supported_formats(int *formats)
|
||||
{
|
||||
int i = 0;
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
formats[i++] = IMAGE_FORMAT_JPEG;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
formats[i++] = IMAGE_FORMAT_PNG;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
formats[i++] = IMAGE_FORMAT_GIF;
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
|
||||
const char *get_decoder_description(int format)
|
||||
{
|
||||
switch (format) {
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
case IMAGE_FORMAT_JPEG:
|
||||
return IMAGE_JPEG_DECODER_DESCRIPTION;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
case IMAGE_FORMAT_PNG:
|
||||
return IMAGE_PNG_DECODER_DESCRIPTION;
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
case IMAGE_FORMAT_GIF:
|
||||
return IMAGE_GIF_DECODER_DESCRIPTION;
|
||||
#endif
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#ifndef IMAGE_IMAGE_H
|
||||
#define IMAGE_IMAGE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "input_stream.h"
|
||||
|
||||
#define IMAGE_FORMAT_UNKNOWN -1
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
#define IMAGE_FORMAT_PLAIN 0
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
#define IMAGE_FORMAT_JPEG 1
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
#define IMAGE_FORMAT_PNG 2
|
||||
#endif
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
#define IMAGE_FORMAT_GIF 3
|
||||
#endif
|
||||
|
||||
#define IMAGE_MAX_SUPPORTED_FORMAT_COUNT 3
|
||||
|
||||
void* decode(JNIEnv* env, InputStream* stream, bool partially, int* format);
|
||||
void* create(unsigned int width, unsigned int height, const void* data);
|
||||
bool complete(JNIEnv* env, void* image, int format);
|
||||
bool is_completed(void* image, int format);
|
||||
int get_width(void* image, int format);
|
||||
int get_height(void* image, int format);
|
||||
int get_byte_count(void* image, int format);
|
||||
void render(void* image, int format, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color);
|
||||
void advance(void* image, int format);
|
||||
int get_delay(void* image, int format);
|
||||
int get_frame_count(void* image, int format);
|
||||
bool is_opaque(void* image, int format);
|
||||
bool is_gray(void* image, int format, int error);
|
||||
void clahe(void* image, int format, bool to_gray);
|
||||
void recycle(JNIEnv *env, void* image, int format);
|
||||
int get_supported_formats(int *);
|
||||
const char *get_decoder_description(int);
|
||||
|
||||
#endif //IMAGE_IMAGE_H
|
||||
@@ -1,558 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "image_gif.h"
|
||||
#include "image_utils.h"
|
||||
#include "java_wrapper.h"
|
||||
#include "../log.h"
|
||||
#include "../utils.h"
|
||||
|
||||
static int error_code = 0;
|
||||
|
||||
typedef struct {
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
unsigned char alpha;
|
||||
} RGBA;
|
||||
|
||||
static int custom_read_fun(GifFileType* gif, GifByteType* bytes, int size) {
|
||||
bool attach;
|
||||
int read;
|
||||
PatchHeadInputStream* patch_head_input_stream = gif->UserData;
|
||||
JNIEnv *env = obtain_env(&attach);
|
||||
|
||||
if (env == NULL) {
|
||||
LOGE(MSG("Can't get JNIEnv"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = read_patch_head_input_stream(env, patch_head_input_stream, bytes, 0, (size_t) size);
|
||||
|
||||
if (attach) {
|
||||
release_env();
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
static void generate_prepare(GIF_FRAME_INFO* frame_info_array, int count)
|
||||
{
|
||||
int disposal = 0xff;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++){
|
||||
GIF_FRAME_INFO* frame_info = frame_info_array + i;
|
||||
|
||||
switch (disposal) {
|
||||
case DISPOSAL_UNSPECIFIED:
|
||||
case DISPOSE_DO_NOT:
|
||||
frame_info->prepare = IMAGE_GIF_PREPARE_NONE;
|
||||
break;
|
||||
case DISPOSE_BACKGROUND:
|
||||
frame_info->prepare = IMAGE_GIF_PREPARE_BACKGROUND;
|
||||
break;
|
||||
case DISPOSE_PREVIOUS:
|
||||
frame_info->prepare = IMAGE_GIF_PREPARE_USE_BACKUP;
|
||||
break;
|
||||
default:
|
||||
frame_info->prepare = IMAGE_GIF_PREPARE_BACKGROUND;
|
||||
break;
|
||||
}
|
||||
|
||||
disposal = frame_info->disposal;
|
||||
}
|
||||
}
|
||||
|
||||
static void read_gcb(GifFileType* gif_file, int index, GIF_FRAME_INFO* frame_info)
|
||||
{
|
||||
GraphicsControlBlock gcb;
|
||||
if (DGifSavedExtensionToGCB(gif_file, index, &gcb) == GIF_OK) {
|
||||
frame_info->tran = gcb.TransparentColor;
|
||||
frame_info->delay = gcb.DelayTime * 10;
|
||||
frame_info->disposal = gcb.DisposalMode;
|
||||
frame_info->prepare = IMAGE_GIF_PREPARE_UNKNOWN;
|
||||
} else {
|
||||
frame_info->tran = -1;
|
||||
frame_info->delay = 0;
|
||||
frame_info->disposal = DISPOSE_DO_NOT;
|
||||
frame_info->prepare = IMAGE_GIF_PREPARE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void fix_gif_file(GifFileType* gif_file) {
|
||||
if (gif_file->ImageCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
SavedImage last_image = gif_file->SavedImages[gif_file->ImageCount - 1];
|
||||
// If RasterBits is NULL, discard this frame
|
||||
if (last_image.RasterBits == NULL) {
|
||||
gif_file->ImageCount--;
|
||||
// Free last image
|
||||
if (last_image.ImageDesc.ColorMap != NULL) {
|
||||
GifFreeMapObject(last_image.ImageDesc.ColorMap);
|
||||
last_image.ImageDesc.ColorMap = NULL;
|
||||
}
|
||||
GifFreeExtensions(&last_image.ExtensionBlockCount, &last_image.ExtensionBlocks);
|
||||
}
|
||||
}
|
||||
|
||||
void* GIF_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially)
|
||||
{
|
||||
GIF* gif = NULL;
|
||||
GifFileType* gif_file = NULL;
|
||||
void* buffer = NULL;
|
||||
void*shown_buffer = NULL;
|
||||
GIF_FRAME_INFO* frame_info_array = NULL;
|
||||
int i;
|
||||
|
||||
gif = (GIF*) malloc(sizeof(GIF));
|
||||
if (gif == NULL) {
|
||||
WTF_OM;
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Open
|
||||
gif_file = DGifOpen(patch_head_input_stream, &custom_read_fun, &error_code);
|
||||
if (gif_file == NULL) {
|
||||
WTF_OM;
|
||||
free(gif);
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Buffer
|
||||
buffer = malloc(gif_file->SWidth * gif_file->SHeight * sizeof(RGBA));
|
||||
shown_buffer = malloc(gif_file->SWidth * gif_file->SHeight * sizeof(RGBA));
|
||||
if (buffer == NULL || shown_buffer == NULL) {
|
||||
WTF_OM;
|
||||
free(buffer);
|
||||
free(shown_buffer);
|
||||
DGifCloseFile(gif_file, &error_code);
|
||||
free(gif);
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (partially) {
|
||||
// Glance
|
||||
if (DGifGlance(gif_file) != GIF_OK) {
|
||||
LOGE(MSG("GIF error code %d"), error_code);
|
||||
DGifCloseFile(gif_file, &error_code);
|
||||
free(buffer);
|
||||
free(gif);
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Frame info
|
||||
frame_info_array = (GIF_FRAME_INFO*) malloc(sizeof(GIF_FRAME_INFO));
|
||||
if (frame_info_array == NULL) {
|
||||
WTF_OM;
|
||||
DGifCloseFile(gif_file, &error_code);
|
||||
free(buffer);
|
||||
free(gif);
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read gcb
|
||||
read_gcb(gif_file, 0, frame_info_array);
|
||||
|
||||
gif->partially = true;
|
||||
gif->patch_head_input_stream = patch_head_input_stream;
|
||||
} else {
|
||||
// Slurp
|
||||
if (DGifSlurp(gif_file) == GIF_ERROR) {
|
||||
fix_gif_file(gif_file);
|
||||
}
|
||||
if (gif_file->ImageCount <= 0) {
|
||||
LOGE(MSG("No frame"));
|
||||
DGifCloseFile(gif_file, &error_code);
|
||||
free(buffer);
|
||||
free(gif);
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Frame info
|
||||
frame_info_array = (GIF_FRAME_INFO*) malloc(gif_file->ImageCount * sizeof(GIF_FRAME_INFO));
|
||||
if (frame_info_array == NULL) {
|
||||
WTF_OM;
|
||||
DGifCloseFile(gif_file, &error_code);
|
||||
free(buffer);
|
||||
free(gif);
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read gcb
|
||||
for (i = 0; i < gif_file->ImageCount; i++) {
|
||||
read_gcb(gif_file, i, frame_info_array + i);
|
||||
}
|
||||
|
||||
// Generate prepare
|
||||
generate_prepare(frame_info_array, gif_file->ImageCount);
|
||||
|
||||
// Close input stream
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
|
||||
gif->partially = false;
|
||||
gif->patch_head_input_stream = NULL;
|
||||
}
|
||||
|
||||
gif->gif_file = gif_file;
|
||||
gif->frame_info_array = frame_info_array;
|
||||
gif->buffer = buffer;
|
||||
gif->buffer_index = -1;
|
||||
gif->backup = NULL;
|
||||
gif->shown_buffer = shown_buffer;
|
||||
|
||||
GIF_advance(gif);
|
||||
|
||||
return gif;
|
||||
}
|
||||
|
||||
bool GIF_complete(JNIEnv* env, GIF* gif)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!gif->partially) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (gif->gif_file == NULL || gif->patch_head_input_stream == NULL) {
|
||||
LOGE(MSG("Some stuff is NULL"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DGifSlurp(gif->gif_file) == GIF_ERROR) {
|
||||
fix_gif_file(gif->gif_file);
|
||||
}
|
||||
|
||||
// Close input stream
|
||||
close_patch_head_input_stream(env, gif->patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &gif->patch_head_input_stream);
|
||||
gif->patch_head_input_stream = NULL;
|
||||
|
||||
gif->partially = false;
|
||||
|
||||
gif->frame_info_array = (GIF_FRAME_INFO*) realloc(gif->frame_info_array,
|
||||
gif->gif_file->ImageCount * sizeof(GIF_FRAME_INFO));
|
||||
if (gif->frame_info_array == NULL) {
|
||||
WTF_OM;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read gcb
|
||||
for (i = 0; i < gif->gif_file->ImageCount; i++) {
|
||||
read_gcb(gif->gif_file, i, gif->frame_info_array + i);
|
||||
}
|
||||
|
||||
// Generate prepare
|
||||
generate_prepare(gif->frame_info_array, gif->gif_file->ImageCount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GIF_is_completed(GIF* gif)
|
||||
{
|
||||
return !gif->partially;
|
||||
}
|
||||
|
||||
void* GIF_get_pixels(GIF* gif)
|
||||
{
|
||||
if (!gif->partially && GIF_get_frame_count(gif) == 1) {
|
||||
return gif->buffer;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int GIF_get_width(GIF* gif)
|
||||
{
|
||||
return gif->gif_file->SWidth;
|
||||
}
|
||||
|
||||
int GIF_get_height(GIF* gif)
|
||||
{
|
||||
return gif->gif_file->SHeight;
|
||||
}
|
||||
|
||||
int GIF_get_byte_count(GIF* gif)
|
||||
{
|
||||
int i;
|
||||
SavedImage saved_image;
|
||||
int size = 0;
|
||||
// Add buffer size
|
||||
if (gif->buffer != NULL) {
|
||||
size += gif->gif_file->SWidth * gif->gif_file->SHeight * 4;
|
||||
}
|
||||
// Add backup size
|
||||
if (gif->backup != NULL) {
|
||||
size += gif->gif_file->SWidth * gif->gif_file->SHeight * 4;
|
||||
}
|
||||
// Add shown buffer size
|
||||
if (gif->shown_buffer != NULL) {
|
||||
size += gif->gif_file->SWidth * gif->gif_file->SHeight * 4;
|
||||
}
|
||||
// Add frames size
|
||||
if (gif->gif_file->SavedImages != NULL) {
|
||||
for (i = 0; i < gif->gif_file->ImageCount; i++) {
|
||||
saved_image = gif->gif_file->SavedImages[i];
|
||||
if (saved_image.RasterBits != NULL) {
|
||||
size += saved_image.ImageDesc.Width * saved_image.ImageDesc.Height * 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void GIF_render(GIF* gif, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color)
|
||||
{
|
||||
copy_pixels(gif->shown_buffer, gif->gif_file->SWidth, gif->gif_file->SHeight, src_x, src_y,
|
||||
dst, dst_w, dst_h, dst_x, dst_y,
|
||||
width, height, fill_blank, default_color);
|
||||
}
|
||||
|
||||
static void backup(GIF* gif)
|
||||
{
|
||||
if (gif->backup == NULL) {
|
||||
gif->backup = (unsigned char*) malloc((size_t) (gif->gif_file->SWidth * gif->gif_file->SHeight * 4));
|
||||
if (gif->backup == NULL) {
|
||||
WTF_OM;
|
||||
return;
|
||||
}
|
||||
}
|
||||
memcpy(gif->backup, gif->buffer, (size_t) (gif->gif_file->SWidth * gif->gif_file->SHeight * 4));
|
||||
}
|
||||
|
||||
static void restore(GIF* gif)
|
||||
{
|
||||
if (gif->backup == NULL) {
|
||||
LOGE(MSG("Backup is NULL"));
|
||||
} else {
|
||||
memcpy(gif->buffer, gif->backup, (size_t) (gif->gif_file->SWidth * gif->gif_file->SHeight * 4));
|
||||
}
|
||||
}
|
||||
|
||||
static void switch_buffer_backup(GIF* gif)
|
||||
{
|
||||
unsigned char* temp;
|
||||
|
||||
if (gif->backup == NULL) {
|
||||
backup(gif);
|
||||
} else {
|
||||
temp = gif->buffer;
|
||||
gif->buffer = gif->backup;
|
||||
gif->backup = temp;
|
||||
}
|
||||
}
|
||||
|
||||
static void clear(RGBA* pixels, int num, RGBA color) {
|
||||
RGBA* ptr = pixels;
|
||||
int i;
|
||||
for (i = 0; i < num; i++) {
|
||||
*(ptr++) = color;
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_color_from_table(const ColorMapObject* cmap, int index,
|
||||
RGBA* color) {
|
||||
if (cmap == NULL || index < 0 || index >= cmap->ColorCount) {
|
||||
return false;
|
||||
} else {
|
||||
GifColorType gct = cmap->Colors[index];
|
||||
color->red = gct.Red;
|
||||
color->green = gct.Green;
|
||||
color->blue = gct.Blue;
|
||||
color->alpha = 0xff;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_bg(GifFileType* gif_file, void* pixels)
|
||||
{
|
||||
RGBA color;
|
||||
if (!get_color_from_table(gif_file->SColorMap, gif_file->SBackGroundColor, &color)) {
|
||||
color.red = 0x00;
|
||||
color.green = 0x00;
|
||||
color.blue = 0x00;
|
||||
color.alpha = 0x00;
|
||||
}
|
||||
clear(pixels, gif_file->SWidth * gif_file->SHeight, color);
|
||||
}
|
||||
|
||||
static void copy_line(GifByteType* src, RGBA* dst,
|
||||
const ColorMapObject* cmap, int tran, int len)
|
||||
{
|
||||
for (; len > 0; len--, src++, dst++) {
|
||||
int index = *src;
|
||||
if (tran == -1 || index != tran) {
|
||||
get_color_from_table(cmap, index, dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void blend(GifFileType* gif_file, int index, void* pixels, int tran)
|
||||
{
|
||||
int width = gif_file->SWidth;
|
||||
int height = gif_file->SHeight;
|
||||
SavedImage cur = gif_file->SavedImages[index];
|
||||
GifImageDesc desc = cur.ImageDesc;
|
||||
int copy_width = MIN(width - desc.Left, desc.Width);
|
||||
int copy_height = MIN(height - desc.Top, desc.Height);
|
||||
ColorMapObject *cmap = desc.ColorMap;
|
||||
GifByteType* src = cur.RasterBits;
|
||||
RGBA* dst = pixels;
|
||||
GifByteType* src_ptr;
|
||||
RGBA* dst_ptr;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
if (cmap == NULL) {
|
||||
cmap = gif_file->SColorMap;
|
||||
}
|
||||
if (cmap != NULL) {
|
||||
for (i = 0; i < copy_height; i++) {
|
||||
src_ptr = src + (i * desc.Width);
|
||||
dst_ptr = dst + ((desc.Top + i) * width + desc.Left);
|
||||
len = (size_t) copy_width;
|
||||
copy_line(src_ptr, dst_ptr, cmap, tran, len);
|
||||
}
|
||||
} else {
|
||||
LOGW(MSG("Can't find color map"));
|
||||
}
|
||||
}
|
||||
|
||||
void GIF_advance(GIF* gif)
|
||||
{
|
||||
int index;
|
||||
GIF_FRAME_INFO frame_info;
|
||||
|
||||
index = (gif->buffer_index + 1) % gif->gif_file->ImageCount;
|
||||
if (index != 0 && gif->partially) {
|
||||
LOGE(MSG("The png is only decoded partially. Only the first frame can be shown."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (gif->frame_info_array == NULL) {
|
||||
frame_info.tran = -1;
|
||||
frame_info.disposal = DISPOSE_DO_NOT;
|
||||
frame_info.delay = 0;
|
||||
frame_info.prepare = IMAGE_GIF_PREPARE_BACKGROUND;
|
||||
} else {
|
||||
memcpy(&frame_info, gif->frame_info_array + index, sizeof(GIF_FRAME_INFO));
|
||||
}
|
||||
|
||||
if (frame_info.disposal == DISPOSE_PREVIOUS && frame_info.prepare == IMAGE_GIF_PREPARE_USE_BACKUP) {
|
||||
switch_buffer_backup(gif);
|
||||
} else {
|
||||
// Backup
|
||||
if (frame_info.disposal == DISPOSE_PREVIOUS) {
|
||||
backup(gif);
|
||||
}
|
||||
|
||||
// Prepare
|
||||
switch (frame_info.prepare) {
|
||||
case IMAGE_GIF_PREPARE_NONE:
|
||||
// Do nothing
|
||||
break;
|
||||
default:
|
||||
case IMAGE_GIF_PREPARE_BACKGROUND:
|
||||
// Set bg
|
||||
clear_bg(gif->gif_file, gif->buffer);
|
||||
break;
|
||||
case IMAGE_GIF_PREPARE_USE_BACKUP:
|
||||
restore(gif);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
blend(gif->gif_file, index, gif->buffer, frame_info.tran);
|
||||
|
||||
// Copy to shown buffer
|
||||
memcpy(gif->shown_buffer, gif->buffer, (size_t) (gif->gif_file->SWidth * gif->gif_file->SHeight * 4));
|
||||
|
||||
gif->buffer_index = index;
|
||||
}
|
||||
|
||||
int GIF_get_delay(GIF* gif)
|
||||
{
|
||||
if (gif->frame_info_array == NULL) {
|
||||
return 0;
|
||||
} else {
|
||||
return gif->frame_info_array[gif->buffer_index].delay;
|
||||
}
|
||||
}
|
||||
|
||||
int GIF_get_frame_count(GIF* gif)
|
||||
{
|
||||
return gif->gif_file->ImageCount;
|
||||
}
|
||||
|
||||
bool GIF_is_opaque(GIF* gif)
|
||||
{
|
||||
return gif->frame_info_array->tran < 0;
|
||||
}
|
||||
|
||||
void GIF_recycle(JNIEnv* env, GIF* gif)
|
||||
{
|
||||
DGifCloseFile(gif->gif_file, &error_code);
|
||||
gif->gif_file = NULL;
|
||||
|
||||
free(gif->frame_info_array);
|
||||
gif->frame_info_array = NULL;
|
||||
|
||||
free(gif->buffer);
|
||||
gif->buffer = NULL;
|
||||
|
||||
free(gif->backup);
|
||||
gif->backup = NULL;
|
||||
|
||||
free(gif->shown_buffer);
|
||||
gif->shown_buffer = NULL;
|
||||
|
||||
if (gif->patch_head_input_stream != NULL) {
|
||||
close_patch_head_input_stream(env, gif->patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &gif->patch_head_input_stream);
|
||||
gif->patch_head_input_stream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // IMAGE_SUPPORT_GIF
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#ifndef IMAGE_IMAGE_GIF_H
|
||||
#define IMAGE_IMAGE_GIF_H
|
||||
|
||||
#include "config.h"
|
||||
#ifdef IMAGE_SUPPORT_GIF
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "patch_head_input_stream.h"
|
||||
#include "gif_lib.h"
|
||||
#include "../utils.h"
|
||||
|
||||
#define IMAGE_GIF_DECODER_DESCRIPTION ("giflib " MAKESTRING(STRINGIZE, GIFLIB_MAJOR) "." \
|
||||
MAKESTRING(STRINGIZE, GIFLIB_MINOR) "." \
|
||||
MAKESTRING(STRINGIZE, GIFLIB_RELEASE))
|
||||
|
||||
#define IMAGE_GIF_MAGIC_NUMBER_0 0x47
|
||||
#define IMAGE_GIF_MAGIC_NUMBER_1 0x49
|
||||
|
||||
#define IMAGE_GIF_PREPARE_UNKNOWN 0x00
|
||||
#define IMAGE_GIF_PREPARE_NONE 0x01
|
||||
#define IMAGE_GIF_PREPARE_BACKGROUND 0x02
|
||||
#define IMAGE_GIF_PREPARE_USE_BACKUP 0x03
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int tran;
|
||||
int disposal;
|
||||
int delay;
|
||||
int prepare;
|
||||
} GIF_FRAME_INFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GifFileType* gif_file;
|
||||
GIF_FRAME_INFO* frame_info_array;
|
||||
void* buffer;
|
||||
int buffer_index;
|
||||
void* backup;
|
||||
bool partially;
|
||||
// Use extra buffer to avoid blink
|
||||
void* shown_buffer;
|
||||
PatchHeadInputStream* patch_head_input_stream;
|
||||
} GIF;
|
||||
|
||||
void* GIF_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially);
|
||||
bool GIF_complete(JNIEnv* env, GIF* gif);
|
||||
bool GIF_is_completed(GIF* gif);
|
||||
void* GIF_get_pixels(GIF* gif);
|
||||
int GIF_get_width(GIF* gif);
|
||||
int GIF_get_height(GIF* gif);
|
||||
int GIF_get_byte_count(GIF* gif);
|
||||
void GIF_render(GIF* gif, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color);
|
||||
void GIF_advance(GIF* gif);
|
||||
int GIF_get_delay(GIF* gif);
|
||||
int GIF_get_frame_count(GIF* gif);
|
||||
bool GIF_is_opaque(GIF* gif);
|
||||
void GIF_recycle(JNIEnv* env, GIF* gif);
|
||||
|
||||
#endif // IMAGE_SUPPORT_GIF
|
||||
|
||||
#endif // IMAGE_IMAGE_GIF_H
|
||||
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 1/3/2016.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "image_jpeg.h"
|
||||
#include "image_utils.h"
|
||||
#include "java_wrapper.h"
|
||||
#include "../log.h"
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub;
|
||||
jmp_buf setjmp_buffer;
|
||||
};
|
||||
|
||||
typedef struct my_error_mgr * my_error_ptr;
|
||||
|
||||
static char emsg[JMSG_LENGTH_MAX];
|
||||
|
||||
static void my_error_exit(j_common_ptr cinfo)
|
||||
{
|
||||
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
||||
(*cinfo->err->format_message)(cinfo, emsg);
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
static size_t custom_read(void * custom_stuff, unsigned char * buffer, size_t size)
|
||||
{
|
||||
bool attach;
|
||||
size_t read;
|
||||
PatchHeadInputStream* patch_head_input_stream = custom_stuff;
|
||||
JNIEnv *env = obtain_env(&attach);
|
||||
|
||||
if (env == NULL) {
|
||||
LOGE(MSG("Can't get JNIEnv"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = read_patch_head_input_stream(env, patch_head_input_stream, buffer, 0, size);
|
||||
|
||||
if (attach) {
|
||||
release_env();
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
void* JPEG_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially)
|
||||
{
|
||||
JPEG* jpeg = NULL;
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct my_error_mgr jerr;
|
||||
unsigned char* buffer = NULL;
|
||||
size_t stride;
|
||||
unsigned char* line_buffer_array[3];
|
||||
int read_lines;
|
||||
|
||||
jpeg = (JPEG*) malloc(sizeof(JPEG));
|
||||
if (jpeg == NULL) {
|
||||
WTF_OM;
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Init
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
LOGE(MSG("%s"), emsg);
|
||||
free(jpeg);
|
||||
free(buffer);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
jpeg_create_decompress(&cinfo);
|
||||
jpeg_custom_src(&cinfo, &custom_read, patch_head_input_stream);
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
|
||||
// Start decompress
|
||||
cinfo.out_color_space = JCS_EXT_RGBA;
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
stride = cinfo.output_components * cinfo.output_width;
|
||||
buffer = malloc(stride * cinfo.output_height);
|
||||
if (buffer == NULL) {
|
||||
free(jpeg);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy buffer
|
||||
line_buffer_array[0] = buffer;
|
||||
line_buffer_array[1] = line_buffer_array[0] + stride;
|
||||
line_buffer_array[2] = line_buffer_array[1] + stride;
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
read_lines = jpeg_read_scanlines(&cinfo, line_buffer_array, 3);
|
||||
line_buffer_array[0] += stride * read_lines;
|
||||
line_buffer_array[1] = line_buffer_array[0] + stride;
|
||||
line_buffer_array[2] = line_buffer_array[1] + stride;
|
||||
}
|
||||
|
||||
// Finish decompress
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
// Close stream
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
|
||||
// Fill jpeg
|
||||
jpeg->width = cinfo.output_width;
|
||||
jpeg->height = cinfo.output_height;
|
||||
jpeg->buffer = buffer;
|
||||
|
||||
return jpeg;
|
||||
}
|
||||
|
||||
bool JPEG_complete(JPEG* jpeg)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JPEG_is_completed(JPEG* jpeg)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void* JPEG_get_pixels(JPEG* jpeg)
|
||||
{
|
||||
return jpeg->buffer;
|
||||
}
|
||||
|
||||
int JPEG_get_width(JPEG* jpeg)
|
||||
{
|
||||
return jpeg->width;
|
||||
}
|
||||
|
||||
int JPEG_get_height(JPEG* jpeg)
|
||||
{
|
||||
return jpeg->height;
|
||||
}
|
||||
|
||||
int JPEG_get_byte_count(JPEG* jpeg)
|
||||
{
|
||||
return jpeg->width * jpeg->height * 4;
|
||||
}
|
||||
|
||||
void JPEG_render(JPEG* jpeg, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color)
|
||||
{
|
||||
copy_pixels(jpeg->buffer, jpeg->width, jpeg->height, src_x, src_y,
|
||||
dst, dst_w, dst_h, dst_x, dst_y,
|
||||
width, height, fill_blank, default_color);
|
||||
}
|
||||
|
||||
void JPEG_advance(JPEG* jpeg)
|
||||
{
|
||||
}
|
||||
|
||||
int JPEG_get_delay(JPEG* jpeg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int JPEG_get_frame_count(JPEG* jpeg)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool JPEG_is_opaque(JPEG* jpeg)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void JPEG_recycle(JPEG* jpeg)
|
||||
{
|
||||
free(jpeg->buffer);
|
||||
jpeg->buffer = NULL;
|
||||
|
||||
free(jpeg);
|
||||
}
|
||||
|
||||
#endif // IMAGE_SUPPORT_JPEG
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 1/3/2016.
|
||||
//
|
||||
|
||||
#ifndef IMAGE_IMAGE_JPEG_H
|
||||
#define IMAGE_IMAGE_JPEG_H
|
||||
|
||||
#include "config.h"
|
||||
#ifdef IMAGE_SUPPORT_JPEG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "jpeglib.h"
|
||||
#include "patch_head_input_stream.h"
|
||||
#include "../utils.h"
|
||||
|
||||
#define IMAGE_JPEG_DECODER_DESCRIPTION ("libjpeg-turbo " MAKESTRING(STRINGIZE, LIBJPEG_TURBO_VERSION))
|
||||
|
||||
#define IMAGE_JPEG_MAGIC_NUMBER_0 0xFF
|
||||
#define IMAGE_JPEG_MAGIC_NUMBER_1 0xD8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
void* buffer;
|
||||
} JPEG;
|
||||
|
||||
void* JPEG_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially);
|
||||
bool JPEG_complete(JPEG* jpeg);
|
||||
bool JPEG_is_completed(JPEG* jpeg);
|
||||
void* JPEG_get_pixels(JPEG* jpeg);
|
||||
int JPEG_get_width(JPEG* jpeg);
|
||||
int JPEG_get_height(JPEG* jpeg);
|
||||
int JPEG_get_byte_count(JPEG* jpeg);
|
||||
void JPEG_render(JPEG* jpeg, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color);
|
||||
void JPEG_advance(JPEG* jpeg);
|
||||
int JPEG_get_delay(JPEG* jpeg);
|
||||
int JPEG_get_frame_count(JPEG* jpeg);
|
||||
bool JPEG_is_opaque(JPEG* jpeg);
|
||||
void JPEG_recycle(JPEG* jpeg);
|
||||
|
||||
#endif // IMAGE_SUPPORT_JPEG
|
||||
|
||||
#endif // IMAGE_IMAGE_JPEG_H
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 5/3/2016.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "image_plain.h"
|
||||
#include "image_utils.h"
|
||||
#include "../log.h"
|
||||
|
||||
void* PLAIN_create(unsigned int width, unsigned int height, const void* data)
|
||||
{
|
||||
PLAIN* plain = NULL;
|
||||
void* buffer = NULL;
|
||||
size_t length;
|
||||
|
||||
plain = (PLAIN*) malloc(sizeof(PLAIN));
|
||||
if (plain == NULL) {
|
||||
WTF_OM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
length = (size_t) (width * height * 4);
|
||||
|
||||
buffer = malloc(length);
|
||||
if (buffer == NULL) {
|
||||
WTF_OM;
|
||||
free(plain);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(buffer, data, length);
|
||||
|
||||
plain->width = width;
|
||||
plain->height = height;
|
||||
plain->buffer = buffer;
|
||||
|
||||
return plain;
|
||||
}
|
||||
|
||||
bool PLAIN_complete(PLAIN* plain)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PLAIN_is_completed(PLAIN* plain)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void* PLAIN_get_pixels(PLAIN* plain)
|
||||
{
|
||||
return plain->buffer;
|
||||
}
|
||||
|
||||
int PLAIN_get_width(PLAIN* plain)
|
||||
{
|
||||
return plain->width;
|
||||
}
|
||||
|
||||
int PLAIN_get_height(PLAIN* plain)
|
||||
{
|
||||
return plain->height;
|
||||
}
|
||||
|
||||
int PLAIN_get_byte_count(PLAIN* plain)
|
||||
{
|
||||
return plain->width * plain->height * 4;
|
||||
}
|
||||
|
||||
void PLAIN_render(PLAIN* plain, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color)
|
||||
{
|
||||
copy_pixels(plain->buffer, plain->width, plain->height, src_x, src_y,
|
||||
dst, dst_w, dst_h, dst_x, dst_y,
|
||||
width, height, fill_blank, default_color);
|
||||
}
|
||||
|
||||
void PLAIN_advance(PLAIN* plain)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int PLAIN_get_delay(PLAIN* plain)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PLAIN_get_frame_count(PLAIN* plain)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool PLAIN_is_opaque(PLAIN* plain)
|
||||
{
|
||||
// TODO Check plain all alpha
|
||||
return false;
|
||||
}
|
||||
|
||||
void PLAIN_recycle(PLAIN* plain)
|
||||
{
|
||||
free(plain->buffer);
|
||||
plain->buffer = NULL;
|
||||
|
||||
free(plain);
|
||||
}
|
||||
|
||||
#endif // IMAGE_SUPPORT_PLAIN
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 5/3/2016.
|
||||
//
|
||||
|
||||
#ifndef IMAGE_IMAGE_PLAIN_H
|
||||
#define IMAGE_IMAGE_PLAIN_H
|
||||
|
||||
#include "config.h"
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "patch_head_input_stream.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
void* buffer;
|
||||
} PLAIN;
|
||||
|
||||
void* PLAIN_create(unsigned int width, unsigned int height, const void* data);
|
||||
bool PLAIN_complete(PLAIN* plain);
|
||||
bool PLAIN_is_completed(PLAIN* plain);
|
||||
void* PLAIN_get_pixels(PLAIN* plain);
|
||||
int PLAIN_get_width(PLAIN* plain);
|
||||
int PLAIN_get_height(PLAIN* plain);
|
||||
int PLAIN_get_byte_count(PLAIN* plain);
|
||||
void PLAIN_render(PLAIN* plain, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color);
|
||||
void PLAIN_advance(PLAIN* plain);
|
||||
int PLAIN_get_delay(PLAIN* plain);
|
||||
int PLAIN_get_frame_count(PLAIN* plain);
|
||||
bool PLAIN_is_opaque(PLAIN* plain);
|
||||
void PLAIN_recycle(PLAIN* plain);
|
||||
|
||||
#endif // IMAGE_SUPPORT_PLAIN
|
||||
|
||||
#endif // IMAGE_IMAGE_PLAIN_H
|
||||
@@ -1,642 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../log.h"
|
||||
#include "../utils.h"
|
||||
#include "image_png.h"
|
||||
#include "image_utils.h"
|
||||
#include "java_wrapper.h"
|
||||
|
||||
static void user_read_fn(png_structp png_ptr,
|
||||
png_bytep data, png_size_t length)
|
||||
{
|
||||
bool attach;
|
||||
PatchHeadInputStream* patch_head_input_stream = png_get_io_ptr(png_ptr);
|
||||
JNIEnv *env = obtain_env(&attach);
|
||||
|
||||
if (env == NULL) {
|
||||
LOGE(MSG("Can't get JNIEnv"));
|
||||
}
|
||||
|
||||
read_patch_head_input_stream(env, patch_head_input_stream, data, 0, length);
|
||||
|
||||
if (attach) {
|
||||
release_env();
|
||||
}
|
||||
}
|
||||
|
||||
static void user_error_fn(png_structp png_ptr,
|
||||
png_const_charp error_msg)
|
||||
{
|
||||
LOGE(MSG("%s"), error_msg);
|
||||
}
|
||||
|
||||
static void user_warn_fn(png_structp png_ptr,
|
||||
png_const_charp error_msg)
|
||||
{
|
||||
LOGW(MSG("%s"), error_msg);
|
||||
}
|
||||
|
||||
static void free_frame_info_array(PNG_FRAME_INFO* frame_info_array, unsigned int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (frame_info_array == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
PNG_FRAME_INFO* frame_info = frame_info_array + i;
|
||||
free(frame_info->buffer);
|
||||
frame_info->buffer = NULL;
|
||||
}
|
||||
free(frame_info_array);
|
||||
}
|
||||
|
||||
static bool read_image(png_structp png_ptr, unsigned char* buffer, unsigned int width, unsigned int height)
|
||||
{
|
||||
int i;
|
||||
unsigned char** line_buffer_ptr_array = (unsigned char**) malloc(height * sizeof(unsigned char*));
|
||||
if (line_buffer_ptr_array == NULL) {
|
||||
WTF_OM;
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < height; i++) {
|
||||
line_buffer_ptr_array[i] = buffer + (width * i * 4);
|
||||
}
|
||||
png_read_image(png_ptr, line_buffer_ptr_array);
|
||||
free(line_buffer_ptr_array);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void read_frame(png_structp png_ptr, png_infop info_ptr, PNG_FRAME_INFO* frame_info)
|
||||
{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int offset_x;
|
||||
unsigned int offset_y;
|
||||
unsigned short delay_num;
|
||||
unsigned short delay_den;
|
||||
unsigned char dop;
|
||||
unsigned char bop;
|
||||
unsigned int delay;
|
||||
unsigned char* buffer = NULL;
|
||||
|
||||
png_read_frame_head(png_ptr, info_ptr);
|
||||
png_get_next_frame_fcTL(png_ptr, info_ptr, &width, &height, &offset_x, &offset_y, &delay_num, &delay_den, &dop, &bop);
|
||||
|
||||
delay = 1000u * delay_num / delay_den;
|
||||
|
||||
frame_info->width = width;
|
||||
frame_info->height = height;
|
||||
frame_info->offset_x = offset_x;
|
||||
frame_info->offset_y = offset_y;
|
||||
frame_info->delay = delay;
|
||||
frame_info->dop = dop;
|
||||
frame_info->bop = bop;
|
||||
frame_info->pop = IMAGE_PNG_PREPARE_UNKNOWN;
|
||||
|
||||
buffer = (unsigned char*) malloc(width * height * 4);
|
||||
if (buffer == NULL) {
|
||||
frame_info->buffer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
read_image(png_ptr, buffer, width, height);
|
||||
frame_info->buffer = buffer;
|
||||
}
|
||||
|
||||
static void generate_pop(PNG_FRAME_INFO* frame_info_array, int count)
|
||||
{
|
||||
unsigned char dop = 0xff;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++){
|
||||
PNG_FRAME_INFO* frame_info = frame_info_array + i;
|
||||
|
||||
switch (dop) {
|
||||
case PNG_DISPOSE_OP_NONE:
|
||||
frame_info->pop = IMAGE_PNG_PREPARE_NONE;
|
||||
break;
|
||||
case PNG_DISPOSE_OP_BACKGROUND:
|
||||
frame_info->pop = IMAGE_PNG_PREPARE_BACKGROUND;
|
||||
break;
|
||||
case PNG_DISPOSE_OP_PREVIOUS:
|
||||
frame_info->pop = IMAGE_PNG_PREPARE_USE_BACKUP;
|
||||
break;
|
||||
default:
|
||||
frame_info->pop = IMAGE_PNG_PREPARE_BACKGROUND;
|
||||
break;
|
||||
}
|
||||
|
||||
dop = frame_info->dop;
|
||||
}
|
||||
}
|
||||
|
||||
void* PNG_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially)
|
||||
{
|
||||
PNG *png = NULL;
|
||||
png_structp png_ptr = NULL;
|
||||
png_infop info_ptr = NULL;
|
||||
bool apng;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
int color_type;
|
||||
int bit_depth;
|
||||
bool is_opaque;
|
||||
unsigned char* buffer = NULL;
|
||||
unsigned int frame_count = 0;
|
||||
bool hide_first_frame = false;
|
||||
PNG_FRAME_INFO* frame_info_array = NULL;
|
||||
int i;
|
||||
|
||||
png = (PNG *) malloc(sizeof(PNG));
|
||||
if (png == NULL) {
|
||||
WTF_OM;
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, &user_error_fn, &user_warn_fn);
|
||||
if (png_ptr == NULL) {
|
||||
free(png);
|
||||
png = NULL;
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
free(png);
|
||||
png = NULL;
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
LOGE(MSG("Error in png decode"));
|
||||
free_frame_info_array(frame_info_array, frame_count);
|
||||
frame_info_array = NULL;
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
free(png);
|
||||
png = NULL;
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set custom read function
|
||||
png_set_read_fn(png_ptr, patch_head_input_stream, &user_read_fn);
|
||||
|
||||
// Get png info
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
// Check apng
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) {
|
||||
apng = true;
|
||||
} else {
|
||||
apng = false;
|
||||
}
|
||||
|
||||
// PNG info
|
||||
width = png_get_image_width(png_ptr, info_ptr);
|
||||
height = png_get_image_height(png_ptr, info_ptr);
|
||||
color_type = png_get_color_type(png_ptr, info_ptr);
|
||||
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||
|
||||
// Create buffer
|
||||
buffer = (unsigned char*) malloc(width * height * 4);
|
||||
if (buffer == NULL) {
|
||||
WTF_OM;
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
free(png);
|
||||
png = NULL;
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (apng) {
|
||||
// Get frame count
|
||||
frame_count = png_get_num_frames(png_ptr, info_ptr);
|
||||
hide_first_frame = png_get_first_frame_is_hidden(png_ptr, info_ptr);
|
||||
if (hide_first_frame) {
|
||||
frame_count--;
|
||||
}
|
||||
|
||||
// Create frame info array
|
||||
frame_info_array = (PNG_FRAME_INFO*) calloc(frame_count, sizeof(PNG_FRAME_INFO));
|
||||
if (frame_info_array == NULL) {
|
||||
WTF_OM;
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
free(png);
|
||||
png = NULL;
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Configure to ARGB
|
||||
png_set_expand(png_ptr);
|
||||
if (bit_depth == 16) {
|
||||
png_set_scale_16(png_ptr);
|
||||
}
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
}
|
||||
if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
|
||||
is_opaque = true;
|
||||
png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
|
||||
} else {
|
||||
is_opaque = false;
|
||||
}
|
||||
|
||||
if (apng) {
|
||||
if (hide_first_frame) {
|
||||
// Skip first frame
|
||||
read_image(png_ptr, buffer, width, height);
|
||||
}
|
||||
|
||||
// Read first frame
|
||||
read_frame(png_ptr, info_ptr, frame_info_array);
|
||||
// Fix dop
|
||||
if (frame_info_array->dop == PNG_DISPOSE_OP_PREVIOUS) {
|
||||
frame_info_array->dop = PNG_DISPOSE_OP_BACKGROUND;
|
||||
}
|
||||
|
||||
if (!partially || frame_count == 1) {
|
||||
// Read all frame
|
||||
for (i = 1; i < frame_count; read_frame(png_ptr, info_ptr, frame_info_array + i++));
|
||||
|
||||
// Generate pop
|
||||
generate_pop(frame_info_array, frame_count);
|
||||
|
||||
// End read
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
|
||||
// Close input stream
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
|
||||
png->partially = false;
|
||||
png->png_ptr = NULL;
|
||||
png->info_ptr = NULL;
|
||||
png->patch_head_input_stream = NULL;
|
||||
} else {
|
||||
png->partially = true;
|
||||
png->png_ptr = png_ptr;
|
||||
png->info_ptr = info_ptr;
|
||||
png->patch_head_input_stream = patch_head_input_stream;
|
||||
}
|
||||
|
||||
// Fill PNG
|
||||
png->width = width;
|
||||
png->height = height;
|
||||
png->is_opaque = is_opaque;
|
||||
png->buffer = buffer;
|
||||
png->apng = true;
|
||||
png->buffer_index = -1;
|
||||
png->frame_info_array = frame_info_array;
|
||||
png->frame_count = frame_count;
|
||||
png->backup = NULL;
|
||||
|
||||
// Render first frame
|
||||
PNG_advance(png);
|
||||
} else {
|
||||
read_image(png_ptr, buffer, width, height);
|
||||
|
||||
// End read
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
|
||||
// Close input stream
|
||||
close_patch_head_input_stream(env, patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &patch_head_input_stream);
|
||||
|
||||
// Fill PNG
|
||||
png->width = width;
|
||||
png->height = height;
|
||||
png->buffer = buffer;
|
||||
png->apng = false;
|
||||
png->buffer_index = 0;
|
||||
png->frame_info_array = NULL;
|
||||
png->frame_count = 0;
|
||||
png->backup = NULL;
|
||||
png->partially = false;
|
||||
png->png_ptr = NULL;
|
||||
png->info_ptr = NULL;
|
||||
png->patch_head_input_stream = NULL;
|
||||
}
|
||||
|
||||
return png;
|
||||
}
|
||||
|
||||
bool PNG_complete(JNIEnv *env, PNG* png)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!png->partially) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (png->png_ptr == NULL || png->info_ptr == NULL || png->patch_head_input_stream == NULL) {
|
||||
LOGE(MSG("Some stuff is NULL"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read left frames
|
||||
for (i = 1; i < png->frame_count; read_frame(png->png_ptr, png->info_ptr, png->frame_info_array + i++));
|
||||
|
||||
// Generate pop
|
||||
generate_pop(png->frame_info_array, png->frame_count);
|
||||
|
||||
// End read
|
||||
png_read_end(png->png_ptr, png->info_ptr);
|
||||
png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL);
|
||||
|
||||
// Close input stream
|
||||
close_patch_head_input_stream(env, png->patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &png->patch_head_input_stream);
|
||||
|
||||
// Clean up
|
||||
png->partially = false;
|
||||
png->png_ptr = NULL;
|
||||
png->info_ptr = NULL;
|
||||
png->patch_head_input_stream = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PNG_is_completed(PNG* png)
|
||||
{
|
||||
return !png->partially;
|
||||
}
|
||||
|
||||
void* PNG_get_pixels(PNG* png)
|
||||
{
|
||||
if (!png->partially && PNG_get_frame_count(png) == 1) {
|
||||
return png->buffer;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int PNG_get_width(PNG* png)
|
||||
{
|
||||
return png->width;
|
||||
}
|
||||
|
||||
int PNG_get_height(PNG* png)
|
||||
{
|
||||
return png->height;
|
||||
}
|
||||
|
||||
int PNG_get_byte_count(PNG* png)
|
||||
{
|
||||
int i;
|
||||
PNG_FRAME_INFO* frame_info;
|
||||
int size = 0;
|
||||
// Add buffer size
|
||||
if (png->buffer != NULL) {
|
||||
size += png->width * png->height * 4;
|
||||
}
|
||||
// Add backup size
|
||||
if (png->backup != NULL) {
|
||||
size += png->width * png->height * 4;
|
||||
}
|
||||
// Add frames size
|
||||
if (png->frame_info_array != NULL) {
|
||||
for (i = 0; i < png->frame_count; i++) {
|
||||
frame_info = png->frame_info_array + i;
|
||||
// Add frame buffer size
|
||||
if (frame_info->buffer != NULL) {
|
||||
size += frame_info->width * frame_info->height * 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void PNG_render(PNG* png, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color)
|
||||
{
|
||||
copy_pixels(png->buffer, png->width, png->height, src_x, src_y,
|
||||
dst, dst_w, dst_h, dst_x, dst_y,
|
||||
width, height, fill_blank, default_color);
|
||||
}
|
||||
|
||||
static void backup(PNG* png)
|
||||
{
|
||||
if (png->backup == NULL) {
|
||||
png->backup = (unsigned char*) malloc(png->width * png->height * 4);
|
||||
if (png->backup == NULL) {
|
||||
WTF_OM;
|
||||
return;
|
||||
}
|
||||
}
|
||||
memcpy(png->backup, png->buffer, png->width * png->height * 4);
|
||||
}
|
||||
|
||||
static void restore(PNG* png)
|
||||
{
|
||||
if (png->backup == NULL) {
|
||||
LOGE(MSG("Backup is NULL"));
|
||||
} else {
|
||||
memcpy(png->buffer, png->backup, png->width * png->height * 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void switch_buffer_backup(PNG* png)
|
||||
{
|
||||
unsigned char* temp;
|
||||
|
||||
if (png->backup == NULL) {
|
||||
backup(png);
|
||||
} else {
|
||||
temp = png->buffer;
|
||||
png->buffer = png->backup;
|
||||
png->backup = temp;
|
||||
}
|
||||
}
|
||||
|
||||
static void blend_over(unsigned char* dp, const unsigned char* sp, size_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
int u, v, al;
|
||||
|
||||
for (i = 0; i < len; i += 4, sp += 4, dp += 4) {
|
||||
if (sp[3] == 255) {
|
||||
memcpy(dp, sp, 4);
|
||||
} else if (sp[3] != 0) {
|
||||
if (dp[3] != 0) {
|
||||
u = sp[3] * 255;
|
||||
v = (255 - sp[3]) * dp[3];
|
||||
al = u + v;
|
||||
dp[0] = (unsigned char) ((sp[0] * u + dp[0] * v) / al);
|
||||
dp[1] = (unsigned char) ((sp[1] * u + dp[1] * v) / al);
|
||||
dp[2] = (unsigned char) ((sp[2] * u + dp[2] * v) / al);
|
||||
dp[3] = (unsigned char) (al / 255);
|
||||
} else {
|
||||
memcpy(dp, sp, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void blend(unsigned char* src, int src_width, int src_height, int offset_x, int offset_y,
|
||||
unsigned char* dst, int dst_width, int dst_height, bool blend_op_over)
|
||||
{
|
||||
int i;
|
||||
unsigned char* src_ptr;
|
||||
unsigned char* dst_ptr;
|
||||
size_t len;
|
||||
int copy_width = MIN(dst_width - offset_x, src_width);
|
||||
int copy_height = MIN(dst_height - offset_y, src_height);
|
||||
|
||||
for (i = 0; i < copy_height; i++) {
|
||||
src_ptr = src + (i * src_width * 4);
|
||||
dst_ptr = dst + (((offset_y + i) * dst_width + offset_x) * 4);
|
||||
len = (size_t) (copy_width * 4);
|
||||
|
||||
if (blend_op_over) {
|
||||
blend_over(dst_ptr, src_ptr, len);
|
||||
} else {
|
||||
memcpy(dst_ptr, src_ptr, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PNG_advance(PNG* png)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (!png->apng) {
|
||||
LOGW(MSG("It is not apng, no need to advance"));
|
||||
return;
|
||||
}
|
||||
|
||||
index = (png->buffer_index + 1) % png->frame_count;
|
||||
if (index != 0 && png->partially) {
|
||||
LOGE(MSG("The png is only decoded partially. Only the first frame can be shown."));
|
||||
return;
|
||||
}
|
||||
|
||||
PNG_FRAME_INFO* frame_info = png->frame_info_array + index;
|
||||
|
||||
if (frame_info->dop == PNG_DISPOSE_OP_PREVIOUS && frame_info->pop == IMAGE_PNG_PREPARE_USE_BACKUP) {
|
||||
switch_buffer_backup(png);
|
||||
} else {
|
||||
// Backup
|
||||
if (frame_info->dop == PNG_DISPOSE_OP_PREVIOUS) {
|
||||
backup(png);
|
||||
}
|
||||
|
||||
// Prepare
|
||||
switch (frame_info->pop) {
|
||||
case IMAGE_PNG_PREPARE_NONE:
|
||||
// Do nothing
|
||||
break;
|
||||
default:
|
||||
case IMAGE_PNG_PREPARE_BACKGROUND:
|
||||
// Set transparent
|
||||
memset(png->buffer, '\0', png->width * png->height * 4);
|
||||
break;
|
||||
case IMAGE_PNG_PREPARE_USE_BACKUP:
|
||||
restore(png);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
blend(frame_info->buffer, frame_info->width, frame_info->height, frame_info->offset_x, frame_info->offset_y,
|
||||
png->buffer, png->width, png->height, frame_info->bop == PNG_BLEND_OP_OVER);
|
||||
|
||||
png->buffer_index = index;
|
||||
}
|
||||
|
||||
int PNG_get_delay(PNG* png)
|
||||
{
|
||||
if (png->apng) {
|
||||
return png->frame_info_array[png->buffer_index].delay;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int PNG_get_frame_count(PNG* png)
|
||||
{
|
||||
if (png->apng) {
|
||||
return png->frame_count;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool PNG_is_opaque(PNG* png)
|
||||
{
|
||||
return png->is_opaque;
|
||||
}
|
||||
|
||||
void PNG_recycle(JNIEnv *env, PNG* png)
|
||||
{
|
||||
if (png == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(png->buffer);
|
||||
png->buffer = NULL;
|
||||
|
||||
free_frame_info_array(png->frame_info_array, png->frame_count);
|
||||
png->frame_info_array = NULL;
|
||||
|
||||
free(png->backup);
|
||||
png->backup = NULL;
|
||||
|
||||
if (png->png_ptr != NULL && png->info_ptr != NULL) {
|
||||
png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL);
|
||||
}
|
||||
png->png_ptr = NULL;
|
||||
png->info_ptr = NULL;
|
||||
|
||||
if (png->patch_head_input_stream != NULL) {
|
||||
close_patch_head_input_stream(env, png->patch_head_input_stream);
|
||||
destroy_patch_head_input_stream(env, &png->patch_head_input_stream);
|
||||
png->patch_head_input_stream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // IMAGE_SUPPORT_PNG
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#ifndef IMAGE_IMAGE_PNG_H
|
||||
#define IMAGE_IMAGE_PNG_H
|
||||
|
||||
#include "config.h"
|
||||
#ifdef IMAGE_SUPPORT_PNG
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "png.h"
|
||||
#include "patch_head_input_stream.h"
|
||||
|
||||
#define IMAGE_PNG_DECODER_DESCRIPTION ("libpng " PNG_LIBPNG_VER_STRING)
|
||||
|
||||
#define IMAGE_PNG_MAGIC_NUMBER_0 0x89
|
||||
#define IMAGE_PNG_MAGIC_NUMBER_1 0x50
|
||||
|
||||
#define IMAGE_PNG_PREPARE_UNKNOWN 0x00
|
||||
#define IMAGE_PNG_PREPARE_NONE 0x01
|
||||
#define IMAGE_PNG_PREPARE_BACKGROUND 0x02
|
||||
#define IMAGE_PNG_PREPARE_USE_BACKUP 0x03
|
||||
|
||||
typedef struct {
|
||||
unsigned char* buffer;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int offset_x;
|
||||
unsigned int offset_y;
|
||||
unsigned int delay; // ms
|
||||
unsigned char dop;
|
||||
unsigned char bop;
|
||||
unsigned char pop;
|
||||
} PNG_FRAME_INFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
bool is_opaque;
|
||||
unsigned char* buffer;
|
||||
bool apng;
|
||||
int buffer_index;
|
||||
PNG_FRAME_INFO* frame_info_array;
|
||||
unsigned int frame_count;
|
||||
unsigned char* backup;
|
||||
bool partially;
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
PatchHeadInputStream* patch_head_input_stream;
|
||||
} PNG;
|
||||
|
||||
void* PNG_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially);
|
||||
bool PNG_complete(JNIEnv* env, PNG* png);
|
||||
bool PNG_is_completed(PNG* png);
|
||||
void* PNG_get_pixels(PNG* png);
|
||||
int PNG_get_width(PNG* png);
|
||||
int PNG_get_height(PNG* png);
|
||||
int PNG_get_byte_count(PNG* png);
|
||||
void PNG_render(PNG* png, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color);
|
||||
void PNG_advance(PNG* png);
|
||||
int PNG_get_delay(PNG* png);
|
||||
int PNG_get_frame_count(PNG* png);
|
||||
bool PNG_is_opaque(PNG* png);
|
||||
void PNG_recycle(JNIEnv* env, PNG* png);
|
||||
|
||||
#endif // IMAGE_SUPPORT_PNG
|
||||
|
||||
#endif // IMAGE_IMAGE_PNG_H
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#include "image_utils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LITTLE_ENDIAN 0x00
|
||||
#define BIG_ENDIAN 0x01
|
||||
|
||||
static unsigned int endian = ~0U;
|
||||
|
||||
static unsigned int get_endian() {
|
||||
unsigned int x = 1;
|
||||
|
||||
if (endian == ~0U) {
|
||||
if (1 == ((char *)&x)[0]) {
|
||||
endian = LITTLE_ENDIAN;
|
||||
} else {
|
||||
endian = BIG_ENDIAN;
|
||||
}
|
||||
}
|
||||
|
||||
return endian;
|
||||
}
|
||||
|
||||
static int convert_color(int origin) {
|
||||
int result;
|
||||
unsigned char* orPtr = (unsigned char *) &origin;
|
||||
unsigned char* rePtr = (unsigned char *) &result;
|
||||
|
||||
if (get_endian() == BIG_ENDIAN) {
|
||||
rePtr[0] = orPtr[1];
|
||||
rePtr[1] = orPtr[2];
|
||||
rePtr[2] = orPtr[3];
|
||||
rePtr[3] = orPtr[0];
|
||||
} else {
|
||||
rePtr[0] = orPtr[2];
|
||||
rePtr[1] = orPtr[1];
|
||||
rePtr[2] = orPtr[0];
|
||||
rePtr[3] = orPtr[3];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void memset_int(int* dst, int val, size_t size) {
|
||||
int* maxPtr = dst + size;
|
||||
int* ptr = dst;
|
||||
while(ptr < maxPtr)
|
||||
*ptr++ = val;
|
||||
}
|
||||
|
||||
bool copy_pixels_internal(const void* src, int src_w, int src_h, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int color)
|
||||
{
|
||||
int left;
|
||||
int line;
|
||||
size_t line_stride;
|
||||
int src_stride;
|
||||
int src_pos;
|
||||
int dst_pos;
|
||||
size_t dst_blank_length;
|
||||
|
||||
// Sanitize
|
||||
if (src_x < 0) {
|
||||
width -= src_x;
|
||||
dst_x -= src_x;
|
||||
src_x = 0;
|
||||
}
|
||||
if (dst_x < 0) {
|
||||
width -= dst_x;
|
||||
src_x -= dst_x;
|
||||
dst_x = 0;
|
||||
}
|
||||
if (width <= 0) {
|
||||
return false;
|
||||
}
|
||||
if (src_y < 0) {
|
||||
height -= src_y;
|
||||
dst_y -= src_y;
|
||||
src_y = 0;
|
||||
}
|
||||
if (dst_y < 0) {
|
||||
height -= dst_y;
|
||||
src_y -= dst_y;
|
||||
dst_y = 0;
|
||||
}
|
||||
if (height <= 0) {
|
||||
return false;
|
||||
}
|
||||
left = src_x + width - src_w;
|
||||
if (left > 0) {
|
||||
width -= left;
|
||||
}
|
||||
left = dst_x + width - dst_w;
|
||||
if (left > 0) {
|
||||
width -= left;
|
||||
}
|
||||
if (width <= 0) {
|
||||
return false;
|
||||
}
|
||||
left = src_y + height - src_h;
|
||||
if (left > 0) {
|
||||
height -= left;
|
||||
}
|
||||
left = dst_y + height - dst_h;
|
||||
if (left > 0) {
|
||||
height -= left;
|
||||
}
|
||||
if (height <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Init
|
||||
line_stride = (size_t) (width * 4);
|
||||
src_stride = src_w * 4;
|
||||
src_pos = src_y * src_stride + src_x * 4;
|
||||
dst_pos = 0;
|
||||
|
||||
dst_blank_length = (size_t) (dst_y * dst_w + dst_x) * 4;
|
||||
// Fill start blank if necessary
|
||||
if (fill_blank) {
|
||||
memset_int((int *) (dst + dst_pos), color, dst_blank_length / 4);
|
||||
}
|
||||
|
||||
// First line
|
||||
dst_pos += dst_blank_length;
|
||||
memcpy(dst + dst_pos, src + src_pos, line_stride);
|
||||
dst_pos += line_stride;
|
||||
src_pos += src_stride;
|
||||
|
||||
// Other lines
|
||||
dst_blank_length = (size_t) ((dst_w - width) * 4);
|
||||
for (line = 1; line < height; line++) {
|
||||
if (fill_blank) {
|
||||
memset_int((int *) (dst + dst_pos), color, dst_blank_length / 4);
|
||||
}
|
||||
dst_pos += dst_blank_length;
|
||||
memcpy(dst + dst_pos, src + src_pos, line_stride);
|
||||
dst_pos += line_stride;
|
||||
src_pos += src_stride;
|
||||
}
|
||||
|
||||
// Fill left blank if necessary
|
||||
if (fill_blank) {
|
||||
memset_int((int *) (dst + dst_pos), color, (size_t) (dst_w * dst_h * 4 - dst_pos) / 4);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void copy_pixels(const void* src, int src_w, int src_h, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color)
|
||||
{
|
||||
int color = 0;
|
||||
if (fill_blank) {
|
||||
color = convert_color(default_color);
|
||||
}
|
||||
|
||||
if (!copy_pixels_internal(src, src_w, src_h, src_x, src_y, dst, dst_w, dst_h, dst_x,
|
||||
dst_y, width, height, fill_blank, color) && fill_blank) {
|
||||
memset_int(dst, color, (size_t) (dst_w * dst_h));
|
||||
}
|
||||
}
|
||||
@@ -1,304 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <android/bitmap.h>
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include "java_wrapper.h"
|
||||
#include "input_stream.h"
|
||||
#include "image.h"
|
||||
#include "../log.h"
|
||||
|
||||
static JavaVM* jvm;
|
||||
|
||||
static void* tile_buffer;
|
||||
|
||||
JNIEnv *obtain_env(bool *attach)
|
||||
{
|
||||
JNIEnv *env;
|
||||
switch ((*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION_1_6)) {
|
||||
case JNI_EDETACHED:
|
||||
if ((*jvm)->AttachCurrentThread(jvm, &env, NULL) == JNI_OK) {
|
||||
*attach = true;
|
||||
return env;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
case JNI_OK:
|
||||
*attach = false;
|
||||
return env;
|
||||
default:
|
||||
case JNI_EVERSION:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void release_env()
|
||||
{
|
||||
(*jvm)->DetachCurrentThread(jvm);
|
||||
}
|
||||
|
||||
jobject create_image_object(JNIEnv* env, void* ptr, int format, int width, int height)
|
||||
{
|
||||
jclass image_clazz;
|
||||
jmethodID constructor;
|
||||
|
||||
image_clazz = (*env)->FindClass(env, "com/hippo/image/Image");
|
||||
constructor = (*env)->GetMethodID(env, image_clazz, "<init>", "(JIII)V");
|
||||
if (constructor == 0) {
|
||||
LOGE(MSG("Can't find Image object constructor"));
|
||||
return NULL;
|
||||
} else {
|
||||
return (*env)->NewObject(env, image_clazz, constructor,
|
||||
(jlong) (uintptr_t) ptr, (jint) format, (jint) width, (jint) height);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_hippo_image_Image_nativeDecode(JNIEnv* env,
|
||||
jclass clazz, jobject is, jboolean partially)
|
||||
{
|
||||
InputStream* input_stream;
|
||||
int format;
|
||||
void* image;
|
||||
jobject image_object;
|
||||
|
||||
input_stream = create_input_stream(env, is);
|
||||
if (input_stream == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image = decode(env, input_stream, partially, &format);
|
||||
if (image == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image_object = create_image_object(env, image, format,
|
||||
get_width(image, format), get_height(image, format));
|
||||
if (image_object == NULL) {
|
||||
recycle(env, image, format);
|
||||
return NULL;
|
||||
} else {
|
||||
return image_object;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_hippo_image_Image_nativeCreate(JNIEnv* env,
|
||||
jclass clazz, jobject bitmap)
|
||||
{
|
||||
#ifdef IMAGE_SUPPORT_PLAIN
|
||||
AndroidBitmapInfo info;
|
||||
void *pixels = NULL;
|
||||
void* image = NULL;
|
||||
jobject image_object;
|
||||
|
||||
AndroidBitmap_getInfo(env, bitmap, &info);
|
||||
AndroidBitmap_lockPixels(env, bitmap, &pixels);
|
||||
if (pixels == NULL) {
|
||||
LOGE(MSG("Can't lock bitmap pixels"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image = create(info.width, info.height, pixels);
|
||||
|
||||
AndroidBitmap_unlockPixels(env, bitmap);
|
||||
|
||||
if (image == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image_object = create_image_object(env, image, IMAGE_FORMAT_PLAIN,
|
||||
info.width, info.height);
|
||||
if (image_object == NULL) {
|
||||
recycle(env, image, IMAGE_FORMAT_PLAIN);
|
||||
return NULL;
|
||||
} else {
|
||||
return image_object;
|
||||
}
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_hippo_image_Image_nativeComplete(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format)
|
||||
{
|
||||
return (jboolean) complete(env, (void*) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_hippo_image_Image_nativeIsCompleted(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format)
|
||||
{
|
||||
return (jboolean) is_completed((void*) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_hippo_image_Image_nativeGetByteCount(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format)
|
||||
{
|
||||
return (jint) get_byte_count((void*) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeRender(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format,
|
||||
jint src_x, jint src_y, jobject dst, jint dst_x, jint dst_y,
|
||||
jint width, jint height, jboolean fill_blank, jint default_color)
|
||||
{
|
||||
AndroidBitmapInfo info;
|
||||
void *pixels = NULL;
|
||||
|
||||
AndroidBitmap_getInfo(env, dst, &info);
|
||||
AndroidBitmap_lockPixels(env, dst, &pixels);
|
||||
if (pixels == NULL) {
|
||||
LOGE(MSG("Can't lock bitmap pixels"));
|
||||
return;
|
||||
}
|
||||
|
||||
render((void*) (intptr_t) ptr, format, src_x, src_y,
|
||||
pixels, info.width, info.height, dst_x, dst_y,
|
||||
width, height, fill_blank, default_color);
|
||||
|
||||
AndroidBitmap_unlockPixels(env, dst);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeTexImage(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format, jboolean init,
|
||||
jint src_x, jint src_y, jint width, jint height)
|
||||
{
|
||||
// Check tile_buffer NULL
|
||||
if (NULL == tile_buffer) {
|
||||
return;
|
||||
}
|
||||
// Check render size
|
||||
if (width * height > IMAGE_TILE_MAX_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
render((void*) (intptr_t) ptr, format, src_x, src_y,
|
||||
tile_buffer, width, height, 0, 0,
|
||||
width, height, false, 0);
|
||||
|
||||
if (init) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, tile_buffer);
|
||||
} else {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, tile_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeAdvance(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format)
|
||||
{
|
||||
advance((void*) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_hippo_image_Image_nativeGetDelay(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format)
|
||||
{
|
||||
return (jint) get_delay((void*) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_hippo_image_Image_nativeFrameCount(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format)
|
||||
{
|
||||
return (jint) get_frame_count((void*) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_hippo_image_Image_nativeIsOpaque(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format)
|
||||
{
|
||||
return (jboolean) is_opaque((void*) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_hippo_image_Image_nativeIsGray(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format, jint error)
|
||||
{
|
||||
return (jboolean) is_gray((void*) (intptr_t) ptr, format, error);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeClahe(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format, jboolean to_gray)
|
||||
{
|
||||
clahe((void*) (intptr_t) ptr, format, to_gray);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeRecycle(JNIEnv* env,
|
||||
jclass clazz, jlong ptr, jint format)
|
||||
{
|
||||
recycle(env, (void*) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT jintArray JNICALL
|
||||
Java_com_hippo_image_Image_nativeGetSupportedImageFormats(
|
||||
JNIEnv *env, jclass clazz)
|
||||
{
|
||||
int formats[IMAGE_MAX_SUPPORTED_FORMAT_COUNT];
|
||||
int count = get_supported_formats(formats);
|
||||
jintArray array = (*env)->NewIntArray(env, count);
|
||||
if (array == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
(*env)->SetIntArrayRegion(env, array, 0, count, formats);
|
||||
return array;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_hippo_image_Image_nativeGetDecoderDescription(
|
||||
JNIEnv *env, jclass clazz, jint format)
|
||||
{
|
||||
const char *description = get_decoder_description(format);
|
||||
if (description == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
return (*env)->NewStringUTF(env, description);
|
||||
}
|
||||
}
|
||||
|
||||
bool image_onLoad(JavaVM *vm)
|
||||
{
|
||||
jvm = vm;
|
||||
|
||||
tile_buffer = malloc(IMAGE_TILE_MAX_SIZE * 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNI_OnUnload(JavaVM *vm, void *reserved)
|
||||
{
|
||||
free(tile_buffer);
|
||||
tile_buffer = NULL;
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#include "image_utils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LITTLE_ENDIAN 0x00
|
||||
#define BIG_ENDIAN 0x01
|
||||
|
||||
static unsigned int endian = ~0U;
|
||||
|
||||
static unsigned int get_endian() {
|
||||
unsigned int x = 1;
|
||||
|
||||
if (endian == ~0U) {
|
||||
if (1 == ((char *) &x)[0]) {
|
||||
endian = LITTLE_ENDIAN;
|
||||
} else {
|
||||
endian = BIG_ENDIAN;
|
||||
}
|
||||
}
|
||||
|
||||
return endian;
|
||||
}
|
||||
|
||||
static int convert_color(int origin) {
|
||||
int result;
|
||||
unsigned char *orPtr = (unsigned char *) &origin;
|
||||
unsigned char *rePtr = (unsigned char *) &result;
|
||||
|
||||
if (get_endian() == BIG_ENDIAN) {
|
||||
rePtr[0] = orPtr[1];
|
||||
rePtr[1] = orPtr[2];
|
||||
rePtr[2] = orPtr[3];
|
||||
rePtr[3] = orPtr[0];
|
||||
} else {
|
||||
rePtr[0] = orPtr[2];
|
||||
rePtr[1] = orPtr[1];
|
||||
rePtr[2] = orPtr[0];
|
||||
rePtr[3] = orPtr[3];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void memset_int(int *dst, int val, size_t size) {
|
||||
int *maxPtr = dst + size;
|
||||
int *ptr = dst;
|
||||
while (ptr < maxPtr)
|
||||
*ptr++ = val;
|
||||
}
|
||||
|
||||
bool copy_pixels_internal(const void *src, int src_w, int src_h, int src_x, int src_y,
|
||||
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int color) {
|
||||
int left;
|
||||
int line;
|
||||
size_t line_stride;
|
||||
int src_stride;
|
||||
int src_pos;
|
||||
int dst_pos;
|
||||
size_t dst_blank_length;
|
||||
|
||||
// Sanitize
|
||||
if (src_x < 0) {
|
||||
width -= src_x;
|
||||
dst_x -= src_x;
|
||||
src_x = 0;
|
||||
}
|
||||
if (dst_x < 0) {
|
||||
width -= dst_x;
|
||||
src_x -= dst_x;
|
||||
dst_x = 0;
|
||||
}
|
||||
if (width <= 0) {
|
||||
return false;
|
||||
}
|
||||
if (src_y < 0) {
|
||||
height -= src_y;
|
||||
dst_y -= src_y;
|
||||
src_y = 0;
|
||||
}
|
||||
if (dst_y < 0) {
|
||||
height -= dst_y;
|
||||
src_y -= dst_y;
|
||||
dst_y = 0;
|
||||
}
|
||||
if (height <= 0) {
|
||||
return false;
|
||||
}
|
||||
left = src_x + width - src_w;
|
||||
if (left > 0) {
|
||||
width -= left;
|
||||
}
|
||||
left = dst_x + width - dst_w;
|
||||
if (left > 0) {
|
||||
width -= left;
|
||||
}
|
||||
if (width <= 0) {
|
||||
return false;
|
||||
}
|
||||
left = src_y + height - src_h;
|
||||
if (left > 0) {
|
||||
height -= left;
|
||||
}
|
||||
left = dst_y + height - dst_h;
|
||||
if (left > 0) {
|
||||
height -= left;
|
||||
}
|
||||
if (height <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Init
|
||||
line_stride = (size_t) (width * 4);
|
||||
src_stride = src_w * 4;
|
||||
src_pos = src_y * src_stride + src_x * 4;
|
||||
dst_pos = 0;
|
||||
|
||||
dst_blank_length = (size_t) (dst_y * dst_w + dst_x) * 4;
|
||||
// Fill start blank if necessary
|
||||
if (fill_blank) {
|
||||
memset_int((int *) (dst + dst_pos), color, dst_blank_length / 4);
|
||||
}
|
||||
|
||||
// First line
|
||||
dst_pos += dst_blank_length;
|
||||
memcpy(dst + dst_pos, src + src_pos, line_stride);
|
||||
dst_pos += line_stride;
|
||||
src_pos += src_stride;
|
||||
|
||||
// Other lines
|
||||
dst_blank_length = (size_t) ((dst_w - width) * 4);
|
||||
for (line = 1; line < height; line++) {
|
||||
if (fill_blank) {
|
||||
memset_int((int *) (dst + dst_pos), color, dst_blank_length / 4);
|
||||
}
|
||||
dst_pos += dst_blank_length;
|
||||
memcpy(dst + dst_pos, src + src_pos, line_stride);
|
||||
dst_pos += line_stride;
|
||||
src_pos += src_stride;
|
||||
}
|
||||
|
||||
// Fill left blank if necessary
|
||||
if (fill_blank) {
|
||||
memset_int((int *) (dst + dst_pos), color, (size_t) (dst_w * dst_h * 4 - dst_pos) / 4);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void copy_pixels(const void *src, int src_w, int src_h, int src_x, int src_y,
|
||||
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color) {
|
||||
int color = 0;
|
||||
if (fill_blank) {
|
||||
color = convert_color(default_color);
|
||||
}
|
||||
|
||||
if (!copy_pixels_internal(src, src_w, src_h, src_x, src_y, dst, dst_w, dst_h, dst_x,
|
||||
dst_y, width, height, fill_blank, color) && fill_blank) {
|
||||
memset_int(dst, color, (size_t) (dst_w * dst_h));
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -26,8 +26,8 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
void copy_pixels(const void* src, int src_w, int src_h, int src_x, int src_y,
|
||||
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color);
|
||||
void copy_pixels(const void *src, int src_w, int src_h, int src_x, int src_y,
|
||||
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height, bool fill_blank, int default_color);
|
||||
|
||||
#endif //IMAGE_IMAGE_UTILS_H
|
||||
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <android/bitmap.h>
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include "java_wrapper.h"
|
||||
#include "image.h"
|
||||
#include "log.h"
|
||||
|
||||
static JavaVM *jvm;
|
||||
|
||||
static void *tile_buffer;
|
||||
|
||||
static int jniGetFDFromFileDescriptor(JNIEnv *env, jobject fileDescriptor) {
|
||||
jint fd = -1;
|
||||
jclass fdClass = (*env)->FindClass(env, "java/io/FileDescriptor");
|
||||
|
||||
if (fdClass != NULL) {
|
||||
jfieldID fdClassDescriptorFieldID = (*env)->GetFieldID(env, fdClass, "descriptor", "I");
|
||||
if (fdClassDescriptorFieldID != NULL && fileDescriptor != NULL) {
|
||||
fd = (*env)->GetIntField(env, fileDescriptor, fdClassDescriptorFieldID);
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
JNIEnv *obtain_env(bool *attach) {
|
||||
JNIEnv *env;
|
||||
switch ((*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_6)) {
|
||||
case JNI_EDETACHED:
|
||||
if ((*jvm)->AttachCurrentThread(jvm, &env, NULL) == JNI_OK) {
|
||||
*attach = true;
|
||||
return env;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
case JNI_OK:
|
||||
*attach = false;
|
||||
return env;
|
||||
default:
|
||||
case JNI_EVERSION:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void release_env() {
|
||||
(*jvm)->DetachCurrentThread(jvm);
|
||||
}
|
||||
|
||||
jobject create_image_object(JNIEnv *env, void *ptr, int format, int width, int height) {
|
||||
jclass image_clazz;
|
||||
jmethodID constructor;
|
||||
|
||||
image_clazz = (*env)->FindClass(env, "com/hippo/image/Image");
|
||||
constructor = (*env)->GetMethodID(env, image_clazz, "<init>", "(JIII)V");
|
||||
if (constructor == 0) {
|
||||
LOGE(MSG("Can't find Image object constructor"));
|
||||
return NULL;
|
||||
} else {
|
||||
return (*env)->NewObject(env, image_clazz, constructor,
|
||||
(jlong) (uintptr_t) ptr, (jint) format, (jint) width,
|
||||
(jint) height);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_hippo_image_Image_nativeDecodeFdInt(JNIEnv *env,
|
||||
jclass clazz, jint fd, jboolean partially) {
|
||||
int format;
|
||||
void *image;
|
||||
jobject image_object;
|
||||
|
||||
image = createFromFd(env, fd, partially, &format);
|
||||
if (image == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image_object = create_image_object(env, image, format,
|
||||
get_width(image, format), get_height(image, format));
|
||||
if (image_object == NULL) {
|
||||
recycle(env, image, format);
|
||||
return NULL;
|
||||
} else {
|
||||
return image_object;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_hippo_image_Image_nativeDecode(JNIEnv *env,
|
||||
jclass clazz, jobject fd, jboolean partially) {
|
||||
return Java_com_hippo_image_Image_nativeDecodeFdInt(env, clazz,
|
||||
jniGetFDFromFileDescriptor(env, fd),
|
||||
partially);
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_hippo_image_Image_nativeCreate(JNIEnv *env,
|
||||
jclass clazz, jobject bitmap) {
|
||||
AndroidBitmapInfo info;
|
||||
void *pixels = NULL;
|
||||
void *image = NULL;
|
||||
jobject image_object;
|
||||
|
||||
AndroidBitmap_getInfo(env, bitmap, &info);
|
||||
AndroidBitmap_lockPixels(env, bitmap, &pixels);
|
||||
if (pixels == NULL) {
|
||||
LOGE(MSG("Can't lock bitmap pixels"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image = create(info.width, info.height, pixels);
|
||||
|
||||
AndroidBitmap_unlockPixels(env, bitmap);
|
||||
|
||||
if (image == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image_object = create_image_object(env, image, 0,
|
||||
info.width, info.height);
|
||||
if (image_object == NULL) {
|
||||
recycle(env, image, 0);
|
||||
return NULL;
|
||||
} else {
|
||||
return image_object;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_hippo_image_Image_nativeGetByteCount(JNIEnv *env,
|
||||
jclass clazz, jlong ptr, jint format) {
|
||||
return (jint) get_byte_count((void *) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeRender(JNIEnv *env,
|
||||
jclass clazz, jlong ptr, jint format,
|
||||
jint src_x, jint src_y, jobject dst, jint dst_x, jint dst_y,
|
||||
jint width, jint height, jboolean fill_blank,
|
||||
jint default_color) {
|
||||
AndroidBitmapInfo info;
|
||||
void *pixels = NULL;
|
||||
|
||||
AndroidBitmap_getInfo(env, dst, &info);
|
||||
AndroidBitmap_lockPixels(env, dst, &pixels);
|
||||
if (pixels == NULL) {
|
||||
LOGE(MSG("Can't lock bitmap pixels"));
|
||||
return;
|
||||
}
|
||||
|
||||
render((void *) (intptr_t) ptr, format, src_x, src_y,
|
||||
pixels, info.width, info.height, dst_x, dst_y,
|
||||
width, height, fill_blank, default_color);
|
||||
|
||||
AndroidBitmap_unlockPixels(env, dst);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeTexImage(JNIEnv *env,
|
||||
jclass clazz, jlong ptr, jint format, jboolean init,
|
||||
jint src_x, jint src_y, jint width, jint height) {
|
||||
// Check tile_buffer NULL
|
||||
if (NULL == tile_buffer) {
|
||||
return;
|
||||
}
|
||||
// Check render size
|
||||
if (width * height > IMAGE_TILE_MAX_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
render((void *) (intptr_t) ptr, format, src_x, src_y,
|
||||
tile_buffer, width, height, 0, 0,
|
||||
width, height, false, 0);
|
||||
|
||||
if (init) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, tile_buffer);
|
||||
} else {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, tile_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeAdvance(JNIEnv *env,
|
||||
jclass clazz, jlong ptr, jint format) {
|
||||
advance((void *) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_hippo_image_Image_nativeGetDelay(JNIEnv *env,
|
||||
jclass clazz, jlong ptr, jint format) {
|
||||
return (jint) get_delay((void *) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_hippo_image_Image_nativeIsOpaque(JNIEnv *env,
|
||||
jclass clazz, jlong ptr, jint format) {
|
||||
return (jboolean) is_opaque((void *) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_hippo_image_Image_nativeIsGray(JNIEnv *env,
|
||||
jclass clazz, jlong ptr, jint format, jint error) {
|
||||
return (jboolean) is_gray((void *) (intptr_t) ptr, format, error);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeClahe(JNIEnv *env,
|
||||
jclass clazz, jlong ptr, jint format, jboolean to_gray) {
|
||||
clahe((void *) (intptr_t) ptr, format, to_gray);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeRecycle(JNIEnv *env,
|
||||
jclass clazz, jlong ptr, jint format) {
|
||||
recycle(env, (void *) (intptr_t) ptr, format);
|
||||
}
|
||||
|
||||
bool image_onLoad(JavaVM *vm) {
|
||||
jvm = vm;
|
||||
|
||||
tile_buffer = malloc(IMAGE_TILE_MAX_SIZE * 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNI_OnUnload(JavaVM *vm, void *reserved) {
|
||||
free(tile_buffer);
|
||||
tile_buffer = NULL;
|
||||
}
|
||||
|
||||
typedef struct Memarea {
|
||||
void *buffer;
|
||||
long size;
|
||||
} Memarea;
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_hippo_image_Image_nativeDecodeAddr(JNIEnv *env, jclass clazz, jlong addr,
|
||||
jboolean partially) {
|
||||
int format;
|
||||
void *image;
|
||||
jobject image_object;
|
||||
|
||||
Memarea *memarea = (Memarea *) addr;
|
||||
image = createFromAddr(env, memarea->buffer, memarea->size, partially, &format);
|
||||
free(memarea);
|
||||
if (image == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image_object = create_image_object(env, image, format,
|
||||
get_width(image, format), get_height(image, format));
|
||||
if (image_object == NULL) {
|
||||
recycle(env, image, format);
|
||||
return NULL;
|
||||
} else {
|
||||
return image_object;
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -1,211 +0,0 @@
|
||||
# Copyright 2018 Hippo Seven
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(jpeg C)
|
||||
|
||||
set(LIBJPEG_TURBO_SOURCES
|
||||
libjpeg-turbo/jaricom.c
|
||||
libjpeg-turbo/jcomapi.c
|
||||
libjpeg-turbo/jdapimin.c
|
||||
libjpeg-turbo/jdapistd.c
|
||||
libjpeg-turbo/jdarith.c
|
||||
libjpeg-turbo/jdatasrc.c
|
||||
libjpeg-turbo/jdatasrc-tj.c
|
||||
libjpeg-turbo/jdcoefct.c
|
||||
libjpeg-turbo/jdcolor.c
|
||||
libjpeg-turbo/jddctmgr.c
|
||||
libjpeg-turbo/jdhuff.c
|
||||
libjpeg-turbo/jdinput.c
|
||||
libjpeg-turbo/jdmainct.c
|
||||
libjpeg-turbo/jdmarker.c
|
||||
libjpeg-turbo/jdmaster.c
|
||||
libjpeg-turbo/jdmerge.c
|
||||
libjpeg-turbo/jdphuff.c
|
||||
libjpeg-turbo/jdpostct.c
|
||||
libjpeg-turbo/jdsample.c
|
||||
libjpeg-turbo/jdtrans.c
|
||||
libjpeg-turbo/jerror.c
|
||||
libjpeg-turbo/jfdctflt.c
|
||||
libjpeg-turbo/jfdctfst.c
|
||||
libjpeg-turbo/jfdctint.c
|
||||
libjpeg-turbo/jidctflt.c
|
||||
libjpeg-turbo/jidctfst.c
|
||||
libjpeg-turbo/jidctint.c
|
||||
libjpeg-turbo/jidctred.c
|
||||
libjpeg-turbo/jmemmgr.c
|
||||
libjpeg-turbo/jmemnobs.c
|
||||
libjpeg-turbo/jquant1.c
|
||||
libjpeg-turbo/jquant2.c
|
||||
libjpeg-turbo/jutils.c
|
||||
)
|
||||
set(LIBJPEG_TURBO_INCLUDES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libjpeg-turbo
|
||||
)
|
||||
|
||||
if (${ANDROID_ABI} STREQUAL "armeabi-v7a")
|
||||
|
||||
enable_language(ASM)
|
||||
|
||||
add_definitions(-DNEON_INTRINSICS)
|
||||
|
||||
set(LIBJPEG_TURBO_SOURCES
|
||||
${LIBJPEG_TURBO_SOURCES}
|
||||
libjpeg-turbo/simd/arm/jccolor-neon.c
|
||||
libjpeg-turbo/simd/arm/jidctred-neon.c
|
||||
libjpeg-turbo/simd/arm/jquanti-neon.c
|
||||
libjpeg-turbo/simd/arm/jidctint-neon.c
|
||||
libjpeg-turbo/simd/arm/jidctfst-neon.c
|
||||
libjpeg-turbo/simd/arm/jfdctint-neon.c
|
||||
libjpeg-turbo/simd/arm/jfdctfst-neon.c
|
||||
libjpeg-turbo/simd/arm/jdsample-neon.c
|
||||
libjpeg-turbo/simd/arm/jdmerge-neon.c
|
||||
libjpeg-turbo/simd/arm/jdcolor-neon.c
|
||||
libjpeg-turbo/simd/arm/jcsample-neon.c
|
||||
libjpeg-turbo/simd/arm/jcphuff-neon.c
|
||||
libjpeg-turbo/simd/arm/jcgray-neon.c
|
||||
libjpeg-turbo/simd/arm/aarch32/jchuff-neon.c
|
||||
libjpeg-turbo/simd/arm/aarch32/jsimd.c
|
||||
)
|
||||
|
||||
elseif (${ANDROID_ABI} STREQUAL "arm64-v8a")
|
||||
|
||||
enable_language(ASM)
|
||||
|
||||
add_definitions(-DNEON_INTRINSICS)
|
||||
|
||||
set(LIBJPEG_TURBO_SOURCES
|
||||
${LIBJPEG_TURBO_SOURCES}
|
||||
libjpeg-turbo/simd/arm/jccolor-neon.c
|
||||
libjpeg-turbo/simd/arm/jidctred-neon.c
|
||||
libjpeg-turbo/simd/arm/jquanti-neon.c
|
||||
libjpeg-turbo/simd/arm/jidctint-neon.c
|
||||
libjpeg-turbo/simd/arm/jidctfst-neon.c
|
||||
libjpeg-turbo/simd/arm/jfdctint-neon.c
|
||||
libjpeg-turbo/simd/arm/jfdctfst-neon.c
|
||||
libjpeg-turbo/simd/arm/jdsample-neon.c
|
||||
libjpeg-turbo/simd/arm/jdmerge-neon.c
|
||||
libjpeg-turbo/simd/arm/jdcolor-neon.c
|
||||
libjpeg-turbo/simd/arm/jcsample-neon.c
|
||||
libjpeg-turbo/simd/arm/jcphuff-neon.c
|
||||
libjpeg-turbo/simd/arm/jcgray-neon.c
|
||||
libjpeg-turbo/simd/arm/aarch64/jchuff-neon.c
|
||||
libjpeg-turbo/simd/arm/aarch64/jsimd.c
|
||||
)
|
||||
|
||||
elseif (${ANDROID_ABI} STREQUAL "x86")
|
||||
|
||||
enable_language(ASM_NASM)
|
||||
|
||||
set(LIBJPEG_TURBO_SOURCES
|
||||
${LIBJPEG_TURBO_SOURCES}
|
||||
libjpeg-turbo/simd/i386/jsimd.c
|
||||
libjpeg-turbo/simd/i386/jsimdcpu.asm
|
||||
libjpeg-turbo/simd/i386/jfdctflt-3dn.asm
|
||||
libjpeg-turbo/simd/i386/jidctflt-3dn.asm
|
||||
libjpeg-turbo/simd/i386/jquant-3dn.asm
|
||||
libjpeg-turbo/simd/i386/jccolor-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jcgray-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jcsample-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jdcolor-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jdmerge-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jdsample-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jfdctfst-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jfdctint-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jidctfst-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jidctint-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jidctred-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jquant-mmx.asm
|
||||
libjpeg-turbo/simd/i386/jfdctflt-sse.asm
|
||||
libjpeg-turbo/simd/i386/jidctflt-sse.asm
|
||||
libjpeg-turbo/simd/i386/jquant-sse.asm
|
||||
libjpeg-turbo/simd/i386/jccolor-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jcgray-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jchuff-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jcphuff-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jcsample-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jdcolor-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jdmerge-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jdsample-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jfdctfst-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jfdctint-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jidctflt-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jidctfst-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jidctint-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jidctred-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jquantf-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jquanti-sse2.asm
|
||||
libjpeg-turbo/simd/i386/jccolor-avx2.asm
|
||||
libjpeg-turbo/simd/i386/jcgray-avx2.asm
|
||||
libjpeg-turbo/simd/i386/jcsample-avx2.asm
|
||||
libjpeg-turbo/simd/i386/jdcolor-avx2.asm
|
||||
libjpeg-turbo/simd/i386/jdmerge-avx2.asm
|
||||
libjpeg-turbo/simd/i386/jdsample-avx2.asm
|
||||
libjpeg-turbo/simd/i386/jfdctint-avx2.asm
|
||||
libjpeg-turbo/simd/i386/jidctint-avx2.asm
|
||||
libjpeg-turbo/simd/i386/jquanti-avx2.asm
|
||||
)
|
||||
|
||||
set(CMAKE_ASM_NASM_FLAGS "-DELF -DPIC -I${CMAKE_CURRENT_SOURCE_DIR}/libjpeg-turbo/simd/nasm")
|
||||
|
||||
elseif (${ANDROID_ABI} STREQUAL "x86_64")
|
||||
|
||||
enable_language(ASM_NASM)
|
||||
|
||||
set(LIBJPEG_TURBO_SOURCES
|
||||
${LIBJPEG_TURBO_SOURCES}
|
||||
libjpeg-turbo/simd/x86_64/jsimd.c
|
||||
libjpeg-turbo/simd/x86_64/jsimdcpu.asm
|
||||
libjpeg-turbo/simd/x86_64/jfdctflt-sse.asm
|
||||
libjpeg-turbo/simd/x86_64/jccolor-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jcgray-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jchuff-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jcphuff-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jcsample-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jdcolor-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jdmerge-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jdsample-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jfdctfst-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jfdctint-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jidctflt-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jidctfst-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jidctint-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jidctred-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jquantf-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jquanti-sse2.asm
|
||||
libjpeg-turbo/simd/x86_64/jccolor-avx2.asm
|
||||
libjpeg-turbo/simd/x86_64/jcgray-avx2.asm
|
||||
libjpeg-turbo/simd/x86_64/jcsample-avx2.asm
|
||||
libjpeg-turbo/simd/x86_64/jdcolor-avx2.asm
|
||||
libjpeg-turbo/simd/x86_64/jdmerge-avx2.asm
|
||||
libjpeg-turbo/simd/x86_64/jdsample-avx2.asm
|
||||
libjpeg-turbo/simd/x86_64/jfdctint-avx2.asm
|
||||
libjpeg-turbo/simd/x86_64/jidctint-avx2.asm
|
||||
libjpeg-turbo/simd/x86_64/jquanti-avx2.asm
|
||||
)
|
||||
|
||||
set(CMAKE_ASM_NASM_FLAGS "-D__x86_64__ -DELF -DPIC -I${CMAKE_CURRENT_SOURCE_DIR}/libjpeg-turbo/simd/nasm")
|
||||
|
||||
else ()
|
||||
|
||||
set(LIBJPEG_TURBO_SOURCES
|
||||
${LIBJPEG_TURBO_SOURCES}
|
||||
libjpeg-turbo/jsimd_none.c
|
||||
)
|
||||
|
||||
endif ()
|
||||
|
||||
add_library(jpeg STATIC ${LIBJPEG_TURBO_SOURCES})
|
||||
target_include_directories(jpeg PUBLIC ${LIBJPEG_TURBO_INCLUDES})
|
||||
@@ -1,37 +0,0 @@
|
||||
/* Version ID for the JPEG library.
|
||||
* Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
|
||||
*/
|
||||
#define JPEG_LIB_VERSION 62
|
||||
|
||||
/* libjpeg-turbo version */
|
||||
#define LIBJPEG_TURBO_VERSION 2.1.3
|
||||
|
||||
/* libjpeg-turbo version in integer form */
|
||||
#define LIBJPEG_TURBO_VERSION_NUMBER 2001003
|
||||
|
||||
/* Support arithmetic encoding */
|
||||
#define C_ARITH_CODING_SUPPORTED 1
|
||||
|
||||
/* Support arithmetic decoding */
|
||||
#define D_ARITH_CODING_SUPPORTED 1
|
||||
|
||||
/* Support in-memory source/destination managers */
|
||||
#define MEM_SRCDST_SUPPORTED 1
|
||||
|
||||
/* Use accelerated SIMD routines. */
|
||||
#define WITH_SIMD 1
|
||||
|
||||
/*
|
||||
* Define BITS_IN_JSAMPLE as either
|
||||
* 8 for 8-bit sample values (the usual setting)
|
||||
* 12 for 12-bit sample values
|
||||
* Only 8 and 12 are legal data precisions for lossy JPEG according to the
|
||||
* JPEG standard, and the IJG code does not support anything else!
|
||||
* We do not support run-time selection of data precision, sorry.
|
||||
*/
|
||||
|
||||
#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
|
||||
|
||||
/* Define if your (broken) compiler shifts signed values as if they were
|
||||
unsigned. */
|
||||
/* #undef RIGHT_SHIFT_IS_UNSIGNED */
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 Tarsin Norbin
|
||||
*
|
||||
* This file is part of EhViewer
|
||||
*
|
||||
* EhViewer is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* EhViewer is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* EhViewer. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* libjpeg-turbo build number */
|
||||
#define BUILD "20220523"
|
||||
|
||||
/* Compiler's inline keyword */
|
||||
#undef inline
|
||||
|
||||
/* How to obtain function inlining. */
|
||||
#define INLINE __inline__ __attribute__((always_inline))
|
||||
|
||||
/* How to obtain thread-local storage */
|
||||
#define THREAD_LOCAL __thread
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "libjpeg-turbo"
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "2.1.3"
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#define SIZEOF_SIZE_T __SIZEOF_SIZE_T__
|
||||
|
||||
/* Define if your compiler has __builtin_ctzl() and sizeof(unsigned long) == sizeof(size_t). */
|
||||
#define HAVE_BUILTIN_CTZL
|
||||
|
||||
/* Define to 1 if you have the <intrin.h> header file. */
|
||||
/* #undef HAVE_INTRIN_H */
|
||||
|
||||
#if defined(_MSC_VER) && defined(HAVE_INTRIN_H)
|
||||
#if (SIZEOF_SIZE_T == 8)
|
||||
#define HAVE_BITSCANFORWARD64
|
||||
#elif (SIZEOF_SIZE_T == 4)
|
||||
#define HAVE_BITSCANFORWARD
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__has_attribute)
|
||||
#if __has_attribute(fallthrough)
|
||||
#define FALLTHROUGH __attribute__((fallthrough));
|
||||
#else
|
||||
#define FALLTHROUGH
|
||||
#endif
|
||||
#else
|
||||
#define FALLTHROUGH
|
||||
#endif
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 Tarsin Norbin
|
||||
*
|
||||
* This file is part of EhViewer
|
||||
*
|
||||
* EhViewer is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* EhViewer is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* EhViewer. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jversion.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2010, 2012-2022, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
* This file contains software version identification.
|
||||
*/
|
||||
|
||||
#if JPEG_LIB_VERSION >= 80
|
||||
|
||||
#define JVERSION "8d 15-Jan-2012"
|
||||
|
||||
#elif JPEG_LIB_VERSION >= 70
|
||||
|
||||
#define JVERSION "7 27-Jun-2009"
|
||||
|
||||
#else
|
||||
|
||||
#define JVERSION "6b 27-Mar-1998"
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NOTE: It is our convention to place the authors in the following order:
|
||||
* - libjpeg-turbo authors (2009-) in descending order of the date of their
|
||||
* most recent contribution to the project, then in ascending order of the
|
||||
* date of their first contribution to the project, then in alphabetical
|
||||
* order
|
||||
* - Upstream authors in descending order of the date of the first inclusion of
|
||||
* their code
|
||||
*/
|
||||
|
||||
#define JCOPYRIGHT \
|
||||
"Copyright (C) 2009-2022 D. R. Commander\n" \
|
||||
"Copyright (C) 2015, 2020 Google, Inc.\n" \
|
||||
"Copyright (C) 2019-2020 Arm Limited\n" \
|
||||
"Copyright (C) 2015-2016, 2018 Matthieu Darbois\n" \
|
||||
"Copyright (C) 2011-2016 Siarhei Siamashka\n" \
|
||||
"Copyright (C) 2015 Intel Corporation\n" \
|
||||
"Copyright (C) 2013-2014 Linaro Limited\n" \
|
||||
"Copyright (C) 2013-2014 MIPS Technologies, Inc.\n" \
|
||||
"Copyright (C) 2009, 2012 Pierre Ossman for Cendio AB\n" \
|
||||
"Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
|
||||
"Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
|
||||
"Copyright (C) 1991-2020 Thomas G. Lane, Guido Vollbeding"
|
||||
|
||||
#define JCOPYRIGHT_SHORT \
|
||||
"Copyright (C) 1991-2022 The libjpeg-turbo Project and many others"
|
||||
Submodule native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo deleted from 3331f85edc.
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020, D. R. Commander. All Rights Reserved.
|
||||
* Copyright (C) 2020-2021, Arm Limited. All Rights Reserved.
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#define HAVE_VLD1_S16_X3
|
||||
#define HAVE_VLD1_U16_X2
|
||||
#define HAVE_VLD1Q_U8_X4
|
||||
|
||||
/* Define compiler-independent count-leading-zeros and byte-swap macros */
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#define BUILTIN_CLZ(x) _CountLeadingZeros(x)
|
||||
#define BUILTIN_CLZLL(x) _CountLeadingZeros64(x)
|
||||
#define BUILTIN_BSWAP64(x) _byteswap_uint64(x)
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
#define BUILTIN_CLZ(x) __builtin_clz(x)
|
||||
#define BUILTIN_CLZLL(x) __builtin_clzll(x)
|
||||
#define BUILTIN_BSWAP64(x) __builtin_bswap64(x)
|
||||
#else
|
||||
#error "Unknown compiler"
|
||||
#endif
|
||||
@@ -1,97 +0,0 @@
|
||||
# Copyright 2018 Hippo Seven
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(png C)
|
||||
|
||||
set(LIBPNG_SOURCES
|
||||
libpng/png.c
|
||||
libpng/pngerror.c
|
||||
libpng/pngget.c
|
||||
libpng/pngmem.c
|
||||
libpng/pngpread.c
|
||||
libpng/pngread.c
|
||||
libpng/pngrio.c
|
||||
libpng/pngrtran.c
|
||||
libpng/pngrutil.c
|
||||
libpng/pngset.c
|
||||
libpng/pngtrans.c
|
||||
)
|
||||
|
||||
set(LIBPNG_INCLUDES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libpng
|
||||
)
|
||||
set(LIBPNG_DEFINITIONS)
|
||||
set(LIBPNG_LIBRARIES z)
|
||||
|
||||
if (${ANDROID_ABI} STREQUAL "armeabi-v7a")
|
||||
|
||||
enable_language(ASM)
|
||||
|
||||
set(LIBPNG_SOURCES
|
||||
${LIBPNG_SOURCES}
|
||||
libpng/arm/arm_init.c
|
||||
libpng/arm/filter_neon.S
|
||||
${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c
|
||||
)
|
||||
set(LIBPNG_INCLUDES
|
||||
${LIBPNG_INCLUDES}
|
||||
${ANDROID_NDK}/sources/android/cpufeatures
|
||||
)
|
||||
set(LIBPNG_DEFINITIONS
|
||||
${LIBPNG_DEFINITIONS}
|
||||
-DPNG_ARM_NEON_API_SUPPORTED
|
||||
-DPNG_ARM_NEON_CHECK_SUPPORTED
|
||||
-DPNG_ARM_NEON_OPT=1
|
||||
-DPNG_ARM_NEON_IMPLEMENTATION=2
|
||||
-DPNG_ARM_NEON_FILE=\"contrib/arm-neon/android-ndk.c\"
|
||||
)
|
||||
set(LIBPNG_LIBRARIES
|
||||
${LIBPNG_LIBRARIES}
|
||||
)
|
||||
|
||||
elseif (${ANDROID_ABI} STREQUAL "arm64-v8a")
|
||||
|
||||
enable_language(ASM)
|
||||
|
||||
set(LIBPNG_SOURCES
|
||||
${LIBPNG_SOURCES}
|
||||
libpng/arm/arm_init.c
|
||||
libpng/arm/filter_neon_intrinsics.c
|
||||
libpng/arm/palette_neon_intrinsics.c
|
||||
${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c
|
||||
)
|
||||
set(LIBPNG_INCLUDES
|
||||
${LIBPNG_INCLUDES}
|
||||
${ANDROID_NDK}/sources/android/cpufeatures
|
||||
)
|
||||
set(LIBPNG_DEFINITIONS
|
||||
${LIBPNG_DEFINITIONS}
|
||||
-DPNG_ARM_NEON_API_SUPPORTED
|
||||
-DPNG_ARM_NEON_CHECK_SUPPORTED
|
||||
-DPNG_ARM_NEON_OPT=1
|
||||
-DPNG_ARM_NEON_IMPLEMENTATION=1
|
||||
-DPNG_ARM_NEON_FILE=\"contrib/arm-neon/android-ndk.c\"
|
||||
)
|
||||
set(LIBPNG_LIBRARIES
|
||||
${LIBPNG_LIBRARIES}
|
||||
)
|
||||
|
||||
endif ()
|
||||
|
||||
add_library(png STATIC ${LIBPNG_SOURCES})
|
||||
target_include_directories(png PUBLIC ${LIBPNG_INCLUDES})
|
||||
target_compile_definitions(png PRIVATE ${LIBPNG_DEFINITIONS})
|
||||
target_link_libraries(png PRIVATE ${LIBPNG_LIBRARIES})
|
||||
Submodule native/src/main/jni/image/libpng/libpng deleted from c81fed4715.
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 Tarsin Norbin
|
||||
*
|
||||
* This file is part of EhViewer
|
||||
*
|
||||
* EhViewer is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* EhViewer is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* EhViewer. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* libpng 1.6.34 STANDARD API DEFINITION */
|
||||
|
||||
/* pnglibconf.h - library build configuration */
|
||||
|
||||
/* Libpng version 1.6.34 - September 29, 2017 */
|
||||
|
||||
/* Copyright (c) 1998-2017 Glenn Randers-Pehrson */
|
||||
|
||||
/* This code is released under the libpng license. */
|
||||
/* For conditions of distribution and use, see the disclaimer */
|
||||
/* and license in png.h */
|
||||
|
||||
/* pnglibconf.h */
|
||||
/* Machine generated file: DO NOT EDIT */
|
||||
/* Derived from: scripts/pnglibconf.dfa */
|
||||
#ifndef PNGLCONF_H
|
||||
#define PNGLCONF_H
|
||||
/* options */
|
||||
#define PNG_16BIT_SUPPORTED
|
||||
#define PNG_ALIGNED_MEMORY_SUPPORTED
|
||||
/*#undef PNG_ARM_NEON_API_SUPPORTED*/
|
||||
/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
|
||||
/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/
|
||||
/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/
|
||||
#define PNG_BENIGN_ERRORS_SUPPORTED
|
||||
#define PNG_BENIGN_READ_ERRORS_SUPPORTED
|
||||
/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
|
||||
#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
|
||||
#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
|
||||
#define PNG_COLORSPACE_SUPPORTED
|
||||
#define PNG_CONSOLE_IO_SUPPORTED
|
||||
#define PNG_CONVERT_tIME_SUPPORTED
|
||||
#define PNG_EASY_ACCESS_SUPPORTED
|
||||
/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/
|
||||
#define PNG_ERROR_TEXT_SUPPORTED
|
||||
#define PNG_FIXED_POINT_SUPPORTED
|
||||
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
|
||||
#define PNG_FLOATING_POINT_SUPPORTED
|
||||
#define PNG_FORMAT_AFIRST_SUPPORTED
|
||||
#define PNG_FORMAT_BGR_SUPPORTED
|
||||
#define PNG_GAMMA_SUPPORTED
|
||||
#define PNG_GET_PALETTE_MAX_SUPPORTED
|
||||
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
||||
#define PNG_INCH_CONVERSIONS_SUPPORTED
|
||||
#define PNG_INFO_IMAGE_SUPPORTED
|
||||
#define PNG_IO_STATE_SUPPORTED
|
||||
#define PNG_MNG_FEATURES_SUPPORTED
|
||||
#define PNG_POINTER_INDEXING_SUPPORTED
|
||||
#define PNG_PROGRESSIVE_READ_SUPPORTED
|
||||
#define PNG_READ_16BIT_SUPPORTED
|
||||
#define PNG_READ_ALPHA_MODE_SUPPORTED
|
||||
#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_BACKGROUND_SUPPORTED
|
||||
#define PNG_READ_BGR_SUPPORTED
|
||||
#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
|
||||
#define PNG_READ_COMPOSITE_NODIV_SUPPORTED
|
||||
#define PNG_READ_COMPRESSED_TEXT_SUPPORTED
|
||||
#define PNG_READ_EXPAND_16_SUPPORTED
|
||||
#define PNG_READ_EXPAND_SUPPORTED
|
||||
#define PNG_READ_FILLER_SUPPORTED
|
||||
#define PNG_READ_GAMMA_SUPPORTED
|
||||
#define PNG_READ_GET_PALETTE_MAX_SUPPORTED
|
||||
#define PNG_READ_GRAY_TO_RGB_SUPPORTED
|
||||
#define PNG_READ_INTERLACING_SUPPORTED
|
||||
#define PNG_READ_INT_FUNCTIONS_SUPPORTED
|
||||
#define PNG_READ_INVERT_ALPHA_SUPPORTED
|
||||
#define PNG_READ_INVERT_SUPPORTED
|
||||
#define PNG_READ_OPT_PLTE_SUPPORTED
|
||||
#define PNG_READ_PACKSWAP_SUPPORTED
|
||||
#define PNG_READ_PACK_SUPPORTED
|
||||
#define PNG_READ_QUANTIZE_SUPPORTED
|
||||
#define PNG_READ_RGB_TO_GRAY_SUPPORTED
|
||||
#define PNG_READ_SCALE_16_TO_8_SUPPORTED
|
||||
#define PNG_READ_SHIFT_SUPPORTED
|
||||
#define PNG_READ_STRIP_16_TO_8_SUPPORTED
|
||||
#define PNG_READ_STRIP_ALPHA_SUPPORTED
|
||||
#define PNG_READ_SUPPORTED
|
||||
#define PNG_READ_SWAP_ALPHA_SUPPORTED
|
||||
#define PNG_READ_SWAP_SUPPORTED
|
||||
#define PNG_READ_TEXT_SUPPORTED
|
||||
#define PNG_READ_TRANSFORMS_SUPPORTED
|
||||
#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_USER_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_USER_TRANSFORM_SUPPORTED
|
||||
#define PNG_READ_bKGD_SUPPORTED
|
||||
#define PNG_READ_cHRM_SUPPORTED
|
||||
#define PNG_READ_eXIf_SUPPORTED
|
||||
#define PNG_READ_gAMA_SUPPORTED
|
||||
#define PNG_READ_hIST_SUPPORTED
|
||||
#define PNG_READ_iCCP_SUPPORTED
|
||||
#define PNG_READ_iTXt_SUPPORTED
|
||||
#define PNG_READ_oFFs_SUPPORTED
|
||||
#define PNG_READ_pCAL_SUPPORTED
|
||||
#define PNG_READ_pHYs_SUPPORTED
|
||||
#define PNG_READ_sBIT_SUPPORTED
|
||||
#define PNG_READ_sCAL_SUPPORTED
|
||||
#define PNG_READ_sPLT_SUPPORTED
|
||||
#define PNG_READ_sRGB_SUPPORTED
|
||||
#define PNG_READ_tEXt_SUPPORTED
|
||||
#define PNG_READ_tIME_SUPPORTED
|
||||
#define PNG_READ_tRNS_SUPPORTED
|
||||
#define PNG_READ_zTXt_SUPPORTED
|
||||
/*#undef PNG_SAVE_INT_32_SUPPORTED*/
|
||||
#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_SEQUENTIAL_READ_SUPPORTED
|
||||
#define PNG_SETJMP_SUPPORTED
|
||||
#define PNG_SET_OPTION_SUPPORTED
|
||||
#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_SET_USER_LIMITS_SUPPORTED
|
||||
/*#undef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED*/
|
||||
/*#undef PNG_SIMPLIFIED_READ_BGR_SUPPORTED*/
|
||||
/*#undef PNG_SIMPLIFIED_READ_SUPPORTED*/
|
||||
/*#undef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED*/
|
||||
/*#undef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED*/
|
||||
/*#undef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED*/
|
||||
/*#undef PNG_SIMPLIFIED_WRITE_SUPPORTED*/
|
||||
/*#undef PNG_STDIO_SUPPORTED*/
|
||||
#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_TEXT_SUPPORTED
|
||||
#define PNG_TIME_RFC1123_SUPPORTED
|
||||
#define PNG_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_USER_CHUNKS_SUPPORTED
|
||||
#define PNG_USER_LIMITS_SUPPORTED
|
||||
#define PNG_USER_MEM_SUPPORTED
|
||||
#define PNG_USER_TRANSFORM_INFO_SUPPORTED
|
||||
#define PNG_USER_TRANSFORM_PTR_SUPPORTED
|
||||
#define PNG_WARNINGS_SUPPORTED
|
||||
/*
|
||||
#define PNG_WRITE_16BIT_SUPPORTED
|
||||
#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
|
||||
#define PNG_WRITE_BGR_SUPPORTED
|
||||
#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
|
||||
#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
|
||||
#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
|
||||
#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
|
||||
#define PNG_WRITE_FILLER_SUPPORTED
|
||||
#define PNG_WRITE_FILTER_SUPPORTED
|
||||
#define PNG_WRITE_FLUSH_SUPPORTED
|
||||
#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED
|
||||
#define PNG_WRITE_INTERLACING_SUPPORTED
|
||||
#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
|
||||
#define PNG_WRITE_INVERT_ALPHA_SUPPORTED
|
||||
#define PNG_WRITE_INVERT_SUPPORTED
|
||||
#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
|
||||
#define PNG_WRITE_PACKSWAP_SUPPORTED
|
||||
#define PNG_WRITE_PACK_SUPPORTED
|
||||
#define PNG_WRITE_SHIFT_SUPPORTED
|
||||
#define PNG_WRITE_SUPPORTED
|
||||
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
|
||||
#define PNG_WRITE_SWAP_SUPPORTED
|
||||
#define PNG_WRITE_TEXT_SUPPORTED
|
||||
#define PNG_WRITE_TRANSFORMS_SUPPORTED
|
||||
#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
|
||||
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||
#define PNG_WRITE_bKGD_SUPPORTED
|
||||
#define PNG_WRITE_cHRM_SUPPORTED
|
||||
#define PNG_WRITE_eXIf_SUPPORTED
|
||||
#define PNG_WRITE_gAMA_SUPPORTED
|
||||
#define PNG_WRITE_hIST_SUPPORTED
|
||||
#define PNG_WRITE_iCCP_SUPPORTED
|
||||
#define PNG_WRITE_iTXt_SUPPORTED
|
||||
#define PNG_WRITE_oFFs_SUPPORTED
|
||||
#define PNG_WRITE_pCAL_SUPPORTED
|
||||
#define PNG_WRITE_pHYs_SUPPORTED
|
||||
#define PNG_WRITE_sBIT_SUPPORTED
|
||||
#define PNG_WRITE_sCAL_SUPPORTED
|
||||
#define PNG_WRITE_sPLT_SUPPORTED
|
||||
#define PNG_WRITE_sRGB_SUPPORTED
|
||||
#define PNG_WRITE_tEXt_SUPPORTED
|
||||
#define PNG_WRITE_tIME_SUPPORTED
|
||||
#define PNG_WRITE_tRNS_SUPPORTED
|
||||
#define PNG_WRITE_zTXt_SUPPORTED
|
||||
*/
|
||||
#define PNG_bKGD_SUPPORTED
|
||||
#define PNG_cHRM_SUPPORTED
|
||||
#define PNG_eXIf_SUPPORTED
|
||||
#define PNG_gAMA_SUPPORTED
|
||||
#define PNG_hIST_SUPPORTED
|
||||
#define PNG_iCCP_SUPPORTED
|
||||
#define PNG_iTXt_SUPPORTED
|
||||
#define PNG_oFFs_SUPPORTED
|
||||
#define PNG_pCAL_SUPPORTED
|
||||
#define PNG_pHYs_SUPPORTED
|
||||
#define PNG_sBIT_SUPPORTED
|
||||
#define PNG_sCAL_SUPPORTED
|
||||
#define PNG_sPLT_SUPPORTED
|
||||
#define PNG_sRGB_SUPPORTED
|
||||
#define PNG_tEXt_SUPPORTED
|
||||
#define PNG_tIME_SUPPORTED
|
||||
#define PNG_tRNS_SUPPORTED
|
||||
#define PNG_zTXt_SUPPORTED
|
||||
/* end of options */
|
||||
/* apng */
|
||||
#define PNG_APNG_SUPPORTED
|
||||
#define PNG_READ_APNG_SUPPORTED
|
||||
/*#undef PNG_WRITE_APNG_SUPPORTED*/
|
||||
/* end of apng */
|
||||
/* settings */
|
||||
#define PNG_API_RULE 0
|
||||
#define PNG_DEFAULT_READ_MACROS 1
|
||||
#define PNG_GAMMA_THRESHOLD_FIXED 5000
|
||||
#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
|
||||
#define PNG_INFLATE_BUF_SIZE 1024
|
||||
#define PNG_LINKAGE_API extern
|
||||
#define PNG_LINKAGE_CALLBACK extern
|
||||
#define PNG_LINKAGE_DATA extern
|
||||
#define PNG_LINKAGE_FUNCTION extern
|
||||
#define PNG_MAX_GAMMA_8 11
|
||||
#define PNG_QUANTIZE_BLUE_BITS 5
|
||||
#define PNG_QUANTIZE_GREEN_BITS 5
|
||||
#define PNG_QUANTIZE_RED_BITS 5
|
||||
#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1)
|
||||
#define PNG_TEXT_Z_DEFAULT_STRATEGY 0
|
||||
#define PNG_USER_CHUNK_CACHE_MAX 1000
|
||||
#define PNG_USER_CHUNK_MALLOC_MAX 8000000
|
||||
#define PNG_USER_HEIGHT_MAX 1000000
|
||||
#define PNG_USER_WIDTH_MAX 1000000
|
||||
#define PNG_ZBUF_SIZE 8192
|
||||
#define PNG_ZLIB_VERNUM 0 /* unknown */
|
||||
#define PNG_Z_DEFAULT_COMPRESSION (-1)
|
||||
#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
|
||||
#define PNG_Z_DEFAULT_STRATEGY 1
|
||||
#define PNG_sCAL_PRECISION 5
|
||||
#define PNG_sRGB_PROFILE_CHECKS 2
|
||||
/* end of settings */
|
||||
#endif /* PNGLCONF_H */
|
||||
@@ -1,27 +0,0 @@
|
||||
# Copyright 2015 Hippo Seven
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := stream
|
||||
LOCAL_SRC_FILES := \
|
||||
input_stream.c \
|
||||
input_stream_pipe.c \
|
||||
output_stream.c \
|
||||
output_stream_pipe.c \
|
||||
patch_head_input_stream.c
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
@@ -1,28 +0,0 @@
|
||||
# Copyright 2018 Hippo Seven
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(stream C)
|
||||
|
||||
set(STREAM_SOURCES
|
||||
input_stream.c
|
||||
input_stream_pipe.c
|
||||
output_stream.c
|
||||
output_stream_pipe.c
|
||||
patch_head_input_stream.c
|
||||
)
|
||||
set(STREAM_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_library(stream STATIC ${STREAM_SOURCES})
|
||||
target_include_directories(stream PUBLIC ${STREAM_INCLUDES})
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/28/2015.
|
||||
//
|
||||
|
||||
#ifndef STREAM_CONFIG_H
|
||||
#define STREAM_CONFIG_H
|
||||
|
||||
#define STREAM_SUPPORT_INPUT
|
||||
//#define STREAM_SUPPORT_INPUT_PIPE
|
||||
#define STREAM_SUPPORT_INPUT_PATCH_HEAD
|
||||
#define STREAM_SUPPORT_OUTPUT
|
||||
//#define STREAM_SUPPORT_OUTPUT_PIPE
|
||||
|
||||
#endif // STREAM_CONFIG_H
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 10/19/2015.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
#ifdef STREAM_SUPPORT_INPUT
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../log.h"
|
||||
#include "../utils.h"
|
||||
#include "input_stream.h"
|
||||
#include "stream_utils.h"
|
||||
|
||||
InputStream* create_input_stream(JNIEnv* env, jobject is)
|
||||
{
|
||||
jclass streamCls = (*env)->GetObjectClass(env, is);
|
||||
jmethodID readMID = (*env)->GetMethodID(env, streamCls, "read", "([BII)I");
|
||||
jmethodID closeMID = (*env)->GetMethodID(env, streamCls, "close", "()V");
|
||||
jbyteArray buffer;
|
||||
|
||||
if (readMID == NULL || closeMID == NULL) {
|
||||
LOGE(MSG("Can't get read or close method id"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = (*env)->NewByteArray(env, BUFFER_SIZE);
|
||||
buffer = (*env)->NewGlobalRef(env, buffer);
|
||||
if (buffer == NULL) {
|
||||
LOGE(MSG("Can't create buffer"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
InputStream* inputStream = (InputStream*) malloc(sizeof(InputStream));
|
||||
if (inputStream == NULL) {
|
||||
LOGE(MSG("Out of memory"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inputStream->is = (*env)->NewGlobalRef(env, is);
|
||||
inputStream->readMID = readMID;
|
||||
inputStream->closeMID = closeMID;
|
||||
inputStream->buffer = buffer;
|
||||
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
void destroy_input_stream(JNIEnv* env, InputStream** inputStream)
|
||||
{
|
||||
if (inputStream != NULL && *inputStream != NULL) {
|
||||
(*env)->DeleteGlobalRef(env, (*inputStream)->is);
|
||||
(*env)->DeleteGlobalRef(env, (*inputStream)->buffer);
|
||||
free(*inputStream);
|
||||
*inputStream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
size_t read_input_stream(JNIEnv* env, InputStream* inputStream, unsigned char* buffer, int offset, size_t size)
|
||||
{
|
||||
size_t remainSize = size;
|
||||
size_t readSize = 0;
|
||||
int bufferOffset = offset;
|
||||
int len;
|
||||
|
||||
while (remainSize > 0) {
|
||||
len = MIN(BUFFER_SIZE, remainSize);
|
||||
|
||||
len = (*env)->CallIntMethod(env, inputStream->is, inputStream->readMID, inputStream->buffer, 0, len);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
LOGE(MSG("Catch exception"));
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
len = -1;
|
||||
}
|
||||
|
||||
// end of the stream or catch exception
|
||||
if (len < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
(*env)->GetByteArrayRegion(env, inputStream->buffer, 0, len, (jbyte *) (buffer + bufferOffset));
|
||||
|
||||
remainSize -= len;
|
||||
readSize += len;
|
||||
bufferOffset += len;
|
||||
}
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
void close_input_stream(JNIEnv* env, InputStream* inputStream)
|
||||
{
|
||||
(*env)->CallVoidMethod(env, inputStream->is, inputStream->closeMID);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
LOGE(MSG("Catch exception"));
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // STREAM_SUPPORT_INPUT
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 10/19/2015.
|
||||
//
|
||||
|
||||
#ifndef STREAM_INPUT_STREAM_H
|
||||
#define STREAM_INPUT_STREAM_H
|
||||
|
||||
#include "config.h"
|
||||
#ifdef STREAM_SUPPORT_INPUT
|
||||
|
||||
#include <jni.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
jobject is;
|
||||
jmethodID readMID;
|
||||
jmethodID closeMID;
|
||||
jbyteArray buffer;
|
||||
} InputStream;
|
||||
|
||||
InputStream* create_input_stream(JNIEnv* env, jobject is);
|
||||
void destroy_input_stream(JNIEnv* env, InputStream** inputStream);
|
||||
size_t read_input_stream(JNIEnv* env, InputStream* inputStream, unsigned char* buffer, int offset, size_t size);
|
||||
void close_input_stream(JNIEnv* env, InputStream* inputStream);
|
||||
|
||||
#endif // STREAM_SUPPORT_INPUT
|
||||
|
||||
#endif // STREAM_INPUT_STREAM_H
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 10/19/2015.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
#if defined(STREAM_SUPPORT_INPUT) && defined(STREAM_SUPPORT_INPUT_PIPE)
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "input_stream_pipe.h"
|
||||
#include "../log.h"
|
||||
|
||||
InputStreamPipe* create_input_stream_pipe(JNIEnv* env, jobject isPipe)
|
||||
{
|
||||
jclass streamPipeCls = (*env)->GetObjectClass(env, isPipe);
|
||||
jmethodID obtainMID = (*env)->GetMethodID(env, streamPipeCls, "obtain", "()V");
|
||||
jmethodID releaseMID = (*env)->GetMethodID(env, streamPipeCls, "release", "()V");
|
||||
jmethodID openMID = (*env)->GetMethodID(env, streamPipeCls, "open", "()Ljava/io/InputStream;");
|
||||
jmethodID closeMID = (*env)->GetMethodID(env, streamPipeCls, "close", "()V");
|
||||
|
||||
if (obtainMID == NULL || releaseMID == NULL || openMID == NULL || closeMID == NULL) {
|
||||
LOGE(MSG("Can't get method id"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
InputStreamPipe* inputStreamPipe = (InputStreamPipe*) malloc(sizeof(InputStreamPipe));
|
||||
if (inputStreamPipe == NULL) {
|
||||
LOGE(MSG("Out of memory"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inputStreamPipe->isPipe = (*env)->NewGlobalRef(env, isPipe);
|
||||
inputStreamPipe->obtainMID = obtainMID;
|
||||
inputStreamPipe->releaseMID = releaseMID;
|
||||
inputStreamPipe->openMID = openMID;
|
||||
inputStreamPipe->closeMID = closeMID;
|
||||
|
||||
return inputStreamPipe;
|
||||
}
|
||||
|
||||
void destroy_input_stream_pipe(JNIEnv* env, InputStreamPipe** inputStreamPipe)
|
||||
{
|
||||
if (inputStreamPipe != NULL && *inputStreamPipe != NULL) {
|
||||
(*env)->DeleteGlobalRef(env, (*inputStreamPipe)->isPipe);
|
||||
free(*inputStreamPipe);
|
||||
*inputStreamPipe = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void obtain_input_stream_pipe(JNIEnv* env, InputStreamPipe* inputStreamPipe)
|
||||
{
|
||||
(*env)->CallVoidMethod(env, inputStreamPipe->isPipe, inputStreamPipe->obtainMID);
|
||||
}
|
||||
|
||||
void release_input_stream_pipe(JNIEnv* env, InputStreamPipe* inputStreamPipe)
|
||||
{
|
||||
(*env)->CallVoidMethod(env, inputStreamPipe->isPipe, inputStreamPipe->releaseMID);
|
||||
}
|
||||
|
||||
InputStream* open_input_stream_from_pipe(JNIEnv* env, InputStreamPipe* inputStreamPipe)
|
||||
{
|
||||
jobject is = (*env)->CallObjectMethod(env, inputStreamPipe->isPipe, inputStreamPipe->openMID);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
LOGE(MSG("Catch exception"));
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return create_input_stream(env, is);
|
||||
}
|
||||
|
||||
void close_input_stream_from_pipe(JNIEnv* env, InputStreamPipe* inputStreamPipe)
|
||||
{
|
||||
(*env)->CallVoidMethod(env, inputStreamPipe->isPipe, inputStreamPipe->closeMID);
|
||||
}
|
||||
|
||||
#endif // STREAM_SUPPORT_INPUT && STREAM_SUPPORT_INPUT_PIPE
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 10/19/2015.
|
||||
//
|
||||
|
||||
#ifndef STREAM_INPUT_STREAM_PIPE_H
|
||||
#define STREAM_INPUT_STREAM_PIPE_H
|
||||
|
||||
#include "config.h"
|
||||
#if defined(STREAM_SUPPORT_INPUT) && defined(STREAM_SUPPORT_INPUT_PIPE)
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "input_stream.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
jobject isPipe;
|
||||
jmethodID obtainMID;
|
||||
jmethodID releaseMID;
|
||||
jmethodID openMID;
|
||||
jmethodID closeMID;
|
||||
} InputStreamPipe;
|
||||
|
||||
InputStreamPipe* create_input_stream_pipe(JNIEnv* env, jobject isPipe);
|
||||
void destroy_input_stream_pipe(JNIEnv* env, InputStreamPipe** inputStreamPipe);
|
||||
void obtain_input_stream_pipe(JNIEnv* env, InputStreamPipe* inputStreamPipe);
|
||||
void release_input_stream_pipe(JNIEnv* env, InputStreamPipe* inputStreamPipe);
|
||||
InputStream* open_input_stream_from_pipe(JNIEnv* env, InputStreamPipe* inputStreamPipe);
|
||||
void close_input_stream_from_pipe(JNIEnv* env, InputStreamPipe* inputStreamPipe);
|
||||
|
||||
#endif // STREAM_SUPPORT_INPUT && STREAM_SUPPORT_INPUT_PIPE
|
||||
|
||||
#endif // STREAM_INPUT_STREAM_PIPE_H
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 10/19/2015.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
#ifdef STREAM_SUPPORT_OUTPUT
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../log.h"
|
||||
#include "../utils.h"
|
||||
#include "output_stream.h"
|
||||
#include "stream_utils.h"
|
||||
|
||||
OutputStream* create_output_stream(JNIEnv* env, jobject os)
|
||||
{
|
||||
jclass streamCls = (*env)->GetObjectClass(env, os);
|
||||
jmethodID writeMID = (*env)->GetMethodID(env, streamCls, "write", "([BII)V");
|
||||
jmethodID closeMID = (*env)->GetMethodID(env, streamCls, "close", "()V");
|
||||
jbyteArray buffer;
|
||||
|
||||
if (writeMID == NULL || closeMID == NULL) {
|
||||
LOGE(MSG("Can't get write or close method id"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = (*env)->NewByteArray(env, BUFFER_SIZE);
|
||||
buffer = (*env)->NewGlobalRef(env, buffer);
|
||||
if (buffer == NULL) {
|
||||
LOGE(MSG("Can't create buffer"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OutputStream* outputStream = (OutputStream*) malloc(sizeof(OutputStream));
|
||||
if (outputStream == NULL) {
|
||||
LOGE(MSG("Out of memory"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
outputStream->os = (*env)->NewGlobalRef(env, os);
|
||||
outputStream->writeMID = writeMID;
|
||||
outputStream->closeMID = closeMID;
|
||||
outputStream->buffer = buffer;
|
||||
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
void destroy_output_stream(JNIEnv* env, OutputStream** outputStream)
|
||||
{
|
||||
if (outputStream != NULL && *outputStream != NULL) {
|
||||
(*env)->DeleteGlobalRef(env, (*outputStream)->os);
|
||||
(*env)->DeleteGlobalRef(env, (*outputStream)->buffer);
|
||||
free(*outputStream);
|
||||
*outputStream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
size_t write_output_stream(JNIEnv* env, OutputStream* outputStream, const unsigned char* buffer, int offset, size_t size)
|
||||
{
|
||||
size_t remainSize = size;
|
||||
size_t readSize = 0;
|
||||
int bufferOffset = offset;
|
||||
int len;
|
||||
|
||||
while (remainSize > 0) {
|
||||
len = MIN(BUFFER_SIZE, remainSize);
|
||||
|
||||
// Copy date from buffer to outputStream->buffer
|
||||
(*env)->SetByteArrayRegion(env, outputStream->buffer, 0, len, (jbyte *) (buffer + bufferOffset));
|
||||
|
||||
// Invoke OutputStream.write
|
||||
(*env)->CallVoidMethod(env, outputStream->os, outputStream->writeMID, outputStream->buffer, 0, len);
|
||||
|
||||
// Catch exception
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
LOGE(MSG("Catch exception"));
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
break;
|
||||
}
|
||||
|
||||
remainSize -= len;
|
||||
readSize += len;
|
||||
bufferOffset += len;
|
||||
}
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
void close_output_stream(JNIEnv* env, OutputStream* outputStream)
|
||||
{
|
||||
(*env)->CallVoidMethod(env, outputStream->os, outputStream->closeMID);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
LOGE(MSG("Catch exception"));
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // STREAM_SUPPORT_OUTPUT
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 10/19/2015.
|
||||
//
|
||||
|
||||
#ifndef STREAM_OUTPUT_STREAM_H
|
||||
#define STREAM_OUTPUT_STREAM_H
|
||||
|
||||
#include "config.h"
|
||||
#ifdef STREAM_SUPPORT_OUTPUT
|
||||
|
||||
#include <jni.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
jobject os;
|
||||
jmethodID writeMID;
|
||||
jmethodID closeMID;
|
||||
jbyteArray buffer;
|
||||
} OutputStream;
|
||||
|
||||
OutputStream* create_output_stream(JNIEnv* env, jobject os);
|
||||
void destroy_output_stream(JNIEnv* env, OutputStream** outputStream);
|
||||
size_t write_output_stream(JNIEnv* env, OutputStream* outputStream, const unsigned char* buffer, int offset, size_t size);
|
||||
void close_output_stream(JNIEnv* env, OutputStream* outputStream);
|
||||
|
||||
#endif // STREAM_SUPPORT_OUTPUT
|
||||
|
||||
#endif // STREAM_OUTPUT_STREAM_H
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 10/19/2015.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
#if defined(STREAM_SUPPORT_OUTPUT) && defined(STREAM_SUPPORT_OUTPUT_PIPE)
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "output_stream_pipe.h"
|
||||
#include "../log.h"
|
||||
|
||||
OutputStreamPipe* create_output_stream_pipe(JNIEnv* env, jobject osPipe)
|
||||
{
|
||||
jclass streamPipeCls = (*env)->GetObjectClass(env, osPipe);
|
||||
jmethodID obtainMID = (*env)->GetMethodID(env, streamPipeCls, "obtain", "()V");
|
||||
jmethodID releaseMID = (*env)->GetMethodID(env, streamPipeCls, "release", "()V");
|
||||
jmethodID openMID = (*env)->GetMethodID(env, streamPipeCls, "open", "()Ljava/io/OutputStream;");
|
||||
jmethodID closeMID = (*env)->GetMethodID(env, streamPipeCls, "close", "()V");
|
||||
|
||||
if (obtainMID == NULL || releaseMID == NULL || openMID == NULL || closeMID == NULL) {
|
||||
LOGE(MSG("Can't get method id"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OutputStreamPipe* outputStreamPipe = (OutputStreamPipe*) malloc(sizeof(OutputStreamPipe));
|
||||
if (outputStreamPipe == NULL) {
|
||||
LOGE(MSG("Out of memory"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
outputStreamPipe->osPipe = (*env)->NewGlobalRef(env, osPipe);
|
||||
outputStreamPipe->obtainMID = obtainMID;
|
||||
outputStreamPipe->releaseMID = releaseMID;
|
||||
outputStreamPipe->openMID = openMID;
|
||||
outputStreamPipe->closeMID = closeMID;
|
||||
|
||||
return outputStreamPipe;
|
||||
}
|
||||
|
||||
void destroy_output_stream_pipe(JNIEnv* env, OutputStreamPipe** outputStreamPipe)
|
||||
{
|
||||
if (outputStreamPipe != NULL && *outputStreamPipe != NULL) {
|
||||
(*env)->DeleteGlobalRef(env, (*outputStreamPipe)->osPipe);
|
||||
free(*outputStreamPipe);
|
||||
*outputStreamPipe = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void obtain_output_stream_pipe(JNIEnv* env, OutputStreamPipe* outputStreamPipe)
|
||||
{
|
||||
(*env)->CallVoidMethod(env, outputStreamPipe->osPipe, outputStreamPipe->obtainMID);
|
||||
}
|
||||
|
||||
void release_output_stream_pipe(JNIEnv* env, OutputStreamPipe* outputStreamPipe)
|
||||
{
|
||||
(*env)->CallVoidMethod(env, outputStreamPipe->osPipe, outputStreamPipe->releaseMID);
|
||||
}
|
||||
|
||||
OutputStream* open_output_stream_from_pipe(JNIEnv* env, OutputStreamPipe* outputStreamPipe)
|
||||
{
|
||||
jobject os = (*env)->CallObjectMethod(env, outputStreamPipe->osPipe, outputStreamPipe->openMID);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
LOGE(MSG("Catch exception"));
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return create_output_stream(env, os);
|
||||
}
|
||||
|
||||
void close_output_stream_from_pipe(JNIEnv* env, OutputStreamPipe* outputStreamPipe)
|
||||
{
|
||||
(*env)->CallVoidMethod(env, outputStreamPipe->osPipe, outputStreamPipe->closeMID);
|
||||
}
|
||||
|
||||
#endif // STREAM_SUPPORT_OUTPUT && STREAM_SUPPORT_OUTPUT_PIPE
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 10/19/2015.
|
||||
//
|
||||
|
||||
#ifndef STREAM_OUTPUT_STREAM_PIPE_H
|
||||
#define STREAM_OUTPUT_STREAM_PIPE_H
|
||||
|
||||
#include "config.h"
|
||||
#if defined(STREAM_SUPPORT_OUTPUT) && defined(STREAM_SUPPORT_OUTPUT_PIPE)
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "output_stream.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
jobject osPipe;
|
||||
jmethodID obtainMID;
|
||||
jmethodID releaseMID;
|
||||
jmethodID openMID;
|
||||
jmethodID closeMID;
|
||||
} OutputStreamPipe;
|
||||
|
||||
OutputStreamPipe* create_output_stream_pipe(JNIEnv* env, jobject osPipe);
|
||||
void destroy_output_stream_pipe(JNIEnv* env, OutputStreamPipe** outputStreamPipe);
|
||||
void obtain_output_stream_pipe(JNIEnv* env, OutputStreamPipe* outputStreamPipe);
|
||||
void release_output_stream_pipe(JNIEnv* env, OutputStreamPipe* outputStreamPipe);
|
||||
OutputStream* open_output_stream_from_pipe(JNIEnv* env, OutputStreamPipe* outputStreamPipe);
|
||||
void close_output_stream_from_pipe(JNIEnv* env, OutputStreamPipe* outputStreamPipe);
|
||||
|
||||
#endif // STREAM_SUPPORT_OUTPUT && STREAM_SUPPORT_OUTPUT_PIPE
|
||||
|
||||
#endif // STREAM_OUTPUT_STREAM_PIPE_H
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 1/1/2016.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
#if defined(STREAM_SUPPORT_INPUT) && defined(STREAM_SUPPORT_INPUT_PATCH_HEAD)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "patch_head_input_stream.h"
|
||||
#include "../log.h"
|
||||
#include "../utils.h"
|
||||
|
||||
#define READ_BUFFER_SIZE (256 * 1024) // 256KB
|
||||
|
||||
PatchHeadInputStream* create_patch_head_input_stream(
|
||||
InputStream* input_stream, const unsigned char* patch, unsigned int patch_length)
|
||||
{
|
||||
unsigned char* patch_copy;
|
||||
|
||||
PatchHeadInputStream* patch_head_input_stream = (PatchHeadInputStream*) malloc(sizeof(PatchHeadInputStream));
|
||||
if (patch_head_input_stream == NULL) {
|
||||
WTF_OM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy patch
|
||||
patch_copy = (unsigned char*) malloc(patch_length * sizeof(char));
|
||||
if (patch_copy == NULL) {
|
||||
WTF_OM;
|
||||
free(patch_head_input_stream);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(patch_copy, patch, patch_length);
|
||||
|
||||
patch_head_input_stream->input_stream = input_stream;
|
||||
patch_head_input_stream->patch = patch_copy;
|
||||
patch_head_input_stream->patch_length = patch_length;
|
||||
patch_head_input_stream->read_count = 0;
|
||||
|
||||
return patch_head_input_stream;
|
||||
}
|
||||
|
||||
size_t read_patch_head_input_stream(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream,
|
||||
unsigned char* buffer, int offset, size_t size)
|
||||
{
|
||||
size_t len = MIN(size, patch_head_input_stream->patch_length - patch_head_input_stream->read_count);
|
||||
int buffer_offset = offset;
|
||||
|
||||
if (len > 0) {
|
||||
memcpy(buffer + buffer_offset, patch_head_input_stream->patch + patch_head_input_stream->read_count, len);
|
||||
patch_head_input_stream->read_count += len;
|
||||
buffer_offset += len;
|
||||
}
|
||||
|
||||
if (size > len) {
|
||||
len += read_input_stream(env, patch_head_input_stream->input_stream, buffer, buffer_offset, size - len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void* read_patch_head_input_stream_all(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, size_t* length)
|
||||
{
|
||||
size_t len = 0;
|
||||
size_t read;
|
||||
void* buffer = NULL;
|
||||
|
||||
buffer = malloc(READ_BUFFER_SIZE);
|
||||
if (buffer == NULL) {
|
||||
WTF_OM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
// Read from stream
|
||||
read = read_patch_head_input_stream(env, patch_head_input_stream, buffer, len, READ_BUFFER_SIZE);
|
||||
len += read;
|
||||
// Check stream end
|
||||
if (read < READ_BUFFER_SIZE) {
|
||||
// Get the end, shrink the buffer
|
||||
buffer = realloc(buffer, len);
|
||||
*length = len;
|
||||
return buffer;
|
||||
}
|
||||
// Extent buffer
|
||||
buffer = realloc(buffer, len + READ_BUFFER_SIZE);
|
||||
if (buffer == NULL) {
|
||||
WTF_OM;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void destroy_patch_head_input_stream(JNIEnv* env, PatchHeadInputStream** patch_head_input_stream)
|
||||
{
|
||||
if (patch_head_input_stream != NULL && *patch_head_input_stream != NULL) {
|
||||
// Free input stream
|
||||
destroy_input_stream(env, &(*patch_head_input_stream)->input_stream);
|
||||
// Free patch
|
||||
free((*patch_head_input_stream)->patch);
|
||||
(*patch_head_input_stream)->patch = NULL;
|
||||
// Free itself
|
||||
free(*patch_head_input_stream);
|
||||
*patch_head_input_stream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void close_patch_head_input_stream(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream)
|
||||
{
|
||||
close_input_stream(env, patch_head_input_stream->input_stream);
|
||||
}
|
||||
|
||||
#endif // STREAM_SUPPORT_INPUT && STREAM_SUPPORT_INPUT_PATCH_HEAD
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 1/1/2016.
|
||||
//
|
||||
|
||||
#ifndef STREAM_PATCH_HEAD_INPUT_STREAM_H
|
||||
#define STREAM_PATCH_HEAD_INPUT_STREAM_H
|
||||
|
||||
#include "config.h"
|
||||
#if defined(STREAM_SUPPORT_INPUT) && defined(STREAM_SUPPORT_INPUT_PATCH_HEAD)
|
||||
|
||||
#include "input_stream.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
InputStream* input_stream;
|
||||
unsigned char* patch;
|
||||
unsigned int patch_length;
|
||||
unsigned int read_count;
|
||||
} PatchHeadInputStream;
|
||||
|
||||
PatchHeadInputStream* create_patch_head_input_stream(
|
||||
InputStream* input_stream, const unsigned char* patch, unsigned int patch_length);
|
||||
void destroy_patch_head_input_stream(JNIEnv* env, PatchHeadInputStream** patch_head_input_stream);
|
||||
size_t read_patch_head_input_stream(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream,
|
||||
unsigned char* buffer, int offset, size_t size);
|
||||
void* read_patch_head_input_stream_all(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, size_t* length);
|
||||
void close_patch_head_input_stream(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream);
|
||||
|
||||
#endif // STREAM_SUPPORT_INPUT && STREAM_SUPPORT_INPUT_PATCH_HEAD
|
||||
|
||||
#endif // STREAM_PATCH_HEAD_INPUT_STREAM_H
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 10/19/2015.
|
||||
//
|
||||
|
||||
#ifndef STREAM_STREAM_UTILS_H
|
||||
#define STREAM_STREAM_UTILS_H
|
||||
|
||||
#define BUFFER_SIZE 256
|
||||
|
||||
#endif // STREAM_STREAM_UTILS_H
|
||||
Submodule native/src/main/jni/libarchive updated: c59388054f...37d2cf6063.
@@ -21,9 +21,9 @@
|
||||
#include <archive.h>
|
||||
#include <lzma.h>
|
||||
#include <zlib.h>
|
||||
#include "image/libjpeg-turbo/jconfigint.h"
|
||||
#include <nettle/config.h>
|
||||
|
||||
#include "java_wrapper.h"
|
||||
#include "image/java_wrapper.h"
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
JNIEnv *env;
|
||||
@@ -49,12 +49,12 @@ Java_com_hippo_Native_getliblzmaVersion(JNIEnv *env, jclass clazz) {
|
||||
return (*env)->NewStringUTF(env, lzma_version_string());
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_hippo_Native_getlibjpeg_1turboVersion(JNIEnv *env, jclass clazz) {
|
||||
return (*env)->NewStringUTF(env, VERSION);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_hippo_Native_getzlibVersion(JNIEnv *env, jclass clazz) {
|
||||
return (*env)->NewStringUTF(env, ZLIB_VERSION);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_hippo_Native_getnettleVersion(JNIEnv *env, jclass clazz) {
|
||||
return (*env)->NewStringUTF(env, PACKAGE_STRING);
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(nettle C)
|
||||
|
||||
set(LIBNETTLE_DEFINITIONS
|
||||
-DHAVE_CONFIG_H)
|
||||
|
||||
set(LIBNETTLE_SOURCES
|
||||
nettle/aes-decrypt-internal.c
|
||||
nettle/aes-decrypt.c
|
||||
nettle/aes-decrypt-table.c
|
||||
nettle/aes128-decrypt.c
|
||||
nettle/aes192-decrypt.c
|
||||
nettle/aes256-decrypt.c
|
||||
nettle/aes-encrypt-internal.c
|
||||
nettle/aes-encrypt.c
|
||||
nettle/aes-encrypt-table.c
|
||||
nettle/aes128-encrypt.c
|
||||
nettle/aes192-encrypt.c
|
||||
nettle/aes256-encrypt.c
|
||||
nettle/aes-invert-internal.c
|
||||
nettle/aes-set-key-internal.c
|
||||
nettle/aes-set-encrypt-key.c
|
||||
nettle/aes-set-decrypt-key.c
|
||||
nettle/aes128-set-encrypt-key.c
|
||||
nettle/aes128-set-decrypt-key.c
|
||||
nettle/aes128-meta.c
|
||||
nettle/aes192-set-encrypt-key.c
|
||||
nettle/aes192-set-decrypt-key.c
|
||||
nettle/aes192-meta.c
|
||||
nettle/aes256-set-encrypt-key.c
|
||||
nettle/aes256-set-decrypt-key.c
|
||||
nettle/aes256-meta.c
|
||||
nettle/nist-keywrap.c
|
||||
nettle/arcfour.c
|
||||
nettle/arcfour-crypt.c
|
||||
nettle/arctwo.c
|
||||
nettle/arctwo-meta.c
|
||||
nettle/blowfish.c
|
||||
nettle/blowfish-bcrypt.c
|
||||
nettle/base16-encode.c
|
||||
nettle/base16-decode.c
|
||||
nettle/base16-meta.c
|
||||
nettle/base64-encode.c
|
||||
nettle/base64-decode.c
|
||||
nettle/base64-meta.c
|
||||
nettle/base64url-encode.c
|
||||
nettle/base64url-decode.c
|
||||
nettle/base64url-meta.c
|
||||
nettle/buffer.c
|
||||
nettle/buffer-init.c
|
||||
nettle/camellia-crypt-internal.c
|
||||
nettle/camellia-table.c
|
||||
nettle/camellia-absorb.c
|
||||
nettle/camellia-invert-key.c
|
||||
nettle/camellia128-set-encrypt-key.c
|
||||
nettle/camellia128-crypt.c
|
||||
nettle/camellia128-set-decrypt-key.c
|
||||
nettle/camellia128-meta.c
|
||||
nettle/camellia192-meta.c
|
||||
nettle/camellia256-set-encrypt-key.c
|
||||
nettle/camellia256-crypt.c
|
||||
nettle/camellia256-set-decrypt-key.c
|
||||
nettle/camellia256-meta.c
|
||||
nettle/cast128.c
|
||||
nettle/cast128-meta.c
|
||||
nettle/cbc.c
|
||||
nettle/cbc-aes128-encrypt.c
|
||||
nettle/cbc-aes192-encrypt.c
|
||||
nettle/cbc-aes256-encrypt.c
|
||||
nettle/ccm.c
|
||||
nettle/ccm-aes128.c
|
||||
nettle/ccm-aes192.c
|
||||
nettle/ccm-aes256.c
|
||||
nettle/cfb.c
|
||||
nettle/siv-cmac.c
|
||||
nettle/siv-cmac-aes128.c
|
||||
nettle/siv-cmac-aes256.c
|
||||
nettle/cnd-memcpy.c
|
||||
nettle/chacha-crypt.c
|
||||
nettle/chacha-core-internal.c
|
||||
nettle/chacha-poly1305.c
|
||||
nettle/chacha-poly1305-meta.c
|
||||
nettle/chacha-set-key.c
|
||||
nettle/chacha-set-nonce.c
|
||||
nettle/ctr.c
|
||||
nettle/ctr16.c
|
||||
nettle/des.c
|
||||
nettle/des3.c
|
||||
nettle/eax.c
|
||||
nettle/eax-aes128.c
|
||||
nettle/eax-aes128-meta.c
|
||||
nettle/ghash-set-key.c
|
||||
nettle/ghash-update.c
|
||||
nettle/gcm.c
|
||||
nettle/gcm-aes.c
|
||||
nettle/gcm-aes128.c
|
||||
nettle/gcm-aes128-meta.c
|
||||
nettle/gcm-aes192.c
|
||||
nettle/gcm-aes192-meta.c
|
||||
nettle/gcm-aes256.c
|
||||
nettle/gcm-aes256-meta.c
|
||||
nettle/gcm-camellia128.c
|
||||
nettle/gcm-camellia128-meta.c
|
||||
nettle/gcm-camellia256.c
|
||||
nettle/gcm-camellia256-meta.c
|
||||
nettle/cmac.c
|
||||
nettle/cmac64.c
|
||||
nettle/cmac-aes128.c
|
||||
nettle/cmac-aes256.c
|
||||
nettle/cmac-des3.c
|
||||
nettle/cmac-aes128-meta.c
|
||||
nettle/cmac-aes256-meta.c
|
||||
nettle/cmac-des3-meta.c
|
||||
nettle/gost28147.c
|
||||
nettle/gosthash94.c
|
||||
nettle/gosthash94-meta.c
|
||||
nettle/hmac.c
|
||||
nettle/hmac-gosthash94.c
|
||||
nettle/hmac-md5.c
|
||||
nettle/hmac-ripemd160.c
|
||||
nettle/hmac-sha1.c
|
||||
nettle/hmac-sha224.c
|
||||
nettle/hmac-sha256.c
|
||||
nettle/hmac-sha384.c
|
||||
nettle/hmac-sha512.c
|
||||
nettle/hmac-streebog.c
|
||||
nettle/hmac-sm3.c
|
||||
nettle/hmac-md5-meta.c
|
||||
nettle/hmac-ripemd160-meta.c
|
||||
nettle/hmac-sha1-meta.c
|
||||
nettle/hmac-sha224-meta.c
|
||||
nettle/hmac-sha256-meta.c
|
||||
nettle/hmac-sha384-meta.c
|
||||
nettle/hmac-sha512-meta.c
|
||||
nettle/hmac-streebog-meta.c
|
||||
nettle/hmac-sm3-meta.c
|
||||
nettle/knuth-lfib.c
|
||||
nettle/hkdf.c
|
||||
nettle/md2.c
|
||||
nettle/md2-meta.c
|
||||
nettle/md4.c
|
||||
nettle/md4-meta.c
|
||||
nettle/md5.c
|
||||
nettle/md5-compress.c
|
||||
nettle/md5-compat.c
|
||||
nettle/md5-meta.c
|
||||
nettle/memeql-sec.c
|
||||
nettle/memxor.c
|
||||
nettle/memxor3.c
|
||||
nettle/nettle-lookup-hash.c
|
||||
nettle/nettle-meta-aeads.c
|
||||
nettle/nettle-meta-armors.c
|
||||
nettle/nettle-meta-ciphers.c
|
||||
nettle/nettle-meta-hashes.c
|
||||
nettle/nettle-meta-macs.c
|
||||
nettle/pbkdf2.c
|
||||
nettle/pbkdf2-hmac-gosthash94.c
|
||||
nettle/pbkdf2-hmac-sha1.c
|
||||
nettle/pbkdf2-hmac-sha256.c
|
||||
nettle/pbkdf2-hmac-sha384.c
|
||||
nettle/pbkdf2-hmac-sha512.c
|
||||
nettle/poly1305-aes.c
|
||||
nettle/poly1305-internal.c
|
||||
nettle/realloc.c
|
||||
nettle/ripemd160.c
|
||||
nettle/ripemd160-compress.c
|
||||
nettle/ripemd160-meta.c
|
||||
nettle/salsa20-core-internal.c
|
||||
nettle/salsa20-crypt-internal.c
|
||||
nettle/salsa20-crypt.c
|
||||
nettle/salsa20r12-crypt.c
|
||||
nettle/salsa20-set-key.c
|
||||
nettle/salsa20-set-nonce.c
|
||||
nettle/salsa20-128-set-key.c
|
||||
nettle/salsa20-256-set-key.c
|
||||
nettle/sha1.c
|
||||
nettle/sha1-compress.c
|
||||
nettle/sha1-meta.c
|
||||
nettle/sha256.c
|
||||
nettle/sha256-compress.c
|
||||
nettle/sha224-meta.c
|
||||
nettle/sha256-meta.c
|
||||
nettle/sha512.c
|
||||
nettle/sha512-compress.c
|
||||
nettle/sha384-meta.c
|
||||
nettle/sha512-meta.c
|
||||
nettle/sha512-224-meta.c
|
||||
nettle/sha512-256-meta.c
|
||||
nettle/sha3.c
|
||||
nettle/sha3-permute.c
|
||||
nettle/sha3-224.c
|
||||
nettle/sha3-224-meta.c
|
||||
nettle/sha3-256.c
|
||||
nettle/sha3-256-meta.c
|
||||
nettle/sha3-384.c
|
||||
nettle/sha3-384-meta.c
|
||||
nettle/sha3-512.c
|
||||
nettle/sha3-512-meta.c
|
||||
nettle/shake256.c
|
||||
nettle/sm3.c
|
||||
nettle/sm3-meta.c
|
||||
nettle/serpent-set-key.c
|
||||
nettle/serpent-encrypt.c
|
||||
nettle/serpent-decrypt.c
|
||||
nettle/serpent-meta.c
|
||||
nettle/streebog.c
|
||||
nettle/streebog-meta.c
|
||||
nettle/twofish.c
|
||||
nettle/twofish-meta.c
|
||||
nettle/umac-nh.c
|
||||
nettle/umac-nh-n.c
|
||||
nettle/umac-l2.c
|
||||
nettle/umac-l3.c
|
||||
nettle/umac-poly64.c
|
||||
nettle/umac-poly128.c
|
||||
nettle/umac-set-key.c
|
||||
nettle/umac32.c
|
||||
nettle/umac64.c
|
||||
nettle/umac96.c
|
||||
nettle/umac128.c
|
||||
nettle/version.c
|
||||
nettle/write-be32.c
|
||||
nettle/write-le32.c
|
||||
nettle/write-le64.c
|
||||
nettle/yarrow256.c
|
||||
nettle/yarrow_key_event.c
|
||||
nettle/xts.c
|
||||
nettle/xts-aes128.c
|
||||
nettle/xts-aes256.c
|
||||
)
|
||||
|
||||
set(LIBNETTLE_INCLUDES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nettle
|
||||
)
|
||||
|
||||
add_library(nettle STATIC ${LIBNETTLE_SOURCES})
|
||||
target_include_directories(nettle PUBLIC ${LIBNETTLE_INCLUDES})
|
||||
target_compile_definitions(nettle PRIVATE ${LIBNETTLE_DEFINITIONS})
|
||||
@@ -0,0 +1,275 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define if building universal (internal helper macro) */
|
||||
/* #undef AC_APPLE_UNIVERSAL_BUILD */
|
||||
|
||||
/* Define to 1 if using 'alloca.c'. */
|
||||
/* #undef C_ALLOCA */
|
||||
|
||||
/* Define to 1 if you have 'alloca', as a function or macro. */
|
||||
#define HAVE_ALLOCA 1
|
||||
|
||||
/* Define to 1 if <alloca.h> works. */
|
||||
#define HAVE_ALLOCA_H 1
|
||||
|
||||
/* Define if __builtin_bswap64 is available */
|
||||
#define HAVE_BUILTIN_BSWAP64 1
|
||||
|
||||
/* Define if clock_gettime is available */
|
||||
#define HAVE_CLOCK_GETTIME 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define if fcntl file locking is available */
|
||||
#define HAVE_FCNTL_LOCKING 1
|
||||
|
||||
/* Define if the compiler understands __attribute__ */
|
||||
#define HAVE_GCC_ATTRIBUTE 1
|
||||
|
||||
/* Define to 1 if you have the `getline' function. */
|
||||
#define HAVE_GETLINE 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have dlopen (with -ldl). */
|
||||
#define HAVE_LIBDL 1
|
||||
|
||||
/* Define to 1 if you have the `gmp' library (-lgmp). */
|
||||
/* #undef HAVE_LIBGMP */
|
||||
|
||||
/* Define if compiler and linker supports __attribute__ ifunc */
|
||||
#define HAVE_LINK_IFUNC 1
|
||||
|
||||
/* Define to 1 if you have the <malloc.h> header file. */
|
||||
#define HAVE_MALLOC_H 1
|
||||
|
||||
/* Define to 1 each of the following for which a native (ie. CPU specific)
|
||||
implementation of the corresponding routine exists. */
|
||||
/* #undef HAVE_NATIVE_memxor3 */
|
||||
/* #undef HAVE_NATIVE_aes_decrypt */
|
||||
/* #undef HAVE_NATIVE_aes_encrypt */
|
||||
/* #undef HAVE_NATIVE_aes128_decrypt */
|
||||
/* #undef HAVE_NATIVE_aes128_encrypt */
|
||||
/* #undef HAVE_NATIVE_aes128_invert_key */
|
||||
/* #undef HAVE_NATIVE_aes128_set_decrypt_key */
|
||||
/* #undef HAVE_NATIVE_aes128_set_encrypt_key */
|
||||
/* #undef HAVE_NATIVE_aes192_decrypt */
|
||||
/* #undef HAVE_NATIVE_aes192_encrypt */
|
||||
/* #undef HAVE_NATIVE_aes192_invert_key */
|
||||
/* #undef HAVE_NATIVE_aes192_set_decrypt_key */
|
||||
/* #undef HAVE_NATIVE_aes192_set_encrypt_key */
|
||||
/* #undef HAVE_NATIVE_aes256_decrypt */
|
||||
/* #undef HAVE_NATIVE_aes256_encrypt */
|
||||
/* #undef HAVE_NATIVE_aes256_invert_key */
|
||||
/* #undef HAVE_NATIVE_aes256_set_decrypt_key */
|
||||
/* #undef HAVE_NATIVE_aes256_set_encrypt_key */
|
||||
/* #undef HAVE_NATIVE_cbc_aes128_encrypt */
|
||||
/* #undef HAVE_NATIVE_cbc_aes192_encrypt */
|
||||
/* #undef HAVE_NATIVE_cbc_aes256_encrypt */
|
||||
/* #undef HAVE_NATIVE_chacha_core */
|
||||
/* #undef HAVE_NATIVE_chacha_2core */
|
||||
/* #undef HAVE_NATIVE_chacha_3core */
|
||||
/* #undef HAVE_NATIVE_chacha_4core */
|
||||
/* #undef HAVE_NATIVE_fat_chacha_2core */
|
||||
/* #undef HAVE_NATIVE_fat_chacha_3core */
|
||||
/* #undef HAVE_NATIVE_fat_chacha_4core */
|
||||
/* #undef HAVE_NATIVE_ecc_curve25519_modp */
|
||||
/* #undef HAVE_NATIVE_ecc_curve448_modp */
|
||||
/* #undef HAVE_NATIVE_ecc_secp192r1_modp */
|
||||
/* #undef HAVE_NATIVE_ecc_secp192r1_redc */
|
||||
/* #undef HAVE_NATIVE_ecc_secp224r1_modp */
|
||||
/* #undef HAVE_NATIVE_ecc_secp224r1_redc */
|
||||
/* #undef HAVE_NATIVE_ecc_secp256r1_modp */
|
||||
/* #undef HAVE_NATIVE_ecc_secp256r1_redc */
|
||||
/* #undef HAVE_NATIVE_ecc_secp384r1_modp */
|
||||
/* #undef HAVE_NATIVE_ecc_secp384r1_redc */
|
||||
/* #undef HAVE_NATIVE_ecc_secp521r1_modp */
|
||||
/* #undef HAVE_NATIVE_ecc_secp521r1_redc */
|
||||
/* #undef HAVE_NATIVE_ghash_set_key */
|
||||
/* #undef HAVE_NATIVE_ghash_update */
|
||||
/* #undef HAVE_NATIVE_salsa20_core */
|
||||
/* #undef HAVE_NATIVE_salsa20_2core */
|
||||
/* #undef HAVE_NATIVE_fat_salsa20_2core */
|
||||
/* #undef HAVE_NATIVE_sha1_compress */
|
||||
/* #undef HAVE_NATIVE_sha256_compress */
|
||||
/* #undef HAVE_NATIVE_sha512_compress */
|
||||
/* #undef HAVE_NATIVE_sha3_permute */
|
||||
/* #undef HAVE_NATIVE_umac_nh */
|
||||
/* #undef HAVE_NATIVE_umac_nh_n */
|
||||
|
||||
/* Define to 1 if you have the <openssl/ecdsa.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_ECDSA_H */
|
||||
|
||||
/* Define to 1 if you have the <openssl/evp.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_EVP_H */
|
||||
|
||||
/* Define to 1 if you have the `secure_getenv' function. */
|
||||
/* #undef HAVE_SECURE_GETENV */
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the <valgrind/memcheck.h> header file. */
|
||||
/* #undef HAVE_VALGRIND_MEMCHECK_H */
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "nettle-bugs@lists.lysator.liu.se"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "nettle"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "nettle 3.8"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "nettle"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "3.8"
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#define SIZEOF_LONG __SIZEOF_LONG__
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#define SIZEOF_SIZE_T __SIZEOF_SIZE_T__
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
automatically deduced at runtime.
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
/* #undef STACK_DIRECTION */
|
||||
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. This
|
||||
macro is obsolete. */
|
||||
#define TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* Defined if public key features are enabled */
|
||||
/* #undef WITH_HOGWEED */
|
||||
|
||||
/* Define if you have openssl's libcrypto (used for benchmarking) */
|
||||
/* #undef WITH_OPENSSL */
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||
# if defined __BIG_ENDIAN__
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef WORDS_BIGENDIAN
|
||||
/* # undef WORDS_BIGENDIAN */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
/* #undef gid_t */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
/* #undef uid_t */
|
||||
|
||||
/* AIX requires this to be the first thing in the file. */
|
||||
#ifndef __GNUC__
|
||||
# if HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# else
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
char *alloca ();
|
||||
# endif
|
||||
# endif
|
||||
/* Needed for alloca on windows */
|
||||
# if HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
# endif
|
||||
#else /* defined __GNUC__ */
|
||||
# if HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
/* Needed for alloca on windows, also with gcc */
|
||||
# if HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if HAVE_STRERROR
|
||||
#define STRERROR strerror
|
||||
#else
|
||||
#define STRERROR(x) (sys_errlist[x])
|
||||
#endif
|
||||
|
||||
|
||||
#if __GNUC__ && HAVE_GCC_ATTRIBUTE
|
||||
# define NORETURN __attribute__ ((__noreturn__))
|
||||
# define PRINTF_STYLE(f, a) __attribute__ ((__format__ (__printf__, f, a)))
|
||||
# define UNUSED __attribute__ ((__unused__))
|
||||
#else
|
||||
# define NORETURN
|
||||
# define PRINTF_STYLE(f, a)
|
||||
# define UNUSED
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__x86_64__) || defined(__arch64__)
|
||||
# define HAVE_NATIVE_64_BIT 1
|
||||
#else
|
||||
/* Needs include of <limits.h> before use. */
|
||||
# define HAVE_NATIVE_64_BIT (SIZEOF_LONG * CHAR_BIT >= 64)
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Submodule
+1
Submodule native/src/main/jni/nettle/nettle added at ea4ea5e690.
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/* version.h
|
||||
|
||||
Information about library version.
|
||||
|
||||
Copyright (C) 2015 Red Hat, Inc.
|
||||
Copyright (C) 2015 Niels Möller
|
||||
|
||||
This file is part of GNU Nettle.
|
||||
|
||||
GNU Nettle is free software: you can redistribute it and/or
|
||||
modify it under the terms of either:
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
or
|
||||
|
||||
* the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
GNU Nettle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef NETTLE_VERSION_H_INCLUDED
|
||||
#define NETTLE_VERSION_H_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Individual version numbers in decimal */
|
||||
#define NETTLE_VERSION_MAJOR 3
|
||||
#define NETTLE_VERSION_MINOR 8
|
||||
|
||||
#define NETTLE_USE_MINI_GMP 0
|
||||
|
||||
/* We need a preprocessor constant for GMP_NUMB_BITS, simply using
|
||||
sizeof(mp_limb_t) * CHAR_BIT is not good enough. */
|
||||
#if NETTLE_USE_MINI_GMP
|
||||
# define GMP_NUMB_BITS n/a
|
||||
#endif
|
||||
|
||||
int
|
||||
nettle_version_major (void);
|
||||
|
||||
int
|
||||
nettle_version_minor (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NETTLE_VERSION_H_INCLUDED */
|
||||
Reference in new issue
Block a user