blob: b6b8fe840da721cbf0669122fea8a47322a12944 [file] [log] [blame]
reed@android.com6f598152010-01-21 15:34:19 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2010 The Android Open Source Project
reed@android.com6f598152010-01-21 15:34:19 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com6f598152010-01-21 15:34:19 +00006 */
7
epoger@google.comec3ed6a2011-07-28 14:26:00 +00008
scroggo27631bd2015-06-15 09:10:03 -07009#include "SkJpegUtility.h"
reed@android.com6f598152010-01-21 15:34:19 +000010
msarettc2d0bc52015-10-15 13:18:05 -070011#if defined(SK_BUILD_FOR_ANDROID) && !defined(SK_JPEG_NO_INDEX_SUPPORTED)
12#define SK_JPEG_INDEX_SUPPORTED
13#endif
14
reed@android.com6f598152010-01-21 15:34:19 +000015/////////////////////////////////////////////////////////////////////
16static void sk_init_source(j_decompress_ptr cinfo) {
17 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
18 src->next_input_byte = (const JOCTET*)src->fBuffer;
19 src->bytes_in_buffer = 0;
msarettc2d0bc52015-10-15 13:18:05 -070020#ifdef SK_JPEG_INDEX_SUPPORTED
djsollen@google.com11399402013-03-20 17:45:27 +000021 src->current_offset = 0;
22#endif
scroggo@google.com4d213ab2013-08-28 13:08:54 +000023 if (!src->fStream->rewind()) {
24 SkDebugf("xxxxxxxxxxxxxx failure to rewind\n");
25 cinfo->err->error_exit((j_common_ptr)cinfo);
26 }
djsollen@google.com57f49692011-02-23 20:46:31 +000027}
28
msarettc2d0bc52015-10-15 13:18:05 -070029#ifdef SK_JPEG_INDEX_SUPPORTED
djsollen@google.com11399402013-03-20 17:45:27 +000030static boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) {
31 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
scroggo@google.comd4c35652013-08-01 15:03:42 +000032 size_t bo = (size_t) byte_offset;
djsollen@google.com11399402013-03-20 17:45:27 +000033
scroggo@google.comd4c35652013-08-01 15:03:42 +000034 if (bo > src->current_offset) {
35 (void)src->fStream->skip(bo - src->current_offset);
djsollen@google.com11399402013-03-20 17:45:27 +000036 } else {
scroggo@google.com4d213ab2013-08-28 13:08:54 +000037 if (!src->fStream->rewind()) {
38 SkDebugf("xxxxxxxxxxxxxx failure to rewind\n");
39 cinfo->err->error_exit((j_common_ptr)cinfo);
40 return false;
41 }
scroggo@google.comd4c35652013-08-01 15:03:42 +000042 (void)src->fStream->skip(bo);
djsollen@google.com11399402013-03-20 17:45:27 +000043 }
44
scroggo@google.comd4c35652013-08-01 15:03:42 +000045 src->current_offset = bo;
djsollen@google.com11399402013-03-20 17:45:27 +000046 src->next_input_byte = (const JOCTET*)src->fBuffer;
47 src->bytes_in_buffer = 0;
48 return true;
49}
50#endif
51
reed@android.com6f598152010-01-21 15:34:19 +000052static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
53 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
halcanary96fcdcc2015-08-27 07:41:13 -070054 if (src->fDecoder != nullptr && src->fDecoder->shouldCancelDecode()) {
reed@android.com6f598152010-01-21 15:34:19 +000055 return FALSE;
56 }
57 size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize);
58 // note that JPEG is happy with less than the full read,
59 // as long as the result is non-zero
60 if (bytes == 0) {
61 return FALSE;
62 }
63
msarettc2d0bc52015-10-15 13:18:05 -070064#ifdef SK_JPEG_INDEX_SUPPORTED
djsollen@google.com11399402013-03-20 17:45:27 +000065 src->current_offset += bytes;
66#endif
reed@android.com6f598152010-01-21 15:34:19 +000067 src->next_input_byte = (const JOCTET*)src->fBuffer;
68 src->bytes_in_buffer = bytes;
69 return TRUE;
70}
71
72static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
reed@android.com6f598152010-01-21 15:34:19 +000073 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
74
reed@android.com3f1f06a2010-03-03 21:04:12 +000075 if (num_bytes > (long)src->bytes_in_buffer) {
robertphillips@google.com8b169312013-10-15 17:47:36 +000076 size_t bytesToSkip = num_bytes - src->bytes_in_buffer;
reed@android.comb8fd84b2010-01-21 18:04:44 +000077 while (bytesToSkip > 0) {
robertphillips@google.com8b169312013-10-15 17:47:36 +000078 size_t bytes = src->fStream->skip(bytesToSkip);
reed@android.comb8fd84b2010-01-21 18:04:44 +000079 if (bytes <= 0 || bytes > bytesToSkip) {
80// SkDebugf("xxxxxxxxxxxxxx failure to skip request %d returned %d\n", bytesToSkip, bytes);
81 cinfo->err->error_exit((j_common_ptr)cinfo);
82 return;
83 }
msarettc2d0bc52015-10-15 13:18:05 -070084#ifdef SK_JPEG_INDEX_SUPPORTED
djsollen@google.com11399402013-03-20 17:45:27 +000085 src->current_offset += bytes;
86#endif
reed@android.comb8fd84b2010-01-21 18:04:44 +000087 bytesToSkip -= bytes;
reed@android.com6f598152010-01-21 15:34:19 +000088 }
89 src->next_input_byte = (const JOCTET*)src->fBuffer;
90 src->bytes_in_buffer = 0;
91 } else {
92 src->next_input_byte += num_bytes;
93 src->bytes_in_buffer -= num_bytes;
94 }
95}
96
reed@android.com6f598152010-01-21 15:34:19 +000097static void sk_term_source(j_decompress_ptr /*cinfo*/) {}
98
99
reed@android.com6f598152010-01-21 15:34:19 +0000100///////////////////////////////////////////////////////////////////////////////
101
scroggo@google.comd4c35652013-08-01 15:03:42 +0000102skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder)
scroggoa1193e42015-01-21 12:09:53 -0800103 : fStream(stream)
scroggo@google.comd4c35652013-08-01 15:03:42 +0000104 , fDecoder(decoder) {
reed@android.com6f598152010-01-21 15:34:19 +0000105
djsollen@google.com57f49692011-02-23 20:46:31 +0000106 init_source = sk_init_source;
107 fill_input_buffer = sk_fill_input_buffer;
108 skip_input_data = sk_skip_input_data;
scroggo@google.coma9348992013-09-25 21:17:41 +0000109 resync_to_restart = jpeg_resync_to_restart;
djsollen@google.com57f49692011-02-23 20:46:31 +0000110 term_source = sk_term_source;
msarettc2d0bc52015-10-15 13:18:05 -0700111#ifdef SK_JPEG_INDEX_SUPPORTED
djsollen@google.com11399402013-03-20 17:45:27 +0000112 seek_input_data = sk_seek_input_data;
113#endif
reed@android.com6f598152010-01-21 15:34:19 +0000114// SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
115}
116
reed@android.com6f598152010-01-21 15:34:19 +0000117///////////////////////////////////////////////////////////////////////////////
118
119static void sk_init_destination(j_compress_ptr cinfo) {
120 skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
121
122 dest->next_output_byte = dest->fBuffer;
123 dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
124}
125
126static boolean sk_empty_output_buffer(j_compress_ptr cinfo) {
127 skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
128
129// if (!dest->fStream->write(dest->fBuffer, skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer))
130 if (!dest->fStream->write(dest->fBuffer,
131 skjpeg_destination_mgr::kBufferSize)) {
132 ERREXIT(cinfo, JERR_FILE_WRITE);
133 return false;
134 }
135
136 dest->next_output_byte = dest->fBuffer;
137 dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
138 return TRUE;
139}
140
141static void sk_term_destination (j_compress_ptr cinfo) {
142 skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
143
144 size_t size = skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer;
145 if (size > 0) {
146 if (!dest->fStream->write(dest->fBuffer, size)) {
147 ERREXIT(cinfo, JERR_FILE_WRITE);
148 return;
149 }
150 }
151 dest->fStream->flush();
152}
153
154skjpeg_destination_mgr::skjpeg_destination_mgr(SkWStream* stream)
155 : fStream(stream) {
156 this->init_destination = sk_init_destination;
157 this->empty_output_buffer = sk_empty_output_buffer;
158 this->term_destination = sk_term_destination;
159}
160
161void skjpeg_error_exit(j_common_ptr cinfo) {
162 skjpeg_error_mgr* error = (skjpeg_error_mgr*)cinfo->err;
163
164 (*error->output_message) (cinfo);
165
166 /* Let the memory manager delete any temp files before we die */
167 jpeg_destroy(cinfo);
168
169 longjmp(error->fJmpBuf, -1);
170}