Compare commits
37
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
162b88915e | ||
|
|
d014b6947c | ||
|
|
a6188964c9 | ||
|
|
722fbec72c | ||
|
|
22190fb686 | ||
|
|
49ea70c839 | ||
|
|
c655e7e1c9 | ||
|
|
d13cd1e07f | ||
|
|
7365fd0448 | ||
|
|
f1febca312 | ||
|
|
dbf67404c0 | ||
|
|
8cfe8c4b80 | ||
|
|
674f53315f | ||
|
|
e51cd6b90d | ||
|
|
a44f12b2e0 | ||
|
|
a2552ed5b9 | ||
|
|
763c007950 | ||
|
|
b221bf8e52 | ||
|
|
ab9a89685c | ||
|
|
41ccb16227 | ||
|
|
f6bf7b1ba6 | ||
|
|
09e7113df1 | ||
|
|
62a7e283a4 | ||
|
|
a7f7bf1316 | ||
|
|
a72fca3dfb | ||
|
|
c5e7a6e8f9 | ||
|
|
80a20f25b9 | ||
|
|
500163fe1a | ||
|
|
50c6111773 | ||
|
|
3a05649c71 | ||
|
|
9d25376e1f | ||
|
|
89935b5639 | ||
|
|
e095627aee | ||
|
|
b61e46e956 | ||
|
|
76459c5dd2 | ||
|
|
7ad67a3dbd | ||
|
|
577b49ac19 |
No files matched your search
@@ -1,12 +1,3 @@
|
||||
[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
|
||||
|
||||
@@ -34,9 +34,11 @@ with Material Design 3 and Dynamic Color Support
|
||||
|
||||
# Download
|
||||
|
||||
[Github 下载](https://github.com/Ehviewer-Overhauled/Ehviewer/releases)
|
||||
<a href="https://github.com/Ehviewer-Overhauled/Ehviewer/releases"><img alt="Get it on Google Play" src="art/get-it-on-github.svg" width="200px"/></a>
|
||||
|
||||
[CI 版本下载(需登录)](https://github.com/Ehviewer-Overhauled/Ehviewer/actions/workflows/ci.yml)
|
||||
App 分为 1.8 与 1.7 两个版本。1.8 版本适配 Android 12 及以上系统,为开发主线;1.7 版本适配 Android 11 及以下版本,削减了 Android 12 及以上系统的独有功能,使其能在低版本 Android 上正常工作
|
||||
|
||||
App is divided into two versions: 1.7 and 1.8 . Version 1.8 support Android 12 and above, also the develop mainline. Version 1.7 support Android 11 and below, drop down some spicetify functions for Android 12 to make app useable on lower Android System
|
||||
|
||||
# Screenshot
|
||||
|
||||
@@ -54,12 +56,8 @@ Here is the libraries
|
||||
- [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/)
|
||||
- [giflib](http://giflib.sourceforge.net)
|
||||
- [greenDAO](https://github.com/greenrobot/greenDAO)
|
||||
- [jsoup](https://github.com/jhy/jsoup)
|
||||
- [libjpeg-turbo](https://libjpeg-turbo.org/)
|
||||
- [libpng](http://www.libpng.org/pub/png/libpng.html)
|
||||
- [okhttp](https://github.com/square/okhttp)
|
||||
- [roaster](https://github.com/forge/roaster)
|
||||
- [TapTargetView](https://github.com/KeepSafe/TapTargetView)
|
||||
|
||||
+5
-6
@@ -32,10 +32,10 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "moe.tarsin.ehviewer"
|
||||
minSdkVersion 26
|
||||
minSdkVersion 31
|
||||
targetSdkVersion 33
|
||||
versionCode 114533
|
||||
versionName "1.7.29.1"
|
||||
versionCode 180004
|
||||
versionName "1.8.0.4"
|
||||
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ dependencies {
|
||||
implementation "androidx.biometric:biometric-ktx:1.2.0-alpha04"
|
||||
implementation "androidx.browser:browser:1.4.0"
|
||||
|
||||
def collection_version = "1.3.0-alpha01"
|
||||
def collection_version = "1.3.0-alpha02"
|
||||
implementation "androidx.collection:collection:$collection_version"
|
||||
implementation "androidx.collection:collection-ktx:$collection_version"
|
||||
|
||||
@@ -122,7 +122,7 @@ dependencies {
|
||||
implementation "androidx.documentfile:documentfile:1.1.0-alpha01"
|
||||
implementation "androidx.dynamicanimation:dynamicanimation:1.1.0-alpha03"
|
||||
|
||||
def fragment_version = "1.5.0"
|
||||
def fragment_version = "1.5.1"
|
||||
implementation "androidx.fragment:fragment:$fragment_version"
|
||||
implementation "androidx.fragment:fragment-ktx:$fragment_version"
|
||||
|
||||
@@ -148,7 +148,6 @@ dependencies {
|
||||
|
||||
implementation 'com.drakeet.drawer:drawer:1.0.3'
|
||||
implementation 'com.google.android.material:material:1.7.0-alpha03'
|
||||
implementation 'com.getkeepsafe.taptargetview:taptargetview:1.13.3'
|
||||
implementation 'com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:1.0.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.10'
|
||||
implementation 'dev.rikka.rikkax.core:core-ktx:1.4.1'
|
||||
|
||||
@@ -26,11 +26,12 @@
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
|
||||
<!-- Required to maintain app compatibility. -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
|
||||
<uses-feature
|
||||
android:glEsVersion="0x00020000"
|
||||
android:required="true" />
|
||||
|
||||
@@ -167,6 +167,7 @@ public final class DiskLruCache implements Closeable {
|
||||
* its sequence number is not equal to its entry's sequence number.
|
||||
*/
|
||||
private long nextSequenceNumber = 0;
|
||||
|
||||
private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) {
|
||||
this.directory = directory;
|
||||
this.appVersion = appVersion;
|
||||
@@ -175,21 +176,7 @@ public final class DiskLruCache implements Closeable {
|
||||
this.journalFileBackup = new File(directory, JOURNAL_FILE_BACKUP);
|
||||
this.valueCount = valueCount;
|
||||
this.maxSize = maxSize;
|
||||
} private final Callable<Void> cleanupCallable = new Callable<>() {
|
||||
public Void call() throws Exception {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (journalWriter == null) {
|
||||
return null; // Closed.
|
||||
}
|
||||
trimToSize();
|
||||
if (journalRebuildRequired()) {
|
||||
rebuildJournal();
|
||||
redundantOpCount = 0;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the cache in {@code directory}, creating a cache if none exists
|
||||
@@ -244,7 +231,21 @@ public final class DiskLruCache implements Closeable {
|
||||
cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
|
||||
cache.rebuildJournal();
|
||||
return cache;
|
||||
}
|
||||
} private final Callable<Void> cleanupCallable = new Callable<>() {
|
||||
public Void call() throws Exception {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (journalWriter == null) {
|
||||
return null; // Closed.
|
||||
}
|
||||
trimToSize();
|
||||
if (journalRebuildRequired()) {
|
||||
rebuildJournal();
|
||||
redundantOpCount = 0;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
private static void deleteIfExists(File file) throws IOException {
|
||||
if (file.exists() && !file.delete()) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.hippo.conaco.ValueHelper;
|
||||
import com.hippo.image.ImageBitmap;
|
||||
import com.hippo.streampipe.InputStreamPipe;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ImageBitmapHelper implements ValueHelper<ImageBitmap> {
|
||||
@@ -34,7 +35,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 {
|
||||
|
||||
@@ -34,7 +34,6 @@ import com.hippo.unifile.UniFile;
|
||||
import com.hippo.yorozuya.thread.PVLock;
|
||||
import com.hippo.yorozuya.thread.PriorityThread;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@@ -50,7 +49,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
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;
|
||||
@@ -250,18 +249,18 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
Pipe pipe = new Pipe();
|
||||
|
||||
synchronized (streams) {
|
||||
if (streams.get(index) != null) {
|
||||
continue;
|
||||
}
|
||||
streams.put(index, pipe.getInputStream());
|
||||
streams.notify();
|
||||
}
|
||||
|
||||
archiveAccessor.extracttoOutputStream(index, pipe.getOutputFd());
|
||||
pipe.closeOutputFd();
|
||||
long addr = archiveAccessor.extracttoOutputStream(index);
|
||||
|
||||
synchronized (streams) {
|
||||
streams.put(index, addr);
|
||||
streams.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,7 +270,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 {
|
||||
@@ -283,16 +282,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,52 +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 android.os.ParcelFileDescriptor;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
class Pipe {
|
||||
private ParcelFileDescriptor[] fd;
|
||||
{
|
||||
try {
|
||||
fd = ParcelFileDescriptor.createPipe();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private final InputStream inputStream = new FileInputStream(fd[0].getFileDescriptor());
|
||||
|
||||
InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
int getOutputFd() {
|
||||
return fd[1].getFd();
|
||||
}
|
||||
|
||||
void closeOutputFd() {
|
||||
try {
|
||||
fd[1].close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,14 +44,13 @@ class VersionPreference @JvmOverloads constructor(
|
||||
val info = NativeLibInfo().addLib(Native.getlibarchiveVersion())
|
||||
.addLib("lzma(xz-utils)", Native.getliblzmaVersion())
|
||||
.addLib("zlib", Native.getzlibVersion())
|
||||
.addLib("libjpeg-turbo", Native.getlibjpeg_turboVersion())
|
||||
.addLib(Native.getnettleVersion())
|
||||
builder.setMessage(info.getMessage())
|
||||
}
|
||||
|
||||
inner class NativeLibInfo {
|
||||
private var message: String = ""
|
||||
fun addLib(libname:String, libversion:String): NativeLibInfo {
|
||||
fun addLib(libname: String, libversion: String): NativeLibInfo {
|
||||
message = "$message$libname $libversion\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,17 @@ 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();
|
||||
} finally {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (image == null) {
|
||||
error = GetText.getString(R.string.error_decoding_failed);
|
||||
}
|
||||
|
||||
@@ -226,6 +226,9 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
private int mSize;
|
||||
private int mCurrentIndex;
|
||||
private int mSavingPage = -1;
|
||||
private EditTextDialogBuilder builder;
|
||||
private boolean dialogShown = false;
|
||||
private AlertDialog dialog;
|
||||
|
||||
private void buildProvider() {
|
||||
if (mGalleryProvider != null) {
|
||||
@@ -287,7 +290,16 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
}
|
||||
outState.putInt(KEY_PAGE, mPage);
|
||||
outState.putInt(KEY_CURRENT_INDEX, mCurrentIndex);
|
||||
}
|
||||
} ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestPermission(),
|
||||
result -> {
|
||||
if (result && mSavingPage != -1) {
|
||||
saveImage(mSavingPage);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
mSavingPage = -1;
|
||||
});
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(@NonNull Context newBase) {
|
||||
@@ -477,16 +489,7 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
FrameLayout mainLayout = (FrameLayout) ViewUtils.$$(this, R.id.main);
|
||||
mainLayout.addView(new GalleryGuideView(this));
|
||||
}
|
||||
} ActivityResultLauncher<String> requestStoragePermissionLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestPermission(),
|
||||
result -> {
|
||||
if (result && mSavingPage != -1) {
|
||||
saveImage(mSavingPage);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
mSavingPage = -1;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
@@ -1046,6 +1049,66 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class GalleryMenuHelper implements DialogInterface.OnClickListener {
|
||||
|
||||
private final View mView;
|
||||
@@ -1306,69 +1369,5 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
|
||||
@@ -55,8 +55,6 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator;
|
||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
||||
|
||||
import com.getkeepsafe.taptargetview.TapTarget;
|
||||
import com.getkeepsafe.taptargetview.TapTargetView;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.h6ah4i.android.widget.advrecyclerview.animator.DraggableItemAnimator;
|
||||
@@ -390,90 +388,9 @@ public class DownloadsScene extends ToolbarScene
|
||||
|
||||
updateView();
|
||||
|
||||
guide();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void guide() {
|
||||
if (Settings.getGuideDownloadThumb() && null != mRecyclerView) {
|
||||
mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (Settings.getGuideDownloadThumb()) {
|
||||
guideDownloadThumb();
|
||||
}
|
||||
if (null != mRecyclerView) {
|
||||
ViewUtils.removeOnGlobalLayoutListener(mRecyclerView.getViewTreeObserver(), this);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
guideDownloadLabels();
|
||||
}
|
||||
}
|
||||
|
||||
private void guideDownloadThumb() {
|
||||
MainActivity activity = getMainActivity();
|
||||
if (null == activity || !Settings.getGuideDownloadThumb() || null == mLayoutManager || null == mRecyclerView) {
|
||||
guideDownloadLabels();
|
||||
return;
|
||||
}
|
||||
int position = mLayoutManager.findFirstCompletelyVisibleItemPositions(null)[0];
|
||||
if (position < 0) {
|
||||
guideDownloadLabels();
|
||||
return;
|
||||
}
|
||||
RecyclerView.ViewHolder holder = mRecyclerView.findViewHolderForAdapterPosition(position);
|
||||
if (null == holder) {
|
||||
guideDownloadLabels();
|
||||
return;
|
||||
}
|
||||
|
||||
TapTargetView.showFor(requireActivity(),
|
||||
TapTarget.forView(((DownloadHolder) holder).thumb,
|
||||
getString(R.string.guide_download_thumb_title),
|
||||
getString(R.string.guide_download_thumb_text))
|
||||
.transparentTarget(true),
|
||||
new TapTargetView.Listener() {
|
||||
@Override
|
||||
public void onTargetDismissed(TapTargetView view, boolean userInitiated) {
|
||||
super.onTargetDismissed(view, userInitiated);
|
||||
Settings.putGuideDownloadThumb(false);
|
||||
guideDownloadLabels();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void guideDownloadLabels() {
|
||||
MainActivity activity = getMainActivity();
|
||||
if (null == activity || !Settings.getGuideDownloadLabels()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Display display = activity.getWindowManager().getDefaultDisplay();
|
||||
Point point = new Point();
|
||||
display.getSize(point);
|
||||
Rect bounds = new Rect(point.x + LayoutUtils.dp2pix(requireContext(), 20),
|
||||
point.y / 3 + LayoutUtils.dp2pix(requireContext(), 20),
|
||||
point.x - LayoutUtils.dp2pix(requireContext(), 20),
|
||||
point.y / 3 - LayoutUtils.dp2pix(requireContext(), 20));
|
||||
|
||||
TapTargetView.showFor(requireActivity(),
|
||||
TapTarget.forBounds(bounds,
|
||||
getString(R.string.guide_download_labels_title),
|
||||
getString(R.string.guide_download_labels_text))
|
||||
.transparentTarget(true),
|
||||
new TapTargetView.Listener() {
|
||||
@Override
|
||||
public void onTargetDismissed(TapTargetView view, boolean userInitiated) {
|
||||
super.onTargetClick(view);
|
||||
Settings.puttGuideDownloadLabels(false);
|
||||
openDrawer(Gravity.RIGHT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
@@ -45,8 +45,6 @@ import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.getkeepsafe.taptargetview.TapTarget;
|
||||
import com.getkeepsafe.taptargetview.TapTargetView;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.hippo.annotation.Implemented;
|
||||
@@ -311,40 +309,9 @@ public class FavoritesScene extends BaseScene implements
|
||||
mHelper.firstRefresh();
|
||||
}
|
||||
|
||||
guideCollections();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void guideCollections() {
|
||||
Activity activity = getMainActivity();
|
||||
if (null == activity || !Settings.getGuideCollections()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Display display = activity.getWindowManager().getDefaultDisplay();
|
||||
Point point = new Point();
|
||||
display.getSize(point);
|
||||
Rect bounds = new Rect(point.x + LayoutUtils.dp2pix(requireContext(), 20),
|
||||
point.y / 3 + LayoutUtils.dp2pix(requireContext(), 20),
|
||||
point.x - LayoutUtils.dp2pix(requireContext(), 20),
|
||||
point.y / 3 - LayoutUtils.dp2pix(requireContext(), 20));
|
||||
|
||||
TapTargetView.showFor(requireActivity(),
|
||||
TapTarget.forBounds(bounds,
|
||||
getString(R.string.guide_collections_title),
|
||||
getString(R.string.guide_collections_text))
|
||||
.transparentTarget(true),
|
||||
new TapTargetView.Listener() {
|
||||
@Override
|
||||
public void onTargetDismissed(TapTargetView view, boolean userInitiated) {
|
||||
super.onTargetClick(view);
|
||||
Settings.putGuideCollections(false);
|
||||
openDrawer(Gravity.RIGHT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// keyword of mUrlBuilder, fav cat of mUrlBuilder, mFavCatArray.
|
||||
// They changed, call it
|
||||
private void updateSearchBar() {
|
||||
|
||||
@@ -59,8 +59,6 @@ import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.getkeepsafe.taptargetview.TapTarget;
|
||||
import com.getkeepsafe.taptargetview.TapTargetView;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.h6ah4i.android.widget.advrecyclerview.animator.DraggableItemAnimator;
|
||||
@@ -634,40 +632,9 @@ public final class GalleryListScene extends BaseScene
|
||||
mHelper.firstRefresh();
|
||||
}
|
||||
|
||||
guideQuickSearch();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void guideQuickSearch() {
|
||||
Activity activity = getMainActivity();
|
||||
if (null == activity || !Settings.getGuideQuickSearch()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Display display = activity.getWindowManager().getDefaultDisplay();
|
||||
Point point = new Point();
|
||||
display.getSize(point);
|
||||
Rect bounds = new Rect(point.x + LayoutUtils.dp2pix(requireContext(), 20),
|
||||
point.y / 3 + LayoutUtils.dp2pix(requireContext(), 20),
|
||||
point.x - LayoutUtils.dp2pix(requireContext(), 20),
|
||||
point.y / 3 - LayoutUtils.dp2pix(requireContext(), 20));
|
||||
|
||||
TapTargetView.showFor(requireActivity(),
|
||||
TapTarget.forBounds(bounds,
|
||||
getString(R.string.guide_quick_search_title),
|
||||
getString(R.string.guide_quick_search_text))
|
||||
.transparentTarget(true),
|
||||
new TapTargetView.Listener() {
|
||||
@Override
|
||||
public void onTargetDismissed(TapTargetView view, boolean userInitiated) {
|
||||
super.onTargetClick(view);
|
||||
Settings.putGuideQuickSearch(false);
|
||||
openDrawer(Gravity.RIGHT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
@@ -57,6 +57,7 @@ public abstract class GalleryProvider {
|
||||
public void stop() {
|
||||
OSUtils.checkMainLoop();
|
||||
mImageCache.evictAll();
|
||||
Image.lazyEvictAll();
|
||||
}
|
||||
|
||||
public void setGLRoot(GLRoot glRoot) {
|
||||
@@ -245,18 +246,14 @@ public abstract class GalleryProvider {
|
||||
}
|
||||
|
||||
public void add(Integer key, ImageWrapper value) {
|
||||
if (value.getFormat() != Image.FORMAT_GIF && value.obtain()) {
|
||||
put(key, value);
|
||||
}
|
||||
if (value.getFormat() != Image.FORMAT_ANIMATED)
|
||||
if (value.obtain())
|
||||
put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int sizeOf(Integer key, ImageWrapper value) {
|
||||
int size = value.getWidth() * value.getHeight() * 4;
|
||||
if (value.getFormat() == Image.FORMAT_GIF) {
|
||||
size *= 5;
|
||||
}
|
||||
return size;
|
||||
return value.getWidth() * value.getHeight() * 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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()
|
||||
*/
|
||||
|
||||
@@ -33,6 +33,7 @@ final class DocumentsContractApi21 {
|
||||
private static final String TAG = DocumentsContractApi21.class.getSimpleName();
|
||||
private static final String PATH_DOCUMENT = "document";
|
||||
private static final String PATH_TREE = "tree";
|
||||
|
||||
private DocumentsContractApi21() {
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ class FileDescriptorRandomAccessFile implements UniRandomAccessFile {
|
||||
private final int flushAfterWrite;
|
||||
private final Object closeLock = new Object();
|
||||
private volatile boolean closed = false;
|
||||
|
||||
private FileDescriptorRandomAccessFile(ParcelFileDescriptor pfd, FileDescriptor fd, String mode) {
|
||||
this.pfd = pfd;
|
||||
this.fd = fd;
|
||||
|
||||
@@ -82,6 +82,13 @@ public class BatteryView extends AppCompatTextView {
|
||||
}
|
||||
mCurrentColor = color;
|
||||
super.setTextColor(color);
|
||||
}
|
||||
|
||||
private void startCharger() {
|
||||
if (!mIsChargerWorking) {
|
||||
getHandler().post(mCharger);
|
||||
mIsChargerWorking = true;
|
||||
}
|
||||
} private final Runnable mCharger = new Runnable() {
|
||||
|
||||
private int level = 0;
|
||||
@@ -97,13 +104,6 @@ public class BatteryView extends AppCompatTextView {
|
||||
}
|
||||
};
|
||||
|
||||
private void startCharger() {
|
||||
if (!mIsChargerWorking) {
|
||||
getHandler().post(mCharger);
|
||||
mIsChargerWorking = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void stopCharger() {
|
||||
if (mIsChargerWorking) {
|
||||
getHandler().removeCallbacks(mCharger);
|
||||
@@ -145,6 +145,7 @@ public class BatteryView extends AppCompatTextView {
|
||||
|
||||
|
||||
|
||||
|
||||
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -97,6 +97,10 @@ public class TextClock extends AppCompatTextView {
|
||||
} else {
|
||||
mTime = Calendar.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
public CharSequence getFormat12Hour() {
|
||||
return mFormat12;
|
||||
} private final Runnable mTicker = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -109,10 +113,6 @@ public class TextClock extends AppCompatTextView {
|
||||
}
|
||||
};
|
||||
|
||||
public CharSequence getFormat12Hour() {
|
||||
return mFormat12;
|
||||
}
|
||||
|
||||
public void setFormat12Hour(CharSequence format) {
|
||||
mFormat12 = format;
|
||||
|
||||
@@ -144,19 +144,7 @@ public class TextClock extends AppCompatTextView {
|
||||
|
||||
createTime(timeZone);
|
||||
onTimeChanged();
|
||||
} private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
|
||||
@@ -170,7 +158,19 @@ public class TextClock extends AppCompatTextView {
|
||||
|
||||
public CharSequence getFormat() {
|
||||
return mFormat;
|
||||
}
|
||||
} private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
chooseFormat();
|
||||
onTimeChanged();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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 GeneralPublic 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/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="44dp"
|
||||
android:height="44dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<group
|
||||
android:scaleX="0.37947997"
|
||||
android:scaleY="0.37947997"
|
||||
android:translateX="35.1"
|
||||
android:translateY="39.584126">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M39.893,68.066L39.893,75.977L0,75.977L0,4.59L39.893,4.59L39.893,12.5L8.984,12.5L8.984,34.766L38.086,34.766L38.086,42.578L8.984,42.578L8.984,68.066L39.893,68.066Z" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M99.609,75.977L90.918,75.977L90.918,41.699A23.436,23.436 0,0 0,90.662 38.109Q90.055,34.207 88.013,31.958Q85.629,29.334 81.028,28.863A20.84,20.84 0,0 0,78.906 28.76A23.134,23.134 0,0 0,74.45 29.16Q71.926,29.656 69.994,30.767A11.122,11.122 0,0 0,66.968 33.301A13.32,13.32 0,0 0,64.756 37.276Q63.399,40.971 63.213,46.495A53.517,53.517 0,0 0,63.184 48.291L63.184,75.977L54.395,75.977L54.395,0L63.184,0L63.184,22.266A66.935,66.935 0,0 1,63.115 25.383Q63.043,26.914 62.897,28.251A33.547,33.547 0,0 1,62.695 29.785L63.281,29.785A16.11,16.11 0,0 1,69.394 24.035A19.448,19.448 0,0 1,70.068 23.682A20.88,20.88 0,0 1,77.292 21.622A25.763,25.763 0,0 1,79.98 21.484A32.643,32.643 0,0 1,85.483 21.917Q91.249,22.905 94.678,26.147Q98.472,29.735 99.347,36.631A35.274,35.274 0,0 1,99.609 41.064L99.609,75.977Z" />
|
||||
</group>
|
||||
</vector>
|
||||
@@ -84,10 +84,10 @@
|
||||
<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:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:showDividers="middle">
|
||||
|
||||
<FrameLayout
|
||||
|
||||
@@ -230,8 +230,8 @@
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:insetLeft="40dp"
|
||||
android:insetRight="40dp"
|
||||
android:insetTop="16dp"
|
||||
android:insetRight="40dp"
|
||||
android:text="@string/read">
|
||||
|
||||
<requestFocus />
|
||||
@@ -244,11 +244,11 @@
|
||||
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:insetRight="40dp"
|
||||
android:nextFocusDown="@+id/torrent" />
|
||||
|
||||
|
||||
<android.widget.Space
|
||||
|
||||
@@ -188,11 +188,11 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
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:chipSpacingHorizontal="8dp"
|
||||
app:ensureMinTouchTargetSize="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/uploader"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
@@ -18,4 +18,5 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
@@ -18,4 +18,5 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Custom preference -->
|
||||
|
||||
</resources>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Custom preference -->
|
||||
|
||||
</resources>
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
</resources>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Custom preference -->
|
||||
|
||||
</resources>
|
||||
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
|
||||
</resources>
|
||||
File renamed without changes.
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="646" height="250" id="svg8502" version="1.1" inkscape:version="0.91 r13725" sodipodi:docname="get-it-on-github.svg" inkscape:export-filename="/home/nixdorf/Lokaler Speicher/Build/andOTP/assets/badges/get-it-on-github.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90">
|
||||
<defs id="defs8504" />
|
||||
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="0.50000001" inkscape:cx="-223.13537" inkscape:cy="546.37524" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" inkscape:window-width="1920" inkscape:window-height="1021" inkscape:window-x="0" inkscape:window-y="31" inkscape:window-maximized="1" />
|
||||
<metadata id="metadata8507">
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Andrew Nayenko</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>https://f-droid.org</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(-289,-312.36218)">
|
||||
<rect style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#a6a6a6;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" id="rect3007" width="560" height="164" x="332" y="355.36218" rx="20" ry="20" />
|
||||
<text sodipodi:linespacing="100%" id="text3013" y="402.36697" x="508.95129" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.39519119px;line-height:100%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" xml:space="preserve"><tspan y="402.36697" x="508.95129" id="tspan3015" sodipodi:role="line" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:34.125px;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans'">GET IT ON</tspan></text>
|
||||
<text xml:space="preserve" style="color:black;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:29.70882034px;line-height:100%;font-family:Rokkitt;-inkscape-font-specification:'Rokkitt Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:white;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;enable-background:accumulate" x="508.21259" y="489.36108" id="text5902" sodipodi:linespacing="100%"><tspan sodipodi:role="line" id="tspan5904" x="508.21259" y="489.36108" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:87.5px;line-height:100%;font-family:'Roboto Slab';-inkscape-font-specification:'Roboto Slab Bold';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:1">GitHub</tspan></text>
|
||||
<g transform="matrix(1.0017681,0,0,1.0017681,68.770756,92.660249)" id="g5136">
|
||||
<path style="fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none" d="m 350.60937,282.4375 c -33.34765,0 -60.38671,27.03516 -60.38671,60.38672 0,26.67969 17.30078,49.3164 41.29687,57.30078 3.01563,0.55859 4.125,-1.30859 4.125,-2.90625 0,-1.4375 -0.0547,-6.19531 -0.082,-11.24219 -16.80078,3.65235 -20.34375,-7.125 -20.34375,-7.125 -2.75,-6.98047 -6.70703,-8.83594 -6.70703,-8.83594 -5.48047,-3.74609 0.41406,-3.67187 0.41406,-3.67187 6.0625,0.42578 9.25781,6.22266 9.25781,6.22266 5.38282,9.23437 14.125,6.5664 17.57032,5.02343 0.54296,-3.90234 2.10937,-6.57031 3.83593,-8.07812 -13.41406,-1.52735 -27.51562,-6.70313 -27.51562,-29.84375 0,-6.59375 2.35937,-11.98047 6.22265,-16.20703 -0.625,-1.52344 -2.6914,-7.66407 0.58594,-15.98047 0,0 5.07031,-1.625 16.60938,6.1875 4.82031,-1.33594 9.98437,-2.00781 15.11718,-2.03125 5.13282,0.0234 10.30079,0.69531 15.12891,2.03125 11.52344,-7.8125 16.58984,-6.1875 16.58984,-6.1875 3.28516,8.3164 1.21875,14.45703 0.58985,15.98047 3.87109,4.22656 6.21484,9.61328 6.21484,16.20703 0,23.19531 -14.125,28.30078 -27.57422,29.79687 2.16797,1.875 4.09766,5.55078 4.09766,11.1836 0,8.07812 -0.0703,14.58203 -0.0703,16.57031 0,1.60937 1.08593,3.49219 4.14843,2.89844 23.98047,-7.9961 41.26172,-30.6211 41.26172,-57.29297 0,-33.35156 -27.03515,-60.38672 -60.38672,-60.38672" id="path4937" inkscape:connector-curvature="0" />
|
||||
<path style="fill:white;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 313.09375,369.14062 c -0.13281,0.30079 -0.60547,0.38672 -1.03516,0.1836 -0.4375,-0.19922 -0.68359,-0.60547 -0.54297,-0.91016 0.12891,-0.30859 0.60157,-0.39062 1.03907,-0.1875 0.4414,0.19922 0.6914,0.61328 0.53906,0.91406" id="path4939" inkscape:connector-curvature="0" />
|
||||
<path style="fill:white;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 315.53906,371.86719 c -0.28906,0.26562 -0.85156,0.14453 -1.23437,-0.27735 -0.39453,-0.42187 -0.46875,-0.98437 -0.17578,-1.25781 0.29687,-0.26562 0.84375,-0.14062 1.23828,0.28125 0.39453,0.42578 0.47265,0.98438 0.17187,1.25391" id="path4941" inkscape:connector-curvature="0" />
|
||||
<path style="fill:white;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 317.92187,375.34375 c -0.37109,0.25781 -0.97656,0.0156 -1.35156,-0.51953 -0.37109,-0.53906 -0.37109,-1.17969 0.008,-1.4375 0.375,-0.25781 0.97266,-0.0274 1.35157,0.5039 0.36718,0.54688 0.36718,1.19141 -0.008,1.45313" id="path4943" inkscape:connector-curvature="0" />
|
||||
<path style="fill:white;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 321.18359,378.70312 c -0.33203,0.36719 -1.03906,0.26954 -1.55468,-0.23046 -0.52735,-0.48438 -0.67579,-1.17579 -0.34375,-1.54297 0.33593,-0.36328 1.04687,-0.26172 1.5664,0.23047 0.52344,0.48828 0.6836,1.18359 0.33203,1.54296" id="path4945-3" inkscape:connector-curvature="0" />
|
||||
<path style="fill:white;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 325.68359,380.65625 c -0.14843,0.47266 -0.82812,0.6875 -1.51172,0.48828 -0.68359,-0.20703 -1.1289,-0.76172 -0.99218,-1.24219 0.14453,-0.47265 0.82422,-0.69922 1.51562,-0.48437 0.67969,0.20703 1.12891,0.75781 0.98828,1.23828" id="path4947-6" inkscape:connector-curvature="0" />
|
||||
<path style="fill:white;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 330.625,381.01953 c 0.0156,0.49609 -0.5625,0.91016 -1.28125,0.91797 -0.72266,0.0156 -1.30859,-0.38672 -1.31641,-0.875 0,-0.50391 0.57032,-0.91406 1.28907,-0.92578 0.71875,-0.0156 1.30859,0.38672 1.30859,0.88281" id="path4949" inkscape:connector-curvature="0" />
|
||||
<path style="fill:white;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 335.22266,380.23437 c 0.0859,0.48829 -0.41407,0.98438 -1.125,1.11719 -0.70313,0.12891 -1.35157,-0.17187 -1.44141,-0.65234 -0.0859,-0.5 0.42187,-0.9961 1.12109,-1.125 0.71485,-0.125 1.35547,0.16797 1.44532,0.66015" id="path4951-7" inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.5 KiB |
+1
-1
@@ -9,7 +9,7 @@ android {
|
||||
ndkVersion "25.0.8775105"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 26
|
||||
minSdkVersion 31
|
||||
targetSdkVersion 33
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@ public class Native {
|
||||
|
||||
public static native String getliblzmaVersion();
|
||||
|
||||
public static native String getlibjpeg_turboVersion();
|
||||
|
||||
public static native String getzlibVersion();
|
||||
|
||||
public static native String getnettleVersion();
|
||||
|
||||
@@ -47,7 +47,7 @@ public class UriArchiveAccessor {
|
||||
|
||||
private native int openArchive(long addr, long size);
|
||||
|
||||
public native void extracttoOutputStream(int index, int fd);
|
||||
public native long extracttoOutputStream(int index);
|
||||
|
||||
public native boolean needPassword();
|
||||
|
||||
|
||||
@@ -20,65 +20,68 @@ import android.graphics.Bitmap;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.io.FileDescriptor;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
public static final int FORMAT_ANIMATED = 1;
|
||||
|
||||
/**
|
||||
* Plain image format, for {@code Image} from {@link #create(Bitmap)}
|
||||
*/
|
||||
public static final int FORMAT_PLAIN = 0;
|
||||
private static final ArrayList<Image> imageList = new ArrayList<>();
|
||||
private static boolean needEvictAll = false;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
private static final AtomicInteger sImageCount = new AtomicInteger();
|
||||
private final int mFormat;
|
||||
private final int mWidth;
|
||||
private final int mHeight;
|
||||
private long mNativePtr;
|
||||
private Throwable mRecycleTracker;
|
||||
|
||||
private Image(long nativePtr, int format, int width, int height) {
|
||||
if (needEvictAll)
|
||||
evictAll();
|
||||
|
||||
mNativePtr = nativePtr;
|
||||
mFormat = format;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
sImageCount.getAndIncrement();
|
||||
imageList.add(this);
|
||||
}
|
||||
|
||||
public static void lazyEvictAll() {
|
||||
needEvictAll = true;
|
||||
}
|
||||
|
||||
private static void evictAll() {
|
||||
(new ArrayList<>(imageList)).forEach(Image::recycle);
|
||||
needEvictAll = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode image from {@code InputStream}
|
||||
*/
|
||||
@Nullable
|
||||
public static Image decode(Integer fd, boolean partially) {
|
||||
return nativeDecodeFdInt(fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode image from {@code InputStream}
|
||||
*/
|
||||
@Nullable
|
||||
public static Image decodeAddr(Long addr, boolean partially) {
|
||||
return nativeDecodeAddr(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,58 +97,30 @@ public final class Image {
|
||||
* It is useful for debug.
|
||||
*/
|
||||
public static int getImageCount() {
|
||||
return sImageCount.get();
|
||||
return imageList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all supported image formats, exclude {@link #FORMAT_PLAIN}
|
||||
*/
|
||||
public static int[] getSupportedImageFormats() {
|
||||
return nativeGetSupportedImageFormats();
|
||||
}
|
||||
private static native Image nativeDecode(FileDescriptor fd);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
private static native Image nativeDecode(InputStream is, boolean partially);
|
||||
private static native Image nativeDecodeAddr(long addr);
|
||||
|
||||
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,
|
||||
private static native void nativeRender(long nativePtr,
|
||||
int srcX, int srcY, Bitmap dst, int dstX, int dstY,
|
||||
int width, int height, boolean fillBlank, int defaultColor);
|
||||
int width, int height);
|
||||
|
||||
private static native void nativeTexImage(long nativePtr, int format,
|
||||
boolean init, int offsetX, int offsetY, int width, int height);
|
||||
private static native void nativeTexImage(long nativePtr, boolean init, int offsetX, int offsetY, int width, int height);
|
||||
|
||||
private static native void nativeAdvance(long nativePtr, int format);
|
||||
private static native void nativeAdvance(long nativePtr);
|
||||
|
||||
private static native int nativeGetDelay(long nativePtr, int format);
|
||||
private static native int nativeGetDelay(long nativePtr);
|
||||
|
||||
private static native int nativeFrameCount(long nativePtr, int format);
|
||||
private static native boolean nativeIsOpaque(long nativePtr);
|
||||
|
||||
private static native boolean nativeIsOpaque(long nativePtr, int format);
|
||||
|
||||
private static native boolean nativeIsGray(long nativePtr, int format, int error);
|
||||
|
||||
private static native void nativeClahe(long nativePtr, int format, boolean toGray);
|
||||
|
||||
private static native void nativeRecycle(long nativePtr, int format);
|
||||
|
||||
private static native int[] nativeGetSupportedImageFormats();
|
||||
|
||||
private static native String nativeGetDecoderDescription(int format);
|
||||
private static native void nativeRecycle(long nativePtr);
|
||||
|
||||
/**
|
||||
* Return the format of the image
|
||||
@@ -168,48 +143,19 @@ public final class Image {
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the minimum number of bytes that can be used to store this image's pixels.
|
||||
*/
|
||||
public int getByteCount() {
|
||||
checkRecycled();
|
||||
return nativeGetByteCount(mNativePtr, mFormat);
|
||||
}
|
||||
|
||||
private void checkRecycled() {
|
||||
if (mNativePtr == 0) {
|
||||
if (mRecycleTracker != null) {
|
||||
throw new IllegalStateException("The image is recycled.", mRecycleTracker);
|
||||
} else {
|
||||
throw new IllegalStateException("The image is recycled.");
|
||||
}
|
||||
throw new IllegalStateException("The image is recycled.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
public void render(int srcX, int srcY, Bitmap dst, int dstX, int dstY,
|
||||
int width, int height, boolean fillBlank, int defaultColor) {
|
||||
checkRecycled();
|
||||
nativeRender(mNativePtr, mFormat, srcX, srcY, dst, dstX, dstY,
|
||||
width, height, fillBlank, defaultColor);
|
||||
nativeRender(mNativePtr, srcX, srcY, dst, dstX, dstY, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,7 +165,7 @@ public final class Image {
|
||||
*/
|
||||
public void texImage(boolean init, int offsetX, int offsetY, int width, int height) {
|
||||
checkRecycled();
|
||||
nativeTexImage(mNativePtr, mFormat, init, offsetX, offsetY, width, height);
|
||||
nativeTexImage(mNativePtr, init, offsetX, offsetY, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,7 +173,7 @@ public final class Image {
|
||||
*/
|
||||
public void advance() {
|
||||
checkRecycled();
|
||||
nativeAdvance(mNativePtr, mFormat);
|
||||
nativeAdvance(mNativePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,40 +181,16 @@ public final class Image {
|
||||
*/
|
||||
public int getDelay() {
|
||||
checkRecycled();
|
||||
int delay = nativeGetDelay(mNativePtr, mFormat);
|
||||
int delay = nativeGetDelay(mNativePtr);
|
||||
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
|
||||
*/
|
||||
public boolean isOpaque() {
|
||||
checkRecycled();
|
||||
return nativeIsOpaque(mNativePtr, mFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code true} if the image is gray.
|
||||
*/
|
||||
public boolean isGray(int error) {
|
||||
checkRecycled();
|
||||
return nativeIsGray(mNativePtr, mFormat, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Improves contrast in this image with CLAHE.
|
||||
*/
|
||||
public void clahe(boolean toGray) {
|
||||
checkRecycled();
|
||||
nativeClahe(mNativePtr, mFormat, toGray);
|
||||
return nativeIsOpaque(mNativePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,14 +198,11 @@ public final class Image {
|
||||
* It must be called when the image will not be used.
|
||||
* The image can't be used after this method is called.
|
||||
*/
|
||||
public void recycle() {
|
||||
public synchronized void recycle() {
|
||||
if (mNativePtr != 0) {
|
||||
nativeRecycle(mNativePtr, mFormat);
|
||||
nativeRecycle(mNativePtr);
|
||||
mNativePtr = 0;
|
||||
|
||||
sImageCount.getAndDecrement();
|
||||
|
||||
mRecycleTracker = new Throwable("It's a ImageRecycleTracker");
|
||||
imageList.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -44,8 +45,6 @@ public final class ImageBitmap implements Animatable, Runnable {
|
||||
private final Bitmap mBitmap;
|
||||
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;
|
||||
@@ -60,10 +59,8 @@ public final class ImageBitmap implements Animatable, Runnable {
|
||||
image.render(0, 0, mBitmap, 0, 0, width, height, false, 0);
|
||||
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 +70,17 @@ 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 {
|
||||
@@ -223,13 +218,6 @@ public final class ImageBitmap implements Animatable, Runnable {
|
||||
return mIsOpaque;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return byte count of image
|
||||
*/
|
||||
public int getByteCount() {
|
||||
return mByteCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return image is animated
|
||||
*/
|
||||
@@ -237,13 +225,6 @@ public final class ImageBitmap implements Animatable, Runnable {
|
||||
return mImage != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return image frame count
|
||||
*/
|
||||
public int getFrameCount() {
|
||||
return mFrameCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw image to canvas
|
||||
*/
|
||||
|
||||
@@ -43,21 +43,27 @@ static char *passwd = NULL;
|
||||
static void *archiveAddr = NULL;
|
||||
static jlong archiveSize = 0;
|
||||
|
||||
const char supportExt[9][6] = {
|
||||
"jpeg",
|
||||
"jpg",
|
||||
"png",
|
||||
"gif",
|
||||
"webp",
|
||||
"bmp",
|
||||
"ico",
|
||||
"wbmp",
|
||||
"heif"
|
||||
};
|
||||
|
||||
static int filename_is_playable_file(const char *name) {
|
||||
const char *dotptr = strrchr(name, '.');
|
||||
if (dotptr++) {
|
||||
switch (*dotptr) {
|
||||
case 'j':
|
||||
return (strcmp(dotptr, "jpg") == 0) || (strcmp(dotptr, "jpeg") == 0);
|
||||
case 'p':
|
||||
return strcmp(dotptr, "png") == 0;
|
||||
case 'g':
|
||||
return strcmp(dotptr, "gif") == 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
if (!dotptr++)
|
||||
return false;
|
||||
int i;
|
||||
for (i = 0; i < 9; i++)
|
||||
if (strcmp(dotptr, supportExt[i]) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static long archive_list_all_entries() {
|
||||
@@ -111,7 +117,6 @@ Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jlong add
|
||||
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;
|
||||
}
|
||||
@@ -121,35 +126,35 @@ Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jlong add
|
||||
return r;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *_, jobject thiz, jint index,
|
||||
jint fd) {
|
||||
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) {
|
||||
archive_alloc();
|
||||
cur_index = 0;
|
||||
}
|
||||
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) {
|
||||
for (;;) {
|
||||
ret = archive_read_data_block(arc, &buff, &size, &offset);
|
||||
if (ret == ARCHIVE_EOF)
|
||||
break;
|
||||
if (ret != ARCHIVE_OK) {
|
||||
LOGE("%s%s", "Archive read failed:", archive_error_string(arc));
|
||||
break;
|
||||
}
|
||||
write(fd, buff, size);
|
||||
}
|
||||
memarea->size = archive_entry_size(entry);
|
||||
memarea->buffer = malloc(memarea->size);
|
||||
ret = archive_read_data(arc, memarea->buffer, memarea->size);
|
||||
if (ret != memarea->size)
|
||||
LOGE("%s", "No enough data read, WTF?");
|
||||
if (ret < 0)
|
||||
LOGE("%s%s", "Archive read failed:", archive_error_string(arc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (jlong) memarea;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
@@ -172,7 +177,6 @@ Java_com_hippo_UriArchiveAccessor_providePassword(JNIEnv *_, jobject thiz, jstri
|
||||
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)))
|
||||
|
||||
@@ -13,9 +13,22 @@
|
||||
# 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
|
||||
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})
|
||||
@@ -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,111 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include <android/data_space.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "image.h"
|
||||
#include "image_utils.h"
|
||||
|
||||
void decodeCommon(IMAGE *image, SOURCE *src) {
|
||||
image->src = src;
|
||||
AImageDecoder *decoder = src->decoder;
|
||||
image->isAnimated = AImageDecoder_isAnimated(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;
|
||||
src->stride = AImageDecoder_getMinimumStride(decoder);
|
||||
image->bufferLen = (int) (image->height * src->stride);
|
||||
image->buffer = malloc(image->bufferLen);
|
||||
if (image->isAnimated) {
|
||||
AImageDecoder_setInternallyHandleDisposePrevious(decoder, false);
|
||||
AImageDecoderFrameInfo *frameInfo = AImageDecoderFrameInfo_create();
|
||||
AImageDecoder_getFrameInfo(decoder, frameInfo);
|
||||
image->delay = (int) AImageDecoderFrameInfo_getDuration(frameInfo) / 1000000;
|
||||
AImageDecoderFrameInfo_delete(frameInfo);
|
||||
}
|
||||
AImageDecoder_decodeImage(decoder, image->buffer, src->stride, image->bufferLen);
|
||||
if (!image->isAnimated) {
|
||||
recycleSource(image->src);
|
||||
image->src = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
IMAGE *createFromFd(int fd) {
|
||||
AImageDecoder *decoder = NULL;
|
||||
if (AImageDecoder_createFromFd(fd, &decoder) != ANDROID_IMAGE_DECODER_SUCCESS)
|
||||
return NULL;
|
||||
IMAGE *image = calloc(1, sizeof(IMAGE));
|
||||
SOURCE *src = calloc(1, sizeof(SOURCE));
|
||||
src->decoder = decoder;
|
||||
src->fd = fd;
|
||||
decodeCommon(image, src);
|
||||
return image;
|
||||
}
|
||||
|
||||
IMAGE *createFromAddr(void *addr, long size) {
|
||||
AImageDecoder *decoder;
|
||||
AImageDecoder_createFromBuffer((const void *) addr, size, &decoder);
|
||||
IMAGE *image = calloc(1, sizeof(IMAGE));
|
||||
SOURCE *src = calloc(1, sizeof(SOURCE));
|
||||
src->decoder = decoder;
|
||||
src->srcBuffer = addr;
|
||||
decodeCommon(image, src);
|
||||
return image;
|
||||
}
|
||||
|
||||
IMAGE *create(int32_t width, int32_t height, const void *data) {
|
||||
IMAGE *plain = calloc(1, sizeof(IMAGE));
|
||||
void *buffer = NULL;
|
||||
size_t length = width * height * 4;
|
||||
|
||||
buffer = malloc(length);
|
||||
memcpy(buffer, data, length);
|
||||
|
||||
plain->width = width;
|
||||
plain->height = height;
|
||||
plain->buffer = buffer;
|
||||
plain->bufferLen = (int) length;
|
||||
|
||||
return plain;
|
||||
}
|
||||
|
||||
void render(IMAGE *image, int src_x, int src_y,
|
||||
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height) {
|
||||
copy_pixels(image->buffer, image->width, image->height, src_x, src_y, dst, dst_w, dst_h, dst_x,
|
||||
dst_y, width, height);
|
||||
}
|
||||
|
||||
void advance(IMAGE *image) {
|
||||
if (image->isAnimated) {
|
||||
AImageDecoder_advanceFrame(image->src->decoder);
|
||||
if (AImageDecoder_decodeImage(image->src->decoder, image->buffer, image->src->stride,
|
||||
image->bufferLen) == ANDROID_IMAGE_DECODER_FINISHED) {
|
||||
AImageDecoder_rewind(image->src->decoder);
|
||||
AImageDecoder_decodeImage(image->src->decoder, image->buffer, image->src->stride,
|
||||
image->bufferLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_IMAGE_H
|
||||
#define IMAGE_IMAGE_H
|
||||
|
||||
#include <android/imagedecoder.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
AImageDecoder *decoder;
|
||||
void *srcBuffer;
|
||||
size_t stride;
|
||||
int fd;
|
||||
} SOURCE;
|
||||
|
||||
typedef struct {
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
void *buffer;
|
||||
int bufferLen;
|
||||
bool isAnimated;
|
||||
bool alpha;
|
||||
int delay;
|
||||
SOURCE *src;
|
||||
} IMAGE;
|
||||
|
||||
static void recycleSource(SOURCE *src) {
|
||||
if (!src)
|
||||
return;
|
||||
AImageDecoder_delete(src->decoder);
|
||||
free(src->srcBuffer);
|
||||
free(src);
|
||||
}
|
||||
|
||||
static void recycle(IMAGE *image) {
|
||||
if (!image)
|
||||
return;
|
||||
recycleSource(image->src);
|
||||
free(image->buffer);
|
||||
free(image);
|
||||
}
|
||||
|
||||
IMAGE *createFromFd(int fd);
|
||||
|
||||
IMAGE *createFromAddr(void *addr, long size);
|
||||
|
||||
IMAGE *create(int32_t width, int32_t height, const void *data);
|
||||
|
||||
void render(IMAGE *image, int src_x, int src_y,
|
||||
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
|
||||
int width, int height);
|
||||
|
||||
void advance(IMAGE *image);
|
||||
|
||||
#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,24 +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.
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_CLAHE_H
|
||||
#define IMAGE_CLAHE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
void IMAGE_clahe(void* data, int width, int height, bool to_gray);
|
||||
|
||||
#endif //IMAGE_CLAHE_H
|
||||
@@ -1,36 +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.
|
||||
*/
|
||||
|
||||
#include "gray.h"
|
||||
#include "pixel.h"
|
||||
|
||||
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;
|
||||
|
||||
if (e1 > error || e1 < -error
|
||||
|| e2 > error || e2 < -error
|
||||
|| e3 > error || e3 < -error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,24 +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.
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_GRAY_H
|
||||
#define IMAGE_GRAY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool IMAGE_is_gray(void* data, int width, int height, int error);
|
||||
|
||||
#endif //IMAGE_GRAY_H
|
||||
@@ -1,30 +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.
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_PIXEL_H
|
||||
#define IMAGE_PIXEL_H
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE c1;
|
||||
BYTE c2;
|
||||
BYTE c3;
|
||||
BYTE c4;
|
||||
} PIXEL;
|
||||
|
||||
#endif //IMAGE_PIXEL_H
|
||||
@@ -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,107 @@
|
||||
/*
|
||||
* 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 "image_utils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
bool 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) {
|
||||
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;
|
||||
|
||||
// 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++) {
|
||||
dst_pos += dst_blank_length;
|
||||
memcpy(dst + dst_pos, src + src_pos, line_stride);
|
||||
dst_pos += line_stride;
|
||||
src_pos += src_stride;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
+4
-8
@@ -17,17 +17,13 @@
|
||||
* EhViewer. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/27/2015.
|
||||
//
|
||||
|
||||
#ifndef IMAGE_IMAGE_UTILS_H
|
||||
#define IMAGE_IMAGE_UTILS_H
|
||||
|
||||
#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);
|
||||
bool 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);
|
||||
|
||||
#endif //IMAGE_IMAGE_UTILS_H
|
||||
#endif /* IMAGE_IMAGE_UTILS_H */
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 <jni.h>
|
||||
|
||||
#include "java_wrapper.h"
|
||||
#include "image.h"
|
||||
#include "log.h"
|
||||
|
||||
static void *tile_buffer = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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");
|
||||
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) {
|
||||
IMAGE *image = createFromFd(fd);
|
||||
if (!image)
|
||||
return NULL;
|
||||
return create_image_object(env, image, image->isAnimated, image->width, image->height);
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_hippo_image_Image_nativeDecode(JNIEnv *env, jclass clazz, jobject fd) {
|
||||
return Java_com_hippo_image_Image_nativeDecodeFdInt(env, clazz,
|
||||
jniGetFDFromFileDescriptor(env, fd));
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_hippo_image_Image_nativeCreate(JNIEnv *env, jclass clazz, jobject bitmap) {
|
||||
AndroidBitmapInfo info;
|
||||
void *pixels = NULL;
|
||||
void *image = NULL;
|
||||
|
||||
AndroidBitmap_getInfo(env, bitmap, &info);
|
||||
AndroidBitmap_lockPixels(env, bitmap, &pixels);
|
||||
|
||||
image = create(info.width, info.height, pixels);
|
||||
AndroidBitmap_unlockPixels(env, bitmap);
|
||||
return create_image_object(env, image, 0, info.width, info.height);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeRender(JNIEnv *env, jclass clazz, jlong ptr, jint src_x,
|
||||
jint src_y, jobject dst, jint dst_x, jint dst_y, jint width,
|
||||
jint height) {
|
||||
AndroidBitmapInfo info;
|
||||
void *pixels = NULL;
|
||||
|
||||
AndroidBitmap_getInfo(env, dst, &info);
|
||||
AndroidBitmap_lockPixels(env, dst, &pixels);
|
||||
|
||||
render((IMAGE *) ptr, src_x, src_y, pixels, info.width, info.height, dst_x, dst_y, width,
|
||||
height);
|
||||
|
||||
AndroidBitmap_unlockPixels(env, dst);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeTexImage(JNIEnv *env, jclass clazz, jlong ptr, jboolean init,
|
||||
jint src_x, jint src_y, jint width, jint height) {
|
||||
if (width * height > IMAGE_TILE_MAX_SIZE)
|
||||
return;
|
||||
|
||||
render((IMAGE *) ptr, src_x, src_y, tile_buffer, width, height, 0, 0, width, height);
|
||||
|
||||
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) {
|
||||
advance((IMAGE *) ptr);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_hippo_image_Image_nativeGetDelay(JNIEnv *env, jclass clazz, jlong ptr) {
|
||||
return ((IMAGE *) ptr)->delay;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_hippo_image_Image_nativeIsOpaque(JNIEnv *env, jclass clazz, jlong ptr) {
|
||||
return ((IMAGE *) ptr)->alpha;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_hippo_image_Image_nativeRecycle(JNIEnv *env, jclass clazz, jlong ptr) {
|
||||
recycle((IMAGE *) ptr);
|
||||
}
|
||||
|
||||
bool image_onLoad() {
|
||||
tile_buffer = malloc(IMAGE_TILE_MAX_SIZE * 4);
|
||||
return tile_buffer != NULL;
|
||||
}
|
||||
|
||||
void image_onUnload() {
|
||||
free(tile_buffer);
|
||||
tile_buffer = NULL;
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_hippo_image_Image_nativeDecodeAddr(JNIEnv *env, jclass clazz, jlong addr) {
|
||||
Memarea *memarea = (Memarea *) addr;
|
||||
IMAGE *image = createFromAddr(memarea->buffer, memarea->size);
|
||||
free(memarea);
|
||||
return create_image_object(env, image, image->isAnimated, image->width, image->height);
|
||||
}
|
||||
+7
-9
@@ -17,22 +17,20 @@
|
||||
* EhViewer. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 12/28/2015.
|
||||
//
|
||||
|
||||
#ifndef IMAGE_JAVA_WRAPPER_H
|
||||
#define IMAGE_JAVA_WRAPPER_H
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define IMAGE_TILE_MAX_SIZE (512 * 512)
|
||||
|
||||
bool image_onLoad(JavaVM *vm);
|
||||
typedef struct Memarea {
|
||||
void *buffer;
|
||||
long size;
|
||||
} Memarea;
|
||||
|
||||
JNIEnv *obtain_env(bool *attach);
|
||||
bool image_onLoad();
|
||||
|
||||
void release_env();
|
||||
void image_onUnload();
|
||||
|
||||
#endif // IMAGE_JAVA_WRAPPER_H
|
||||
#endif /* IMAGE_JAVA_WRAPPER_H */
|
||||
@@ -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 */
|
||||
@@ -14,18 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by Hippo on 10/19/2015.
|
||||
//
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define TAG "Image"
|
||||
#define TAG "ImageDecoder_wrapper"
|
||||
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG ,__VA_ARGS__)
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG ,__VA_ARGS__)
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG ,__VA_ARGS__)
|
||||
@@ -33,11 +27,4 @@
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG ,__VA_ARGS__)
|
||||
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, TAG ,__VA_ARGS__)
|
||||
|
||||
#define FILE_LINE MAKESTRING(STRINGIZE, __LINE__ )
|
||||
#define MSG(msg) __FILE__ "(" FILE_LINE "): "msg
|
||||
|
||||
#define OUT_OF_MEMORY "Out of memory"
|
||||
|
||||
#define WTF_OM LOGE(MSG(OUT_OF_MEMORY))
|
||||
|
||||
#endif //LOG_H
|
||||
#endif /* LOG_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
|
||||
@@ -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/29/2015.
|
||||
//
|
||||
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#define STRINGIZE(L) #L
|
||||
#define MAKESTRING(M, L) M(L)
|
||||
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#endif // UTILS_H
|
||||
@@ -21,10 +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;
|
||||
@@ -40,6 +39,11 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNI_OnUnload(JavaVM *vm, void *reserved) {
|
||||
image_onUnload();
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_hippo_Native_getlibarchiveVersion(JNIEnv *env, jclass clazz) {
|
||||
return (*env)->NewStringUTF(env, ARCHIVE_VERSION_STRING);
|
||||
@@ -50,11 +54,6 @@ 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);
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"baseBranches": [
|
||||
"1.8.x.x",
|
||||
"1.7.x.x"
|
||||
],
|
||||
|
||||
"extends": [
|
||||
"config:base"
|
||||
]
|
||||
|
||||
Reference in new issue
Block a user