summaryrefslogtreecommitdiffstats
path: root/jni_jpegstream/src/jpeg_hook.cpp
diff options
context:
space:
mode:
authorRuben Brunk <rubenbrunk@google.com>2013-06-28 20:02:54 -0700
committerRuben Brunk <rubenbrunk@google.com>2013-07-11 13:41:29 -0700
commita8221bbdb8ece9b02dbf7b72565f9fbc5b314f7c (patch)
tree0fd84567e4f8a8d2bff0e7dcd696c88d518251cb /jni_jpegstream/src/jpeg_hook.cpp
parent0c1b4c6422a4d2d9b81cc0946d1c9675440a94e2 (diff)
downloadandroid_packages_apps_Gallery2-a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7c.tar.gz
android_packages_apps_Gallery2-a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7c.tar.bz2
android_packages_apps_Gallery2-a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7c.zip
Added jpeg streaming classes.
- Provides streaming operations for decompressing/compressing JPEG files. - Allows pixel operations to be performed on large JPEG images without holding the entire bitmap in memory. Change-Id: I597ddf282b59d2ba6d6bca4722208121e3728f94
Diffstat (limited to 'jni_jpegstream/src/jpeg_hook.cpp')
-rw-r--r--jni_jpegstream/src/jpeg_hook.cpp198
1 files changed, 198 insertions, 0 deletions
diff --git a/jni_jpegstream/src/jpeg_hook.cpp b/jni_jpegstream/src/jpeg_hook.cpp
new file mode 100644
index 000000000..cca54e405
--- /dev/null
+++ b/jni_jpegstream/src/jpeg_hook.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 "error_codes.h"
+#include "jni_defines.h"
+#include "jpeg_hook.h"
+
+#include <stddef.h>
+#include <string.h>
+
+void Mgr_init_destination_fcn(j_compress_ptr cinfo) {
+ DestManager *dst = reinterpret_cast<DestManager*>(cinfo->dest);
+ dst->mgr.next_output_byte = reinterpret_cast<JOCTET*>(dst->outStream->getBufferPtr());
+ dst->mgr.free_in_buffer = dst->outStream->getBufferSize();
+}
+
+boolean Mgr_empty_output_buffer_fcn(j_compress_ptr cinfo) {
+ DestManager *dst = reinterpret_cast<DestManager*>(cinfo->dest);
+ int32_t len = dst->outStream->getBufferSize();
+ if (dst->outStream->write(len, 0) != J_SUCCESS) {
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ }
+ dst->mgr.next_output_byte = reinterpret_cast<JOCTET*>(dst->outStream->getBufferPtr());
+ dst->mgr.free_in_buffer = len;
+ return TRUE;
+}
+
+void Mgr_term_destination_fcn(j_compress_ptr cinfo) {
+ DestManager *dst = reinterpret_cast<DestManager*>(cinfo->dest);
+ int32_t remaining = dst->outStream->getBufferSize() - dst->mgr.free_in_buffer;
+ if (dst->outStream->write(remaining, 0) != J_SUCCESS) {
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ }
+}
+
+int32_t MakeDst(j_compress_ptr cinfo, JNIEnv *env, jobject outStream) {
+ if (cinfo->dest != NULL) {
+ LOGE("DestManager already exists, cannot allocate!");
+ return J_ERROR_FATAL;
+ } else {
+ size_t size = sizeof(DestManager);
+ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_PERMANENT, size);
+ if (cinfo->dest == NULL) {
+ LOGE("Could not allocate memory for DestManager.");
+ return J_ERROR_FATAL;
+ }
+ memset(cinfo->dest, '0', size);
+ }
+ DestManager *d = reinterpret_cast<DestManager*>(cinfo->dest);
+ d->mgr.init_destination = Mgr_init_destination_fcn;
+ d->mgr.empty_output_buffer = Mgr_empty_output_buffer_fcn;
+ d->mgr.term_destination = Mgr_term_destination_fcn;
+ d->outStream = new OutputStreamWrapper();
+ if(d->outStream->init(env, outStream)) {
+ return J_SUCCESS;
+ }
+ return J_ERROR_FATAL;
+}
+
+void UpdateDstEnv(j_compress_ptr cinfo, JNIEnv* env) {
+ DestManager* d = reinterpret_cast<DestManager*>(cinfo->dest);
+ d->outStream->updateEnv(env);
+}
+
+void CleanDst(j_compress_ptr cinfo) {
+ if (cinfo != NULL && cinfo->dest != NULL) {
+ DestManager *d = reinterpret_cast<DestManager*>(cinfo->dest);
+ if (d->outStream != NULL) {
+ delete d->outStream;
+ d->outStream = NULL;
+ }
+ }
+}
+
+boolean Mgr_fill_input_buffer_fcn(j_decompress_ptr cinfo) {
+ SourceManager *src = reinterpret_cast<SourceManager*>(cinfo->src);
+ int32_t bytesRead = src->inStream->read(src->inStream->getBufferSize(), 0);
+ if (bytesRead == J_DONE) {
+ if (src->start_of_file == TRUE) {
+ ERREXIT(cinfo, JERR_INPUT_EMPTY);
+ }
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+ bytesRead = src->inStream->forceReadEOI();
+ } else if (bytesRead < 0) {
+ ERREXIT(cinfo, JERR_FILE_READ);
+ } else if (bytesRead == 0) {
+ LOGW("read 0 bytes from InputStream.");
+ }
+ src->mgr.next_input_byte = reinterpret_cast<JOCTET*>(src->inStream->getBufferPtr());
+ src->mgr.bytes_in_buffer = bytesRead;
+ if (bytesRead != 0) {
+ src->start_of_file = FALSE;
+ }
+ return TRUE;
+}
+
+void Mgr_init_source_fcn(j_decompress_ptr cinfo) {
+ SourceManager *s = reinterpret_cast<SourceManager*>(cinfo->src);
+ s->start_of_file = TRUE;
+ Mgr_fill_input_buffer_fcn(cinfo);
+}
+
+void Mgr_skip_input_data_fcn(j_decompress_ptr cinfo, long num_bytes) {
+ // Cannot skip negative or 0 bytes.
+ if (num_bytes <= 0) {
+ LOGW("skipping 0 bytes in InputStream");
+ return;
+ }
+ SourceManager *src = reinterpret_cast<SourceManager*>(cinfo->src);
+ if (src->mgr.bytes_in_buffer >= num_bytes) {
+ src->mgr.bytes_in_buffer -= num_bytes;
+ src->mgr.next_input_byte += num_bytes;
+ } else {
+ // if skipping more bytes than remain in buffer, set skip_bytes
+ int64_t skip = num_bytes - src->mgr.bytes_in_buffer;
+ src->mgr.next_input_byte += src->mgr.bytes_in_buffer;
+ src->mgr.bytes_in_buffer = 0;
+ int64_t actual = src->inStream->skip(skip);
+ if (actual < 0) {
+ ERREXIT(cinfo, JERR_FILE_READ);
+ }
+ skip -= actual;
+ while (skip > 0) {
+ actual = src->inStream->skip(skip);
+ if (actual < 0) {
+ ERREXIT(cinfo, JERR_FILE_READ);
+ }
+ skip -= actual;
+ if (actual == 0) {
+ // Multiple zero byte skips, likely EOF
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+ return;
+ }
+ }
+ }
+}
+
+void Mgr_term_source_fcn(j_decompress_ptr cinfo) {
+ //noop
+}
+
+int32_t MakeSrc(j_decompress_ptr cinfo, JNIEnv *env, jobject inStream){
+ if (cinfo->src != NULL) {
+ LOGE("SourceManager already exists, cannot allocate!");
+ return J_ERROR_FATAL;
+ } else {
+ size_t size = sizeof(SourceManager);
+ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_PERMANENT, size);
+ if (cinfo->src == NULL) {
+ // Could not allocate memory.
+ LOGE("Could not allocate memory for SourceManager.");
+ return J_ERROR_FATAL;
+ }
+ memset(cinfo->src, '0', size);
+ }
+ SourceManager *s = reinterpret_cast<SourceManager*>(cinfo->src);
+ s->start_of_file = TRUE;
+ s->mgr.init_source = Mgr_init_source_fcn;
+ s->mgr.fill_input_buffer = Mgr_fill_input_buffer_fcn;
+ s->mgr.skip_input_data = Mgr_skip_input_data_fcn;
+ s->mgr.resync_to_restart = jpeg_resync_to_restart; // use default restart
+ s->mgr.term_source = Mgr_term_source_fcn;
+ s->inStream = new InputStreamWrapper();
+ if(s->inStream->init(env, inStream)) {
+ return J_SUCCESS;
+ }
+ return J_ERROR_FATAL;
+}
+
+void UpdateSrcEnv(j_decompress_ptr cinfo, JNIEnv* env) {
+ SourceManager* s = reinterpret_cast<SourceManager*>(cinfo->src);
+ s->inStream->updateEnv(env);
+}
+
+void CleanSrc(j_decompress_ptr cinfo) {
+ if (cinfo != NULL && cinfo->src != NULL) {
+ SourceManager *s = reinterpret_cast<SourceManager*>(cinfo->src);
+ if (s->inStream != NULL) {
+ delete s->inStream;
+ s->inStream = NULL;
+ }
+ }
+}