• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 
9 #include "SkJpegUtility.h"
10 
11 /////////////////////////////////////////////////////////////////////
sk_init_source(j_decompress_ptr cinfo)12 static 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;
16 #ifdef SK_BUILD_FOR_ANDROID
17     src->current_offset = 0;
18 #endif
19     if (!src->fStream->rewind()) {
20         SkDebugf("xxxxxxxxxxxxxx failure to rewind\n");
21         cinfo->err->error_exit((j_common_ptr)cinfo);
22     }
23 }
24 
25 #ifdef SK_BUILD_FOR_ANDROID
sk_seek_input_data(j_decompress_ptr cinfo,long byte_offset)26 static boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) {
27     skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
28     size_t bo = (size_t) byte_offset;
29 
30     if (bo > src->current_offset) {
31         (void)src->fStream->skip(bo - src->current_offset);
32     } else {
33         if (!src->fStream->rewind()) {
34             SkDebugf("xxxxxxxxxxxxxx failure to rewind\n");
35             cinfo->err->error_exit((j_common_ptr)cinfo);
36             return false;
37         }
38         (void)src->fStream->skip(bo);
39     }
40 
41     src->current_offset = bo;
42     src->next_input_byte = (const JOCTET*)src->fBuffer;
43     src->bytes_in_buffer = 0;
44     return true;
45 }
46 #endif
47 
sk_fill_input_buffer(j_decompress_ptr cinfo)48 static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
49     skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
50     if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) {
51         return FALSE;
52     }
53     size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize);
54     // note that JPEG is happy with less than the full read,
55     // as long as the result is non-zero
56     if (bytes == 0) {
57         return FALSE;
58     }
59 
60 #ifdef SK_BUILD_FOR_ANDROID
61     src->current_offset += bytes;
62 #endif
63     src->next_input_byte = (const JOCTET*)src->fBuffer;
64     src->bytes_in_buffer = bytes;
65     return TRUE;
66 }
67 
sk_skip_input_data(j_decompress_ptr cinfo,long num_bytes)68 static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
69     skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
70 
71     if (num_bytes > (long)src->bytes_in_buffer) {
72         size_t bytesToSkip = num_bytes - src->bytes_in_buffer;
73         while (bytesToSkip > 0) {
74             size_t bytes = src->fStream->skip(bytesToSkip);
75             if (bytes <= 0 || bytes > bytesToSkip) {
76 //              SkDebugf("xxxxxxxxxxxxxx failure to skip request %d returned %d\n", bytesToSkip, bytes);
77                 cinfo->err->error_exit((j_common_ptr)cinfo);
78                 return;
79             }
80 #ifdef SK_BUILD_FOR_ANDROID
81             src->current_offset += bytes;
82 #endif
83             bytesToSkip -= bytes;
84         }
85         src->next_input_byte = (const JOCTET*)src->fBuffer;
86         src->bytes_in_buffer = 0;
87     } else {
88         src->next_input_byte += num_bytes;
89         src->bytes_in_buffer -= num_bytes;
90     }
91 }
92 
sk_term_source(j_decompress_ptr)93 static void sk_term_source(j_decompress_ptr /*cinfo*/) {}
94 
95 
96 ///////////////////////////////////////////////////////////////////////////////
97 
skjpeg_source_mgr(SkStream * stream,SkImageDecoder * decoder)98 skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder)
99     : fStream(SkRef(stream))
100     , fDecoder(decoder) {
101 
102     init_source = sk_init_source;
103     fill_input_buffer = sk_fill_input_buffer;
104     skip_input_data = sk_skip_input_data;
105     resync_to_restart = jpeg_resync_to_restart;
106     term_source = sk_term_source;
107 #ifdef SK_BUILD_FOR_ANDROID
108     seek_input_data = sk_seek_input_data;
109 #endif
110 //    SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
111 }
112 
~skjpeg_source_mgr()113 skjpeg_source_mgr::~skjpeg_source_mgr() {
114     SkSafeUnref(fStream);
115 }
116 
117 ///////////////////////////////////////////////////////////////////////////////
118 
sk_init_destination(j_compress_ptr cinfo)119 static 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 
sk_empty_output_buffer(j_compress_ptr cinfo)126 static 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 
sk_term_destination(j_compress_ptr cinfo)141 static 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 
skjpeg_destination_mgr(SkWStream * stream)154 skjpeg_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 
skjpeg_error_exit(j_common_ptr cinfo)161 void 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 }
171