blob: 8d8f62f5a243f57438a7be44456e32f15a42deb9 [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
reed@android.com6f598152010-01-21 15:34:19 +00009#include "SkJpegUtility.h"
10
11/////////////////////////////////////////////////////////////////////
12static void sk_init_source(j_decompress_ptr cinfo) {
13 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
14 src->next_input_byte = (const JOCTET*)src->fBuffer;
15 src->bytes_in_buffer = 0;
scroggo@google.comd79277f2013-08-07 19:53:53 +000016#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.com11399402013-03-20 17:45:27 +000017 src->current_offset = 0;
18#endif
djsollen@google.com57f49692011-02-23 20:46:31 +000019 src->fStream->rewind();
20}
21
scroggo@google.comd79277f2013-08-07 19:53:53 +000022#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.com11399402013-03-20 17:45:27 +000023static boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) {
24 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
scroggo@google.comd4c35652013-08-01 15:03:42 +000025 size_t bo = (size_t) byte_offset;
djsollen@google.com11399402013-03-20 17:45:27 +000026
scroggo@google.comd4c35652013-08-01 15:03:42 +000027 if (bo > src->current_offset) {
28 (void)src->fStream->skip(bo - src->current_offset);
djsollen@google.com11399402013-03-20 17:45:27 +000029 } else {
30 src->fStream->rewind();
scroggo@google.comd4c35652013-08-01 15:03:42 +000031 (void)src->fStream->skip(bo);
djsollen@google.com11399402013-03-20 17:45:27 +000032 }
33
scroggo@google.comd4c35652013-08-01 15:03:42 +000034 src->current_offset = bo;
djsollen@google.com11399402013-03-20 17:45:27 +000035 src->next_input_byte = (const JOCTET*)src->fBuffer;
36 src->bytes_in_buffer = 0;
37 return true;
38}
39#endif
40
reed@android.com6f598152010-01-21 15:34:19 +000041static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
42 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
43 if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) {
44 return FALSE;
45 }
46 size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize);
47 // note that JPEG is happy with less than the full read,
48 // as long as the result is non-zero
49 if (bytes == 0) {
50 return FALSE;
51 }
52
scroggo@google.comd79277f2013-08-07 19:53:53 +000053#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.com11399402013-03-20 17:45:27 +000054 src->current_offset += bytes;
55#endif
reed@android.com6f598152010-01-21 15:34:19 +000056 src->next_input_byte = (const JOCTET*)src->fBuffer;
57 src->bytes_in_buffer = bytes;
58 return TRUE;
59}
60
61static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
reed@android.com6f598152010-01-21 15:34:19 +000062 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
63
reed@android.com3f1f06a2010-03-03 21:04:12 +000064 if (num_bytes > (long)src->bytes_in_buffer) {
reed@android.comb8fd84b2010-01-21 18:04:44 +000065 long bytesToSkip = num_bytes - src->bytes_in_buffer;
66 while (bytesToSkip > 0) {
67 long bytes = (long)src->fStream->skip(bytesToSkip);
68 if (bytes <= 0 || bytes > bytesToSkip) {
69// SkDebugf("xxxxxxxxxxxxxx failure to skip request %d returned %d\n", bytesToSkip, bytes);
70 cinfo->err->error_exit((j_common_ptr)cinfo);
71 return;
72 }
scroggo@google.comd79277f2013-08-07 19:53:53 +000073#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.com11399402013-03-20 17:45:27 +000074 src->current_offset += bytes;
75#endif
reed@android.comb8fd84b2010-01-21 18:04:44 +000076 bytesToSkip -= bytes;
reed@android.com6f598152010-01-21 15:34:19 +000077 }
78 src->next_input_byte = (const JOCTET*)src->fBuffer;
79 src->bytes_in_buffer = 0;
80 } else {
81 src->next_input_byte += num_bytes;
82 src->bytes_in_buffer -= num_bytes;
83 }
84}
85
86static boolean sk_resync_to_restart(j_decompress_ptr cinfo, int desired) {
87 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
88
89 // what is the desired param for???
90
91 if (!src->fStream->rewind()) {
92 SkDebugf("xxxxxxxxxxxxxx failure to rewind\n");
93 cinfo->err->error_exit((j_common_ptr)cinfo);
94 return FALSE;
95 }
96 src->next_input_byte = (const JOCTET*)src->fBuffer;
97 src->bytes_in_buffer = 0;
98 return TRUE;
99}
100
101static void sk_term_source(j_decompress_ptr /*cinfo*/) {}
102
103
reed@android.com6f598152010-01-21 15:34:19 +0000104///////////////////////////////////////////////////////////////////////////////
105
scroggo@google.comd4c35652013-08-01 15:03:42 +0000106skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder)
107 : fStream(SkRef(stream))
108 , fDecoder(decoder) {
reed@android.com6f598152010-01-21 15:34:19 +0000109
djsollen@google.com57f49692011-02-23 20:46:31 +0000110 init_source = sk_init_source;
111 fill_input_buffer = sk_fill_input_buffer;
112 skip_input_data = sk_skip_input_data;
113 resync_to_restart = sk_resync_to_restart;
114 term_source = sk_term_source;
scroggo@google.comd79277f2013-08-07 19:53:53 +0000115#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.com11399402013-03-20 17:45:27 +0000116 seek_input_data = sk_seek_input_data;
117#endif
reed@android.com6f598152010-01-21 15:34:19 +0000118// SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
119}
120
djsollen@google.com57f49692011-02-23 20:46:31 +0000121skjpeg_source_mgr::~skjpeg_source_mgr() {
scroggo@google.comd4c35652013-08-01 15:03:42 +0000122 SkSafeUnref(fStream);
djsollen@google.com57f49692011-02-23 20:46:31 +0000123}
124
reed@android.com6f598152010-01-21 15:34:19 +0000125///////////////////////////////////////////////////////////////////////////////
126
127static void sk_init_destination(j_compress_ptr cinfo) {
128 skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
129
130 dest->next_output_byte = dest->fBuffer;
131 dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
132}
133
134static boolean sk_empty_output_buffer(j_compress_ptr cinfo) {
135 skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
136
137// if (!dest->fStream->write(dest->fBuffer, skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer))
138 if (!dest->fStream->write(dest->fBuffer,
139 skjpeg_destination_mgr::kBufferSize)) {
140 ERREXIT(cinfo, JERR_FILE_WRITE);
141 return false;
142 }
143
144 dest->next_output_byte = dest->fBuffer;
145 dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
146 return TRUE;
147}
148
149static void sk_term_destination (j_compress_ptr cinfo) {
150 skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
151
152 size_t size = skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer;
153 if (size > 0) {
154 if (!dest->fStream->write(dest->fBuffer, size)) {
155 ERREXIT(cinfo, JERR_FILE_WRITE);
156 return;
157 }
158 }
159 dest->fStream->flush();
160}
161
162skjpeg_destination_mgr::skjpeg_destination_mgr(SkWStream* stream)
163 : fStream(stream) {
164 this->init_destination = sk_init_destination;
165 this->empty_output_buffer = sk_empty_output_buffer;
166 this->term_destination = sk_term_destination;
167}
168
169void skjpeg_error_exit(j_common_ptr cinfo) {
170 skjpeg_error_mgr* error = (skjpeg_error_mgr*)cinfo->err;
171
172 (*error->output_message) (cinfo);
173
174 /* Let the memory manager delete any temp files before we die */
175 jpeg_destroy(cinfo);
176
177 longjmp(error->fJmpBuf, -1);
178}