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 #include "webp_encoder.h"
16 #include "webp/mux.h"
17 #include "image_log.h"
18 #include "image_trace.h"
19 #include "media_errors.h"
20 #include "pixel_convert_adapter.h"
21 
22 #undef LOG_DOMAIN
23 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
24 
25 #undef LOG_TAG
26 #define LOG_TAG "WebpEncoder"
27 
28 namespace OHOS {
29 namespace ImagePlugin {
30 using namespace MultimediaPlugin;
31 using namespace Media;
32 namespace {
33 constexpr uint32_t WEBP_IMAGE_NUM = 1;
34 constexpr uint32_t COMPONENT_NUM_3 = 3;
35 constexpr uint32_t COMPONENT_NUM_4 = 4;
36 } // namespace
37 
StreamWriter(const uint8_t * data,size_t data_size,const WebPPicture * const picture)38 static int StreamWriter(const uint8_t* data, size_t data_size, const WebPPicture* const picture)
39 {
40     IMAGE_LOGD("StreamWriter data_size=%{public}zu", data_size);
41 
42     auto webpEncoder = static_cast<WebpEncoder*>(picture->custom_ptr);
43     return webpEncoder->Write(data, data_size) ? 1 : 0;
44 }
45 
WebpEncoder()46 WebpEncoder::WebpEncoder()
47 {
48     IMAGE_LOGD("create IN");
49 
50     IMAGE_LOGD("create OUT");
51 }
52 
~WebpEncoder()53 WebpEncoder::~WebpEncoder()
54 {
55     IMAGE_LOGD("release IN");
56 
57     pixelMaps_.clear();
58 
59     IMAGE_LOGD("release OUT");
60 }
61 
StartEncode(OutputDataStream & outputStream,PlEncodeOptions & option)62 uint32_t WebpEncoder::StartEncode(OutputDataStream &outputStream, PlEncodeOptions &option)
63 {
64     ImageTrace imageTrace("WebpEncoder::StartEncode");
65     IMAGE_LOGD("StartEncode IN, quality=%{public}u, numberHint=%{public}u",
66         option.quality, option.numberHint);
67 
68     pixelMaps_.clear();
69 
70     outputStream_ = &outputStream;
71     encodeOpts_ = option;
72 
73     IMAGE_LOGD("StartEncode OUT");
74     return SUCCESS;
75 }
76 
AddImage(Media::PixelMap & pixelMap)77 uint32_t WebpEncoder::AddImage(Media::PixelMap &pixelMap)
78 {
79     ImageTrace imageTrace("WebpEncoder::AddImage");
80     IMAGE_LOGD("AddImage IN");
81 
82     if (pixelMaps_.size() >= WEBP_IMAGE_NUM) {
83         IMAGE_LOGE("AddImage, add pixel map out of range=%{public}u.", WEBP_IMAGE_NUM);
84         return ERR_IMAGE_ADD_PIXEL_MAP_FAILED;
85     }
86 
87     pixelMaps_.push_back(&pixelMap);
88 
89     IMAGE_LOGD("AddImage OUT");
90     return SUCCESS;
91 }
92 
AddPicture(Media::Picture & picture)93 uint32_t WebpEncoder::AddPicture(Media::Picture &picture)
94 {
95     ImageTrace imageTrace("WebpEncoder::AddPicture");
96     return ERR_IMAGE_ENCODE_FAILED;
97 }
98 
FinalizeEncode()99 uint32_t WebpEncoder::FinalizeEncode()
100 {
101     ImageTrace imageTrace("WebpEncoder::FinalizeEncode");
102     IMAGE_LOGD("FinalizeEncode IN");
103 
104     if (pixelMaps_.empty()) {
105         IMAGE_LOGE("FinalizeEncode, no pixel map input.");
106         return ERR_IMAGE_INVALID_PARAMETER;
107     }
108 
109     IMAGE_LOGD("FinalizeEncode, quality=%{public}u, numberHint=%{public}u",
110         encodeOpts_.quality, encodeOpts_.numberHint);
111 
112     uint32_t errorCode = ERROR;
113 
114     Media::PixelMap &pixelMap = *(pixelMaps_[0]);
115     WebPConfig webpConfig;
116     WebPPicture webpPicture;
117     WebPPictureInit(&webpPicture);
118 
119     errorCode = SetEncodeConfig(pixelMap, webpConfig, webpPicture);
120     IMAGE_LOGD("FinalizeEncode, config, %{public}u.", errorCode);
121 
122     if (errorCode != SUCCESS) {
123         IMAGE_LOGE("FinalizeEncode, config failed=%{public}u.", errorCode);
124         WebPPictureFree(&webpPicture);
125         return errorCode;
126     }
127 
128     errorCode = DoEncode(pixelMap, webpConfig, webpPicture);
129     IMAGE_LOGD("FinalizeEncode, encode,%{public}u.", errorCode);
130     WebPPictureFree(&webpPicture);
131 
132     if (errorCode != SUCCESS) {
133         IMAGE_LOGE("FinalizeEncode, encode failed=%{public}u.", errorCode);
134     }
135 
136     IMAGE_LOGD("FinalizeEncode OUT");
137     return errorCode;
138 }
139 
Write(const uint8_t * data,size_t data_size)140 bool WebpEncoder::Write(const uint8_t* data, size_t data_size)
141 {
142     IMAGE_LOGD("Write data_size=%{public}zu, iccValid=%{public}d", data_size, iccValid_);
143 
144     if (iccValid_) {
145         return memoryStream_.write(data, data_size);
146     }
147 
148     return outputStream_->Write(data, data_size);
149 }
150 
CheckEncodeFormat(Media::PixelMap & pixelMap)151 bool WebpEncoder::CheckEncodeFormat(Media::PixelMap &pixelMap)
152 {
153     PixelFormat pixelFormat = GetPixelFormat(pixelMap);
154     IMAGE_LOGD("CheckEncodeFormat, pixelFormat=%{public}u", pixelFormat);
155 
156     switch (pixelFormat) {
157         case PixelFormat::RGBA_8888: {
158             IMAGE_LOGD("CheckEncodeFormat, RGBA_8888");
159             return true;
160         }
161         case PixelFormat::BGRA_8888: {
162             IMAGE_LOGD("CheckEncodeFormat, BGRA_8888");
163             return true;
164         }
165         case PixelFormat::RGBA_F16: {
166             IMAGE_LOGD("CheckEncodeFormat, RGBA_F16");
167             return true;
168         }
169         case PixelFormat::ARGB_8888: {
170             IMAGE_LOGD("CheckEncodeFormat, ARGB_8888");
171             return true;
172         }
173         case PixelFormat::RGB_888: {
174             IMAGE_LOGD("CheckEncodeFormat, RGB_888");
175             return true;
176         }
177         case PixelFormat::RGB_565: {
178             bool isOpaque = IsOpaque(pixelMap);
179             IMAGE_LOGD("CheckEncodeFormat, RGB_565, isOpaque=%{public}d", isOpaque);
180             return isOpaque;
181         }
182         case PixelFormat::ALPHA_8: {
183             IMAGE_LOGD("CheckEncodeFormat, ALPHA_8");
184             return true;
185         }
186         default: {
187             IMAGE_LOGE("CheckEncodeFormat, pixelFormat=%{public}u", pixelFormat);
188             return false;
189         }
190     }
191 }
192 
DoTransform(Media::PixelMap & pixelMap,char * dst,int componentsNum)193 bool WebpEncoder::DoTransform(Media::PixelMap &pixelMap, char* dst, int componentsNum)
194 {
195     IMAGE_LOGD("DoTransform IN");
196 
197     PixelFormat pixelFormat = GetPixelFormat(pixelMap);
198     AlphaType alphaType = GetAlphaType(pixelMap);
199     IMAGE_LOGD("DoTransform, pixelFormat=%{public}u, alphaType=%{public}d, componentsNum=%{public}d",
200         pixelFormat, alphaType, componentsNum);
201 
202     if ((pixelFormat == PixelFormat::RGBA_8888) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
203         return DoTransformRGBX(pixelMap, dst, componentsNum);
204     } else if ((pixelFormat == PixelFormat::RGBA_8888) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL)) {
205         return DoTransformMemcpy(pixelMap, dst, componentsNum);
206     } else if ((pixelFormat == PixelFormat::RGBA_8888) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_PREMUL)) {
207         return DoTransformRgbA(pixelMap, dst, componentsNum);
208     } else if ((pixelFormat == PixelFormat::BGRA_8888) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
209         return DoTransformBGRX(pixelMap, dst, componentsNum);
210     } else if ((pixelFormat == PixelFormat::BGRA_8888) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL)) {
211         return DoTransformBGRA(pixelMap, dst, componentsNum);
212     } else if ((pixelFormat == PixelFormat::BGRA_8888) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_PREMUL)) {
213         return DoTransformBgrA(pixelMap, dst, componentsNum);
214     } else if ((pixelFormat == PixelFormat::RGBA_F16) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
215         return DoTransformF16To8888(pixelMap, dst, componentsNum);
216     } else if ((pixelFormat == PixelFormat::RGBA_F16) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL)) {
217         return DoTransformF16To8888(pixelMap, dst, componentsNum);
218     } else if ((pixelFormat == PixelFormat::RGBA_F16) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_PREMUL)) {
219         return DoTransformF16pTo8888(pixelMap, dst, componentsNum);
220     } else if ((pixelFormat == PixelFormat::ARGB_8888) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
221         return DoTransformArgbToRgb(pixelMap, dst, componentsNum);
222     } else if ((pixelFormat == PixelFormat::ARGB_8888) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL)) {
223         return DoTransformArgbToRgba(pixelMap, dst, componentsNum);
224     } else if ((pixelFormat == PixelFormat::ARGB_8888) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_PREMUL)) {
225         return DoTransformArgbToRgba(pixelMap, dst, componentsNum);
226     } else if (pixelFormat == PixelFormat::RGB_888) {
227         return DoTransformMemcpy(pixelMap, dst, componentsNum);
228     } else if ((pixelFormat == PixelFormat::RGB_565) && IsOpaque(pixelMap)) {
229         IMAGE_LOGD("DoTransform, RGB_565, Opaque");
230         return DoTransformRGB565(pixelMap, dst, componentsNum);
231     } else if (pixelFormat == PixelFormat::ALPHA_8) {
232         IMAGE_LOGD("DoTransform, ALPHA_8");
233         return DoTransformGray(pixelMap, dst, componentsNum);
234     }
235 
236     IMAGE_LOGD("DoTransform OUT");
237     return false;
238 }
239 
SetEncodeConfig(Media::PixelMap & pixelMap,WebPConfig & webpConfig,WebPPicture & webpPicture)240 uint32_t WebpEncoder::SetEncodeConfig(Media::PixelMap &pixelMap, WebPConfig &webpConfig, WebPPicture &webpPicture)
241 {
242     IMAGE_LOGD("SetEncodeConfig IN");
243 
244     if (pixelMap.GetPixels() == nullptr) {
245         IMAGE_LOGE("SetEncodeConfig, pixels invalid.");
246         return ERROR;
247     }
248 
249     if (!CheckEncodeFormat(pixelMap)) {
250         IMAGE_LOGE("SetEncodeConfig, check invalid.");
251         return ERR_IMAGE_UNKNOWN_FORMAT;
252     }
253 
254     if (GetPixelFormat(pixelMap) == PixelFormat::RGBA_F16) {
255         componentsNum_ = COMPONENT_NUM_4;
256     } else {
257         componentsNum_ = IsOpaque(pixelMap) ? COMPONENT_NUM_3 : COMPONENT_NUM_4;
258     }
259     IMAGE_LOGD("SetEncodeConfig, componentsNum=%{public}u", componentsNum_);
260 
261     if (!WebPConfigPreset(&webpConfig, WEBP_PRESET_DEFAULT, encodeOpts_.quality)) {
262         IMAGE_LOGE("SetEncodeConfig, config preset issue.");
263         return ERROR;
264     }
265 
266     GetIcc(pixelMap);
267 
268     webpConfig.lossless = 1; // Lossless encoding (0=lossy(default), 1=lossless).
269     webpConfig.method = 0; // quality/speed trade-off (0=fast, 6=slower-better)
270     webpPicture.use_argb = 1; // Main flag for encoder selecting between ARGB or YUV input.
271 
272     webpPicture.width = pixelMap.GetWidth(); // dimensions (less or equal to WEBP_MAX_DIMENSION)
273     webpPicture.height = pixelMap.GetHeight(); // dimensions (less or equal to WEBP_MAX_DIMENSION)
274     webpPicture.writer = StreamWriter;
275     webpPicture.custom_ptr = static_cast<void*>(this);
276 
277     auto colorSpace = GetColorSpace(pixelMap);
278     IMAGE_LOGD("SetEncodeConfig, "
279         "width=%{public}u, height=%{public}u, colorspace=%{public}d, componentsNum=%{public}d.",
280         webpPicture.width, webpPicture.height, colorSpace, componentsNum_);
281 
282     IMAGE_LOGD("SetEncodeConfig OUT");
283     return SUCCESS;
284 }
285 
DoEncode(Media::PixelMap & pixelMap,WebPConfig & webpConfig,WebPPicture & webpPicture)286 uint32_t WebpEncoder::DoEncode(Media::PixelMap &pixelMap, WebPConfig &webpConfig, WebPPicture &webpPicture)
287     __attribute__((no_sanitize("cfi")))
288 {
289     IMAGE_LOGD("DoEncode IN");
290 
291     const int width = pixelMap.GetWidth();
292     const int height = webpPicture.height;
293     const int rgbStride = width * componentsNum_;
294     const int rgbSize = rgbStride * height;
295     IMAGE_LOGD("DoEncode, width=%{public}d, height=%{public}d, componentsNum=%{public}d,"
296         " rgbStride=%{public}d, rgbSize=%{public}d", width, height, componentsNum_, rgbStride, rgbSize);
297 
298     std::unique_ptr<uint8_t[]> rgb = std::make_unique<uint8_t[]>(rgbSize);
299     if (!DoTransform(pixelMap, reinterpret_cast<char*>(&rgb[0]), componentsNum_)) {
300         IMAGE_LOGE("DoEncode, transform issue.");
301         return ERROR;
302     }
303 
304     auto importProc = WebPPictureImportRGB;
305     if (componentsNum_ != COMPONENT_NUM_3) {
306         importProc = (IsOpaque(pixelMap)) ? WebPPictureImportRGBX : WebPPictureImportRGBA;
307     }
308 
309     IMAGE_LOGD("DoEncode, importProc");
310     if (!importProc(&webpPicture, &rgb[0], rgbStride)) {
311         IMAGE_LOGE("DoEncode, import issue.");
312         return ERROR;
313     }
314 
315     IMAGE_LOGD("DoEncode, WebPEncode");
316     if (!WebPEncode(&webpConfig, &webpPicture)) {
317         IMAGE_LOGE("DoEncode, encode issue.");
318         return ERROR;
319     }
320 
321     IMAGE_LOGD("DoEncode, iccValid=%{public}d", iccValid_);
322     if (iccValid_) {
323         auto res = DoEncodeForICC(pixelMap);
324         if (res != SUCCESS) {
325             IMAGE_LOGE("DoEncode, encode for icc issue.");
326             return res;
327         }
328     }
329 
330     IMAGE_LOGD("DoEncode OUT");
331     return SUCCESS;
332 }
333 
DoEncodeForICC(Media::PixelMap & pixelMap)334 uint32_t WebpEncoder::DoEncodeForICC(Media::PixelMap &pixelMap)
335 {
336     IMAGE_LOGD("DoEncodeForICC IN");
337 
338     auto encodedData = memoryStream_.detachAsData();
339     if (encodedData == nullptr) {
340         IMAGE_LOGE("DoEncodeForICC, detachAsData failed.");
341         return ERROR;
342     }
343 
344     WebPData webpEncode = { encodedData->bytes(), encodedData->size() };
345     WebPData webpIcc = { iccBytes_, iccSize_ };
346 
347     auto mux = WebPMuxNew();
348     if (WebPMuxSetImage(mux, &webpEncode, 0) != WEBP_MUX_OK) {
349         IMAGE_LOGE("DoEncodeForICC, image issue.");
350         WebPMuxDelete(mux);
351         return ERROR;
352     }
353 
354     if (WebPMuxSetChunk(mux, "ICCP", &webpIcc, 0) != WEBP_MUX_OK) {
355         IMAGE_LOGE("DoEncodeForICC, icc issue.");
356         WebPMuxDelete(mux);
357         return ERROR;
358     }
359 
360     WebPData webpAssembled;
361     if (WebPMuxAssemble(mux, &webpAssembled) != WEBP_MUX_OK) {
362         IMAGE_LOGE("DoEncodeForICC, assemble issue.");
363         WebPMuxDelete(mux);
364         return ERROR;
365     }
366 
367     outputStream_->Write(webpAssembled.bytes, webpAssembled.size);
368     WebPDataClear(&webpAssembled);
369     WebPMuxDelete(mux);
370 
371     IMAGE_LOGD("DoEncodeForICC OUT");
372     return SUCCESS;
373 }
374 
GetColorSpace(Media::PixelMap & pixelMap)375 ColorSpace WebpEncoder::GetColorSpace(Media::PixelMap &pixelMap)
376 {
377     return pixelMap.GetColorSpace();
378 }
379 
GetPixelFormat(Media::PixelMap & pixelMap)380 PixelFormat WebpEncoder::GetPixelFormat(Media::PixelMap &pixelMap)
381 {
382     return pixelMap.GetPixelFormat();
383 }
384 
GetAlphaType(Media::PixelMap & pixelMap)385 AlphaType WebpEncoder::GetAlphaType(Media::PixelMap &pixelMap)
386 {
387     return pixelMap.GetAlphaType();
388 }
389 
GetIcc(Media::PixelMap & pixelMap)390 bool WebpEncoder::GetIcc(Media::PixelMap &pixelMap)
391 {
392     return iccValid_;
393 }
394 
IsOpaque(Media::PixelMap & pixelMap)395 bool WebpEncoder::IsOpaque(Media::PixelMap &pixelMap)
396 {
397     return (GetAlphaType(pixelMap) == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE);
398 }
399 
DoTransformMemcpy(Media::PixelMap & pixelMap,char * dst,int componentsNum)400 bool WebpEncoder::DoTransformMemcpy(Media::PixelMap &pixelMap, char* dst, int componentsNum)
401 {
402     IMAGE_LOGD("DoTransformMemcpy IN");
403 
404     auto src = pixelMap.GetPixels();
405     if ((src == nullptr) || (dst == nullptr)) {
406         IMAGE_LOGE("DoTransformMemcpy, address issue.");
407         return false;
408     }
409 
410     const int32_t width = pixelMap.GetWidth();
411     const int32_t height = pixelMap.GetHeight();
412     const uint32_t rowBytes = pixelMap.GetRowBytes();
413     const int stride = pixelMap.GetWidth() * componentsNum;
414 
415     IMAGE_LOGD("width=%{public}u, height=%{public}u, rowBytes=%{public}u, stride=%{public}d, componentsNum=%{public}d",
416         width, height, rowBytes, stride, componentsNum);
417 
418     for (int32_t h = 0; h < height; h++) {
419         transform_scanline_memcpy(reinterpret_cast<char*>(&dst[h * stride]),
420             reinterpret_cast<const char*>(&src[h * rowBytes]),
421             width, componentsNum);
422     }
423 
424     IMAGE_LOGD("DoTransformMemcpy OUT");
425     return true;
426 }
427 
DoTransformRGBX(Media::PixelMap & pixelMap,char * dst,int componentsNum)428 bool WebpEncoder::DoTransformRGBX(Media::PixelMap &pixelMap, char* dst, int componentsNum)
429 {
430     IMAGE_LOGD("DoTransformRGBX IN");
431 
432     const void *srcPixels = pixelMap.GetPixels();
433     uint32_t srcRowBytes = pixelMap.GetRowBytes();
434     const ImageInfo srcInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
435         PixelFormat::RGBA_8888, AlphaType::IMAGE_ALPHA_TYPE_OPAQUE);
436 
437     void *dstPixels = dst;
438     uint32_t dstRowBytes = pixelMap.GetWidth() * componentsNum;
439     const ImageInfo dstInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
440         PixelFormat::RGB_888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
441 
442     ShowTransformParam(srcInfo, srcRowBytes, dstInfo, dstRowBytes, componentsNum);
443 
444     if ((srcPixels == nullptr) || (dstPixels == nullptr)) {
445         IMAGE_LOGE("DoTransformRGBX, address issue.");
446         return false;
447     }
448 
449     const Position dstPos;
450     if (!PixelConvertAdapter::WritePixelsConvert(srcPixels, srcRowBytes, srcInfo,
451         dstPixels, dstPos, dstRowBytes, dstInfo)) {
452         IMAGE_LOGE("DoTransformRGBX, pixel convert in adapter failed.");
453         return false;
454     }
455 
456     IMAGE_LOGD("DoTransformRGBX OUT");
457     return true;
458 }
459 
DoTransformRgbA(Media::PixelMap & pixelMap,char * dst,int componentsNum)460 bool WebpEncoder::DoTransformRgbA(Media::PixelMap &pixelMap, char* dst, int componentsNum)
461 {
462     IMAGE_LOGD("DoTransformRgbA IN");
463 
464     const void *srcPixels = pixelMap.GetPixels();
465     uint32_t srcRowBytes = pixelMap.GetRowBytes();
466     const ImageInfo srcInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
467         PixelFormat::RGBA_8888, AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
468 
469     void *dstPixels = dst;
470     uint32_t dstRowBytes = pixelMap.GetWidth() * componentsNum;
471     const ImageInfo dstInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
472         PixelFormat::RGBA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
473 
474     ShowTransformParam(srcInfo, srcRowBytes, dstInfo, dstRowBytes, componentsNum);
475 
476     if ((srcPixels == nullptr) || (dstPixels == nullptr)) {
477         IMAGE_LOGE("DoTransformRgbA, address issue.");
478         return false;
479     }
480 
481     const Position dstPos;
482     if (!PixelConvertAdapter::WritePixelsConvert(srcPixels, srcRowBytes, srcInfo,
483         dstPixels, dstPos, dstRowBytes, dstInfo)) {
484         IMAGE_LOGE("DoTransformRgbA, pixel convert in adapter failed.");
485         return false;
486     }
487 
488     IMAGE_LOGD("DoTransformRgbA OUT");
489     return true;
490 }
491 
DoTransformBGRX(Media::PixelMap & pixelMap,char * dst,int componentsNum)492 bool WebpEncoder::DoTransformBGRX(Media::PixelMap &pixelMap, char* dst, int componentsNum)
493 {
494     IMAGE_LOGD("DoTransformBGRX IN");
495 
496     const void *srcPixels = pixelMap.GetPixels();
497     uint32_t srcRowBytes = pixelMap.GetRowBytes();
498     const ImageInfo srcInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
499         PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
500 
501     void *dstPixels = dst;
502     uint32_t dstRowBytes = pixelMap.GetWidth() * componentsNum;
503     const ImageInfo dstInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
504         PixelFormat::RGB_888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
505 
506     ShowTransformParam(srcInfo, srcRowBytes, dstInfo, dstRowBytes, componentsNum);
507 
508     if ((srcPixels == nullptr) || (dstPixels == nullptr)) {
509         IMAGE_LOGE("DoTransformBGRX, address issue.");
510         return false;
511     }
512 
513     const Position dstPos;
514     if (!PixelConvertAdapter::WritePixelsConvert(srcPixels, srcRowBytes, srcInfo,
515         dstPixels, dstPos, dstRowBytes, dstInfo)) {
516         IMAGE_LOGE("DoTransformBGRX, pixel convert in adapter failed.");
517         return false;
518     }
519 
520     IMAGE_LOGD("DoTransformBGRX OUT");
521     return true;
522 }
523 
DoTransformBGRA(Media::PixelMap & pixelMap,char * dst,int componentsNum)524 bool WebpEncoder::DoTransformBGRA(Media::PixelMap &pixelMap, char* dst, int componentsNum)
525 {
526     IMAGE_LOGD("DoTransformBGRA IN");
527 
528     const void *srcPixels = pixelMap.GetPixels();
529     uint32_t srcRowBytes = pixelMap.GetRowBytes();
530     const ImageInfo srcInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
531         PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
532 
533     void *dstPixels = dst;
534     uint32_t dstRowBytes = pixelMap.GetWidth() * componentsNum;
535     const ImageInfo dstInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
536         PixelFormat::RGBA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
537 
538     ShowTransformParam(srcInfo, srcRowBytes, dstInfo, dstRowBytes, componentsNum);
539 
540     if ((srcPixels == nullptr) || (dstPixels == nullptr)) {
541         IMAGE_LOGE("DoTransformBGRA, address issue.");
542         return false;
543     }
544 
545     const Position dstPos;
546     if (!PixelConvertAdapter::WritePixelsConvert(srcPixels, srcRowBytes, srcInfo,
547         dstPixels, dstPos, dstRowBytes, dstInfo)) {
548         IMAGE_LOGE("DoTransformBGRA, pixel convert in adapter failed.");
549         return false;
550     }
551 
552     IMAGE_LOGD("DoTransformBGRA OUT");
553     return true;
554 }
555 
DoTransformBgrA(Media::PixelMap & pixelMap,char * dst,int componentsNum)556 bool WebpEncoder::DoTransformBgrA(Media::PixelMap &pixelMap, char* dst, int componentsNum)
557 {
558     IMAGE_LOGD("DoTransformBgrA IN");
559 
560     const void *srcPixels = pixelMap.GetPixels();
561     uint32_t srcRowBytes = pixelMap.GetRowBytes();
562     const ImageInfo srcInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
563         PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
564 
565     void *dstPixels = dst;
566     uint32_t dstRowBytes = pixelMap.GetWidth() * componentsNum;
567     const ImageInfo dstInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
568         PixelFormat::RGBA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
569 
570     ShowTransformParam(srcInfo, srcRowBytes, dstInfo, dstRowBytes, componentsNum);
571 
572     if ((srcPixels == nullptr) || (dstPixels == nullptr)) {
573         IMAGE_LOGE("DoTransformBgrA, address issue.");
574         return false;
575     }
576 
577     const Position dstPos;
578     if (!PixelConvertAdapter::WritePixelsConvert(srcPixels, srcRowBytes, srcInfo,
579         dstPixels, dstPos, dstRowBytes, dstInfo)) {
580         IMAGE_LOGE("DoTransformBgrA, pixel convert in adapter failed.");
581         return false;
582     }
583 
584     IMAGE_LOGD("DoTransformBgrA OUT");
585     return true;
586 }
587 
DoTransformF16To8888(Media::PixelMap & pixelMap,char * dst,int componentsNum)588 bool WebpEncoder::DoTransformF16To8888(Media::PixelMap &pixelMap, char* dst, int componentsNum)
589 {
590     IMAGE_LOGD("DoTransformF16To8888 IN");
591 
592     const void *srcPixels = pixelMap.GetPixels();
593     uint32_t srcRowBytes = pixelMap.GetRowBytes();
594     const ImageInfo srcInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
595         PixelFormat::RGBA_F16, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
596 
597     void *dstPixels = dst;
598     uint32_t dstRowBytes = pixelMap.GetWidth() * componentsNum;
599     const ImageInfo dstInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
600         PixelFormat::RGBA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
601 
602     ShowTransformParam(srcInfo, srcRowBytes, dstInfo, dstRowBytes, componentsNum);
603 
604     if ((srcPixels == nullptr) || (dstPixels == nullptr)) {
605         IMAGE_LOGE("DoTransformF16To8888, address issue.");
606         return false;
607     }
608 
609     const Position dstPos;
610     if (!PixelConvertAdapter::WritePixelsConvert(srcPixels, srcRowBytes, srcInfo,
611         dstPixels, dstPos, dstRowBytes, dstInfo)) {
612         IMAGE_LOGE("DoTransformF16To8888, pixel convert in adapter failed.");
613         return false;
614     }
615 
616     IMAGE_LOGD("DoTransformF16To8888 OUT");
617     return true;
618 }
619 
DoTransformF16pTo8888(Media::PixelMap & pixelMap,char * dst,int componentsNum)620 bool WebpEncoder::DoTransformF16pTo8888(Media::PixelMap &pixelMap, char* dst, int componentsNum)
621 {
622     IMAGE_LOGD("DoTransformF16pTo8888 IN");
623 
624     const void *srcPixels = pixelMap.GetPixels();
625     uint32_t srcRowBytes = pixelMap.GetRowBytes();
626     const ImageInfo srcInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
627         PixelFormat::RGBA_F16, AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
628 
629     void *dstPixels = dst;
630     uint32_t dstRowBytes = pixelMap.GetWidth() * componentsNum;
631     const ImageInfo dstInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
632         PixelFormat::RGBA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
633 
634     ShowTransformParam(srcInfo, srcRowBytes, dstInfo, dstRowBytes, componentsNum);
635 
636     if ((srcPixels == nullptr) || (dstPixels == nullptr)) {
637         IMAGE_LOGE("DoTransformF16pTo8888, address issue.");
638         return false;
639     }
640 
641     const Position dstPos;
642     if (!PixelConvertAdapter::WritePixelsConvert(srcPixels, srcRowBytes, srcInfo,
643         dstPixels, dstPos, dstRowBytes, dstInfo)) {
644         IMAGE_LOGE("DoTransformF16pTo8888, pixel convert in adapter failed.");
645         return false;
646     }
647 
648     IMAGE_LOGD("DoTransformF16pTo8888 OUT");
649     return true;
650 }
651 
DoTransformArgbToRgb(Media::PixelMap & pixelMap,char * dst,int componentsNum)652 bool WebpEncoder::DoTransformArgbToRgb(Media::PixelMap &pixelMap, char* dst, int componentsNum)
653 {
654     IMAGE_LOGD("DoTransformArgbToRgb IN");
655 
656     const void *srcPixels = pixelMap.GetPixels();
657     uint32_t srcRowBytes = pixelMap.GetRowBytes();
658     const ImageInfo srcInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
659         PixelFormat::ARGB_8888, AlphaType::IMAGE_ALPHA_TYPE_OPAQUE);
660 
661     void *dstPixels = dst;
662     uint32_t dstRowBytes = pixelMap.GetWidth() * componentsNum;
663     const ImageInfo dstInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
664         PixelFormat::RGB_888, AlphaType::IMAGE_ALPHA_TYPE_OPAQUE);
665 
666     ShowTransformParam(srcInfo, srcRowBytes, dstInfo, dstRowBytes, componentsNum);
667 
668     if ((srcPixels == nullptr) || (dstPixels == nullptr)) {
669         IMAGE_LOGE("DoTransformArgbToRgb, address issue.");
670         return false;
671     }
672 
673     const Position dstPos;
674     if (!PixelConvertAdapter::WritePixelsConvert(srcPixels, srcRowBytes, srcInfo,
675         dstPixels, dstPos, dstRowBytes, dstInfo)) {
676         IMAGE_LOGE("DoTransformArgbToRgb, pixel convert in adapter failed.");
677         return false;
678     }
679 
680     IMAGE_LOGD("DoTransformArgbToRgb OUT");
681     return true;
682 }
683 
DoTransformArgbToRgba(Media::PixelMap & pixelMap,char * dst,int componentsNum)684 bool WebpEncoder::DoTransformArgbToRgba(Media::PixelMap &pixelMap, char* dst, int componentsNum)
685 {
686     IMAGE_LOGD("DoTransformArgbToRgba IN");
687 
688     const void *srcPixels = pixelMap.GetPixels();
689     uint32_t srcRowBytes = pixelMap.GetRowBytes();
690     const ImageInfo srcInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
691         PixelFormat::ARGB_8888, pixelMap.GetAlphaType());
692 
693     void *dstPixels = dst;
694     uint32_t dstRowBytes = pixelMap.GetWidth() * componentsNum;
695     const ImageInfo dstInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
696         PixelFormat::RGBA_8888, pixelMap.GetAlphaType());
697 
698     ShowTransformParam(srcInfo, srcRowBytes, dstInfo, dstRowBytes, componentsNum);
699 
700     if ((srcPixels == nullptr) || (dstPixels == nullptr)) {
701         IMAGE_LOGE("DoTransformArgbToRgba, address issue.");
702         return false;
703     }
704 
705     const Position dstPos;
706     if (!PixelConvertAdapter::WritePixelsConvert(srcPixels, srcRowBytes, srcInfo,
707         dstPixels, dstPos, dstRowBytes, dstInfo)) {
708         IMAGE_LOGE("DoTransformArgbToRgba, pixel convert in adapter failed.");
709         return false;
710     }
711 
712     IMAGE_LOGD("DoTransformArgbToRgba OUT");
713     return true;
714 }
715 
DoTransformRGB565(Media::PixelMap & pixelMap,char * dst,int componentsNum)716 bool WebpEncoder::DoTransformRGB565(Media::PixelMap &pixelMap, char* dst, int componentsNum)
717 {
718     IMAGE_LOGD("DoTransformRGB565 IN");
719 
720     const void *srcPixels = pixelMap.GetPixels();
721     uint32_t srcRowBytes = pixelMap.GetRowBytes();
722     const ImageInfo srcInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
723         PixelFormat::RGB_565, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
724 
725     void *dstPixels = dst;
726     uint32_t dstRowBytes = pixelMap.GetWidth() * componentsNum;
727     const ImageInfo dstInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
728         PixelFormat::RGB_888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
729 
730     ShowTransformParam(srcInfo, srcRowBytes, dstInfo, dstRowBytes, componentsNum);
731 
732     if ((srcPixels == nullptr) || (dstPixels == nullptr)) {
733         IMAGE_LOGE("DoTransformRGB565, address issue.");
734         return false;
735     }
736 
737     const Position dstPos;
738     if (!PixelConvertAdapter::WritePixelsConvert(srcPixels, srcRowBytes, srcInfo,
739         dstPixels, dstPos, dstRowBytes, dstInfo)) {
740         IMAGE_LOGE("DoTransformRGB565, pixel convert in adapter failed.");
741         return false;
742     }
743 
744     IMAGE_LOGD("DoTransformRGB565 OUT");
745     return true;
746 }
747 
DoTransformGray(Media::PixelMap & pixelMap,char * dst,int componentsNum)748 bool WebpEncoder::DoTransformGray(Media::PixelMap &pixelMap, char* dst, int componentsNum)
749 {
750     IMAGE_LOGD("DoTransformGray IN");
751 
752     const void *srcPixels = pixelMap.GetPixels();
753     uint32_t srcRowBytes = pixelMap.GetRowBytes();
754     const ImageInfo srcInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
755         PixelFormat::ALPHA_8, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
756 
757     void *dstPixels = dst;
758     uint32_t dstRowBytes = pixelMap.GetWidth() * componentsNum;
759     const ImageInfo dstInfo = MakeImageInfo(pixelMap.GetWidth(), pixelMap.GetHeight(),
760         PixelFormat::RGBA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
761 
762     ShowTransformParam(srcInfo, srcRowBytes, dstInfo, dstRowBytes, componentsNum);
763 
764     if ((srcPixels == nullptr) || (dstPixels == nullptr)) {
765         IMAGE_LOGE("DoTransformGray, address issue.");
766         return false;
767     }
768 
769     const Position dstPos;
770     if (!PixelConvertAdapter::WritePixelsConvert(srcPixels, srcRowBytes, srcInfo,
771         dstPixels, dstPos, dstRowBytes, dstInfo)) {
772         IMAGE_LOGE("DoTransformGray, pixel convert in adapter failed.");
773         return false;
774     }
775 
776     IMAGE_LOGD("DoTransformGray OUT");
777     return true;
778 }
779 
MakeImageInfo(int width,int height,PixelFormat pf,AlphaType at,ColorSpace cs)780 ImageInfo WebpEncoder::MakeImageInfo(int width, int height, PixelFormat pf, AlphaType at, ColorSpace cs)
781 {
782     ImageInfo info = {
783         .size = {
784             .width = width,
785             .height = height
786         },
787         .pixelFormat = pf,
788         .colorSpace = cs,
789         .alphaType = at
790     };
791 
792     return info;
793 }
794 
ShowTransformParam(const ImageInfo & srcInfo,const uint32_t & srcRowBytes,const ImageInfo & dstInfo,const uint32_t & dstRowBytes,const int & componentsNum)795 void WebpEncoder::ShowTransformParam(const ImageInfo &srcInfo, const uint32_t &srcRowBytes,
796     const ImageInfo &dstInfo, const uint32_t &dstRowBytes, const int &componentsNum)
797 {
798     IMAGE_LOGD("src(width=%{public}u, height=%{public}u, rowBytes=%{public}u,"
799         " pixelFormat=%{public}u, colorspace=%{public}d, alphaType=%{public}d, baseDensity=%{public}d), "
800         "dst(width=%{public}u, height=%{public}u, rowBytes=%{public}u,"
801         " pixelFormat=%{public}u, colorspace=%{public}d, alphaType=%{public}d, baseDensity=%{public}d), "
802         "componentsNum=%{public}d",
803         srcInfo.size.width, srcInfo.size.height, srcRowBytes,
804         srcInfo.pixelFormat, srcInfo.colorSpace, srcInfo.alphaType, srcInfo.baseDensity,
805         dstInfo.size.width, dstInfo.size.height, dstRowBytes,
806         dstInfo.pixelFormat, dstInfo.colorSpace, dstInfo.alphaType, dstInfo.baseDensity,
807         componentsNum);
808 }
809 } // namespace ImagePlugin
810 } // namespace OHOS
811