blob: a2fe9a8c758229bef3728fd5c25fab18b3c3a174 [file] [log] [blame]
reed@android.com6f598152010-01-21 15:34:19 +00001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "SkJpegUtility.h"
18
19/////////////////////////////////////////////////////////////////////
20static void sk_init_source(j_decompress_ptr cinfo) {
21 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
22 src->next_input_byte = (const JOCTET*)src->fBuffer;
23 src->bytes_in_buffer = 0;
djsollen@google.com57f49692011-02-23 20:46:31 +000024 src->current_offset = 0;
25 src->fStream->rewind();
26}
27
28static boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) {
29 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
30
31 if (byte_offset > src->current_offset) {
32 (void)src->fStream->skip(byte_offset - src->current_offset);
33 } else {
34 src->fStream->rewind();
35 (void)src->fStream->skip(byte_offset);
36 }
37
38 src->current_offset = byte_offset;
39 src->next_input_byte = (const JOCTET*)src->fBuffer;
40 src->bytes_in_buffer = 0;
41 return TRUE;
reed@android.com6f598152010-01-21 15:34:19 +000042}
43
44static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
45 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
46 if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) {
47 return FALSE;
48 }
49 size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize);
50 // note that JPEG is happy with less than the full read,
51 // as long as the result is non-zero
52 if (bytes == 0) {
53 return FALSE;
54 }
55
djsollen@google.com57f49692011-02-23 20:46:31 +000056 src->current_offset += bytes;
reed@android.com6f598152010-01-21 15:34:19 +000057 src->next_input_byte = (const JOCTET*)src->fBuffer;
58 src->bytes_in_buffer = bytes;
59 return TRUE;
60}
61
62static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
reed@android.com6f598152010-01-21 15:34:19 +000063 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
64
reed@android.com3f1f06a2010-03-03 21:04:12 +000065 if (num_bytes > (long)src->bytes_in_buffer) {
reed@android.comb8fd84b2010-01-21 18:04:44 +000066 long bytesToSkip = num_bytes - src->bytes_in_buffer;
67 while (bytesToSkip > 0) {
68 long bytes = (long)src->fStream->skip(bytesToSkip);
69 if (bytes <= 0 || bytes > bytesToSkip) {
70// SkDebugf("xxxxxxxxxxxxxx failure to skip request %d returned %d\n", bytesToSkip, bytes);
71 cinfo->err->error_exit((j_common_ptr)cinfo);
72 return;
73 }
djsollen@google.com57f49692011-02-23 20:46:31 +000074 src->current_offset += bytes;
reed@android.comb8fd84b2010-01-21 18:04:44 +000075 bytesToSkip -= bytes;
reed@android.com6f598152010-01-21 15:34:19 +000076 }
77 src->next_input_byte = (const JOCTET*)src->fBuffer;
78 src->bytes_in_buffer = 0;
79 } else {
80 src->next_input_byte += num_bytes;
81 src->bytes_in_buffer -= num_bytes;
82 }
83}
84
85static boolean sk_resync_to_restart(j_decompress_ptr cinfo, int desired) {
86 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
87
88 // what is the desired param for???
89
90 if (!src->fStream->rewind()) {
91 SkDebugf("xxxxxxxxxxxxxx failure to rewind\n");
92 cinfo->err->error_exit((j_common_ptr)cinfo);
93 return FALSE;
94 }
95 src->next_input_byte = (const JOCTET*)src->fBuffer;
96 src->bytes_in_buffer = 0;
97 return TRUE;
98}
99
100static void sk_term_source(j_decompress_ptr /*cinfo*/) {}
101
102
103static void skmem_init_source(j_decompress_ptr cinfo) {
104 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
105 src->next_input_byte = (const JOCTET*)src->fMemoryBase;
djsollen@google.com57f49692011-02-23 20:46:31 +0000106 src->start_input_byte = (const JOCTET*)src->fMemoryBase;
reed@android.com6f598152010-01-21 15:34:19 +0000107 src->bytes_in_buffer = src->fMemoryBaseSize;
djsollen@google.com57f49692011-02-23 20:46:31 +0000108 src->current_offset = src->fMemoryBaseSize;
reed@android.com6f598152010-01-21 15:34:19 +0000109}
110
111static boolean skmem_fill_input_buffer(j_decompress_ptr cinfo) {
112 SkDebugf("xxxxxxxxxxxxxx skmem_fill_input_buffer called\n");
113 return FALSE;
114}
115
116static void skmem_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
117 skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
118// SkDebugf("xxxxxxxxxxxxxx skmem_skip_input_data called %d\n", num_bytes);
119 src->next_input_byte = (const JOCTET*)((const char*)src->next_input_byte + num_bytes);
120 src->bytes_in_buffer -= num_bytes;
121}
122
123static boolean skmem_resync_to_restart(j_decompress_ptr cinfo, int desired) {
124 SkDebugf("xxxxxxxxxxxxxx skmem_resync_to_restart called\n");
125 return TRUE;
126}
127
128static void skmem_term_source(j_decompress_ptr /*cinfo*/) {}
129
130
131///////////////////////////////////////////////////////////////////////////////
132
djsollen@google.com57f49692011-02-23 20:46:31 +0000133skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder,
134 bool ownStream) : fStream(stream) {
reed@android.com6f598152010-01-21 15:34:19 +0000135 fDecoder = decoder;
136 const void* baseAddr = stream->getMemoryBase();
djsollen@google.com57f49692011-02-23 20:46:31 +0000137 size_t bufferSize = 4096;
138 size_t len;
139 fMemoryBase = NULL;
140 fUnrefStream = ownStream;
141 fMemoryBaseSize = 0;
reed@android.com6f598152010-01-21 15:34:19 +0000142
djsollen@google.com57f49692011-02-23 20:46:31 +0000143 init_source = sk_init_source;
144 fill_input_buffer = sk_fill_input_buffer;
145 skip_input_data = sk_skip_input_data;
146 resync_to_restart = sk_resync_to_restart;
147 term_source = sk_term_source;
148 seek_input_data = sk_seek_input_data;
reed@android.com6f598152010-01-21 15:34:19 +0000149// SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
150}
151
djsollen@google.com57f49692011-02-23 20:46:31 +0000152skjpeg_source_mgr::~skjpeg_source_mgr() {
153 if (fMemoryBase) {
154 sk_free(fMemoryBase);
155 }
156 if (fUnrefStream) {
157 fStream->unref();
158 }
159}
160
reed@android.com6f598152010-01-21 15:34:19 +0000161///////////////////////////////////////////////////////////////////////////////
162
163static void sk_init_destination(j_compress_ptr cinfo) {
164 skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
165
166 dest->next_output_byte = dest->fBuffer;
167 dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
168}
169
170static boolean sk_empty_output_buffer(j_compress_ptr cinfo) {
171 skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
172
173// if (!dest->fStream->write(dest->fBuffer, skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer))
174 if (!dest->fStream->write(dest->fBuffer,
175 skjpeg_destination_mgr::kBufferSize)) {
176 ERREXIT(cinfo, JERR_FILE_WRITE);
177 return false;
178 }
179
180 dest->next_output_byte = dest->fBuffer;
181 dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
182 return TRUE;
183}
184
185static void sk_term_destination (j_compress_ptr cinfo) {
186 skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
187
188 size_t size = skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer;
189 if (size > 0) {
190 if (!dest->fStream->write(dest->fBuffer, size)) {
191 ERREXIT(cinfo, JERR_FILE_WRITE);
192 return;
193 }
194 }
195 dest->fStream->flush();
196}
197
198skjpeg_destination_mgr::skjpeg_destination_mgr(SkWStream* stream)
199 : fStream(stream) {
200 this->init_destination = sk_init_destination;
201 this->empty_output_buffer = sk_empty_output_buffer;
202 this->term_destination = sk_term_destination;
203}
204
205void skjpeg_error_exit(j_common_ptr cinfo) {
206 skjpeg_error_mgr* error = (skjpeg_error_mgr*)cinfo->err;
207
208 (*error->output_message) (cinfo);
209
210 /* Let the memory manager delete any temp files before we die */
211 jpeg_destroy(cinfo);
212
213 longjmp(error->fJmpBuf, -1);
214}