Compare commits

...
41 Commits
Author SHA1 Message Date
tarsin a7f7bf1316 Release 1.8
CI / Build (push) Has been cancelled
Releases / Build (push) Has been cancelled
2022-07-25 10:20:16 +08:00
tarsin a72fca3dfb Fix a lag 2022-07-25 10:16:54 +08:00
tarsin c5e7a6e8f9 Code clean 2022-07-25 10:02:34 +08:00
tarsin 80a20f25b9 Fix animated 2022-07-25 09:28:40 +08:00
tarsin 500163fe1a Merge pull request #132 from Ehviewer-Overhauled/master
Pull master
2022-07-25 07:54:04 +08:00
txyyh 513886eff4 pick gallery_detail_header.xml changes to television (#131)
* Rewrite info TableLayout to ConstraintLayout for television

* Rewrite layout and minor design improve for television
2022-07-25 07:50:58 +08:00
txyyh 0093db9986 Make buttongroup horizontal (#125)
* Use another impl to create space

* Horizontal button
2022-07-25 07:50:41 +08:00
tarsin 50c6111773 Imagedecoder do not support anon pipe, drop it and use memarea 2022-07-24 23:32:03 +08:00
tarsin 3a05649c71 Code clean 2022-07-24 22:34:19 +08:00
tarsin 9d25376e1f Refactor 2022-07-24 21:41:53 +08:00
tarsin 89935b5639 Hard cast 2022-07-24 20:32:39 +08:00
tarsin e095627aee Refactor 2022-07-24 20:20:04 +08:00
tarsin b61e46e956 Clean up 2022-07-24 19:49:34 +08:00
tarsin 76459c5dd2 Initial stupid migrate to ImageDecoder 2022-07-24 19:18:54 +08:00
tarsin 7ad67a3dbd Minsdk 31 2022-07-24 18:24:24 +08:00
tarsin 577b49ac19 Drop image decode native libs 2022-07-24 18:17:37 +08:00
txyyh 182e3a0d40 Rewrite README description (#124) 2022-07-24 17:40:19 +08:00
txyyh 6d140aaa9d Delete FOSSA (#123) 2022-07-24 14:24:31 +08:00
tarsin 17248d3a82 Revert "Use SMAPSHOT version of mdc"
This reverts commit 7a0fab29bc.
2022-07-24 13:07:28 +08:00
txyyh ec80e7a189 Back to corner (#121) 2022-07-24 05:36:07 +08:00
txyyh 493eeadf1b Add note for CI download (#122) 2022-07-24 03:35:28 +08:00
tarsin 7a0fab29bc Use SMAPSHOT version of mdc 2022-07-23 20:41:02 +08:00
hathlife 5f7e40f258 Gallery detail head tv layout (#96)
* Make height of App logo ImageView match parent

* Add TV layout for gallery detail scene.

* Add credits

* Use GPLv3 for all TV layout code
2022-07-23 20:27:42 +08:00
txyyh 0bf6b8d827 Release 1.7.29.1
CI / Build (push) Has been cancelled
Releases / Build (push) Has been cancelled
2022-07-23 17:14:25 +08:00
tarsin 4c6ccab051 Native lib info refactor 2022-07-23 16:25:53 +08:00
tarsin 00377f15b9 Set our own libs 2022-07-23 16:07:23 +08:00
tarsin 96b50eb5aa Add nettle for encrypt 2022-07-23 15:51:43 +08:00
tarsin acdf681d40 Add gnutls libnettle 2022-07-23 14:26:17 +08:00
tarsin b92cf9746b Add .gz .xz .tar .cbz .cbr to supported mimeTypes 2022-07-23 13:28:41 +08:00
txyyh d0dfbaaae0 Rewrite layout and minor design improve (#116)
* Use ConstraintLayout instead

* Specify info Card Text to BodySmall

* Specify thumb shape to none (no corner)
2022-07-23 07:44:33 +08:00
txyyh 0c656e617b Add CI download link (#117)
* Add CI Download link

* Use head in right way
2022-07-23 00:49:03 +08:00
tarsin 148b1a6344 Release 1.7.29.0
CI / Build (push) Has been cancelled
Releases / Build (push) Has been cancelled
2022-07-22 23:12:27 +08:00
tarsin 1fe0b079cd Support auto store archive's passwd 2022-07-22 22:53:44 +08:00
tarsin 87505aa989 Code clean 2022-07-22 22:18:41 +08:00
tarsin 3d7a71647e Initial support for encrypted archive read 2022-07-22 21:28:19 +08:00
txyyh c9d2f698b6 Add MDC-Android to Thanks (#113) 2022-07-22 16:51:52 +08:00
tarsin 233adbddae Drop another spinner 2022-07-22 14:14:29 +08:00
tarsin 6900d8a8c9 Rename .java to .kt 2022-07-22 14:14:29 +08:00
tarsin 640f75d8d9 Finally our data is no need to pass any jByteArray 2022-07-22 10:08:04 +08:00
tarsin 4381eb8c3d Fuck off the buffer 2022-07-22 09:52:35 +08:00
tarsin 3026b16d70 Don't emulate posix read, do mmap instead 2022-07-22 00:13:53 +08:00
97 changed files with 2712 additions and 5838 deletions

No files matched your search

+3 -9
View File
@@ -1,15 +1,9 @@
[submodule "native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo"]
path = native/src/main/jni/image/libjpeg-turbo/libjpeg-turbo
url = https://github.com/Ehviewer-Overhauled/libjpeg-turbo
[submodule "native/src/main/jni/image/giflib/giflib"]
path = native/src/main/jni/image/giflib/giflib
url = https://github.com/Ehviewer-Overhauled/giflib
[submodule "native/src/main/jni/image/libpng/libpng"]
path = native/src/main/jni/image/libpng/libpng
url = https://github.com/Ehviewer-Overhauled/libpng
[submodule "native/src/main/jni/libarchive"]
path = native/src/main/jni/libarchive
url = https://github.com/Ehviewer-Overhauled/libarchive
[submodule "native/src/main/jni/liblzma"]
path = native/src/main/jni/liblzma
url = https://github.com/Ehviewer-Overhauled/xz
[submodule "native/src/main/jni/nettle/nettle"]
path = native/src/main/jni/nettle/nettle
url = https://github.com/Ehviewer-Overhauled/nettle
+12 -14
View File
@@ -21,30 +21,29 @@
</a>
</p>
## Description
这是一个 E-Hentai Android 平台的浏览器
# Description
致力于轻量化与良好性能表现的 EhViewer 分支
已针对性适配 Material Design 3 及其动态取色系统
动态配色仅供 Android 12 及以上平台使用!
EhViewer fork dedicated to lightweight and high-performance
An E-Hentai Application for Android.
with Material Design 3 and Dynamic Color Support
with Material Design 3 and Dynamic Color Support.
Dynamic Color only support Android S and above!
## Download
# Download
[Github 下载](https://github.com/Ehviewer-Overhauled/Ehviewer/releases)
## Screenshot
[CI 版本下载(需登录)](https://github.com/Ehviewer-Overhauled/Ehviewer/actions/workflows/ci.yml)
# Screenshot
![screenshot-01](art/screenshot-01.png)
![screenshot-02](art/screenshot-02.png)
## Thanks
# Thanks
本项目受到了诸多开源项目的帮助
@@ -52,6 +51,7 @@ Here is the libraries
- [AOSP](http://source.android.com/)
- [android-advancedrecyclerview](https://github.com/h6ah4i/android-advancedrecyclerview)
- [material-components-android](https://github.com/material-components/material-components-android)
- [material-design-icons](https://github.com/google/material-design-icons)
- [Apache Commons Lang](https://commons.apache.org/proper/commons-lang/)
- [apng](http://apng.sourceforge.net/)
@@ -67,7 +67,7 @@ Here is the libraries
- [XZ Utils](https://tukaani.org/xz/)
## License
# License
Copyright 2014-2019 Hippo Seven
Copyright 2020-2022 NekoInverter
@@ -78,5 +78,3 @@ Here is the libraries
EhViewer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with EhViewer. If not, see <https://www.gnu.org/licenses/>.
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fasuka-mio%2FEhviewer.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fasuka-mio%2FEhviewer?ref=badge_large)
+3 -3
View File
@@ -32,10 +32,10 @@ android {
defaultConfig {
applicationId "moe.tarsin.ehviewer"
minSdkVersion 26
minSdkVersion 31
targetSdkVersion 33
versionCode 114531
versionName "1.7.28.4"
versionCode 180000
versionName "1.8.0.0"
resConfigs 'zh', 'zh-rCN', 'zh-rHK', 'zh-rTW', 'es', 'ja', 'ko', 'fr', 'de', 'th'
}
+14 -28
View File
@@ -120,35 +120,21 @@
<data android:mimeType="application/x-7z-compressed" />
<data android:mimeType="application/x-rar-compressed" />
<data android:mimeType="application/x-zip-compressed" />
</intent-filter>
<data android:mimeType="application/x-tar" />
<data android:mimeType="application/x-xz" />
<data android:mimeType="application/gzip" />
<data android:mimeType="application/x-cbz" />
<data android:mimeType="application/x-cbr" />
<data android:mimeType="application/x-cbt" />
<data android:mimeType="application/x-cb7" />
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:host="*" />
<data android:pathPattern=".*\\.7z" />
<data android:pathPattern=".*\\.rar" />
<data android:pathPattern=".*\\.zip" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:host="*" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.7z" />
<data android:pathPattern=".*\\.rar" />
<data android:pathPattern=".*\\.zip" />
<!-- untested -->
<data android:mimeType="application/vnd.comicbook+zip" />
<data android:mimeType="application/vnd.comicbook-rar" />
<data android:mimeType="application/x-compressed-tar" />
<data android:mimeType="application/x-bzip-compressed-tar" />
<data android:mimeType="application/x-lzma-compressed-tar" />
<data android:mimeType="application/x-xz-compressed-tar" />
</intent-filter>
</activity>
@@ -49,7 +49,7 @@ class EditTextDialogBuilder constructor(
return mDialog as AlertDialog
}
override fun onEditorAction(v: TextView, actionId: Int, event: KeyEvent): Boolean {
override fun onEditorAction(v: TextView?, p1: Int, event: KeyEvent?): Boolean {
return if (mDialog != null) {
val button = mDialog!!.getButton(DialogInterface.BUTTON_POSITIVE)
button?.performClick()
@@ -16,6 +16,8 @@
package com.hippo.ehviewer;
import android.os.ParcelFileDescriptor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -23,7 +25,9 @@ import com.hippo.conaco.ValueHelper;
import com.hippo.image.ImageBitmap;
import com.hippo.streampipe.InputStreamPipe;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class ImageBitmapHelper implements ValueHelper<ImageBitmap> {
@@ -34,7 +38,8 @@ public class ImageBitmapHelper implements ValueHelper<ImageBitmap> {
public ImageBitmap decode(@NonNull InputStreamPipe isPipe) {
try {
isPipe.obtain();
return ImageBitmap.decode(isPipe.open());
FileInputStream is = (FileInputStream) isPipe.open();
return ImageBitmap.decode(is.getFD());
} catch (OutOfMemoryError | IOException e) {
return null;
} finally {
@@ -41,6 +41,7 @@ import com.hippo.yorozuya.NumberUtils;
import java.io.File;
import java.util.Locale;
import java.util.Set;
public class Settings {
@@ -271,6 +272,11 @@ public class Settings {
private static final int DEFAULT_DOWNLOAD_DELAY = 0;
private static final String KEY_REQUEST_NEWS = "request_news";
private static final boolean DEFAULT_REQUEST_NEWS = true;
private static final String KEY_ARCHIVE_PASSWDS = "archive_passwds";
private static Context sContext;
private static SharedPreferences sSettingsPre;
private static EhConfig sEhConfig;
@@ -384,6 +390,21 @@ public class Settings {
sSettingsPre.edit().putString(key, value).apply();
}
public static Set<String> getStringSet(String key) {
return sSettingsPre.getStringSet(key, null);
}
public static void putStringToStringSet(String key, String value) {
Set<String> set = getStringSet(key);
if (set == null)
set = Set.of(value);
else if (set.contains(value))
return;
else
set.add(value);
sSettingsPre.edit().putStringSet(key, set).apply();
}
public static int getIntFromStr(String key, int defValue) {
try {
return NumberUtils.parseIntSafely(sSettingsPre.getString(key, Integer.toString(defValue)), defValue);
@@ -1139,4 +1160,12 @@ public class Settings {
public static void putClipboardTextHashCode(int value) {
putInt(KEY_CLIPBOARD_TEXT_HASH_CODE, value);
}
public static Set<String> getArchivePasswds() {
return getStringSet(KEY_ARCHIVE_PASSWDS);
}
public static void putPasswdToArchivePasswds(String value) {
putStringToStringSet(KEY_ARCHIVE_PASSWDS, value);
}
}
@@ -18,6 +18,7 @@ package com.hippo.ehviewer.gallery;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.Process;
import androidx.annotation.NonNull;
@@ -26,26 +27,33 @@ import androidx.annotation.Nullable;
import com.hippo.UriArchiveAccessor;
import com.hippo.ehviewer.GetText;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.Settings;
import com.hippo.glgallery.GalleryPageView;
import com.hippo.image.Image;
import com.hippo.unifile.UniFile;
import com.hippo.yorozuya.thread.PVLock;
import com.hippo.yorozuya.thread.PriorityThread;
import java.io.FileNotFoundException;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.atomic.AtomicInteger;
public class ArchiveGalleryProvider extends GalleryProvider2 {
private static final AtomicInteger sIdGenerator = new AtomicInteger();
public static Handler showPasswd;
public static String passwd;
public static PVLock pv = new PVLock(0);
private final UriArchiveAccessor archiveAccessor;
private final Stack<Integer> requests = new Stack<>();
private final AtomicInteger extractingIndex = new AtomicInteger(GalleryPageView.INVALID_INDEX);
private final LinkedHashMap<Integer, InputStream> streams = new LinkedHashMap<>();
private final LinkedHashMap<Integer, Long> streams = new LinkedHashMap<>();
private final AtomicInteger decodingIndex = new AtomicInteger(GalleryPageView.INVALID_INDEX);
private Thread archiveThread;
private Thread decodeThread;
@@ -56,7 +64,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
UriArchiveAccessor archiveAccessor1;
try {
archiveAccessor1 = new UriArchiveAccessor(context, uri);
} catch (FileNotFoundException e) {
} catch (Exception e) {
archiveAccessor1 = null;
e.printStackTrace();
}
@@ -90,6 +98,11 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
decodeThread.interrupt();
decodeThread = null;
}
try {
archiveAccessor.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
@@ -159,9 +172,27 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
}
private class ArchiveTask implements Runnable {
private void waitPasswd() throws InterruptedException {
showPasswd.sendEmptyMessage(0);
pv.p();
}
private void notifyError() {
showPasswd.sendEmptyMessage(1);
}
private void notifyDismiss() {
showPasswd.sendEmptyMessage(2);
}
@Override
public void run() {
size = archiveAccessor.open();
try {
size = archiveAccessor.open();
} catch (Exception e) {
e.printStackTrace();
size = 0;
}
if (size <= 0) {
size = STATE_ERROR;
error = GetText.getString(R.string.error_reading_failed);
@@ -171,6 +202,34 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
// Update size and notify changed
notifyDataChanged();
if (archiveAccessor.needPassword()) {
boolean need_request = true;
Set<String> set = Settings.getArchivePasswds();
if (set != null) {
for (String passwd : set) {
if (archiveAccessor.providePassword(passwd)) {
need_request = false;
break;
}
}
}
while (!Thread.currentThread().isInterrupted() && need_request) {
try {
waitPasswd();
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
if (!archiveAccessor.providePassword(passwd))
notifyError();
else {
Settings.putPasswdToArchivePasswds(passwd);
notifyDismiss();
break;
}
}
}
while (!Thread.currentThread().isInterrupted()) {
int index;
synchronized (requests) {
@@ -194,17 +253,18 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
continue;
}
Pipe pipe = new Pipe(4096 * 16);
synchronized (streams) {
if (streams.get(index) != null) {
continue;
}
streams.put(index, pipe.getInputStream());
streams.notify();
}
archiveAccessor.extractTargetIndexToOutputStream(index, pipe.getOutputStream());
long addr = archiveAccessor.extracttoOutputStream(index);
synchronized (streams) {
streams.put(index, addr);
streams.notify();
}
}
}
}
@@ -214,7 +274,7 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
int index;
InputStream stream;
Long addr;
synchronized (streams) {
if (streams.isEmpty()) {
try {
@@ -226,16 +286,16 @@ public class ArchiveGalleryProvider extends GalleryProvider2 {
continue;
}
Iterator<Map.Entry<Integer, InputStream>> iterator = streams.entrySet().iterator();
Map.Entry<Integer, InputStream> entry = iterator.next();
Iterator<Map.Entry<Integer, Long>> iterator = streams.entrySet().iterator();
Map.Entry<Integer, Long> entry = iterator.next();
iterator.remove();
index = entry.getKey();
stream = entry.getValue();
addr = entry.getValue();
decodingIndex.lazySet(index);
}
try {
Image image = Image.decode(stream, true);
Image image = Image.decodeAddr(addr, true);
if (image != null) {
notifyPageSucceed(index, image);
} else {
@@ -34,6 +34,7 @@ import com.hippo.yorozuya.IOUtils;
import com.hippo.yorozuya.StringUtils;
import com.hippo.yorozuya.thread.PriorityThread;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -258,7 +259,7 @@ public class DirGalleryProvider extends GalleryProvider2 implements Runnable {
InputStream is = null;
try {
is = files[index].openInputStream();
Image image = Image.decode(is, true);
Image image = Image.decode(((FileInputStream)is).getFD(), true);
mDecodingIndex.lazySet(GalleryPageView.INVALID_INDEX);
if (image != null) {
notifyPageSucceed(index, image);
@@ -1,156 +0,0 @@
/*
* Copyright 2019 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.gallery;
import androidx.annotation.NonNull;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
class Pipe {
private final int capacity;
private final byte[] buffer;
private int head = 0;
private int tail = 0;
private boolean full = false;
private boolean inClosed = false;
private boolean outClosed = false;
private final InputStream inputStream = new InputStream() {
@Override
public int read() throws IOException {
synchronized (Pipe.this) {
byte[] bytes = new byte[1];
if (read(bytes, 0, 1) != -1) {
return bytes[0];
} else {
return -1;
}
}
}
@Override
public int read(@NonNull byte[] b, int off, int len) throws IOException {
synchronized (Pipe.this) {
for (; ; ) {
if (inClosed) {
throw new IOException("The InputStream is closed");
}
if (len == 0) {
return 0;
}
if (head == tail && !full) {
if (outClosed) {
// No bytes available and the OutputStream is closed. So it's the end.
return -1;
} else {
// Wait for OutputStream write bytes
try {
Pipe.this.wait();
} catch (InterruptedException e) {
throw new IOException("The thread interrupted", e);
}
}
} else {
int read = Math.min(len, (head < tail ? tail : capacity) - head);
System.arraycopy(buffer, head, b, off, read);
head += read;
if (head == capacity) {
head = 0;
}
full = false;
Pipe.this.notifyAll();
return read;
}
}
}
}
@Override
public void close() {
synchronized (Pipe.this) {
inClosed = true;
Pipe.this.notifyAll();
}
}
};
private final OutputStream outputStream = new OutputStream() {
@Override
public void write(int b) throws IOException {
synchronized (Pipe.this) {
byte[] bytes = new byte[]{(byte) b};
write(bytes, 0, 1);
}
}
@Override
public void write(@NonNull byte[] b, int off, int len) throws IOException {
synchronized (Pipe.this) {
while (len != 0) {
if (head == tail && full) {
// The buffer is full, wait for InputStream read bytes
try {
Pipe.this.wait();
} catch (InterruptedException e) {
throw new IOException("The thread interrupted", e);
}
} else {
int write = Math.min(len, (head <= tail ? capacity : head) - tail);
System.arraycopy(b, off, buffer, tail, write);
off += write;
len -= write;
tail += write;
if (tail == capacity) {
tail = 0;
}
if (head == tail) {
full = true;
}
Pipe.this.notifyAll();
}
}
}
}
@Override
public void close() {
synchronized (Pipe.this) {
outClosed = true;
Pipe.this.notifyAll();
}
}
};
Pipe(int capacity) {
this.capacity = capacity;
this.buffer = new byte[capacity];
}
InputStream getInputStream() {
return inputStream;
}
OutputStream getOutputStream() {
return outputStream;
}
}
@@ -41,6 +41,27 @@ class VersionPreference @JvmOverloads constructor(
override fun onPrepareDialogBuilder(builder: AlertDialog.Builder) {
super.onPrepareDialogBuilder(builder)
builder.setTitle(R.string.show_library_version)
builder.setMessage(Native.getlibarchiveVersion() + "\nlzma(xz-utils) " + Native.getliblzmaVersion() + "\nzlib " + Native.getzlibVersion() + "\nlibjpeg-turbo " + Native.getlibjpeg_turboVersion())
val info = NativeLibInfo().addLib(Native.getlibarchiveVersion())
.addLib("lzma(xz-utils)", Native.getliblzmaVersion())
.addLib("zlib", Native.getzlibVersion())
.addLib(Native.getnettleVersion())
builder.setMessage(info.getMessage())
}
inner class NativeLibInfo {
private var message: String = ""
fun addLib(libname:String, libversion:String): NativeLibInfo {
message = "$message$libname $libversion\n"
return this
}
fun getMessage(): String {
return message;
}
fun addLib(msg: String): NativeLibInfo {
message = "$message$msg\n"
return this
}
}
}
@@ -66,6 +66,7 @@ import com.hippo.yorozuya.thread.PriorityThread;
import com.hippo.yorozuya.thread.PriorityThreadFactory;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -1096,33 +1097,6 @@ public final class SpiderQueen implements Runnable {
void onGetImageFailure(int index, String error);
}
private static class AutoCloseInputStream extends InputStream {
private final InputStreamPipe mPipe;
private final InputStream mIs;
public AutoCloseInputStream(InputStreamPipe pipe, InputStream is) {
mPipe = pipe;
mIs = is;
}
@Override
public int read() throws IOException {
return mIs.read();
}
@Override
public int read(@NonNull byte[] buffer, int byteOffset, int byteCount) throws IOException {
return mIs.read(buffer, byteOffset, byteCount);
}
@Override
public void close() throws IOException {
mPipe.close();
mPipe.release();
}
}
private class SpiderWorker implements Runnable {
private final long mGid;
@@ -1693,7 +1667,7 @@ public final class SpiderQueen implements Runnable {
pipe.obtain();
try {
is = new AutoCloseInputStream(pipe, pipe.open());
is = pipe.open();
} catch (IOException e) {
// Can't open pipe
error = GetText.getString(R.string.error_reading_failed);
@@ -1703,7 +1677,18 @@ public final class SpiderQueen implements Runnable {
}
if (is != null) {
image = Image.decode(is, true);
try {
image = Image.decode(((FileInputStream)is).getFD(), true);
} catch (IOException e) {
e.printStackTrace();
image = null;
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (image == null) {
error = GetText.getString(R.string.error_decoding_failed);
}
@@ -37,6 +37,8 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.view.KeyEvent;
@@ -67,6 +69,7 @@ import androidx.core.view.WindowInsetsControllerCompat;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.materialswitch.MaterialSwitch;
import com.hippo.app.EditTextDialogBuilder;
import com.hippo.ehviewer.AppConfig;
import com.hippo.ehviewer.BuildConfig;
import com.hippo.ehviewer.R;
@@ -103,6 +106,7 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import rikka.core.res.ConfigurationKt;
import rikka.core.res.ResourcesKt;
@@ -314,10 +318,19 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
onRestore(savedInstanceState);
}
builder = new EditTextDialogBuilder(this, null, getString(R.string.archive_passwd));
builder.setTitle(getString(R.string.archive_need_passwd));
builder.setPositiveButton(getString(android.R.string.ok), null);
dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
if (mGalleryProvider == null) {
finish();
return;
}
ArchiveGalleryProvider.showPasswd = new ShowPasswdDialogHandler(this);
mGalleryProvider.start();
// Get start page
@@ -1293,7 +1306,69 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan
}
}
private EditTextDialogBuilder builder;
private boolean dialogShown = false;
private AlertDialog dialog;
private void showPasswdDialog() {
if (!dialogShown) {
dialogShown = true;
dialog.show();
if (dialog.getButton(AlertDialog.BUTTON_POSITIVE) != null) {
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(v -> {
GalleryActivity.this.onProvidePasswd();
});
}
dialog.setOnCancelListener(v -> finish());
}
}
private void onProvidePasswd() {
String passwd = builder.getText();
if (passwd.isEmpty())
builder.setError(getString(R.string.passwd_cannot_be_empty));
else {
ArchiveGalleryProvider.passwd = passwd;
ArchiveGalleryProvider.pv.v();
}
}
private void onPasswdWrong() {
builder.setError(getString(R.string.passwd_wrong));
}
private void onPasswdCorrect() {
dialog.dismiss();
}
private static class ShowPasswdDialogHandler extends Handler {
//弱引用持有HandlerActivity , GC 回收时会被回收掉
private final WeakReference<GalleryActivity> weakReference;
public ShowPasswdDialogHandler(GalleryActivity activity) {
this.weakReference = new WeakReference(activity);
}
@Override
public void handleMessage(Message msg) {
GalleryActivity activity = weakReference.get();
super.handleMessage(msg);
if (null != activity) {
switch (msg.what) {
case 0:
activity.showPasswdDialog();
break;
case 1:
activity.onPasswdWrong();
break;
case 2:
activity.onPasswdCorrect();
break;
}
}
}
}
}
@@ -1,229 +0,0 @@
/*
* Copyright (C) 2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.widget;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import com.hippo.ehviewer.R;
import com.hippo.yorozuya.NumberUtils;
public class AdvanceSearchTable extends LinearLayout {
public static final int SNAME = 0x1;
public static final int STAGS = 0x2;
public static final int SDESC = 0x4;
public static final int STORR = 0x8;
public static final int STO = 0x10;
public static final int SDT1 = 0x20;
public static final int SDT2 = 0x40;
public static final int SH = 0x80;
public static final int SFL = 0x100;
public static final int SFU = 0x200;
public static final int SFT = 0x400;
private static final String STATE_KEY_SUPER = "super";
private static final String STATE_KEY_ADVANCE_SEARCH = "advance_search";
private static final String STATE_KEY_MIN_RATING = "min_rating";
private static final String STATE_KEY_PAGE_FROM = "page_from";
private static final String STATE_KEY_PAGE_TO = "page_to";
private CheckBox mSname;
private CheckBox mStags;
private CheckBox mSdesc;
private CheckBox mStorr;
private CheckBox mSto;
private CheckBox mSdt1;
private CheckBox mSdt2;
private CheckBox mSh;
private CheckBox mSr;
private Spinner mMinRating;
private CheckBox mSp;
private EditText mSpf;
private EditText mSpt;
private CheckBox mSfl;
private CheckBox mSfu;
private CheckBox mSft;
public AdvanceSearchTable(Context context) {
super(context);
init(context);
}
public AdvanceSearchTable(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public void init(Context context) {
setOrientation(LinearLayout.VERTICAL);
LayoutInflater inflater = LayoutInflater.from(getContext());
inflater.inflate(R.layout.widget_advance_search_table, this);
ViewGroup row0 = (ViewGroup) getChildAt(0);
mSname = (CheckBox) row0.getChildAt(0);
mStags = (CheckBox) row0.getChildAt(1);
ViewGroup row1 = (ViewGroup) getChildAt(1);
mSdesc = (CheckBox) row1.getChildAt(0);
mStorr = (CheckBox) row1.getChildAt(1);
ViewGroup row2 = (ViewGroup) getChildAt(2);
mSto = (CheckBox) row2.getChildAt(0);
mSdt1 = (CheckBox) row2.getChildAt(1);
ViewGroup row3 = (ViewGroup) getChildAt(3);
mSdt2 = (CheckBox) row3.getChildAt(0);
mSh = (CheckBox) row3.getChildAt(1);
ViewGroup row4 = (ViewGroup) getChildAt(4);
mSr = (CheckBox) row4.getChildAt(0);
mMinRating = (Spinner) row4.getChildAt(1);
ViewGroup row5 = (ViewGroup) getChildAt(5);
mSp = (CheckBox) row5.getChildAt(0);
mSpf = (EditText) row5.getChildAt(1);
mSpt = (EditText) row5.getChildAt(3);
ViewGroup row7 = (ViewGroup) getChildAt(7);
mSfl = (CheckBox) row7.getChildAt(0);
mSfu = (CheckBox) row7.getChildAt(1);
mSft = (CheckBox) row7.getChildAt(2);
// Avoid java.lang.IllegalStateException: focus search returned a view that wasn't able to take focus!
mSpt.setOnEditorActionListener((v, actionId, event) -> {
View nextView = v.focusSearch(View.FOCUS_DOWN);
if (nextView != null) {
nextView.requestFocus(View.FOCUS_DOWN);
}
return true;
});
}
public int getAdvanceSearch() {
int advanceSearch = 0;
if (mSname.isChecked()) advanceSearch |= SNAME;
if (mStags.isChecked()) advanceSearch |= STAGS;
if (mSdesc.isChecked()) advanceSearch |= SDESC;
if (mStorr.isChecked()) advanceSearch |= STORR;
if (mSto.isChecked()) advanceSearch |= STO;
if (mSdt1.isChecked()) advanceSearch |= SDT1;
if (mSdt2.isChecked()) advanceSearch |= SDT2;
if (mSh.isChecked()) advanceSearch |= SH;
if (mSfl.isChecked()) advanceSearch |= SFL;
if (mSfu.isChecked()) advanceSearch |= SFU;
if (mSft.isChecked()) advanceSearch |= SFT;
return advanceSearch;
}
public void setAdvanceSearch(int advanceSearch) {
mSname.setChecked(NumberUtils.int2boolean(advanceSearch & SNAME));
mStags.setChecked(NumberUtils.int2boolean(advanceSearch & STAGS));
mSdesc.setChecked(NumberUtils.int2boolean(advanceSearch & SDESC));
mStorr.setChecked(NumberUtils.int2boolean(advanceSearch & STORR));
mSto.setChecked(NumberUtils.int2boolean(advanceSearch & STO));
mSdt1.setChecked(NumberUtils.int2boolean(advanceSearch & SDT1));
mSdt2.setChecked(NumberUtils.int2boolean(advanceSearch & SDT2));
mSh.setChecked(NumberUtils.int2boolean(advanceSearch & SH));
mSfl.setChecked(NumberUtils.int2boolean(advanceSearch & SFL));
mSfu.setChecked(NumberUtils.int2boolean(advanceSearch & SFU));
mSft.setChecked(NumberUtils.int2boolean(advanceSearch & SFT));
}
public int getMinRating() {
int position = mMinRating.getSelectedItemPosition();
if (mSr.isChecked() && position >= 0) {
return position + 2;
} else {
return -1;
}
}
public void setMinRating(int minRating) {
if (minRating >= 2 && minRating <= 5) {
mSr.setChecked(true);
mMinRating.setSelection(minRating - 2);
} else {
mSr.setChecked(false);
}
}
public int getPageFrom() {
if (mSp.isChecked()) {
return NumberUtils.parseIntSafely(mSpf.getText().toString(), -1);
}
return -1;
}
public void setPageFrom(int pageFrom) {
if (pageFrom > 0) {
mSpf.setText(Integer.toString(pageFrom));
mSp.setChecked(true);
} else {
mSp.setChecked(false);
mSpf.setText(null);
}
}
public int getPageTo() {
if (mSp.isChecked()) {
return NumberUtils.parseIntSafely(mSpt.getText().toString(), -1);
}
return -1;
}
public void setPageTo(int pageTo) {
if (pageTo > 0) {
mSpt.setText(Integer.toString(pageTo));
mSp.setChecked(true);
} else {
mSp.setChecked(false);
mSpt.setText(null);
}
}
@Override
public Parcelable onSaveInstanceState() {
final Bundle state = new Bundle();
state.putParcelable(STATE_KEY_SUPER, super.onSaveInstanceState());
state.putInt(STATE_KEY_ADVANCE_SEARCH, getAdvanceSearch());
state.putInt(STATE_KEY_MIN_RATING, getMinRating());
state.putInt(STATE_KEY_PAGE_FROM, getPageFrom());
state.putInt(STATE_KEY_PAGE_TO, getPageTo());
return state;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
final Bundle savedState = (Bundle) state;
super.onRestoreInstanceState(savedState.getParcelable(STATE_KEY_SUPER));
setAdvanceSearch(savedState.getInt(STATE_KEY_ADVANCE_SEARCH));
setMinRating(savedState.getInt(STATE_KEY_MIN_RATING));
setPageFrom(savedState.getInt(STATE_KEY_PAGE_FROM));
setPageTo(savedState.getInt(STATE_KEY_PAGE_TO));
}
}
}
@@ -0,0 +1,189 @@
/*
* Copyright (C) 2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.widget
import android.content.Context
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.*
import com.google.android.material.textfield.TextInputLayout
import com.hippo.ehviewer.R
import com.hippo.yorozuya.NumberUtils
class AdvanceSearchTable @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : LinearLayout(context, attrs) {
private var mSname: CheckBox
private var mStags: CheckBox
private var mSdesc: CheckBox
private var mStorr: CheckBox
private var mSto: CheckBox
private var mSdt1: CheckBox
private var mSdt2: CheckBox
private var mSh: CheckBox
private var mSr: CheckBox
private var mMinRating: TextInputLayout
private var mSp: CheckBox
private var mSpf: EditText
private var mSpt: EditText
private var mSfl: CheckBox
private var mSfu: CheckBox
private var mSft: CheckBox
private val mArray: Array<String> = context.resources.getStringArray(R.array.search_min_rating)
init {
orientation = VERTICAL
val inflater = LayoutInflater.from(context)
inflater.inflate(R.layout.widget_advance_search_table, this)
val row0 = getChildAt(0) as ViewGroup
mSname = row0.getChildAt(0) as CheckBox
mStags = row0.getChildAt(1) as CheckBox
val row1 = getChildAt(1) as ViewGroup
mSdesc = row1.getChildAt(0) as CheckBox
mStorr = row1.getChildAt(1) as CheckBox
val row2 = getChildAt(2) as ViewGroup
mSto = row2.getChildAt(0) as CheckBox
mSdt1 = row2.getChildAt(1) as CheckBox
val row3 = getChildAt(3) as ViewGroup
mSdt2 = row3.getChildAt(0) as CheckBox
mSh = row3.getChildAt(1) as CheckBox
val row4 = getChildAt(4) as ViewGroup
mSr = row4.getChildAt(0) as CheckBox
mMinRating = row4.getChildAt(1) as TextInputLayout
val row5 = getChildAt(5) as ViewGroup
mSp = row5.getChildAt(0) as CheckBox
mSpf = row5.getChildAt(1) as EditText
mSpt = row5.getChildAt(3) as EditText
val row7 = getChildAt(7) as ViewGroup
mSfl = row7.getChildAt(0) as CheckBox
mSfu = row7.getChildAt(1) as CheckBox
mSft = row7.getChildAt(2) as CheckBox
mSpt.setOnEditorActionListener { v: TextView, _: Int, _: KeyEvent? ->
val nextView = v.focusSearch(
FOCUS_DOWN
)
nextView?.requestFocus(FOCUS_DOWN)
true
}
mMinRating.isEnabled = mSr.isChecked
mSr.setOnCheckedChangeListener { _: CompoundButton, isChecked: Boolean ->
mMinRating.isEnabled = isChecked
}
mSpt.isEnabled = mSp.isChecked
mSpf.isEnabled = mSp.isChecked
mSp.setOnCheckedChangeListener { _: CompoundButton, isChecked: Boolean ->
mSpt.isEnabled = isChecked
mSpf.isEnabled = isChecked
}
}
var advanceSearch: Int
get() {
var advanceSearch = 0
if (mSname.isChecked) advanceSearch = advanceSearch or SNAME
if (mStags.isChecked) advanceSearch = advanceSearch or STAGS
if (mSdesc.isChecked) advanceSearch = advanceSearch or SDESC
if (mStorr.isChecked) advanceSearch = advanceSearch or STORR
if (mSto.isChecked) advanceSearch = advanceSearch or STO
if (mSdt1.isChecked) advanceSearch = advanceSearch or SDT1
if (mSdt2.isChecked) advanceSearch = advanceSearch or SDT2
if (mSh.isChecked) advanceSearch = advanceSearch or SH
if (mSfl.isChecked) advanceSearch = advanceSearch or SFL
if (mSfu.isChecked) advanceSearch = advanceSearch or SFU
if (mSft.isChecked) advanceSearch = advanceSearch or SFT
return advanceSearch
}
set(advanceSearch) {
mSname.isChecked =
NumberUtils.int2boolean(advanceSearch and SNAME)
mStags.isChecked =
NumberUtils.int2boolean(advanceSearch and STAGS)
mSdesc.isChecked =
NumberUtils.int2boolean(advanceSearch and SDESC)
mStorr.isChecked = NumberUtils.int2boolean(advanceSearch and STORR)
mSto.isChecked = NumberUtils.int2boolean(advanceSearch and STO)
mSdt1.isChecked = NumberUtils.int2boolean(advanceSearch and SDT1)
mSdt2.isChecked = NumberUtils.int2boolean(advanceSearch and SDT2)
mSh.isChecked = NumberUtils.int2boolean(advanceSearch and SH)
mSfl.isChecked = NumberUtils.int2boolean(advanceSearch and SFL)
mSfu.isChecked = NumberUtils.int2boolean(advanceSearch and SFU)
mSft.isChecked = NumberUtils.int2boolean(advanceSearch and SFT)
}
var minRating: Int
get() {
val position = mArray.indexOf(mMinRating.editText!!.text.toString())
return if (mSr.isChecked && position >= 0) {
position + 2
} else {
-1
}
}
set(minRating) {
if (minRating in 2..5) {
mSr.isChecked = true
(mMinRating.editText!! as AutoCompleteTextView).setText(
mArray[minRating - 2],
false
)
} else {
mSr.isChecked = false
}
}
var pageFrom: Int
get() = if (mSp.isChecked) {
NumberUtils.parseIntSafely(mSpf.text.toString(), -1)
} else -1
set(pageFrom) {
if (pageFrom > 0) {
mSpf.setText(pageFrom.toString())
mSp.isChecked = true
} else {
mSp.isChecked = false
mSpf.text = null
}
}
var pageTo: Int
get() = if (mSp.isChecked) {
NumberUtils.parseIntSafely(mSpt.text.toString(), -1)
} else -1
set(pageTo) {
if (pageTo > 0) {
mSpt.setText(pageTo.toString())
mSp.isChecked = true
} else {
mSp.isChecked = false
}
}
companion object {
const val SNAME = 0x1
const val STAGS = 0x2
const val SDESC = 0x4
const val STORR = 0x8
const val STO = 0x10
const val SDT1 = 0x20
const val SDT2 = 0x40
const val SH = 0x80
const val SFL = 0x100
const val SFU = 0x200
const val SFT = 0x400
}
}
@@ -245,7 +245,7 @@ public abstract class GalleryProvider {
}
public void add(Integer key, ImageWrapper value) {
if (value.getFormat() != Image.FORMAT_GIF && value.obtain()) {
if (value.getFormat() != Image.FORMAT_ANIMATED && value.obtain()) {
put(key, value);
}
}
@@ -253,7 +253,7 @@ public abstract class GalleryProvider {
@Override
protected int sizeOf(Integer key, ImageWrapper value) {
int size = value.getWidth() * value.getHeight() * 4;
if (value.getFormat() == Image.FORMAT_GIF) {
if (value.getFormat() == Image.FORMAT_ANIMATED) {
size *= 5;
}
return size;
@@ -153,12 +153,6 @@ public class ImageTexture implements Texture, Animatable {
}
mTiles = list.toArray(new Tile[list.size()]);
if (!mImage.isCompleted()) {
Runnable runnable = new AnimateRunnable();
mAnimateRunnable = runnable;
sThreadExecutor.execute(runnable);
}
}
private static Tile obtainSmallTile() {
@@ -239,7 +233,7 @@ public class ImageTexture implements Texture, Animatable {
}
boolean end = mReleased.get() || mImage.isImageRecycled() || mNeedRelease.get() ||
(mImage.isCompleted() && mImage.getFrameCount() <= 1) || mRunning.get();
(mImage.getFormat() == 0) || mRunning.get();
synchronized (mImage) {
mImageBusy = false;
@@ -597,25 +591,11 @@ public class ImageTexture implements Texture, Animatable {
mImageBusy = true;
}
if (!mImage.isCompleted()) {
try {
sPVLock.p();
} catch (InterruptedException e) {
// Ignore
}
if (!mNeedRelease.get()) {
mImage.complete();
}
sPVLock.v();
}
int frameCount = mImage.getFrameCount();
synchronized (mImage) {
// Release image
mImageBusy = false;
// Check need release, frameCount <= 1
if (mNeedRelease.get() || frameCount <= 1) {
if (mNeedRelease.get() || mImage.getFormat() == 0) {
mAnimateRunnable = null;
return;
}
@@ -122,22 +122,6 @@ public class ImageWrapper {
return mCut.height();
}
/**
* @see Image#complete()
*/
public boolean complete() {
synchronized (mImage) {
return mImage.complete();
}
}
/**
* @see Image#isCompleted()
*/
public boolean isCompleted() {
return mImage.isCompleted();
}
/**
* @see Image#render(int, int, Bitmap, int, int, int, int, boolean, int)
*/
@@ -168,13 +152,6 @@ public class ImageWrapper {
return mImage.getDelay();
}
/**
* @see Image#getFrameCount()
*/
public int getFrameCount() {
return mImage.getFrameCount();
}
/**
* @see Image#isOpaque()
*/
@@ -0,0 +1,191 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2022 hathlife
~
~ This file is part of EhViewer
~
~ EhViewer is free software: you can redistribute it and/or
~ modify it under the terms of the GNU General Public License as
~ published by the Free Software Foundation, either version 3 of the
~ License, or (at your option) any later version.
~
~ EhViewer is distributed in the hope that it will be useful, but
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License along with EhViewer.
~ If not, see <https://www.gnu.org/licenses/>.
~
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/actions"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="@dimen/keyline_margin">
<TextView
android:id="@+id/newerVersion"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:gravity="center"
android:padding="8dp"
android:text="@string/newer_version_avaliable"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/keyline_margin"
android:paddingRight="@dimen/keyline_margin">
<LinearLayout
android:id="@+id/rate"
android:layout_width="484dp"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<androidx.appcompat.widget.AppCompatRatingBar
android:id="@+id/rating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:isIndicator="true"
android:theme="@style/RatingBarTheme" />
<TextView
android:id="@+id/rating_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="0dp"
android:textColor="?android:attr/textColorPrimary" />
</LinearLayout>
<HorizontalScrollView
android:id="@+id/actions_scroll_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:clipToPadding="false"
android:paddingLeft="36dp"
android:paddingRight="@dimen/keyline_margin"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:divider="@drawable/spacer_keyline"
android:orientation="horizontal"
android:showDividers="middle">
<FrameLayout
android:id="@+id/heart_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:nextFocusUp="@+id/download">
<TextView
android:id="@+id/heart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="4dp"
android:gravity="center_horizontal"
android:text="@string/favorited"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@+id/heart_outline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="4dp"
android:gravity="center_horizontal"
android:text="@string/not_favorited"
android:textColor="?android:attr/textColorPrimary" />
</FrameLayout>
<TextView
android:id="@+id/share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:drawablePadding="4dp"
android:focusable="true"
android:gravity="center_horizontal"
android:nextFocusUp="@+id/download"
android:text="@string/share"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@+id/torrent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:drawablePadding="4dp"
android:focusable="true"
android:gravity="center_horizontal"
android:nextFocusUp="@+id/download"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@+id/archive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:drawablePadding="4dp"
android:focusable="true"
android:gravity="center_horizontal"
android:nextFocusUp="@+id/download"
android:text="@string/archive"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@+id/similar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:drawablePadding="4dp"
android:focusable="true"
android:gravity="center_horizontal"
android:nextFocusUp="@+id/download"
android:text="@string/similar_gallery"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@+id/search_cover"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:drawablePadding="4dp"
android:focusable="true"
android:gravity="center_horizontal"
android:nextFocusRight="@+id/search_cover"
android:nextFocusUp="@+id/download"
android:text="@string/search_cover"
android:textColor="?android:attr/textColorPrimary" />
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,263 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2022 hathlife
~
~ This file is part of EhViewer
~
~ EhViewer is free software: you can redistribute it and/or
~ modify it under the terms of the GNU General Public License as
~ published by the Free Software Foundation, either version 3 of the
~ License, or (at your option) any later version.
~
~ EhViewer is distributed in the hope that it will be useful, but
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License along with EhViewer.
~ If not, see <https://www.gnu.org/licenses/>.
~
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:id="@+id/color_bg"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:elevation="4dp"
app:fitsSystemWindowsInsets="top" />
<Space
android:layout_width="match_parent"
android:layout_height="28dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/title"
style="@style/TextAppearance.Material3.HeadlineSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/keyline_margin"
android:layout_marginRight="@dimen/keyline_margin"
android:ellipsize="end"
android:maxLines="5" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.card.MaterialCardView
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="540dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/keyline_margin"
android:layout_marginTop="@dimen/keyline_margin"
android:layout_marginRight="@dimen/keyline_margin"
android:layout_marginBottom="@dimen/keyline_margin"
app:fitsSystemWindowsInsets="top">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/header_content"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.card.MaterialCardView
android:id="@+id/thumb_card"
style="@style/Widget.Material3.CardView.Filled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.hippo.widget.LoadImageView
android:id="@+id/thumb"
android:layout_width="256dp"
android:layout_height="@dimen/gallery_detail_thumb_height" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/info"
style="@style/Widget.Material3.CardView.Filled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="@dimen/keyline_margin"
android:clickable="true"
android:focusable="true"
android:nextFocusRight="@+id/read"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/language"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:singleLine="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/size"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:gravity="right"
android:singleLine="true"
app:layout_constraintBaseline_toBaselineOf="@id/language"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@id/language" />
<TextView
android:id="@+id/favoredTimes"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="left"
android:singleLine="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/language" />
<TextView
android:id="@+id/pages"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:gravity="right"
android:singleLine="true"
app:layout_constraintBaseline_toBaselineOf="@id/favoredTimes"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@id/favoredTimes" />
<TextView
android:id="@+id/posted"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="left"
android:singleLine="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/favoredTimes" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.chip.Chip
android:id="@+id/uploader"
style="@style/Widget.Material3.Chip.Assist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/keyline_margin"
android:ellipsize="end"
android:nextFocusRight="@+id/read"
android:nextFocusDown="@+id/rate"
android:singleLine="true"
android:textAllCaps="true"
app:chipIcon="@drawable/file_upload_black_24dp"
app:ensureMinTouchTargetSize="true"
app:layout_constraintBottom_toBottomOf="@id/thumb_card"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.chip.Chip
android:id="@+id/category"
style="@style/Widget.Material3.Chip.Assist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/keyline_margin"
android:ellipsize="end"
android:nextFocusRight="@+id/read"
android:singleLine="true"
android:textAllCaps="true"
app:chipIcon="@drawable/ic_baseline_label_24"
app:ensureMinTouchTargetSize="true"
app:layout_constraintBottom_toTopOf="@id/uploader"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:id="@+id/action_card"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/keyline_margin"
android:layout_marginRight="@dimen/keyline_margin"
android:orientation="vertical">
<Button
android:id="@+id/read"
style="@style/Widget.Material3.Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:insetLeft="40dp"
android:insetRight="40dp"
android:insetTop="16dp"
android:text="@string/read">
<requestFocus />
</Button>
<Button
android:id="@+id/download"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:nextFocusDown="@+id/torrent"
android:focusable="true"
android:insetLeft="40dp"
android:insetTop="16dp"
android:insetRight="40dp" />
<android.widget.Space
android:layout_width="match_parent"
android:layout_height="80dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</FrameLayout>
@@ -1,17 +1,20 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2022 hathlife
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~ This file is part of EhViewer
~
~ http://www.apache.org/licenses/LICENSE-2.0
~ EhViewer is free software: you can redistribute it and/or
~ modify it under the terms of the GNU General Public License as
~ published by the Free Software Foundation, either version 3 of the
~ License, or (at your option) any later version.
~
~ EhViewer is distributed in the hope that it will be useful, but
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License along with EhViewer.
~ If not, see <https://www.gnu.org/licenses/>.
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
@@ -1,17 +1,20 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2022 hathlife
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~ This file is part of EhViewer
~
~ http://www.apache.org/licenses/LICENSE-2.0
~ EhViewer is free software: you can redistribute it and/or
~ modify it under the terms of the GNU General Public License as
~ published by the Free Software Foundation, either version 3 of the
~ License, or (at your option) any later version.
~
~ EhViewer is distributed in the hope that it will be useful, but
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License along with EhViewer.
~ If not, see <https://www.gnu.org/licenses/>.
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
@@ -36,7 +39,7 @@
<ImageView
android:layout_width="257dp"
android:layout_height="518dp"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:padding="@dimen/keyline_margin"
app:srcCompat="@mipmap/ic_launcher" />
@@ -1,17 +1,20 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2022 hathlife
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~ This file is part of EhViewer
~
~ http://www.apache.org/licenses/LICENSE-2.0
~ EhViewer is free software: you can redistribute it and/or
~ modify it under the terms of the GNU General Public License as
~ published by the Free Software Foundation, either version 3 of the
~ License, or (at your option) any later version.
~
~ EhViewer is distributed in the hope that it will be useful, but
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License along with EhViewer.
~ If not, see <https://www.gnu.org/licenses/>.
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
@@ -1,17 +1,20 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2022 hathlife
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~ This file is part of EhViewer
~
~ http://www.apache.org/licenses/LICENSE-2.0
~ EhViewer is free software: you can redistribute it and/or
~ modify it under the terms of the GNU General Public License as
~ published by the Free Software Foundation, either version 3 of the
~ License, or (at your option) any later version.
~
~ EhViewer is distributed in the hope that it will be useful, but
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License along with EhViewer.
~ If not, see <https://www.gnu.org/licenses/>.
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
@@ -64,16 +64,18 @@
android:layout_marginBottom="@dimen/keyline_margin"
app:fitsSystemWindowsInsets="top">
<RelativeLayout
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/header_content"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.card.MaterialCardView
android:id="@+id/thumb_card"
style="@style/Widget.Material3.CardView.Elevated"
style="@style/Widget.Material3.CardView.Filled"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.hippo.widget.LoadImageView
android:id="@+id/thumb"
@@ -87,12 +89,13 @@
style="@style/Widget.Material3.CardView.Filled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginTop="8dp"
android:layout_marginEnd="@dimen/keyline_margin"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
@@ -101,6 +104,7 @@
<TextView
android:id="@+id/language"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
@@ -110,6 +114,7 @@
<TextView
android:id="@+id/size"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@@ -123,6 +128,7 @@
<TextView
android:id="@+id/favoredTimes"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
@@ -133,6 +139,7 @@
<TextView
android:id="@+id/pages"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@@ -146,6 +153,7 @@
<TextView
android:id="@+id/posted"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
@@ -165,30 +173,31 @@
style="@style/Widget.Material3.Chip.Assist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/thumb_card"
android:layout_alignParentEnd="true"
android:layout_marginEnd="@dimen/keyline_margin"
android:ellipsize="end"
android:singleLine="true"
android:textAllCaps="true"
app:chipIcon="@drawable/file_upload_black_24dp"
app:ensureMinTouchTargetSize="true" />
app:ensureMinTouchTargetSize="true"
app:layout_constraintBottom_toBottomOf="@id/thumb_card"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.chip.Chip
android:id="@+id/category"
style="@style/Widget.Material3.Chip.Assist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/uploader"
android:layout_alignParentEnd="true"
android:layout_marginEnd="@dimen/keyline_margin"
app:chipSpacingHorizontal="8dp"
android:ellipsize="end"
android:singleLine="true"
android:textAllCaps="true"
app:chipIcon="@drawable/ic_baseline_label_24"
app:ensureMinTouchTargetSize="true" />
app:ensureMinTouchTargetSize="true"
app:layout_constraintBottom_toTopOf="@id/uploader"
app:layout_constraintEnd_toEndOf="parent" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
@@ -205,19 +214,17 @@
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:layout_weight="1"
android:clickable="true"
android:focusable="true" />
<android.widget.Space
android:layout_width="8dp"
android:layout_height="wrap_content" />
<Button
android:id="@+id/read"
style="@style/Widget.Material3.Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
+12 -9
View File
@@ -95,27 +95,30 @@
android:layout_height="wrap_content"
android:clipToPadding="false"
android:gravity="bottom"
android:orientation="vertical"
android:orientation="horizontal"
android:paddingLeft="12dp"
android:paddingTop="4dp"
android:paddingRight="12dp"
android:paddingBottom="4dp">
<Button
android:id="@+id/sign_in"
style="@style/Widget.Material3.Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/sign_in" />
<Button
android:id="@+id/register"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:layout_weight="1"
android:text="@string/register" />
<Button
android:id="@+id/sign_in"
style="@style/Widget.Material3.Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:layout_weight="1"
android:text="@string/sign_in" />
</LinearLayout>
<LinearLayout
@@ -12,7 +12,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="match_parent"
@@ -139,13 +140,22 @@
android:minHeight="0dp"
android:text="@string/search_sr" />
<Spinner
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/advance_search_table_item_margin"
android:layout_marginStart="@dimen/advance_search_table_item_margin"
android:layout_weight="1"
android:entries="@array/search_min_rating" />
android:hint="@string/search_sr">
<AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
app:simpleItems="@array/search_min_rating" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<LinearLayout
@@ -764,4 +764,9 @@
<string name="settings_privacy_require_unlock">需要解锁</string>
<string name="proxy_type_name">代理类型</string>
<string name="filter_label">屏蔽项类型</string>
<string name="archive_passwd">归档文件密码</string>
<string name="archive_need_passwd">归档文件需要密码</string>
<string name="passwd_wrong">密码错误</string>
<string name="passwd_cannot_be_empty">密码不能为空</string>
</resources>
+5
View File
@@ -828,4 +828,9 @@
<string name="settings_privacy_require_unlock">Require Unlock</string>
<string name="proxy_type_name">Proxy Type</string>
<string name="filter_label">Blocker Type</string>
<string name="archive_passwd">password</string>
<string name="archive_need_passwd">Archive need password</string>
<string name="passwd_wrong">Password Wrong</string>
<string name="passwd_cannot_be_empty">Password can\'t be empty</string>
</resources>
+1 -1
View File
@@ -9,7 +9,7 @@ android {
ndkVersion "25.0.8775105"
defaultConfig {
minSdkVersion 26
minSdkVersion 31
targetSdkVersion 33
consumerProguardFiles 'proguard-rules.pro'
+2 -4
View File
@@ -28,9 +28,7 @@ public class Native {
public static native String getliblzmaVersion();
public static native String getlibzstdVersion();
public static native String getlibjpeg_turboVersion();
public static native String getzlibVersion();
public static native String getnettleVersion();
}
@@ -21,106 +21,44 @@ package com.hippo;
import android.content.Context;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
public class UriArchiveAccessor implements AutoCloseable {
public static int OPEN_OK = 1;
public static int OPEN_ERR = 2;
private final OsReadableFile osf;
public class UriArchiveAccessor {
ParcelFileDescriptor pfd;
FileDescriptor fd;
long archiveAddr;
Context ctx;
Uri uri;
public UriArchiveAccessor(Context ctx, Uri uri) throws FileNotFoundException {
osf = new OsReadableFile(ctx, uri);
public UriArchiveAccessor(Context ctx, Uri uri) {
this.ctx = ctx;
this.uri = uri;
}
public int open() {
return openArchive(osf);
public int open() throws Exception {
pfd = ctx.getContentResolver().openFileDescriptor(uri, "r");
fd = pfd.getFileDescriptor();
archiveAddr = Os.mmap(0, pfd.getStatSize(), OsConstants.PROT_READ, OsConstants.MAP_PRIVATE, fd, 0);
return openArchive(archiveAddr, pfd.getStatSize());
}
public void extractTargetIndexToOutputStream(int index, OutputStream os) {
extracttoOutputStream(index, os);
}
private native int openArchive(long addr, long size);
private native int openArchive(OsReadableFile osf);
public native long extracttoOutputStream(int index);
private native void extracttoOutputStream(int index, OutputStream os);
public native boolean needPassword();
public native boolean providePassword(String str);
private native void closeArchive();
@Override
public void close() throws IOException {
public void close() throws Exception {
closeArchive();
osf.close();
}
static class OsReadableFile {
ParcelFileDescriptor pfd;
FileDescriptor fd;
public OsReadableFile(Context ctx, Uri uri) throws FileNotFoundException {
pfd = ctx.getContentResolver().openFileDescriptor(uri, "r");
fd = pfd.getFileDescriptor();
}
public int read(byte[] b, int off, int len) throws IOException, ErrnoException {
return Os.read(fd, b, off, len);
}
public int read(byte[] b) throws IOException, ErrnoException {
return read(b, 0, b.length);
}
public long length() throws IOException, ErrnoException {
return Os.fstat(fd).st_size;
}
public long seek(long pos, int whence) throws IOException, ErrnoException {
try {
return Os.lseek(fd, pos, whence);
} catch (Exception e) {
e.printStackTrace();
return -30;
}
}
public void rewind() throws IOException, ErrnoException {
Os.lseek(fd, 0, OsConstants.SEEK_SET);
}
public long skip(long n) throws IOException, ErrnoException {
long pos;
long len;
long newpos;
if (n <= 0) {
return 0;
}
pos = Os.lseek(fd, 0L, OsConstants.SEEK_CUR);
len = length();
newpos = pos + n;
if (newpos > len) {
newpos = len;
}
seek(newpos, OsConstants.SEEK_SET);
/* return the actual number of bytes skipped */
return newpos - pos;
}
public void close() throws IOException {
pfd.close();
try {
Os.close(fd);
} catch (ErrnoException e) {
throw new IOException("An ErrnoException occurs", e);
}
}
Os.munmap(archiveAddr, pfd.getStatSize());
Os.close(fd);
pfd.close();
}
}
+24 -77
View File
@@ -21,6 +21,7 @@ import android.graphics.Bitmap;
import androidx.annotation.Nullable;
import java.io.BufferedInputStream;
import java.io.FileDescriptor;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicInteger;
@@ -28,31 +29,9 @@ import java.util.concurrent.atomic.AtomicInteger;
* The {@code Image} is a image which stored pixel data in native heap
*/
public final class Image {
public static final int FORMAT_NORMAL = 0;
/**
* Unknown image format
*/
public static final int FORMAT_UNKNOWN = -1;
/**
* Plain image format, for {@code Image} from {@link #create(Bitmap)}
*/
public static final int FORMAT_PLAIN = 0;
/**
* JPEG image format
*/
public static final int FORMAT_JPEG = 1;
/**
* PNG image format
*/
public static final int FORMAT_PNG = 2;
/**
* GIF image format
*/
public static final int FORMAT_GIF = 3;
public static final int FORMAT_ANIMATED = 1;
private static final AtomicInteger sImageCount = new AtomicInteger();
private final int mFormat;
@@ -74,11 +53,24 @@ public final class Image {
* Decode image from {@code InputStream}
*/
@Nullable
public static Image decode(InputStream is, boolean partially) {
if (!(is instanceof BufferedInputStream)) {
is = new BufferedInputStream(is);
}
return nativeDecode(is, partially);
public static Image decode(FileDescriptor fd, boolean partially) {
return nativeDecode(fd, partially);
}
/**
* Decode image from {@code InputStream}
*/
@Nullable
public static Image decode(Integer fd, boolean partially) {
return nativeDecodeFdInt(fd, partially);
}
/**
* Decode image from {@code InputStream}
*/
@Nullable
public static Image decodeAddr(Long addr, boolean partially) {
return nativeDecodeAddr(addr, partially);
}
/**
@@ -97,31 +89,16 @@ public final class Image {
return sImageCount.get();
}
/**
* Return all supported image formats, exclude {@link #FORMAT_PLAIN}
*/
public static int[] getSupportedImageFormats() {
return nativeGetSupportedImageFormats();
}
private static native Image nativeDecode(FileDescriptor fd, boolean partially);
/**
* Return decoder description of the image format,
* {@code null} for invalid image format.
*/
public static String getDecoderDescription(int format) {
return nativeGetDecoderDescription(format);
}
private static native Image nativeDecodeFdInt(int fd, boolean partially);
private static native Image nativeDecode(InputStream is, boolean partially);
private static native Image nativeDecodeAddr(long addr, boolean partially);
private static native Image nativeCreate(Bitmap bitmap);
private static native int nativeGetByteCount(long nativePtr, int format);
private static native boolean nativeComplete(long nativePtr, int format);
private static native boolean nativeIsCompleted(long nativePtr, int format);
private static native void nativeRender(long nativePtr, int format,
int srcX, int srcY, Bitmap dst, int dstX, int dstY,
int width, int height, boolean fillBlank, int defaultColor);
@@ -133,8 +110,6 @@ public final class Image {
private static native int nativeGetDelay(long nativePtr, int format);
private static native int nativeFrameCount(long nativePtr, int format);
private static native boolean nativeIsOpaque(long nativePtr, int format);
private static native boolean nativeIsGray(long nativePtr, int format, int error);
@@ -143,10 +118,6 @@ public final class Image {
private static native void nativeRecycle(long nativePtr, int format);
private static native int[] nativeGetSupportedImageFormats();
private static native String nativeGetDecoderDescription(int format);
/**
* Return the format of the image
*/
@@ -186,22 +157,6 @@ public final class Image {
}
}
/**
* Complete the image decoding
*/
public boolean complete() {
checkRecycled();
return nativeComplete(mNativePtr, mFormat);
}
/**
* Is the image decoding completed
*/
public boolean isCompleted() {
checkRecycled();
return nativeIsCompleted(mNativePtr, mFormat);
}
/**
* Render the image to {@code Bitmap}
*/
@@ -239,14 +194,6 @@ public final class Image {
return delay <= 10 ? 100 : delay;
}
/**
* Return frame count. 1 for non-animation image
*/
public int getFrameCount() {
checkRecycled();
return nativeFrameCount(mNativePtr, mFormat);
}
/**
* Return is the image opaque
*/
@@ -28,6 +28,7 @@ import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.FileDescriptor;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.Iterator;
@@ -45,7 +46,6 @@ public final class ImageBitmap implements Animatable, Runnable {
private final int mFormat;
private final boolean mIsOpaque;
private final int mByteCount;
private final int mFrameCount;
private final Set<WeakReference<Callback>> mCallbackSet = new LinkedHashSet<>();
@Nullable
private Image mImage;
@@ -61,9 +61,8 @@ public final class ImageBitmap implements Animatable, Runnable {
mFormat = image.getFormat();
mIsOpaque = image.isOpaque();
mByteCount = image.getByteCount();
mFrameCount = image.getFrameCount();
if (mFrameCount > 1) {
if (mFormat == 1) {
// For animated image, save image object
mImage = image;
} else {
@@ -73,19 +72,18 @@ public final class ImageBitmap implements Animatable, Runnable {
}
private ImageBitmap(@NonNull Bitmap bitmap) {
mFormat = Image.FORMAT_PLAIN;
mFormat = Image.FORMAT_NORMAL;
mBitmap = bitmap;
mIsOpaque = !bitmap.hasAlpha();
mByteCount = bitmap.getRowBytes() * bitmap.getHeight();
mFrameCount = 1;
}
/**
* Decode {@code InputStream}, then create image.
*/
@Nullable
public static ImageBitmap decode(@NonNull InputStream is) {
Image image = Image.decode(is, false);
public static ImageBitmap decode(@NonNull FileDescriptor fd) {
Image image = Image.decode(fd, false);
if (image != null) {
return create(image);
} else {
@@ -237,13 +235,6 @@ public final class ImageBitmap implements Animatable, Runnable {
return mImage != null;
}
/**
* Return image frame count
*/
public int getFrameCount() {
return mFrameCount;
}
/**
* Draw image to canvas
*/
+17
View File
@@ -13,6 +13,20 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Oz -fvisibility=hidden -fvisibility-inlines
-mllvm -polly-detect-profitability-min-per-loop-insts=40 \
-mllvm -polly-invariant-load-hoisting")
# Build GNUTLS libnettle
add_subdirectory(nettle)
# Configure libnettle support for libarchive
include_directories(nettle)
include_directories(.)
set(HAVE_LIBNETTLE 1)
set(HAVE_NETTLE_AES_H 1)
set(HAVE_NETTLE_HMAC_H 1)
set(HAVE_NETTLE_MD5_H 1)
set(HAVE_NETTLE_PBKDF2_H 1)
set(HAVE_NETTLE_RIPEMD160_H 1)
set(HAVE_NETTLE_SHA_H 1)
# Build liblzma
add_subdirectory(liblzma)
@@ -24,6 +38,9 @@ SET(HAVE_LZMA_STREAM_ENCODER_MT 1)
SET(HAVE_LZMADEC_H 1)
SET(HAVE_LIBLZMADEC 1)
# Configure libarchive link's static lib
SET(LIBARCHIVE_CUSTOM_LIBS "liblzma" "nettle")
# Build libarchive
add_subdirectory(libarchive)
+89 -87
View File
@@ -23,6 +23,9 @@
#include <android/log.h>
#include <archive.h>
#include <archive_entry.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdbool.h>
#define LOG_TAG "libarchive_wrapper"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG ,__VA_ARGS__)
@@ -32,38 +35,13 @@
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG ,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG ,__VA_ARGS__)
#define BLOCK_SIZE 4096 * 16
static JNIEnv *env;
static jobject file;
static jmethodID readID;
static jmethodID seekID;
static jmethodID skipID;
static jmethodID rewindID;
static void* read_buffer;
static jbyteArray jbr;
static int cur_index = 0; // Current entry we haven't read any data from it yet
static struct archive* arc;
static void JNI_prepare_environment(JNIEnv* jniEnv, jobject OsReadablefile)
{
env = jniEnv;
file = (*env)->NewGlobalRef(env, OsReadablefile);
readID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, OsReadablefile), "read", "([B)I");
seekID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, OsReadablefile), "seek", "(JI)J");
skipID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, OsReadablefile), "skip", "(J)J");
rewindID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, OsReadablefile), "rewind", "()V");
jbr = (*env)->NewGlobalRef(env, (*env)->NewByteArray(env, BLOCK_SIZE));
read_buffer = malloc(BLOCK_SIZE);
}
static void JNI_destroy_environment()
{
(*env)->DeleteGlobalRef(env, file);
(*env)->DeleteGlobalRef(env, jbr);
free(read_buffer);
}
static struct archive *arc = NULL;
static bool need_encrypt = false;
static char *passwd = NULL;
static void *archiveAddr = NULL;
static jlong archiveSize = 0;
static int filename_is_playable_file(const char *name) {
const char *dotptr = strrchr(name, '.');
@@ -94,99 +72,123 @@ static long archive_list_all_entries() {
return count;
}
ssize_t ins_read(struct archive *a, void *client_data_ptr, const void **buff) {
int32_t r = (*env)->CallIntMethod(env, file, readID, jbr);
(*env)->GetByteArrayRegion(env, jbr, 0, r, read_buffer);
*buff = read_buffer;
return r;
static void archive_release() {
if (arc) {
archive_read_close(arc);
archive_read_free(arc);
arc = NULL;
}
}
int ins_close(struct archive *a, void *client_data) {
(*env)->CallVoidMethod(env, file, rewindID);
return ARCHIVE_OK;
}
la_int64_t ins_seek(struct archive *a, void *client_data, la_int64_t offset, int whence) {
jlong ret = (*env)->CallLongMethod(env, file, seekID, offset, whence);
return ret;
}
la_int64_t ins_skip(struct archive *a, void *client_data, la_int64_t request) {
jlong ret = (*env)->CallLongMethod(env, file, skipID, request);
return ret;
}
static void archive_create() {
static int archive_alloc() {
archive_release();
arc = archive_read_new();
archive_read_set_seek_callback(arc, ins_seek);
archive_read_set_skip_callback(arc, ins_skip);
archive_read_support_format_all(arc);
archive_read_support_filter_all(arc);
if (passwd)
archive_read_add_passphrase(arc, passwd);
return archive_read_open_memory(arc, archiveAddr, archiveSize);
}
JNIEXPORT jint JNICALL
Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jobject osf) {
JNI_prepare_environment(_, osf);
archive_create();
long r = archive_read_open(arc, arc, NULL, ins_read, ins_close);
Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jlong addr, jlong size) {
archiveAddr = (void *) addr;
archiveSize = size;
env = _;
madvise(archiveAddr, archiveSize, MADV_SEQUENTIAL | MADV_WILLNEED);
long r = archive_alloc();
if (r) {
r = 0;
LOGE("%s%s", "Archive open failed:", archive_error_string(arc));
} else {
r = archive_list_all_entries();
LOGI("%s%ld%s", "Found ", r, " image entries in archive");
// We must read through the file|vm then we can know whether it is encrypted
int encryptRet = archive_read_has_encrypted_entries(arc);
switch (encryptRet) {
case 1: // At lease 1 encrypted entry
need_encrypt = true;
break;
case 0: // format supports but no encrypted entry found
case ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW: // Sometimes we might not read through whole file|vm, but it means so far we haven't meet any encrypted entry yet
default:
need_encrypt = false;
}
LOGI("%s%d", "archive_read_has_encrypted_entries returns ", encryptRet);
}
archive_read_close(arc);
archive_read_free(arc);
arc = NULL;
archive_release();
return r;
}
JNIEXPORT void JNICALL
Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *_, jobject thiz, jint index, jobject os) {
typedef struct Memarea {
void* buffer;
long size;
} Memarea;
JNIEXPORT jlong JNICALL
Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *_, jobject thiz, jint index) {
struct archive_entry *entry;
size_t size;
int ret;
la_int64_t offset;
const void* buff;
if (!arc || index < cur_index) {
if (arc)
archive_read_close(arc);
archive_read_free(arc);
archive_create();
archive_read_open(arc, arc, NULL, ins_read, ins_close);
archive_alloc();
cur_index = 0;
}
jmethodID writeID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, os), "write", "([B)V");
jmethodID flushID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, os), "flush", "()V");
jmethodID closeID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, os), "close", "()V");
Memarea* memarea = malloc(sizeof(Memarea));
while (archive_read_next_header(arc, &entry) == ARCHIVE_OK) {
if (!filename_is_playable_file(archive_entry_pathname(entry)))
continue;
if (cur_index++ == index) {
memarea->size = archive_entry_size(entry);
memarea->buffer = malloc(memarea->size);
for (;;) {
ret = archive_read_data_block(arc, &buff, &size, &offset);
if (ret == ARCHIVE_EOF)
break;
if (ret != ARCHIVE_OK) {
ret = archive_read_data(arc, memarea->buffer, memarea->size);
if (ret < 0) {
LOGE("%s%s", "Archive read failed:", archive_error_string(arc));
break;
}
(*env)->SetByteArrayRegion(env, jbr, 0, (int)size, buff);
(*env)->CallVoidMethod(env, os, writeID, jbr);
break;
}
break;
}
}
(*env)->CallVoidMethod(env, os, flushID);
(*env)->CallVoidMethod(env, os, closeID);
return (jlong) memarea;
}
JNIEXPORT void JNICALL
Java_com_hippo_UriArchiveAccessor_closeArchive(JNIEnv *jniEnv, jobject thiz) {
if (arc) {
archive_read_close(arc);
archive_read_free(arc);
archive_release();
free(passwd);
}
JNIEXPORT jboolean JNICALL
Java_com_hippo_UriArchiveAccessor_needPassword(JNIEnv *_, jobject thiz) {
return need_encrypt;
}
JNIEXPORT jboolean JNICALL
Java_com_hippo_UriArchiveAccessor_providePassword(JNIEnv *_, jobject thiz, jstring str) {
struct archive_entry *entry;
jboolean ret = true;
int len = (*env)->GetStringUTFLength(env, str);
if (passwd)
free(passwd);
passwd = calloc(len, sizeof(char));
strcpy(passwd, (*env)->GetStringUTFChars(env, str, NULL));
LOGI("%s%s", "Passwd is ", passwd);
archive_alloc();
while (archive_read_next_header(arc, &entry) == ARCHIVE_OK) {
if (!filename_is_playable_file(archive_entry_pathname(entry)))
continue;
if (!archive_entry_is_encrypted(entry))
continue;
void *tmpBuf = malloc(4096);
if (archive_read_data(arc, tmpBuf, 4096) < ARCHIVE_OK) {
LOGE("%s%s", "Archive read failed:", archive_error_string(arc));
ret = false;
}
free(tmpBuf);
break;
}
JNI_destroy_environment();
}
archive_release();
return ret;
}
+20 -5
View File
@@ -13,9 +13,24 @@
# limitations under the License.
cmake_minimum_required(VERSION 3.4.1)
project(image C)
add_subdirectory(image)
add_subdirectory(stream)
add_subdirectory(libjpeg-turbo)
add_subdirectory(libpng)
add_subdirectory(giflib)
set(IMAGE_SOURCES
image.c
image_utils.c
filter/clahe.c
filter/gray.c
java_wrapper.c
)
set(IMAGE_INCLUDES
${CMAKE_CURRENT_SOURCE_DIR}
)
set(IMAGE_LIBRARIES
log
jnigraphics
GLESv2
)
add_library(image STATIC ${IMAGE_SOURCES})
target_include_directories(image PRIVATE ${IMAGE_INCLUDES})
target_link_libraries(image PRIVATE ${IMAGE_LIBRARIES})
+186
View File
@@ -0,0 +1,186 @@
/*
* Copyright 2018 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "clahe.h"
#include "pixel.h"
#include "../utils.h"
#include "../log.h"
#define TILE_BLOCK 8
#define LIMIT_MULTIPLE 4
#define CL_MAX_LOOP_NUMBER 4
static BYTE clamp(int t) {
t = t > 255 ? 255 : t;
t = t < 0 ? 0 : t;
return (BYTE) t;
}
void IMAGE_clahe(void *data, int width, int height, bool to_gray) {
if (width < TILE_BLOCK || height < TILE_BLOCK) {
return;
}
PIXEL *pixels = data;
if (to_gray) {
for (int i = 0; i < width * height; ++i) {
PIXEL *p = pixels + i;
int t1 = (int) (p->c1 * 0.299f + p->c2 * 0.587f + p->c3 * 0.114f);
p->c1 = clamp(t1);
}
} else {
// RGBA to YUVA
for (int i = 0; i < width * height; ++i) {
PIXEL *p = pixels + i;
int t1 = (int) (p->c1 * 0.299f + p->c2 * 0.587f + p->c3 * 0.114f);
int t2 = (int) (p->c1 * -0.169f + p->c2 * -0.331f + p->c3 * 0.5f + 128);
int t3 = (int) (p->c1 * 0.5f + p->c2 * -0.419f + p->c3 * -0.081f + 128);
p->c1 = clamp(t1);
p->c2 = clamp(t2);
p->c3 = clamp(t3);
}
}
int tile_width = width / TILE_BLOCK;
int tile_height = height / TILE_BLOCK;
int histogram[TILE_BLOCK * TILE_BLOCK][256] = {0};
float accumulation[TILE_BLOCK * TILE_BLOCK][256] = {0.0f};
// Build histogram and accumulation
for (int i = 0; i < TILE_BLOCK; i++) {
for (int j = 0; j < TILE_BLOCK; j++) {
int x_start = tile_width * i;
int x_end = i == TILE_BLOCK - 1 ? width : x_start + tile_width;
int y_start = tile_height * j;
int y_end = j == TILE_BLOCK - 1 ? height : y_start + tile_height;
int tile_size = (x_end - x_start) * (y_end - y_start);
int tile_index = i + TILE_BLOCK * j;
// Count
for (int x = x_start; x < x_end; x++) {
for (int y = y_start; y < y_end; y++) {
PIXEL *p = pixels + x + y * width;
histogram[tile_index][p->c1] += 1;
}
}
// CL
int limit = tile_size * LIMIT_MULTIPLE / 256;
for (int m = 0; m < CL_MAX_LOOP_NUMBER; m++) {
int steal = 0;
for (int n = 0; n < 256; n++) {
if (histogram[tile_index][n] > limit) {
steal += histogram[tile_index][n] - limit;
histogram[tile_index][n] = limit;
}
}
int bonus = steal / 256;
if (bonus == 0 && steal != 0 && m == 0) {
bonus = 1;
}
if (bonus == 0) {
break;
}
for (int n = 0; n < 256; n++) {
histogram[tile_index][n] += bonus;
}
}
// accumulation
for (int n = 0; n < 256; n++) {
accumulation[tile_index][n] = (float) histogram[tile_index][n] / tile_size;
if (n != 0) {
accumulation[tile_index][n] += accumulation[tile_index][n - 1];
}
}
}
}
// Interpolation
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
PIXEL *p = pixels + x + y * width;
// top-left corner
if (x <= tile_width / 2 && y <= tile_height / 2) {
p->c1 = clamp((int) (accumulation[0][p->c1] * 255));
continue;
}
// top-right corner
if (x > width - tile_width / 2 && y <= tile_height / 2) {
p->c1 = clamp((int) (accumulation[TILE_BLOCK - 1][p->c1] * 255));
continue;
}
// bottom-left corner
if (x <= tile_width / 2 && y > height - tile_height / 2) {
p->c1 = clamp((int) (accumulation[TILE_BLOCK * (TILE_BLOCK - 1)][p->c1] * 255));
continue;
}
// bottom-right corner
if (x > width - tile_width / 2 && y > height - tile_height / 2) {
p->c1 = clamp((int) (accumulation[TILE_BLOCK * TILE_BLOCK - 1][p->c1] * 255));
continue;
}
int tile_x_index = (x - tile_width / 2) / tile_width;
int tile_y_index = (y - tile_height / 2) / tile_height;
int tile_index1 = tile_x_index + TILE_BLOCK * tile_y_index;
int tile_index2 = tile_index1 + 1;
float u = (float) (x - (tile_x_index * tile_width + tile_width / 2)) / tile_width;
// top side and bottom side
if (y <= tile_height / 2 || y > height - tile_height / 2) {
p->c1 = clamp((int) (255 * (accumulation[tile_index1][p->c1] * (1 - u) +
accumulation[tile_index2][p->c1] * u)));
continue;
}
int tile_index3 = tile_index1 + TILE_BLOCK;
float v = (float) (y - (tile_y_index * tile_height + tile_height / 2)) / tile_height;
// left side and right side
if (x <= tile_width / 2 || x > width - tile_width / 2) {
p->c1 = clamp((int) (255 * (accumulation[tile_index1][p->c1] * (1 - v) +
accumulation[tile_index3][p->c1] * v)));
continue;
}
int tile_index4 = tile_index2 + TILE_BLOCK;
p->c1 = clamp((int) (255 * (
accumulation[tile_index1][p->c1] * (1 - u) * (1 - v)
+ accumulation[tile_index2][p->c1] * u * (1 - v)
+ accumulation[tile_index3][p->c1] * (1 - u) * v
+ accumulation[tile_index4][p->c1] * u * v)));
}
}
if (to_gray) {
for (int i = 0; i < width * height; ++i) {
PIXEL *p = pixels + i;
p->c2 = p->c1;
p->c3 = p->c1;
}
} else {
// YUVA to RGBA
for (int i = 0; i < width * height; ++i) {
PIXEL *p = pixels + i;
int t1 = (int) (p->c1 + (p->c2 - 128) * -0.00093f + (p->c3 - 128) * 1.401687f);
int t2 = (int) (p->c1 + (p->c2 - 128) * -0.3437f + (p->c3 - 128) * -0.71417f);
int t3 = (int) (p->c1 + (p->c2 - 128) * 1.77216f + (p->c3 - 128) * 0.00099f);
p->c1 = clamp(t1);
p->c2 = clamp(t2);
p->c3 = clamp(t3);
}
}
}
@@ -19,6 +19,6 @@
#include <stdbool.h>
void IMAGE_clahe(void* data, int width, int height, bool to_gray);
void IMAGE_clahe(void *data, int width, int height, bool to_gray);
#endif //IMAGE_CLAHE_H
@@ -17,20 +17,20 @@
#include "gray.h"
#include "pixel.h"
bool IMAGE_is_gray(void* data, int width, int height, int error) {
PIXEL* p = data;
bool IMAGE_is_gray(void *data, int width, int height, int error) {
PIXEL *p = data;
for (int i = 0, n = width * height; i < n; i++, p++) {
int e1 = p->c1 - p->c2;
int e2 = p->c1 - p->c3;
int e3 = p->c2 - p->c3;
for (int i = 0, n = width * height; i < n; i++, p++) {
int e1 = p->c1 - p->c2;
int e2 = p->c1 - p->c3;
int e3 = p->c2 - p->c3;
if (e1 > error || e1 < -error
|| e2 > error || e2 < -error
|| e3 > error || e3 < -error) {
return false;
if (e1 > error || e1 < -error
|| e2 > error || e2 < -error
|| e3 > error || e3 < -error) {
return false;
}
}
}
return true;
return true;
}
@@ -19,6 +19,6 @@
#include <stdbool.h>
bool IMAGE_is_gray(void* data, int width, int height, int error);
bool IMAGE_is_gray(void *data, int width, int height, int error);
#endif //IMAGE_GRAY_H
@@ -19,12 +19,11 @@
typedef unsigned char BYTE;
typedef struct
{
BYTE c1;
BYTE c2;
BYTE c3;
BYTE c4;
typedef struct {
BYTE c1;
BYTE c2;
BYTE c3;
BYTE c4;
} PIXEL;
#endif //IMAGE_PIXEL_H
@@ -1,27 +0,0 @@
# Copyright 2018 Hippo Seven
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.4.1)
project(gif C)
set(GIFLIB_SOURCES
giflib/dgif_lib.c
giflib/gif_hash.c
giflib/gifalloc.c
giflib/openbsd-reallocarray.c
)
set(GIFLIB_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/giflib)
add_library(gif STATIC ${GIFLIB_SOURCES})
target_include_directories(gif PUBLIC ${GIFLIB_INCLUDES})
+192
View File
@@ -0,0 +1,192 @@
/*
* Copyright 2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//
// Created by Hippo on 12/27/2015.
//
#include <android/data_space.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "image.h"
#include "image_utils.h"
#include "filter/clahe.h"
#include "filter/gray.h"
#include "log.h"
void decodeCommon(IMAGE *image) {
AImageDecoder *decoder = image->decoder;
AImageDecoder_setDataSpace(decoder, ADATASPACE_SRGB);
AImageDecoder_setAndroidBitmapFormat(decoder, ANDROID_BITMAP_FORMAT_RGBA_8888);
const AImageDecoderHeaderInfo *headerInfo = AImageDecoder_getHeaderInfo(decoder);
image->height = AImageDecoderHeaderInfo_getHeight(headerInfo);
image->width = AImageDecoderHeaderInfo_getWidth(headerInfo);
image->alpha =
AImageDecoderHeaderInfo_getAlphaFlags(headerInfo) == ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
image->stride = AImageDecoder_getMinimumStride(decoder);
image->bufferLen = image->height * image->stride;
image->buffer = malloc(image->bufferLen);
if (image->isAnimated) {
AImageDecoder_setInternallyHandleDisposePrevious(decoder, false);
image->frameInfo = AImageDecoderFrameInfo_create();
AImageDecoder_getFrameInfo(decoder, image->frameInfo);
}
AImageDecoder_decodeImage(decoder, image->buffer, image->stride, image->bufferLen);
}
IMAGE *createFromFd(JNIEnv *env, int fd, bool partially, int *format) {
AImageDecoder *decoder;
int r = AImageDecoder_createFromFd(fd, &decoder);
LOGD("%s%d", "Create ImageDecoder with ret ", r);
if (r)
return NULL;
IMAGE *image = calloc(1, sizeof(IMAGE));
image->isAnimated = *format = AImageDecoder_isAnimated(decoder);
image->decoder = decoder;
decodeCommon(image);
return image;
}
IMAGE *createFromAddr(JNIEnv *env, void *addr, long size, bool partially, int *format) {
AImageDecoder *decoder;
int r = AImageDecoder_createFromBuffer((const void *) addr, size, &decoder);
LOGD("%s%d", "Create ImageDecoder with ret ", r);
if (r)
return NULL;
IMAGE *image = calloc(1, sizeof(IMAGE));
image->isAnimated = *format = AImageDecoder_isAnimated(decoder);
image->decoder = decoder;
image->srcBuffer = addr;
decodeCommon(image);
return image;
}
void *create(int32_t width, int32_t height, const void *data) {
IMAGE *plain = NULL;
void *buffer = NULL;
size_t length;
plain = malloc(sizeof(IMAGE));
if (plain == NULL) {
WTF_OM;
return NULL;
}
length = (size_t) (width * height * 4);
buffer = malloc(length);
if (buffer == NULL) {
WTF_OM;
free(plain);
return NULL;
}
memcpy(buffer, data, length);
plain->width = width;
plain->height = height;
plain->buffer = buffer;
plain->bufferLen = length;
plain->decoder = NULL;
return plain;
}
int get_width(IMAGE *image, int format) {
return image->width;
}
int get_height(IMAGE *image, int format) {
return image->height;
}
int get_byte_count(IMAGE *image, int format) {
return image->bufferLen;
}
void render(IMAGE *image, int format, int src_x, int src_y,
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
int width, int height, bool fill_blank, int default_color) {
copy_pixels(image->buffer, image->width, image->height, src_x, src_y, dst, dst_w, dst_h, dst_x,
dst_y, width, height, fill_blank, default_color);
}
void advance(IMAGE *image, int format) {
if (format) {
AImageDecoder_advanceFrame(image->decoder);
if (AImageDecoder_decodeImage(image->decoder, image->buffer, image->stride,
image->bufferLen) == ANDROID_IMAGE_DECODER_FINISHED) {
AImageDecoder_rewind(image->decoder);
AImageDecoder_decodeImage(image->decoder, image->buffer, image->stride,
image->bufferLen);
}
}
}
int get_delay(IMAGE *image, int format) {
if (format)
return AImageDecoderFrameInfo_getDuration(image->frameInfo) / 1000000;
return 0;
}
bool is_opaque(IMAGE *image, int format) {
return image->alpha;
}
static void get_image_data(IMAGE *image, int format, void **pixel, int *width, int *height) {
*pixel = image->buffer;
*width = image->width;
*height = image->height;
}
bool is_gray(IMAGE *image, int format, int error) {
void *pixel = NULL;
int width = 0;
int height = 0;
get_image_data(image, format, &pixel, &width, &height);
if (pixel == NULL || width == 0 || height == 0) {
return false;
}
return IMAGE_is_gray(pixel, width, height, error);
}
void clahe(IMAGE *image, int format, bool to_gray) {
void *pixel = NULL;
int width = 0;
int height = 0;
get_image_data(image, format, &pixel, &width, &height);
if (pixel == NULL || width == 0 || height == 0) {
return;
}
IMAGE_clahe(pixel, width, height, to_gray);
}
void recycle(JNIEnv *env, IMAGE *image, int format) {
free(image->buffer);
image->buffer = NULL;
AImageDecoderFrameInfo_delete(image->frameInfo);
AImageDecoder_delete(image->decoder);
free(image->srcBuffer);
free(image);
}
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright 2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//
// Created by Hippo on 12/27/2015.
//
#ifndef IMAGE_IMAGE_H
#define IMAGE_IMAGE_H
#include <android/imagedecoder.h>
#include <stdbool.h>
#include <jni.h>
typedef struct {
int32_t width;
int32_t height;
void *buffer;
int bufferLen;
AImageDecoder *decoder;
void *srcBuffer;
size_t stride;
bool isAnimated;
AImageDecoderFrameInfo *frameInfo;
bool alpha;
} IMAGE;
IMAGE *createFromFd(JNIEnv *env, int fd, bool partially, int *format);
IMAGE *createFromAddr(JNIEnv *env, void *addr, long size, bool partially, int *format);
void *create(int32_t width, int32_t height, const void *data);
int get_width(IMAGE *image, int format);
int get_height(IMAGE *image, int format);
int get_byte_count(IMAGE *image, int format);
void render(IMAGE *image, int format, int src_x, int src_y,
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
int width, int height, bool fill_blank, int default_color);
void advance(IMAGE *image, int format);
int get_delay(IMAGE *image, int format);
bool is_opaque(IMAGE *image, int format);
bool is_gray(IMAGE *image, int format, int error);
void clahe(IMAGE *image, int format, bool to_gray);
void recycle(JNIEnv *env, IMAGE *image, int format);
#endif //IMAGE_IMAGE_H
@@ -1,60 +0,0 @@
# Copyright 2015 Hippo Seven
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
SUPPORT_FORMAT := plain jpeg png gif
LOCAL_MODULE := image
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../stream
LOCAL_SRC_FILES := \
image.c \
image_utils.c \
java_wrapper.c
LOCAL_LDLIBS := -llog -ljnigraphics -lGLESv2
LOCAL_STATIC_LIBRARIES := stream
ifeq ($(filter plain, $(SUPPORT_FORMAT)), plain)
LOCAL_SRC_FILES += image_plain.c
else
LOCAL_CFLAGS += -DIMAGE_NOT_SUPPORT_PLAIN
endif
ifeq ($(filter jpeg, $(SUPPORT_FORMAT)), jpeg)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libjpeg-turbo
LOCAL_SRC_FILES += image_jpeg.c
LOCAL_STATIC_LIBRARIES += jpeg-turbo
else
LOCAL_CFLAGS += -DIMAGE_NOT_SUPPORT_JPEG
endif
ifeq ($(filter png, $(SUPPORT_FORMAT)), png)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libpng
LOCAL_SRC_FILES += image_png.c
LOCAL_STATIC_LIBRARIES += png
else
LOCAL_CFLAGS += -DIMAGE_NOT_SUPPORT_PNG
endif
ifeq ($(filter gif, $(SUPPORT_FORMAT)), gif)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../giflib
LOCAL_SRC_FILES += image_gif.c
LOCAL_STATIC_LIBRARIES += gif
else
LOCAL_CFLAGS += -DIMAGE_NOT_SUPPORT_GIF
endif
include $(BUILD_SHARED_LIBRARY)
@@ -1,44 +0,0 @@
# Copyright 2018 Hippo Seven
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.4.1)
project(image C)
set(IMAGE_SOURCES
image.c
image_utils.c
image_plain.c
image_jpeg.c
image_png.c
image_gif.c
filter/clahe.c
filter/gray.c
java_wrapper.c
)
set(IMAGE_INCLUDES
${CMAKE_CURRENT_SOURCE_DIR}
)
set(IMAGE_LIBRARIES
log
jnigraphics
GLESv2
stream
jpeg
png
gif
)
add_library(image STATIC ${IMAGE_SOURCES})
target_include_directories(image PRIVATE ${IMAGE_INCLUDES})
target_link_libraries(image PRIVATE ${IMAGE_LIBRARIES})
-37
View File
@@ -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);
}
}
}
-532
View File
@@ -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;
}
}
-65
View File
@@ -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
-558
View File
@@ -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
-642
View File
@@ -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;
}
+183
View File
@@ -0,0 +1,183 @@
/*
* Copyright 2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//
// Created by Hippo on 12/27/2015.
//
#include "image_utils.h"
#include <stdlib.h>
#include <string.h>
#define LITTLE_ENDIAN 0x00
#define BIG_ENDIAN 0x01
static unsigned int endian = ~0U;
static unsigned int get_endian() {
unsigned int x = 1;
if (endian == ~0U) {
if (1 == ((char *) &x)[0]) {
endian = LITTLE_ENDIAN;
} else {
endian = BIG_ENDIAN;
}
}
return endian;
}
static int convert_color(int origin) {
int result;
unsigned char *orPtr = (unsigned char *) &origin;
unsigned char *rePtr = (unsigned char *) &result;
if (get_endian() == BIG_ENDIAN) {
rePtr[0] = orPtr[1];
rePtr[1] = orPtr[2];
rePtr[2] = orPtr[3];
rePtr[3] = orPtr[0];
} else {
rePtr[0] = orPtr[2];
rePtr[1] = orPtr[1];
rePtr[2] = orPtr[0];
rePtr[3] = orPtr[3];
}
return result;
}
static void memset_int(int *dst, int val, size_t size) {
int *maxPtr = dst + size;
int *ptr = dst;
while (ptr < maxPtr)
*ptr++ = val;
}
bool copy_pixels_internal(const void *src, int src_w, int src_h, int src_x, int src_y,
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
int width, int height, bool fill_blank, int color) {
int left;
int line;
size_t line_stride;
int src_stride;
int src_pos;
int dst_pos;
size_t dst_blank_length;
// Sanitize
if (src_x < 0) {
width -= src_x;
dst_x -= src_x;
src_x = 0;
}
if (dst_x < 0) {
width -= dst_x;
src_x -= dst_x;
dst_x = 0;
}
if (width <= 0) {
return false;
}
if (src_y < 0) {
height -= src_y;
dst_y -= src_y;
src_y = 0;
}
if (dst_y < 0) {
height -= dst_y;
src_y -= dst_y;
dst_y = 0;
}
if (height <= 0) {
return false;
}
left = src_x + width - src_w;
if (left > 0) {
width -= left;
}
left = dst_x + width - dst_w;
if (left > 0) {
width -= left;
}
if (width <= 0) {
return false;
}
left = src_y + height - src_h;
if (left > 0) {
height -= left;
}
left = dst_y + height - dst_h;
if (left > 0) {
height -= left;
}
if (height <= 0) {
return false;
}
// Init
line_stride = (size_t) (width * 4);
src_stride = src_w * 4;
src_pos = src_y * src_stride + src_x * 4;
dst_pos = 0;
dst_blank_length = (size_t) (dst_y * dst_w + dst_x) * 4;
// Fill start blank if necessary
if (fill_blank) {
memset_int((int *) (dst + dst_pos), color, dst_blank_length / 4);
}
// First line
dst_pos += dst_blank_length;
memcpy(dst + dst_pos, src + src_pos, line_stride);
dst_pos += line_stride;
src_pos += src_stride;
// Other lines
dst_blank_length = (size_t) ((dst_w - width) * 4);
for (line = 1; line < height; line++) {
if (fill_blank) {
memset_int((int *) (dst + dst_pos), color, dst_blank_length / 4);
}
dst_pos += dst_blank_length;
memcpy(dst + dst_pos, src + src_pos, line_stride);
dst_pos += line_stride;
src_pos += src_stride;
}
// Fill left blank if necessary
if (fill_blank) {
memset_int((int *) (dst + dst_pos), color, (size_t) (dst_w * dst_h * 4 - dst_pos) / 4);
}
return true;
}
void copy_pixels(const void *src, int src_w, int src_h, int src_x, int src_y,
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
int width, int height, bool fill_blank, int default_color) {
int color = 0;
if (fill_blank) {
color = convert_color(default_color);
}
if (!copy_pixels_internal(src, src_w, src_h, src_x, src_y, dst, dst_w, dst_h, dst_x,
dst_y, width, height, fill_blank, color) && fill_blank) {
memset_int(dst, color, (size_t) (dst_w * dst_h));
}
}
@@ -26,8 +26,8 @@
#include <stdbool.h>
void copy_pixels(const void* src, int src_w, int src_h, int src_x, int src_y,
void* dst, int dst_w, int dst_h, int dst_x, int dst_y,
int width, int height, bool fill_blank, int default_color);
void copy_pixels(const void *src, int src_w, int src_h, int src_x, int src_y,
void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
int width, int height, bool fill_blank, int default_color);
#endif //IMAGE_IMAGE_UTILS_H
+279
View File
@@ -0,0 +1,279 @@
/*
* Copyright 2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <android/bitmap.h>
#include <GLES2/gl2.h>
#include "java_wrapper.h"
#include "image.h"
#include "log.h"
static JavaVM *jvm;
static void *tile_buffer;
static int jniGetFDFromFileDescriptor(JNIEnv *env, jobject fileDescriptor) {
jint fd = -1;
jclass fdClass = (*env)->FindClass(env, "java/io/FileDescriptor");
if (fdClass != NULL) {
jfieldID fdClassDescriptorFieldID = (*env)->GetFieldID(env, fdClass, "descriptor", "I");
if (fdClassDescriptorFieldID != NULL && fileDescriptor != NULL) {
fd = (*env)->GetIntField(env, fileDescriptor, fdClassDescriptorFieldID);
}
}
return fd;
}
JNIEnv *obtain_env(bool *attach) {
JNIEnv *env;
switch ((*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_6)) {
case JNI_EDETACHED:
if ((*jvm)->AttachCurrentThread(jvm, &env, NULL) == JNI_OK) {
*attach = true;
return env;
} else {
return NULL;
}
case JNI_OK:
*attach = false;
return env;
default:
case JNI_EVERSION:
return NULL;
}
}
void release_env() {
(*jvm)->DetachCurrentThread(jvm);
}
jobject create_image_object(JNIEnv *env, void *ptr, int format, int width, int height) {
jclass image_clazz;
jmethodID constructor;
image_clazz = (*env)->FindClass(env, "com/hippo/image/Image");
constructor = (*env)->GetMethodID(env, image_clazz, "<init>", "(JIII)V");
if (constructor == 0) {
LOGE(MSG("Can't find Image object constructor"));
return NULL;
} else {
return (*env)->NewObject(env, image_clazz, constructor,
(jlong) (uintptr_t) ptr, (jint) format, (jint) width,
(jint) height);
}
}
JNIEXPORT jobject JNICALL
Java_com_hippo_image_Image_nativeDecodeFdInt(JNIEnv *env,
jclass clazz, jint fd, jboolean partially) {
int format;
void *image;
jobject image_object;
image = createFromFd(env, fd, partially, &format);
if (image == NULL) {
return NULL;
}
image_object = create_image_object(env, image, format,
get_width(image, format), get_height(image, format));
if (image_object == NULL) {
recycle(env, image, format);
return NULL;
} else {
return image_object;
}
}
JNIEXPORT jobject JNICALL
Java_com_hippo_image_Image_nativeDecode(JNIEnv *env,
jclass clazz, jobject fd, jboolean partially) {
return Java_com_hippo_image_Image_nativeDecodeFdInt(env, clazz,
jniGetFDFromFileDescriptor(env, fd),
partially);
}
JNIEXPORT jobject JNICALL
Java_com_hippo_image_Image_nativeCreate(JNIEnv *env,
jclass clazz, jobject bitmap) {
AndroidBitmapInfo info;
void *pixels = NULL;
void *image = NULL;
jobject image_object;
AndroidBitmap_getInfo(env, bitmap, &info);
AndroidBitmap_lockPixels(env, bitmap, &pixels);
if (pixels == NULL) {
LOGE(MSG("Can't lock bitmap pixels"));
return NULL;
}
image = create(info.width, info.height, pixels);
AndroidBitmap_unlockPixels(env, bitmap);
if (image == NULL) {
return NULL;
}
image_object = create_image_object(env, image, 0,
info.width, info.height);
if (image_object == NULL) {
recycle(env, image, 0);
return NULL;
} else {
return image_object;
}
}
JNIEXPORT jint JNICALL
Java_com_hippo_image_Image_nativeGetByteCount(JNIEnv *env,
jclass clazz, jlong ptr, jint format) {
return (jint) get_byte_count((void *) (intptr_t) ptr, format);
}
JNIEXPORT void JNICALL
Java_com_hippo_image_Image_nativeRender(JNIEnv *env,
jclass clazz, jlong ptr, jint format,
jint src_x, jint src_y, jobject dst, jint dst_x, jint dst_y,
jint width, jint height, jboolean fill_blank,
jint default_color) {
AndroidBitmapInfo info;
void *pixels = NULL;
AndroidBitmap_getInfo(env, dst, &info);
AndroidBitmap_lockPixels(env, dst, &pixels);
if (pixels == NULL) {
LOGE(MSG("Can't lock bitmap pixels"));
return;
}
render((void *) (intptr_t) ptr, format, src_x, src_y,
pixels, info.width, info.height, dst_x, dst_y,
width, height, fill_blank, default_color);
AndroidBitmap_unlockPixels(env, dst);
return;
}
JNIEXPORT void JNICALL
Java_com_hippo_image_Image_nativeTexImage(JNIEnv *env,
jclass clazz, jlong ptr, jint format, jboolean init,
jint src_x, jint src_y, jint width, jint height) {
// Check tile_buffer NULL
if (NULL == tile_buffer) {
return;
}
// Check render size
if (width * height > IMAGE_TILE_MAX_SIZE) {
return;
}
render((void *) (intptr_t) ptr, format, src_x, src_y,
tile_buffer, width, height, 0, 0,
width, height, false, 0);
if (init) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
0, GL_RGBA, GL_UNSIGNED_BYTE, tile_buffer);
} else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
GL_RGBA, GL_UNSIGNED_BYTE, tile_buffer);
}
}
JNIEXPORT void JNICALL
Java_com_hippo_image_Image_nativeAdvance(JNIEnv *env,
jclass clazz, jlong ptr, jint format) {
advance((void *) (intptr_t) ptr, format);
}
JNIEXPORT jint JNICALL
Java_com_hippo_image_Image_nativeGetDelay(JNIEnv *env,
jclass clazz, jlong ptr, jint format) {
return (jint) get_delay((void *) (intptr_t) ptr, format);
}
JNIEXPORT jboolean JNICALL
Java_com_hippo_image_Image_nativeIsOpaque(JNIEnv *env,
jclass clazz, jlong ptr, jint format) {
return (jboolean) is_opaque((void *) (intptr_t) ptr, format);
}
JNIEXPORT jboolean JNICALL
Java_com_hippo_image_Image_nativeIsGray(JNIEnv *env,
jclass clazz, jlong ptr, jint format, jint error) {
return (jboolean) is_gray((void *) (intptr_t) ptr, format, error);
}
JNIEXPORT void JNICALL
Java_com_hippo_image_Image_nativeClahe(JNIEnv *env,
jclass clazz, jlong ptr, jint format, jboolean to_gray) {
clahe((void *) (intptr_t) ptr, format, to_gray);
}
JNIEXPORT void JNICALL
Java_com_hippo_image_Image_nativeRecycle(JNIEnv *env,
jclass clazz, jlong ptr, jint format) {
recycle(env, (void *) (intptr_t) ptr, format);
}
bool image_onLoad(JavaVM *vm) {
jvm = vm;
tile_buffer = malloc(IMAGE_TILE_MAX_SIZE * 4);
return true;
}
JNIEXPORT void JNICALL
JNI_OnUnload(JavaVM *vm, void *reserved) {
free(tile_buffer);
tile_buffer = NULL;
}
typedef struct Memarea {
void *buffer;
long size;
} Memarea;
JNIEXPORT jobject JNICALL
Java_com_hippo_image_Image_nativeDecodeAddr(JNIEnv *env, jclass clazz, jlong addr,
jboolean partially) {
int format;
void *image;
jobject image_object;
Memarea *memarea = (Memarea *) addr;
image = createFromAddr(env, memarea->buffer, memarea->size, partially, &format);
free(memarea);
if (image == NULL) {
return NULL;
}
image_object = create_image_object(env, image, format,
get_width(image, format), get_height(image, format));
if (image_object == NULL) {
recycle(env, image, format);
return NULL;
} else {
return image_object;
}
}
@@ -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"
@@ -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})
@@ -1,246 +0,0 @@
/*
* Copyright 2022 Tarsin Norbin
*
* This file is part of EhViewer
*
* EhViewer is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* EhViewer is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* EhViewer. If not, see <https://www.gnu.org/licenses/>.
*/
/* libpng 1.6.34 STANDARD API DEFINITION */
/* pnglibconf.h - library build configuration */
/* Libpng version 1.6.34 - September 29, 2017 */
/* Copyright (c) 1998-2017 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
/* For conditions of distribution and use, see the disclaimer */
/* and license in png.h */
/* pnglibconf.h */
/* Machine generated file: DO NOT EDIT */
/* Derived from: scripts/pnglibconf.dfa */
#ifndef PNGLCONF_H
#define PNGLCONF_H
/* options */
#define PNG_16BIT_SUPPORTED
#define PNG_ALIGNED_MEMORY_SUPPORTED
/*#undef PNG_ARM_NEON_API_SUPPORTED*/
/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/
/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/
#define PNG_BENIGN_ERRORS_SUPPORTED
#define PNG_BENIGN_READ_ERRORS_SUPPORTED
/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_COLORSPACE_SUPPORTED
#define PNG_CONSOLE_IO_SUPPORTED
#define PNG_CONVERT_tIME_SUPPORTED
#define PNG_EASY_ACCESS_SUPPORTED
/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/
#define PNG_ERROR_TEXT_SUPPORTED
#define PNG_FIXED_POINT_SUPPORTED
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
#define PNG_FLOATING_POINT_SUPPORTED
#define PNG_FORMAT_AFIRST_SUPPORTED
#define PNG_FORMAT_BGR_SUPPORTED
#define PNG_GAMMA_SUPPORTED
#define PNG_GET_PALETTE_MAX_SUPPORTED
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
#define PNG_INCH_CONVERSIONS_SUPPORTED
#define PNG_INFO_IMAGE_SUPPORTED
#define PNG_IO_STATE_SUPPORTED
#define PNG_MNG_FEATURES_SUPPORTED
#define PNG_POINTER_INDEXING_SUPPORTED
#define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_16BIT_SUPPORTED
#define PNG_READ_ALPHA_MODE_SUPPORTED
#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_READ_BACKGROUND_SUPPORTED
#define PNG_READ_BGR_SUPPORTED
#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_READ_COMPOSITE_NODIV_SUPPORTED
#define PNG_READ_COMPRESSED_TEXT_SUPPORTED
#define PNG_READ_EXPAND_16_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED
#define PNG_READ_FILLER_SUPPORTED
#define PNG_READ_GAMMA_SUPPORTED
#define PNG_READ_GET_PALETTE_MAX_SUPPORTED
#define PNG_READ_GRAY_TO_RGB_SUPPORTED
#define PNG_READ_INTERLACING_SUPPORTED
#define PNG_READ_INT_FUNCTIONS_SUPPORTED
#define PNG_READ_INVERT_ALPHA_SUPPORTED
#define PNG_READ_INVERT_SUPPORTED
#define PNG_READ_OPT_PLTE_SUPPORTED
#define PNG_READ_PACKSWAP_SUPPORTED
#define PNG_READ_PACK_SUPPORTED
#define PNG_READ_QUANTIZE_SUPPORTED
#define PNG_READ_RGB_TO_GRAY_SUPPORTED
#define PNG_READ_SCALE_16_TO_8_SUPPORTED
#define PNG_READ_SHIFT_SUPPORTED
#define PNG_READ_STRIP_16_TO_8_SUPPORTED
#define PNG_READ_STRIP_ALPHA_SUPPORTED
#define PNG_READ_SUPPORTED
#define PNG_READ_SWAP_ALPHA_SUPPORTED
#define PNG_READ_SWAP_SUPPORTED
#define PNG_READ_TEXT_SUPPORTED
#define PNG_READ_TRANSFORMS_SUPPORTED
#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_READ_USER_CHUNKS_SUPPORTED
#define PNG_READ_USER_TRANSFORM_SUPPORTED
#define PNG_READ_bKGD_SUPPORTED
#define PNG_READ_cHRM_SUPPORTED
#define PNG_READ_eXIf_SUPPORTED
#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_hIST_SUPPORTED
#define PNG_READ_iCCP_SUPPORTED
#define PNG_READ_iTXt_SUPPORTED
#define PNG_READ_oFFs_SUPPORTED
#define PNG_READ_pCAL_SUPPORTED
#define PNG_READ_pHYs_SUPPORTED
#define PNG_READ_sBIT_SUPPORTED
#define PNG_READ_sCAL_SUPPORTED
#define PNG_READ_sPLT_SUPPORTED
#define PNG_READ_sRGB_SUPPORTED
#define PNG_READ_tEXt_SUPPORTED
#define PNG_READ_tIME_SUPPORTED
#define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_zTXt_SUPPORTED
/*#undef PNG_SAVE_INT_32_SUPPORTED*/
#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_SEQUENTIAL_READ_SUPPORTED
#define PNG_SETJMP_SUPPORTED
#define PNG_SET_OPTION_SUPPORTED
#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_SET_USER_LIMITS_SUPPORTED
/*#undef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED*/
/*#undef PNG_SIMPLIFIED_READ_BGR_SUPPORTED*/
/*#undef PNG_SIMPLIFIED_READ_SUPPORTED*/
/*#undef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED*/
/*#undef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED*/
/*#undef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED*/
/*#undef PNG_SIMPLIFIED_WRITE_SUPPORTED*/
/*#undef PNG_STDIO_SUPPORTED*/
#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_TEXT_SUPPORTED
#define PNG_TIME_RFC1123_SUPPORTED
#define PNG_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_USER_CHUNKS_SUPPORTED
#define PNG_USER_LIMITS_SUPPORTED
#define PNG_USER_MEM_SUPPORTED
#define PNG_USER_TRANSFORM_INFO_SUPPORTED
#define PNG_USER_TRANSFORM_PTR_SUPPORTED
#define PNG_WARNINGS_SUPPORTED
/*
#define PNG_WRITE_16BIT_SUPPORTED
#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_WRITE_BGR_SUPPORTED
#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
#define PNG_WRITE_FILLER_SUPPORTED
#define PNG_WRITE_FILTER_SUPPORTED
#define PNG_WRITE_FLUSH_SUPPORTED
#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED
#define PNG_WRITE_INTERLACING_SUPPORTED
#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
#define PNG_WRITE_INVERT_ALPHA_SUPPORTED
#define PNG_WRITE_INVERT_SUPPORTED
#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
#define PNG_WRITE_PACKSWAP_SUPPORTED
#define PNG_WRITE_PACK_SUPPORTED
#define PNG_WRITE_SHIFT_SUPPORTED
#define PNG_WRITE_SUPPORTED
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
#define PNG_WRITE_SWAP_SUPPORTED
#define PNG_WRITE_TEXT_SUPPORTED
#define PNG_WRITE_TRANSFORMS_SUPPORTED
#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
#define PNG_WRITE_bKGD_SUPPORTED
#define PNG_WRITE_cHRM_SUPPORTED
#define PNG_WRITE_eXIf_SUPPORTED
#define PNG_WRITE_gAMA_SUPPORTED
#define PNG_WRITE_hIST_SUPPORTED
#define PNG_WRITE_iCCP_SUPPORTED
#define PNG_WRITE_iTXt_SUPPORTED
#define PNG_WRITE_oFFs_SUPPORTED
#define PNG_WRITE_pCAL_SUPPORTED
#define PNG_WRITE_pHYs_SUPPORTED
#define PNG_WRITE_sBIT_SUPPORTED
#define PNG_WRITE_sCAL_SUPPORTED
#define PNG_WRITE_sPLT_SUPPORTED
#define PNG_WRITE_sRGB_SUPPORTED
#define PNG_WRITE_tEXt_SUPPORTED
#define PNG_WRITE_tIME_SUPPORTED
#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_zTXt_SUPPORTED
*/
#define PNG_bKGD_SUPPORTED
#define PNG_cHRM_SUPPORTED
#define PNG_eXIf_SUPPORTED
#define PNG_gAMA_SUPPORTED
#define PNG_hIST_SUPPORTED
#define PNG_iCCP_SUPPORTED
#define PNG_iTXt_SUPPORTED
#define PNG_oFFs_SUPPORTED
#define PNG_pCAL_SUPPORTED
#define PNG_pHYs_SUPPORTED
#define PNG_sBIT_SUPPORTED
#define PNG_sCAL_SUPPORTED
#define PNG_sPLT_SUPPORTED
#define PNG_sRGB_SUPPORTED
#define PNG_tEXt_SUPPORTED
#define PNG_tIME_SUPPORTED
#define PNG_tRNS_SUPPORTED
#define PNG_zTXt_SUPPORTED
/* end of options */
/* apng */
#define PNG_APNG_SUPPORTED
#define PNG_READ_APNG_SUPPORTED
/*#undef PNG_WRITE_APNG_SUPPORTED*/
/* end of apng */
/* settings */
#define PNG_API_RULE 0
#define PNG_DEFAULT_READ_MACROS 1
#define PNG_GAMMA_THRESHOLD_FIXED 5000
#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
#define PNG_INFLATE_BUF_SIZE 1024
#define PNG_LINKAGE_API extern
#define PNG_LINKAGE_CALLBACK extern
#define PNG_LINKAGE_DATA extern
#define PNG_LINKAGE_FUNCTION extern
#define PNG_MAX_GAMMA_8 11
#define PNG_QUANTIZE_BLUE_BITS 5
#define PNG_QUANTIZE_GREEN_BITS 5
#define PNG_QUANTIZE_RED_BITS 5
#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1)
#define PNG_TEXT_Z_DEFAULT_STRATEGY 0
#define PNG_USER_CHUNK_CACHE_MAX 1000
#define PNG_USER_CHUNK_MALLOC_MAX 8000000
#define PNG_USER_HEIGHT_MAX 1000000
#define PNG_USER_WIDTH_MAX 1000000
#define PNG_ZBUF_SIZE 8192
#define PNG_ZLIB_VERNUM 0 /* unknown */
#define PNG_Z_DEFAULT_COMPRESSION (-1)
#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
#define PNG_Z_DEFAULT_STRATEGY 1
#define PNG_sCAL_PRECISION 5
#define PNG_sRGB_PROFILE_CHECKS 2
/* end of settings */
#endif /* PNGLCONF_H */
@@ -1,27 +0,0 @@
# Copyright 2015 Hippo Seven
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := stream
LOCAL_SRC_FILES := \
input_stream.c \
input_stream_pipe.c \
output_stream.c \
output_stream_pipe.c \
patch_head_input_stream.c
include $(BUILD_STATIC_LIBRARY)
@@ -1,28 +0,0 @@
# Copyright 2018 Hippo Seven
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.4.1)
project(stream C)
set(STREAM_SOURCES
input_stream.c
input_stream_pipe.c
output_stream.c
output_stream_pipe.c
patch_head_input_stream.c
)
set(STREAM_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
add_library(stream STATIC ${STREAM_SOURCES})
target_include_directories(stream PUBLIC ${STREAM_INCLUDES})
-30
View File
@@ -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
+7 -7
View File
@@ -21,9 +21,9 @@
#include <archive.h>
#include <lzma.h>
#include <zlib.h>
#include "image/libjpeg-turbo/jconfigint.h"
#include <nettle/config.h>
#include "java_wrapper.h"
#include "image/java_wrapper.h"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;
@@ -49,12 +49,12 @@ Java_com_hippo_Native_getliblzmaVersion(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, lzma_version_string());
}
JNIEXPORT jstring JNICALL
Java_com_hippo_Native_getlibjpeg_1turboVersion(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, VERSION);
}
JNIEXPORT jstring JNICALL
Java_com_hippo_Native_getzlibVersion(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, ZLIB_VERSION);
}
JNIEXPORT jstring JNICALL
Java_com_hippo_Native_getnettleVersion(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, PACKAGE_STRING);
}
+239
View File
@@ -0,0 +1,239 @@
cmake_minimum_required(VERSION 3.4.1)
project(nettle C)
set(LIBNETTLE_DEFINITIONS
-DHAVE_CONFIG_H)
set(LIBNETTLE_SOURCES
nettle/aes-decrypt-internal.c
nettle/aes-decrypt.c
nettle/aes-decrypt-table.c
nettle/aes128-decrypt.c
nettle/aes192-decrypt.c
nettle/aes256-decrypt.c
nettle/aes-encrypt-internal.c
nettle/aes-encrypt.c
nettle/aes-encrypt-table.c
nettle/aes128-encrypt.c
nettle/aes192-encrypt.c
nettle/aes256-encrypt.c
nettle/aes-invert-internal.c
nettle/aes-set-key-internal.c
nettle/aes-set-encrypt-key.c
nettle/aes-set-decrypt-key.c
nettle/aes128-set-encrypt-key.c
nettle/aes128-set-decrypt-key.c
nettle/aes128-meta.c
nettle/aes192-set-encrypt-key.c
nettle/aes192-set-decrypt-key.c
nettle/aes192-meta.c
nettle/aes256-set-encrypt-key.c
nettle/aes256-set-decrypt-key.c
nettle/aes256-meta.c
nettle/nist-keywrap.c
nettle/arcfour.c
nettle/arcfour-crypt.c
nettle/arctwo.c
nettle/arctwo-meta.c
nettle/blowfish.c
nettle/blowfish-bcrypt.c
nettle/base16-encode.c
nettle/base16-decode.c
nettle/base16-meta.c
nettle/base64-encode.c
nettle/base64-decode.c
nettle/base64-meta.c
nettle/base64url-encode.c
nettle/base64url-decode.c
nettle/base64url-meta.c
nettle/buffer.c
nettle/buffer-init.c
nettle/camellia-crypt-internal.c
nettle/camellia-table.c
nettle/camellia-absorb.c
nettle/camellia-invert-key.c
nettle/camellia128-set-encrypt-key.c
nettle/camellia128-crypt.c
nettle/camellia128-set-decrypt-key.c
nettle/camellia128-meta.c
nettle/camellia192-meta.c
nettle/camellia256-set-encrypt-key.c
nettle/camellia256-crypt.c
nettle/camellia256-set-decrypt-key.c
nettle/camellia256-meta.c
nettle/cast128.c
nettle/cast128-meta.c
nettle/cbc.c
nettle/cbc-aes128-encrypt.c
nettle/cbc-aes192-encrypt.c
nettle/cbc-aes256-encrypt.c
nettle/ccm.c
nettle/ccm-aes128.c
nettle/ccm-aes192.c
nettle/ccm-aes256.c
nettle/cfb.c
nettle/siv-cmac.c
nettle/siv-cmac-aes128.c
nettle/siv-cmac-aes256.c
nettle/cnd-memcpy.c
nettle/chacha-crypt.c
nettle/chacha-core-internal.c
nettle/chacha-poly1305.c
nettle/chacha-poly1305-meta.c
nettle/chacha-set-key.c
nettle/chacha-set-nonce.c
nettle/ctr.c
nettle/ctr16.c
nettle/des.c
nettle/des3.c
nettle/eax.c
nettle/eax-aes128.c
nettle/eax-aes128-meta.c
nettle/ghash-set-key.c
nettle/ghash-update.c
nettle/gcm.c
nettle/gcm-aes.c
nettle/gcm-aes128.c
nettle/gcm-aes128-meta.c
nettle/gcm-aes192.c
nettle/gcm-aes192-meta.c
nettle/gcm-aes256.c
nettle/gcm-aes256-meta.c
nettle/gcm-camellia128.c
nettle/gcm-camellia128-meta.c
nettle/gcm-camellia256.c
nettle/gcm-camellia256-meta.c
nettle/cmac.c
nettle/cmac64.c
nettle/cmac-aes128.c
nettle/cmac-aes256.c
nettle/cmac-des3.c
nettle/cmac-aes128-meta.c
nettle/cmac-aes256-meta.c
nettle/cmac-des3-meta.c
nettle/gost28147.c
nettle/gosthash94.c
nettle/gosthash94-meta.c
nettle/hmac.c
nettle/hmac-gosthash94.c
nettle/hmac-md5.c
nettle/hmac-ripemd160.c
nettle/hmac-sha1.c
nettle/hmac-sha224.c
nettle/hmac-sha256.c
nettle/hmac-sha384.c
nettle/hmac-sha512.c
nettle/hmac-streebog.c
nettle/hmac-sm3.c
nettle/hmac-md5-meta.c
nettle/hmac-ripemd160-meta.c
nettle/hmac-sha1-meta.c
nettle/hmac-sha224-meta.c
nettle/hmac-sha256-meta.c
nettle/hmac-sha384-meta.c
nettle/hmac-sha512-meta.c
nettle/hmac-streebog-meta.c
nettle/hmac-sm3-meta.c
nettle/knuth-lfib.c
nettle/hkdf.c
nettle/md2.c
nettle/md2-meta.c
nettle/md4.c
nettle/md4-meta.c
nettle/md5.c
nettle/md5-compress.c
nettle/md5-compat.c
nettle/md5-meta.c
nettle/memeql-sec.c
nettle/memxor.c
nettle/memxor3.c
nettle/nettle-lookup-hash.c
nettle/nettle-meta-aeads.c
nettle/nettle-meta-armors.c
nettle/nettle-meta-ciphers.c
nettle/nettle-meta-hashes.c
nettle/nettle-meta-macs.c
nettle/pbkdf2.c
nettle/pbkdf2-hmac-gosthash94.c
nettle/pbkdf2-hmac-sha1.c
nettle/pbkdf2-hmac-sha256.c
nettle/pbkdf2-hmac-sha384.c
nettle/pbkdf2-hmac-sha512.c
nettle/poly1305-aes.c
nettle/poly1305-internal.c
nettle/realloc.c
nettle/ripemd160.c
nettle/ripemd160-compress.c
nettle/ripemd160-meta.c
nettle/salsa20-core-internal.c
nettle/salsa20-crypt-internal.c
nettle/salsa20-crypt.c
nettle/salsa20r12-crypt.c
nettle/salsa20-set-key.c
nettle/salsa20-set-nonce.c
nettle/salsa20-128-set-key.c
nettle/salsa20-256-set-key.c
nettle/sha1.c
nettle/sha1-compress.c
nettle/sha1-meta.c
nettle/sha256.c
nettle/sha256-compress.c
nettle/sha224-meta.c
nettle/sha256-meta.c
nettle/sha512.c
nettle/sha512-compress.c
nettle/sha384-meta.c
nettle/sha512-meta.c
nettle/sha512-224-meta.c
nettle/sha512-256-meta.c
nettle/sha3.c
nettle/sha3-permute.c
nettle/sha3-224.c
nettle/sha3-224-meta.c
nettle/sha3-256.c
nettle/sha3-256-meta.c
nettle/sha3-384.c
nettle/sha3-384-meta.c
nettle/sha3-512.c
nettle/sha3-512-meta.c
nettle/shake256.c
nettle/sm3.c
nettle/sm3-meta.c
nettle/serpent-set-key.c
nettle/serpent-encrypt.c
nettle/serpent-decrypt.c
nettle/serpent-meta.c
nettle/streebog.c
nettle/streebog-meta.c
nettle/twofish.c
nettle/twofish-meta.c
nettle/umac-nh.c
nettle/umac-nh-n.c
nettle/umac-l2.c
nettle/umac-l3.c
nettle/umac-poly64.c
nettle/umac-poly128.c
nettle/umac-set-key.c
nettle/umac32.c
nettle/umac64.c
nettle/umac96.c
nettle/umac128.c
nettle/version.c
nettle/write-be32.c
nettle/write-le32.c
nettle/write-le64.c
nettle/yarrow256.c
nettle/yarrow_key_event.c
nettle/xts.c
nettle/xts-aes128.c
nettle/xts-aes256.c
)
set(LIBNETTLE_INCLUDES
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/nettle
)
add_library(nettle STATIC ${LIBNETTLE_SOURCES})
target_include_directories(nettle PUBLIC ${LIBNETTLE_INCLUDES})
target_compile_definitions(nettle PRIVATE ${LIBNETTLE_DEFINITIONS})
+275
View File
@@ -0,0 +1,275 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Define to 1 if using 'alloca.c'. */
/* #undef C_ALLOCA */
/* Define to 1 if you have 'alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if <alloca.h> works. */
#define HAVE_ALLOCA_H 1
/* Define if __builtin_bswap64 is available */
#define HAVE_BUILTIN_BSWAP64 1
/* Define if clock_gettime is available */
#define HAVE_CLOCK_GETTIME 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define if fcntl file locking is available */
#define HAVE_FCNTL_LOCKING 1
/* Define if the compiler understands __attribute__ */
#define HAVE_GCC_ATTRIBUTE 1
/* Define to 1 if you have the `getline' function. */
#define HAVE_GETLINE 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have dlopen (with -ldl). */
#define HAVE_LIBDL 1
/* Define to 1 if you have the `gmp' library (-lgmp). */
/* #undef HAVE_LIBGMP */
/* Define if compiler and linker supports __attribute__ ifunc */
#define HAVE_LINK_IFUNC 1
/* Define to 1 if you have the <malloc.h> header file. */
#define HAVE_MALLOC_H 1
/* Define to 1 each of the following for which a native (ie. CPU specific)
implementation of the corresponding routine exists. */
/* #undef HAVE_NATIVE_memxor3 */
/* #undef HAVE_NATIVE_aes_decrypt */
/* #undef HAVE_NATIVE_aes_encrypt */
/* #undef HAVE_NATIVE_aes128_decrypt */
/* #undef HAVE_NATIVE_aes128_encrypt */
/* #undef HAVE_NATIVE_aes128_invert_key */
/* #undef HAVE_NATIVE_aes128_set_decrypt_key */
/* #undef HAVE_NATIVE_aes128_set_encrypt_key */
/* #undef HAVE_NATIVE_aes192_decrypt */
/* #undef HAVE_NATIVE_aes192_encrypt */
/* #undef HAVE_NATIVE_aes192_invert_key */
/* #undef HAVE_NATIVE_aes192_set_decrypt_key */
/* #undef HAVE_NATIVE_aes192_set_encrypt_key */
/* #undef HAVE_NATIVE_aes256_decrypt */
/* #undef HAVE_NATIVE_aes256_encrypt */
/* #undef HAVE_NATIVE_aes256_invert_key */
/* #undef HAVE_NATIVE_aes256_set_decrypt_key */
/* #undef HAVE_NATIVE_aes256_set_encrypt_key */
/* #undef HAVE_NATIVE_cbc_aes128_encrypt */
/* #undef HAVE_NATIVE_cbc_aes192_encrypt */
/* #undef HAVE_NATIVE_cbc_aes256_encrypt */
/* #undef HAVE_NATIVE_chacha_core */
/* #undef HAVE_NATIVE_chacha_2core */
/* #undef HAVE_NATIVE_chacha_3core */
/* #undef HAVE_NATIVE_chacha_4core */
/* #undef HAVE_NATIVE_fat_chacha_2core */
/* #undef HAVE_NATIVE_fat_chacha_3core */
/* #undef HAVE_NATIVE_fat_chacha_4core */
/* #undef HAVE_NATIVE_ecc_curve25519_modp */
/* #undef HAVE_NATIVE_ecc_curve448_modp */
/* #undef HAVE_NATIVE_ecc_secp192r1_modp */
/* #undef HAVE_NATIVE_ecc_secp192r1_redc */
/* #undef HAVE_NATIVE_ecc_secp224r1_modp */
/* #undef HAVE_NATIVE_ecc_secp224r1_redc */
/* #undef HAVE_NATIVE_ecc_secp256r1_modp */
/* #undef HAVE_NATIVE_ecc_secp256r1_redc */
/* #undef HAVE_NATIVE_ecc_secp384r1_modp */
/* #undef HAVE_NATIVE_ecc_secp384r1_redc */
/* #undef HAVE_NATIVE_ecc_secp521r1_modp */
/* #undef HAVE_NATIVE_ecc_secp521r1_redc */
/* #undef HAVE_NATIVE_ghash_set_key */
/* #undef HAVE_NATIVE_ghash_update */
/* #undef HAVE_NATIVE_salsa20_core */
/* #undef HAVE_NATIVE_salsa20_2core */
/* #undef HAVE_NATIVE_fat_salsa20_2core */
/* #undef HAVE_NATIVE_sha1_compress */
/* #undef HAVE_NATIVE_sha256_compress */
/* #undef HAVE_NATIVE_sha512_compress */
/* #undef HAVE_NATIVE_sha3_permute */
/* #undef HAVE_NATIVE_umac_nh */
/* #undef HAVE_NATIVE_umac_nh_n */
/* Define to 1 if you have the <openssl/ecdsa.h> header file. */
/* #undef HAVE_OPENSSL_ECDSA_H */
/* Define to 1 if you have the <openssl/evp.h> header file. */
/* #undef HAVE_OPENSSL_EVP_H */
/* Define to 1 if you have the `secure_getenv' function. */
/* #undef HAVE_SECURE_GETENV */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdio.h> header file. */
#define HAVE_STDIO_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the <valgrind/memcheck.h> header file. */
/* #undef HAVE_VALGRIND_MEMCHECK_H */
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "nettle-bugs@lists.lysator.liu.se"
/* Define to the full name of this package. */
#define PACKAGE_NAME "nettle"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "nettle 3.8"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "nettle"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "3.8"
/* The size of `long', as computed by sizeof. */
#define SIZEOF_LONG __SIZEOF_LONG__
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T __SIZEOF_SIZE_T__
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */
/* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#define STDC_HEADERS 1
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. This
macro is obsolete. */
#define TIME_WITH_SYS_TIME 1
/* Defined if public key features are enabled */
/* #undef WITH_HOGWEED */
/* Define if you have openssl's libcrypto (used for benchmarking) */
/* #undef WITH_OPENSSL */
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef gid_t */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef uid_t */
/* AIX requires this to be the first thing in the file. */
#ifndef __GNUC__
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
/* Needed for alloca on windows */
# if HAVE_MALLOC_H
# include <malloc.h>
# endif
# endif
#else /* defined __GNUC__ */
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
/* Needed for alloca on windows, also with gcc */
# if HAVE_MALLOC_H
# include <malloc.h>
# endif
# endif
#endif
#if HAVE_STRERROR
#define STRERROR strerror
#else
#define STRERROR(x) (sys_errlist[x])
#endif
#if __GNUC__ && HAVE_GCC_ATTRIBUTE
# define NORETURN __attribute__ ((__noreturn__))
# define PRINTF_STYLE(f, a) __attribute__ ((__format__ (__printf__, f, a)))
# define UNUSED __attribute__ ((__unused__))
#else
# define NORETURN
# define PRINTF_STYLE(f, a)
# define UNUSED
#endif
#if defined(__x86_64__) || defined(__arch64__)
# define HAVE_NATIVE_64_BIT 1
#else
/* Needs include of <limits.h> before use. */
# define HAVE_NATIVE_64_BIT (SIZEOF_LONG * CHAR_BIT >= 64)
#endif
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+64
View File
@@ -0,0 +1,64 @@
/* version.h
Information about library version.
Copyright (C) 2015 Red Hat, Inc.
Copyright (C) 2015 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#ifndef NETTLE_VERSION_H_INCLUDED
#define NETTLE_VERSION_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
/* Individual version numbers in decimal */
#define NETTLE_VERSION_MAJOR 3
#define NETTLE_VERSION_MINOR 8
#define NETTLE_USE_MINI_GMP 0
/* We need a preprocessor constant for GMP_NUMB_BITS, simply using
sizeof(mp_limb_t) * CHAR_BIT is not good enough. */
#if NETTLE_USE_MINI_GMP
# define GMP_NUMB_BITS n/a
#endif
int
nettle_version_major (void);
int
nettle_version_minor (void);
#ifdef __cplusplus
}
#endif
#endif /* NETTLE_VERSION_H_INCLUDED */