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 "picture_utils.h"
17
18 #include <fstream>
19 #include <iostream>
20
21 #include "ic_retcode.h"
22 #include "resize_computer.h"
23 #include "securec.h"
24
25 using namespace std;
26
27 namespace IC {
WriteJpegFile(const string & filename,int quality,uint8_t * srcBuffer,int srcWidth,int srcHeight)28 int WriteJpegFile(const string &filename, int quality,
29 uint8_t *srcBuffer, int srcWidth, int srcHeight)
30 {
31 struct jpeg_compress_struct cinfo;
32 struct jpeg_error_mgr jerr;
33 JSAMPROW rowPointer[1];
34 int rowStride = 0;
35 cinfo.err = jpeg_std_error(&jerr);
36 jpeg_create_compress(&cinfo);
37 if (srcBuffer == nullptr) {
38 printf("WriteJpegFile: srcBuffer is nullptr\n");
39 return IC_RETCODE_FAILURE;
40 }
41 FILE *outfile;
42 if ((outfile = fopen(filename.c_str(), "wb")) == nullptr) {
43 printf("WriteJpegFile: can't open %s\n", filename.c_str());
44 return IC_RETCODE_FAILURE;
45 }
46 jpeg_stdio_dest(&cinfo, outfile);
47 cinfo.image_width = srcWidth;
48 cinfo.image_height = srcHeight;
49 cinfo.input_components = NUM_CHANNELS;
50 cinfo.in_color_space = JCS_RGB;
51 jpeg_set_defaults(&cinfo);
52 jpeg_set_quality(&cinfo, quality, TRUE);
53 jpeg_start_compress(&cinfo, TRUE);
54 rowStride = srcWidth * NUM_CHANNELS;
55
56 while (cinfo.next_scanline < cinfo.image_height) {
57 rowPointer[0] = &srcBuffer[cinfo.next_scanline * rowStride];
58 (void)jpeg_write_scanlines(&cinfo, rowPointer, 1);
59 }
60 jpeg_finish_compress(&cinfo);
61
62 fclose(outfile);
63 jpeg_destroy_compress(&cinfo);
64 return IC_RETCODE_SUCCESS;
65 }
66
WriteBgrFile(const string & filename,uint8_t * dataBuffer,int bufferSize)67 int WriteBgrFile(const string &filename, uint8_t *dataBuffer, int bufferSize)
68 {
69 if (dataBuffer == nullptr || bufferSize <= 0) {
70 printf("WriteBgrFile: dataBuffer is nullptr.\n");
71 return IC_RETCODE_FAILURE;
72 }
73 ofstream outfile(filename.c_str(), ofstream::out | ofstream::trunc);
74 if (!outfile.is_open()) {
75 printf("WriteBgrFile: Error writing file from BGR dataBuffer\n");
76 return IC_RETCODE_FAILURE;
77 }
78 outfile.write((const char*)dataBuffer, bufferSize);
79 outfile.close();
80 return IC_RETCODE_SUCCESS;
81 }
82
ConvertToCaffeInput(uint8_t * dataBuffer,int maxSize)83 uint8_t *ConvertToCaffeInput(uint8_t *dataBuffer, int maxSize)
84 {
85 if (dataBuffer == nullptr) {
86 return nullptr;
87 }
88 if (maxSize % NUM_CHANNELS != 0) {
89 return nullptr;
90 }
91 uint8_t *input = new (std::nothrow) uint8_t[maxSize];
92 if (input == nullptr) {
93 return nullptr;
94 }
95 int numPreChannel = maxSize / NUM_CHANNELS;
96 for (int i = 0; i < maxSize; i++) {
97 input[BGR_RED * numPreChannel + i / NUM_CHANNELS] = dataBuffer[i + RGB_RED];
98 input[BGR_BLUE * numPreChannel + i / NUM_CHANNELS] = dataBuffer[i + RGB_BLUE];
99 input[BGR_GREEN * numPreChannel + i / NUM_CHANNELS] = dataBuffer[i + RGB_GREEN];
100 }
101 return input;
102 }
103
ReadJpegFile(const string & filename,int & srcWidth,int & srcHeight)104 uint8_t *ReadJpegFile(const string &filename, int &srcWidth, int &srcHeight)
105 {
106 struct jpeg_decompress_struct cinfo;
107 struct MyErrorMgr jerr;
108 FILE *infile;
109 if ((infile = fopen(filename.c_str(), "rb")) == nullptr) {
110 printf("ReadJpegFile: can't open %s\n", filename.c_str());
111 return nullptr;
112 }
113
114 cinfo.err = jpeg_std_error(&jerr.pub);
115 jpeg_create_decompress(&cinfo);
116 jpeg_stdio_src(&cinfo, infile);
117 (void)jpeg_read_header(&cinfo, TRUE);
118 (void)jpeg_start_decompress(&cinfo);
119 srcHeight = cinfo.output_height;
120 srcWidth = cinfo.output_width;
121 int dataSize = srcHeight * srcWidth * cinfo.output_components;
122 uint8_t *buffer = new (std::nothrow) uint8_t[dataSize];
123 if (buffer == nullptr) {
124 printf("ReadJpegFile: error to alloc buffer.\n");
125 (void)jpeg_finish_decompress(&cinfo);
126 jpeg_destroy_decompress(&cinfo);
127 fclose(infile);
128 return nullptr;
129 }
130 uint8_t *rowptr = nullptr;
131 while (cinfo.output_scanline < srcHeight) {
132 rowptr = buffer + cinfo.output_scanline * srcWidth * cinfo.output_components;
133 (void)jpeg_read_scanlines(&cinfo, &rowptr, 1);
134 }
135
136 (void)jpeg_finish_decompress(&cinfo);
137 jpeg_destroy_decompress(&cinfo);
138 fclose(infile);
139 return buffer;
140 }
141
Resize(const int widthDest,const int heightDest,uint8_t * src,int widthSrc,int heightSrc)142 uint8_t *Resize(
143 const int widthDest, const int heightDest, uint8_t *src, int widthSrc, int heightSrc)
144 {
145 if (src == nullptr) {
146 printf("Resize: src is nullptr.\n");
147 return nullptr;
148 }
149 if (widthDest <= 0 || heightDest <= 0 || widthSrc <= 0 || heightSrc <= 0) {
150 printf("Resize: dimension below zero.\n");
151 return nullptr;
152 }
153 int bufferSize = widthDest * heightDest * NUM_CHANNELS;
154 uint8_t *pDest = new (std::nothrow) uint8_t[bufferSize];
155 PicInfo picInfo = {
156 .widthSrc = widthSrc,
157 .heightSrc = heightSrc,
158 .widthDest = widthDest,
159 .heightDest = heightDest
160 };
161 ResizeComputer resizer(picInfo);
162 if (pDest == nullptr) {
163 printf("Resize: pDest alloc failed.\n");
164 return nullptr;
165 }
166 if (widthDest == widthSrc && heightDest == heightSrc) {
167 if (memcpy_s(pDest, bufferSize, src, bufferSize) != EOK) {
168 printf("Resize: memcpy_s failed.\n");
169 delete[] pDest;
170 return nullptr;
171 } else {
172 return pDest;
173 }
174 }
175 resizer.Compute(pDest, src, bufferSize, widthSrc * heightSrc * NUM_CHANNELS);
176 return pDest;
177 }
178 } // namespace IC