• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include <cstdio>
16 #include <cmath>
17 #include <unistd.h>
18 
19 #include "image_compress.h"
20 
21 #include "png.h"
22 #include "jpeglib.h"
23 #include "app_log_wrapper.h"
24 #include "securec.h"
25 
26 namespace OHOS {
27 namespace AppExecFwk {
28 namespace {
29     constexpr int32_t RGBA_COMPONENTS = 4;
30     constexpr int32_t RGB_COMPONENTS = 3;
31     constexpr int32_t FILE_MAX_SIZE = 10240;
32     constexpr int32_t FILE_COMPRESS_SIZE = 4196;
33     constexpr int32_t BITDEPTH_SIXTHEN = 16;
34     constexpr int32_t BITDEPTH_EIGHT = 8;
35     constexpr int32_t COLOR_CHANNEL_GREEN = 1;
36     constexpr int32_t COLOR_CHANNEL_BLUE = 2;
37     constexpr int32_t COLOR_CHANNEL_ALPHA = 3;
38     constexpr int32_t NUMBER_ONE = 1;
39     constexpr int32_t QUALITY = 30;
40     constexpr double EPSILON = 1e-5;
41     const std::string JPG = "jpg";
42     const std::string PNG = "png";
43     const std::string JPEG = "jpeg";
44     const std::string BUNDLE_PATH = "/data/app/el1/bundle";
45     struct EncodeMemo {
46         ImageRow buffer;
47         uint32_t size;
48     };
49 }
50 
ReleasePngPointer(png_bytepp & rowPointers,uint32_t height)51 void ImageCompress::ReleasePngPointer(png_bytepp& rowPointers, uint32_t height)
52 {
53     if (rowPointers != nullptr) {
54         for (uint32_t i = 0; i < height; ++i) {
55             if (rowPointers[i] != nullptr) {
56                 free(rowPointers[i]);
57             }
58         }
59         free(rowPointers);
60     }
61     rowPointers = nullptr;
62 }
63 
MallocPngPointer(png_bytepp & rowPointers,uint32_t height,uint32_t strides)64 bool ImageCompress::MallocPngPointer(png_bytepp& rowPointers, uint32_t height, uint32_t strides)
65 {
66     if (rowPointers != nullptr || height == 0 || strides == 0) {
67         return false;
68     }
69     rowPointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
70     if (rowPointers == nullptr) {
71         APP_LOGE("ImageCompress: MallocPngPointer malloc buffer failed");
72         return false;
73     }
74     for (uint32_t h = 0; h < height; ++h) {
75         rowPointers[h] = (png_byte*)malloc(strides);
76         if (rowPointers[h] == nullptr) {
77             return false;
78         }
79     }
80     return true;
81 }
82 
IsPathValid(std::string & fileName)83 bool ImageCompress::IsPathValid(std::string& fileName)
84 {
85     if (fileName.find(BUNDLE_PATH) != std::string::npos) {
86         return access(fileName.c_str(), F_OK) == 0;
87     } else {
88         return false;
89     }
90 }
91 
CalRatio(std::string fileName)92 double ImageCompress::CalRatio(std::string fileName)
93 {
94     if (!IsPathValid(fileName)) {
95         APP_LOGE("%{public}s is unavailable", fileName.c_str());
96         return -1.0;
97     }
98     FILE* file = fopen(fileName.c_str(), "rb");
99     if (!file) {
100         APP_LOGE("ImageCompress: CalRatio %{public}s is unavailable", fileName.c_str());
101         return -1.0;
102     }
103     if (fseek(file, 0L, SEEK_END) != 0) {
104         fclose(file);
105         return -1.0;
106     }
107     int32_t fileSize = ftell(file);
108     if (fileSize < FILE_MAX_SIZE) {
109         APP_LOGE("ImageCompress: CalRatio do not need compress");
110         fclose(file);
111         return -1.0;
112     }
113     if (fclose(file) != 0) {
114         return -1.0;
115     }
116     return sqrt(static_cast<double>(FILE_COMPRESS_SIZE) / fileSize);
117 }
118 
NeedCompress(std::string fileName)119 bool ImageCompress::NeedCompress(std::string fileName)
120 {
121     if (!IsPathValid(fileName)) {
122         APP_LOGE("%{public}s is unavailable", fileName.c_str());
123         return false;
124     }
125     FILE* file = fopen(fileName.c_str(), "rb");
126     if (!file) {
127         APP_LOGE("ImageCompress: NeedCompress file %{public}s is unavailable", fileName.c_str());
128         return false;
129     }
130     if (fseek(file, 0L, SEEK_END) != 0) {
131         fclose(file);
132         return false;
133     }
134     int32_t fileSize = ftell(file);
135     if (fileSize < FILE_MAX_SIZE) {
136         APP_LOGE("ImageCompress: CalRatio do not need compress");
137         fclose(file);
138         return false;
139     }
140     if (fclose(file) != 0) {
141         return false;
142     }
143     return true;
144 }
145 
PngToBuffer(png_structp png,png_bytep data,png_size_t length)146 void ImageCompress::PngToBuffer(png_structp png, png_bytep data, png_size_t length)
147 {
148     struct EncodeMemo *p = (struct EncodeMemo*)png_get_io_ptr(png);
149     if (memcpy_s(p->buffer + p->size, length, data, length) != EOK) {
150         APP_LOGE("ImageCompress: memcpy_s buffer failed");
151         return;
152     }
153     p->size += length;
154 }
155 
DoubleEqual(double left,double right)156 bool ImageCompress::DoubleEqual(double left, double right)
157 {
158     return std::abs(left - right ) <= EPSILON;
159 }
160 
InitPngFile(std::shared_ptr<ImageBuffer> & imageBuffer,png_structp & png,png_infop & info)161 bool ImageCompress::InitPngFile(std::shared_ptr<ImageBuffer>& imageBuffer,
162     png_structp& png, png_infop& info)
163 {
164     imageBuffer->SetWidth(png_get_image_width(png, info));
165     imageBuffer->SetHeight(png_get_image_height(png, info));
166     imageBuffer->SetColorType(png_get_color_type(png, info));
167     imageBuffer->SetBitDepth(png_get_bit_depth(png, info));
168     imageBuffer->SetPngComponents(png_get_channels(png, info));
169     if (imageBuffer->GetBitDepth() == BITDEPTH_SIXTHEN) {
170         png_set_strip_16(png);
171     }
172     if (imageBuffer->GetColorType() == PNG_COLOR_TYPE_PALETTE) {
173         png_set_palette_to_rgb(png);
174     }
175     if (png_get_valid(png, info, PNG_INFO_tRNS)) {
176         png_set_tRNS_to_alpha(png);
177     }
178     if (imageBuffer->GetColorType() == PNG_COLOR_TYPE_RGB ||
179         imageBuffer->GetColorType() == PNG_COLOR_TYPE_GRAY ||
180         imageBuffer->GetColorType() == PNG_COLOR_TYPE_PALETTE) {
181         png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
182     }
183     if (imageBuffer->GetColorType() == PNG_COLOR_TYPE_GRAY ||
184         imageBuffer->GetColorType() == PNG_COLOR_TYPE_GRAY_ALPHA) {
185         png_set_gray_to_rgb(png);
186     }
187     png_read_update_info(png, info);
188     if (imageBuffer->GetImageDataPointer()) {
189         png_destroy_read_struct(&png, &info, NULL);
190         return false;
191     }
192 
193     imageBuffer->MallocImageMap(RGBA_COMPONENTS);
194     imageBuffer->SetComponents(RGBA_COMPONENTS);
195     uint32_t strides = imageBuffer->GetWidth() *  RGBA_COMPONENTS;
196     png_bytepp rowPointers = nullptr;
197     if (!MallocPngPointer(rowPointers, imageBuffer->GetHeight(), strides)) {
198         APP_LOGE("ImageCompress: MallocPngPointer image buffer failed");
199         return false;
200     }
201     png_read_image(png, rowPointers);
202     ImageRow imageRow = imageBuffer->GetImageDataPointer().get();
203     if (rowPointers == nullptr) {
204         return false;
205     }
206     for (uint32_t h = 0; h < imageBuffer->GetHeight(); ++h) {
207         if (memcpy_s(imageRow, strides, rowPointers[h], strides) != EOK) {
208             ReleasePngPointer(rowPointers, imageBuffer->GetHeight());
209             png_destroy_read_struct(&png, &info, NULL);
210             return false;
211         }
212         imageRow += strides;
213     }
214     ReleasePngPointer(rowPointers, imageBuffer->GetHeight());
215     return true;
216 }
217 
DecodePngFile(std::string fileName,std::shared_ptr<ImageBuffer> & imageBuffer)218 int ImageCompress::DecodePngFile(std::string fileName, std::shared_ptr<ImageBuffer>& imageBuffer)
219 {
220     if (imageBuffer == nullptr) {
221         APP_LOGE("ImageCompress: DecodePngFile image buffer is unavailable");
222         return -1;
223     }
224     if (!IsPathValid(fileName)) {
225         APP_LOGE("%{public}s is unavailable", fileName.c_str());
226         return -1.0;
227     }
228     double ratio = CalRatio(fileName);
229     if (ratio < 0) {
230         APP_LOGE("ImageCompress: DecodePngFile file %{public}s do not need compress", fileName.c_str());
231         return -1;
232     }
233 
234     FILE* inFile = fopen(fileName.c_str(), "rb");
235     if (inFile == nullptr) {
236         APP_LOGE("open file %{private}s failed", fileName.c_str());
237         return -1;
238     }
239     imageBuffer->SetRatio(ratio);
240     png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
241     if (!png) {
242         fclose(inFile);
243         return -1;
244     }
245 
246     png_infop info = png_create_info_struct(png);
247     if (!info) {
248         fclose(inFile);
249         return -1;
250     }
251 
252     if (setjmp(png_jmpbuf(png))) {
253         fclose(inFile);
254         return -1;
255     }
256 
257     png_init_io(png, inFile);
258     png_read_info(png, info);
259 
260     if (!InitPngFile(imageBuffer, png, info)) {
261         if (fclose(inFile) != EOK) {
262             APP_LOGE("ImageCompress: fclose file %{public}s error", fileName.c_str());
263             return -1;
264         }
265         png_destroy_read_struct(&png, &info, NULL);
266         return -1;
267     }
268 
269     if (fclose(inFile) != EOK) {
270         APP_LOGE("ImageCompress: fclose file %{public}s error", fileName.c_str());
271         return -1;
272     }
273     png_destroy_read_struct(&png, &info, NULL);
274     return 0;
275 }
276 
EncodePngFile(std::shared_ptr<ImageBuffer> & imageBuffer)277 int32_t ImageCompress::EncodePngFile(std::shared_ptr<ImageBuffer>& imageBuffer)
278 {
279     if (imageBuffer == nullptr) {
280         APP_LOGE("ImageCompress: Encode none data");
281         return -1;
282     }
283 
284     png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
285     if (!png) {
286         return -1;
287     }
288 
289     png_infop info = png_create_info_struct(png);
290     if (!info) {
291         return -1;
292     }
293     if (setjmp(png_jmpbuf(png))) {
294         return -1;
295     }
296     png_set_IHDR(
297         png,
298         info,
299         imageBuffer->GetWidth(),
300         imageBuffer->GetHeight(),
301         BITDEPTH_EIGHT,
302         PNG_COLOR_TYPE_RGBA,
303         PNG_INTERLACE_NONE,
304         PNG_COMPRESSION_TYPE_DEFAULT,
305         PNG_FILTER_TYPE_DEFAULT
306     );
307     uint32_t strides = imageBuffer->GetWidth() * RGBA_COMPONENTS;
308     struct EncodeMemo memo;
309     memo.buffer = (ImageRow)malloc(FILE_MAX_SIZE * RGBA_COMPONENTS);
310     if (memo.buffer == nullptr) {
311         return -1;
312     }
313     memo.size = 0;
314     if (!imageBuffer->GetImageDataPointer()) {
315         free(memo.buffer);
316         APP_LOGE("ImageCompress: EncodePngFile should input image buffer");
317         return -1;
318     }
319     ImageRow imageRow = imageBuffer->GetImageDataPointer().get();
320     png_bytep* rowPointers;
321     rowPointers = (png_bytep*)malloc(sizeof(png_bytep) * imageBuffer->GetHeight());
322     if (rowPointers == nullptr) {
323         APP_LOGE("ImageCompress: malloc failed");
324         free(memo.buffer);
325         return -1;
326     }
327     for (uint32_t h = 0; h < imageBuffer->GetHeight(); ++h) {
328         rowPointers[h] = (png_byte*)malloc(strides);
329     }
330     for (uint32_t h = 0; h < imageBuffer->GetHeight(); ++h) {
331         memcpy_s(rowPointers[h], strides, imageRow, strides);
332         imageRow += strides;
333     }
334     png_set_rows(png, info, &rowPointers[0]);
335     png_set_write_fn(png, &memo, PngToBuffer, NULL);
336     png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL);
337     png_destroy_write_struct(&png, &info);
338     imageBuffer->SetCompressData(memo.buffer, memo.size);
339     imageBuffer->SetCompressSize(memo.size);
340     if (memo.buffer) {
341         free(memo.buffer);
342     }
343     memo.buffer = nullptr;
344     ReleasePngPointer(rowPointers, imageBuffer->GetHeight());
345     return 0;
346 }
347 
ResizeRGBAImage(std::shared_ptr<ImageBuffer> & imageBufferIn,std::shared_ptr<ImageBuffer> & imageBufferOut)348 int32_t ImageCompress::ResizeRGBAImage(std::shared_ptr<ImageBuffer>& imageBufferIn,
349                                        std::shared_ptr<ImageBuffer>& imageBufferOut)
350 {
351     if (imageBufferIn == nullptr || imageBufferOut == nullptr) {
352         APP_LOGE("ImageCompress: ResizePRGBAImage should input image buffer");
353         return -1;
354     }
355     double ratio = imageBufferIn->GetRatio();
356     ratio = ratio * (static_cast<double>(imageBufferIn->GetPngComponents()) / RGBA_COMPONENTS) ;
357     if (DoubleEqual(ratio, 0.0)) {
358         return -1;
359     }
360     imageBufferOut->SetWidth(imageBufferIn->GetWidth() * ratio);
361     imageBufferOut->SetHeight(imageBufferIn->GetHeight() * ratio);
362     imageBufferOut->SetComponents(imageBufferIn->GetComponents());
363     imageBufferOut->SetColorType(imageBufferIn->GetColorType());
364     imageBufferOut->SetBitDepth(imageBufferIn->GetBitDepth());
365     imageBufferOut->MallocImageMap(imageBufferOut->GetComponents());
366     ImageRow imageRowIn = imageBufferIn->GetImageDataPointer().get();
367     ImageRow imageRowOut = imageBufferOut->GetImageDataPointer().get();
368     uint32_t outRowStride = imageBufferOut->GetWidth() * imageBufferOut->GetComponents();
369     uint32_t inRowStride = imageBufferIn->GetWidth() * imageBufferIn->GetComponents();
370     uint32_t components = imageBufferIn->GetComponents();
371     for (uint32_t h = 0; h < imageBufferOut->GetHeight(); ++h) {
372         for (uint32_t w = 0; w < imageBufferOut->GetWidth(); ++w) {
373             uint64_t heightIndex = std::round(h / ratio);
374             uint64_t widthIndex = std::round(w / ratio);
375             if (heightIndex > imageBufferIn->GetHeight()) {
376                 heightIndex = imageBufferIn->GetHeight() == 0 ? 0 : imageBufferIn->GetHeight() - 1;
377             }
378             if (widthIndex > imageBufferIn->GetWidth()) {
379                 widthIndex = imageBufferIn->GetWidth() == 0 ? 0 : imageBufferIn->GetWidth() - 1;
380             }
381             imageRowOut[h * outRowStride +  w * components] =
382                 imageRowIn[heightIndex * inRowStride + widthIndex * components];
383             imageRowOut[h * outRowStride +  w * components + COLOR_CHANNEL_GREEN] =
384                 imageRowIn[heightIndex * inRowStride + widthIndex * components + COLOR_CHANNEL_GREEN];
385             imageRowOut[h * outRowStride +  w * components + COLOR_CHANNEL_BLUE] =
386                 imageRowIn[heightIndex * inRowStride + widthIndex * components + COLOR_CHANNEL_BLUE];
387             imageRowOut[h * outRowStride +  w * components + COLOR_CHANNEL_ALPHA] =
388                 imageRowIn[heightIndex * inRowStride + widthIndex * components + COLOR_CHANNEL_ALPHA];
389         }
390     }
391     return 0;
392 }
393 
DecodeJPGFile(std::string fileName,std::shared_ptr<ImageBuffer> & imageBuffer)394 int32_t ImageCompress::DecodeJPGFile(std::string fileName, std::shared_ptr<ImageBuffer>& imageBuffer)
395 {
396     if (imageBuffer == nullptr) {
397         APP_LOGE("ImageCompress: DecodeJPGFile imageBuffer is unavailable");
398         return -1;
399     }
400     if (!IsPathValid(fileName)) {
401         APP_LOGE("%{public}s is unavailable", fileName.c_str());
402         return -1.0;
403     }
404     double ratio = CalRatio(fileName);
405     if (ratio < 0) {
406         APP_LOGE("ImageCompress: DecodePngFile file %{public}s do not need compress", fileName.c_str());
407         return -1;
408     }
409     struct jpeg_decompress_struct cinfo;
410     struct jpeg_error_mgr jerr;
411     cinfo.err = jpeg_std_error(&jerr);
412     FILE* inFile = fopen(fileName.c_str(), "rb");
413     if (!inFile) {
414         APP_LOGE("ImageCompress: DecodeJPGFile file %{public}s is unavailable", fileName.c_str());
415         return -1;
416     }
417 
418     imageBuffer->SetRatio(ratio);
419     jpeg_create_decompress(&cinfo);
420     jpeg_stdio_src(&cinfo, inFile);
421     jpeg_read_header(&cinfo, TRUE);
422     cinfo.out_color_space = JCS_RGB;
423     jpeg_start_decompress(&cinfo);
424     imageBuffer->SetWidth(cinfo.output_width);
425     imageBuffer->SetHeight(cinfo.output_height);
426     imageBuffer->SetComponents(RGB_COMPONENTS);
427     imageBuffer->MallocImageMap(RGB_COMPONENTS);
428 
429     ImageRow imageRow = imageBuffer->GetImageDataPointer().get();
430     uint32_t row_stride = cinfo.output_width * cinfo.output_components;
431     JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, NUMBER_ONE);
432     while (cinfo.output_scanline < cinfo.image_height) {
433         jpeg_read_scanlines(&cinfo, buffer, NUMBER_ONE);
434         if (memcpy_s(imageRow, row_stride, *buffer, row_stride) != EOK) {
435             APP_LOGE("ImageCompress: memcpy_s buffer failed");
436             fclose(inFile);
437             return -1;
438         }
439         imageRow += row_stride;
440     }
441     jpeg_finish_decompress(&cinfo);
442     jpeg_destroy_decompress(&cinfo);
443     if (fclose(inFile) != 0) {
444         return -1;
445     }
446     return 0;
447 }
448 
EncodeJPGFile(std::shared_ptr<ImageBuffer> & imageBuffer)449 int32_t ImageCompress::EncodeJPGFile(std::shared_ptr<ImageBuffer>& imageBuffer)
450 {
451 
452     if (imageBuffer == nullptr) {
453         APP_LOGE("ImageCompress: EncodeJPGFile should read image buffer first");
454         return -1;
455     }
456 
457     struct jpeg_compress_struct cinfo;
458     struct jpeg_error_mgr jerr;
459     cinfo.err = jpeg_std_error(&jerr);
460     jpeg_create_compress(&cinfo);
461     unsigned char* outBuffer = nullptr;
462     int32_t compressSize = 0;
463     jpeg_mem_dest(&cinfo, &outBuffer, reinterpret_cast<size_t *>(&compressSize));
464     cinfo.image_width = imageBuffer->GetWidth();
465     cinfo.image_height = imageBuffer->GetHeight();
466     cinfo.input_components = RGB_COMPONENTS;
467     cinfo.in_color_space = JCS_RGB;
468     jpeg_set_defaults(&cinfo);
469     jpeg_set_quality(&cinfo, QUALITY, TRUE);
470     jpeg_start_compress(&cinfo, TRUE);
471     uint32_t rowStride = imageBuffer->GetWidth() * imageBuffer->GetComponents();
472     ImageRow imageRow = imageBuffer->GetImageDataPointer().get();
473     JSAMPROW rowdata[1];
474     while (cinfo.next_scanline < static_cast<unsigned int>(imageBuffer->GetHeight())) {
475         rowdata[0] = &imageRow[cinfo.next_scanline * rowStride];
476         (void)jpeg_write_scanlines(&cinfo, rowdata, 1);
477     }
478     jpeg_finish_compress(&cinfo);
479     jpeg_destroy_compress(&cinfo);
480     imageBuffer->SetCompressSize(compressSize);
481     imageBuffer->SetCompressData(outBuffer, compressSize);
482     free(outBuffer);
483     outBuffer = nullptr;
484     return 0;
485 }
486 
ResizeRGBImage(std::shared_ptr<ImageBuffer> & imageBufferIn,std::shared_ptr<ImageBuffer> & imageBufferOut)487 int32_t ImageCompress::ResizeRGBImage(std::shared_ptr<ImageBuffer>& imageBufferIn,
488                                       std::shared_ptr<ImageBuffer>& imageBufferOut)
489 {
490     if (imageBufferIn == nullptr || imageBufferOut == nullptr) {
491         APP_LOGE("ImageCompress: ResizePRGBAImage should input image buffer");
492         return -1;
493     }
494     double ratio = imageBufferIn->GetRatio();
495     if (DoubleEqual(ratio, 0.0)) {
496         return -1;
497     }
498     imageBufferOut->SetWidth(imageBufferIn->GetWidth() * ratio);
499     imageBufferOut->SetHeight(imageBufferIn->GetHeight() * ratio);
500     imageBufferOut->SetComponents(imageBufferIn->GetComponents());
501     imageBufferOut->SetColorType(imageBufferIn->GetColorType());
502     imageBufferOut->SetBitDepth(imageBufferIn->GetBitDepth());
503     imageBufferOut->MallocImageMap(imageBufferOut->GetComponents());
504     ImageRow imageRowIn = imageBufferIn->GetImageDataPointer().get();
505     ImageRow imageRowOut = imageBufferOut->GetImageDataPointer().get();
506     uint32_t outRowStride = imageBufferOut->GetWidth() * imageBufferOut->GetComponents();
507     uint32_t inRowStride = imageBufferIn->GetWidth() * imageBufferIn->GetComponents();
508     uint32_t components = imageBufferIn->GetComponents();
509     for (uint32_t h = 0; h < imageBufferOut->GetHeight(); ++h) {
510         for (uint32_t w = 0; w < imageBufferOut->GetWidth(); ++w) {
511             uint64_t heightIndex = std::round(h / ratio);
512             uint64_t widthIndex = std::round(w / ratio);
513             if (heightIndex > imageBufferIn->GetHeight()) {
514                 heightIndex = imageBufferIn->GetHeight() == 0 ? 0 : imageBufferIn->GetHeight() - 1;
515             }
516             if (widthIndex > imageBufferIn->GetWidth()) {
517                 widthIndex = imageBufferIn->GetWidth() == 0 ? 0 : imageBufferIn->GetWidth() - 1;
518             }
519             imageRowOut[h * outRowStride +  w * components] =
520                 imageRowIn[heightIndex * inRowStride + widthIndex * components];
521             imageRowOut[h * outRowStride +  w * components + COLOR_CHANNEL_GREEN] =
522                 imageRowIn[heightIndex * inRowStride + widthIndex * components + COLOR_CHANNEL_GREEN];
523             imageRowOut[h * outRowStride +  w * components + COLOR_CHANNEL_BLUE] =
524                 imageRowIn[heightIndex * inRowStride + widthIndex * components + COLOR_CHANNEL_BLUE];
525         }
526     }
527     return 0;
528 }
529 
CompressImage(std::string inFileName)530 std::shared_ptr<ImageBuffer> ImageCompress::CompressImage(std::string inFileName)
531 {
532     std::string inFileSuffix = inFileName.substr(inFileName.find_last_of('.') + 1);
533     if (inFileSuffix.compare(PNG) != 0 && inFileSuffix.compare(JPG) != 0 && inFileSuffix.compare(JPEG) != 0) {
534         return nullptr;
535     }
536     std::shared_ptr<ImageBuffer> imageBufferIn = std::make_shared<ImageBuffer>();
537     std::shared_ptr<ImageBuffer> imageBufferOut = std::make_shared<ImageBuffer>();
538     if (inFileSuffix.compare("png") == 0 || inFileSuffix.compare("PNG") == 0) {
539         imageBufferIn->SetImageType(PNG);
540         imageBufferOut->SetImageType(PNG);
541         if (DecodePngFile(inFileName, imageBufferIn) != 0) {
542             APP_LOGE("ImageCompress: DecodePngFile decode png file error");
543             return nullptr;
544         }
545         if (ResizeRGBAImage(imageBufferIn, imageBufferOut) != 0) {
546             APP_LOGE("ImageCompress: DecodePngFile resize png file error");
547             return nullptr;
548         }
549         if (EncodePngFile(imageBufferOut) != 0) {
550             return nullptr;
551         }
552     } else if (inFileSuffix.compare(JPG) == 0 || inFileSuffix.compare(JPEG) == 0) {
553         imageBufferIn->SetImageType(JPG);
554         imageBufferOut->SetImageType(JPG);
555         if (DecodeJPGFile(inFileName, imageBufferIn) != 0) {
556             APP_LOGE("ImageCompress: DecodeJPGFile decode jpeg file error");
557             return nullptr;
558         }
559         if (ResizeRGBImage(imageBufferIn, imageBufferOut) != 0) {
560             APP_LOGE("ImageCompress: ResizeRGBImage resize jpeg file error");
561             return nullptr;
562         }
563         if (EncodeJPGFile(imageBufferOut) != 0) {
564             APP_LOGE("ImageCompress: EncodeJPGFile jpeg file error");
565             return nullptr;
566         }
567     } else {
568         APP_LOGE("ImageCompress: input wrong image format");
569         return nullptr;
570     }
571     return imageBufferOut;
572 }
573 }
574 }