• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "jpeg_utils.h"
17 #include "securec.h"
18 
19 namespace OHOS {
20 namespace ImagePlugin {
21 using namespace OHOS::HiviewDFX;
22 
23 static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "JpegUtils" };
24 
25 // these functions are called by libjpeg-turbo third_party library, no need check input parameter.
26 // for error manager
ErrorExit(j_common_ptr dinfo)27 void ErrorExit(j_common_ptr dinfo)
28 {
29     if ((dinfo == nullptr) || (dinfo->err == nullptr)) {
30         return;
31     }
32     // dinfo->err really points to a ErrorMgr struct, so coerce pointer.
33     ErrorMgr *err = static_cast<ErrorMgr *>(dinfo->err);
34     (*dinfo->err->output_message)(dinfo);
35     // return control to the setjmp point.
36     longjmp(err->setjmp_buffer, SET_JUMP_VALUE);
37 }
38 
OutputErrorMessage(j_common_ptr dinfo)39 void OutputErrorMessage(j_common_ptr dinfo)
40 {
41     if ((dinfo == nullptr) || (dinfo->err == nullptr)) {
42         return;
43     }
44     char buffer[JMSG_LENGTH_MAX] = { 0 };
45     dinfo->err->format_message(dinfo, buffer);
46     HiLog::Error(LABEL, "libjpeg error %{public}d <%{public}s>.", dinfo->err->msg_code, buffer);
47 }
48 
49 // for source manager
50 // this is called by jpeg_read_header() before any data is actually read.
InitSrcStream(j_decompress_ptr dinfo)51 void InitSrcStream(j_decompress_ptr dinfo)
52 {
53     if ((dinfo == nullptr) || (dinfo->src == nullptr)) {
54         HiLog::Error(LABEL, "init source stream error.");
55         return;
56     }
57     JpegSrcMgr *src = static_cast<JpegSrcMgr *>(dinfo->src);
58     src->next_input_byte = src->streamData.inputStreamBuffer;
59     src->bytes_in_buffer = 0;
60 }
61 
62 // this is called whenever bytes_in_buffer has reached zero and more data is wanted.
FillInputBuffer(j_decompress_ptr dinfo)63 boolean FillInputBuffer(j_decompress_ptr dinfo)
64 {
65     if (dinfo == nullptr) {
66         HiLog::Error(LABEL, "fill input buffer error, decompress struct is null.");
67         return FALSE;
68     }
69     JpegSrcMgr *src = static_cast<JpegSrcMgr *>(dinfo->src);
70     if ((src == nullptr) || (src->inputStream == nullptr)) {
71         HiLog::Error(LABEL, "fill input buffer error, source stream is null.");
72         ERREXIT(dinfo, JERR_FILE_READ);
73         return FALSE;
74     }
75 
76     uint32_t preReadPos = src->inputStream->Tell();
77     if (!src->inputStream->IsStreamCompleted() && !src->inputStream->Seek(preReadPos + JPEG_BUFFER_SIZE)) {
78         return FALSE;
79     }
80     src->inputStream->Seek(preReadPos);
81     if (!src->inputStream->Read(src->bufferSize, src->streamData)) {
82         HiLog::Error(LABEL, "fill input buffer error, read source stream failed.");
83         return FALSE;
84     }
85     if (!src->inputStream->IsStreamCompleted() && src->streamData.dataSize < JPEG_BUFFER_SIZE) {
86         uint32_t curr = src->inputStream->Tell();
87         src->inputStream->Seek(curr - src->streamData.dataSize);
88         HiLog::Debug(LABEL, "fill input buffer seekTo=%{public}u, rewindSize=%{public}u.",
89                      curr - src->streamData.dataSize, src->streamData.dataSize);
90         return FALSE;
91     }
92     src->next_input_byte = src->streamData.inputStreamBuffer;
93     src->bytes_in_buffer = src->streamData.dataSize;
94     return TRUE;
95 }
96 
97 // skip num_bytes worth of data.
SkipInputData(j_decompress_ptr dinfo,long numBytes)98 void SkipInputData(j_decompress_ptr dinfo, long numBytes)
99 {
100     if (dinfo == nullptr) {
101         HiLog::Error(LABEL, "skip input buffer error, decompress struct is null.");
102         return;
103     }
104     JpegSrcMgr *src = static_cast<JpegSrcMgr *>(dinfo->src);
105     if ((src == nullptr) || (src->inputStream == nullptr)) {
106         HiLog::Error(LABEL, "skip input buffer error, source stream is null.");
107         ERREXIT(dinfo, JERR_FILE_READ);
108         return;
109     }
110     size_t bytes = static_cast<size_t>(numBytes);
111     if (bytes > src->bytes_in_buffer) {
112         size_t bytesToSkip = bytes - src->bytes_in_buffer;
113         uint32_t nowOffset = src->inputStream->Tell();
114         if (bytesToSkip > src->inputStream->GetStreamSize() - nowOffset) {
115             HiLog::Error(LABEL, "skip data:%{public}zu larger than current offset:%{public}u.", bytesToSkip, nowOffset);
116             return;
117         }
118         if (!src->inputStream->Seek(nowOffset + bytesToSkip)) {
119             HiLog::Error(LABEL, "skip data:%{public}zu fail, current offset:%{public}u.", bytesToSkip, nowOffset);
120             ERREXIT(dinfo, JERR_FILE_READ);
121             return;
122         }
123         src->next_input_byte = src->streamData.inputStreamBuffer;
124         src->bytes_in_buffer = 0;
125     } else {
126         src->next_input_byte += numBytes;
127         src->bytes_in_buffer -= numBytes;
128     }
129 }
130 
131 // this is called by jpeg_finish_decompress() after all data has been read. Often a no-op.
TermSrcStream(j_decompress_ptr dinfo)132 void TermSrcStream(j_decompress_ptr dinfo)
133 {}
134 
135 // for destination manager
136 // this is called by jpeg_start_compress() before any data is actually written.
InitDstStream(j_compress_ptr cinfo)137 void InitDstStream(j_compress_ptr cinfo)
138 {
139     if ((cinfo == nullptr) || (cinfo->dest == nullptr)) {
140         HiLog::Error(LABEL, "init destination stream error.");
141         return;
142     }
143     JpegDstMgr *dest = static_cast<JpegDstMgr *>(cinfo->dest);
144     dest->next_output_byte = dest->buffer;
145     dest->free_in_buffer = dest->bufferSize;
146 }
147 
148 // this is called whenever the buffer has filled (free_in_buffer reaches zero).
EmptyOutputBuffer(j_compress_ptr cinfo)149 boolean EmptyOutputBuffer(j_compress_ptr cinfo)
150 {
151     if (cinfo == nullptr) {
152         HiLog::Error(LABEL, "write output buffer error, compress struct is null.");
153         return FALSE;
154     }
155     JpegDstMgr *dest = static_cast<JpegDstMgr *>(cinfo->dest);
156     if ((dest == nullptr) || (dest->outputStream == nullptr)) {
157         HiLog::Error(LABEL, "write output buffer error, dest stream is null.");
158         ERREXIT(cinfo, JERR_FILE_WRITE);
159         return FALSE;
160     }
161     if (!dest->outputStream->Write(dest->buffer, dest->bufferSize)) {
162         HiLog::Error(LABEL, "write output buffer error, write dest stream failed.");
163         ERREXIT(cinfo, JERR_FILE_WRITE);
164         return FALSE;
165     }
166     dest->next_output_byte = dest->buffer;
167     dest->free_in_buffer = dest->bufferSize;
168     return TRUE;
169 }
170 
171 // this is called by jpeg_finish_compress() after all data has been written.
TermDstStream(j_compress_ptr cinfo)172 void TermDstStream(j_compress_ptr cinfo)
173 {
174     if (cinfo == nullptr) {
175         HiLog::Error(LABEL, "term output buffer error, compress struct is null.");
176         return;
177     }
178     JpegDstMgr *dest = static_cast<JpegDstMgr *>(cinfo->dest);
179     if ((dest == nullptr) || (dest->outputStream == nullptr)) {
180         HiLog::Error(LABEL, "term output buffer error, dest stream is null.");
181         ERREXIT(cinfo, JERR_FILE_WRITE);
182         return;
183     }
184     size_t size = dest->bufferSize - dest->free_in_buffer;
185     if (size > 0) {
186         if (!dest->outputStream->Write(dest->buffer, size)) {
187             HiLog::Error(LABEL, "term output buffer error, write dest stream size:%{public}zu failed.", size);
188             ERREXIT(cinfo, JERR_FILE_WRITE);
189             return;
190         }
191     }
192     dest->outputStream->Flush();
193 }
DoubleToString(double num)194 std::string DoubleToString(double num)
195 {
196     char str[256];
197     int32_t ret = sprintf_s(str, sizeof(str), "%lf", num);
198     if (ret <= PRINTF_SUCCESS) {
199         return "";
200     }
201     std::string result = str;
202     return result;
203 }
204 } // namespace ImagePlugin
205 } // namespace OHOS
206