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 
16 #include "output.h"
17 #include <GLES3/gl32.h>
18 #include <cmath>
19 #include <memory>
20 
21 namespace OHOS {
22 namespace Rosen {
Output()23 Output::Output()
24 {
25     CreateProgram(GetVertexShader(), GetFragmentShader());
26 }
27 
GetFilterType()28 FILTER_TYPE Output::GetFilterType()
29 {
30     return FILTER_TYPE::OUTPUT;
31 }
32 
GetPixelMap()33 std::unique_ptr<OHOS::Media::PixelMap> Output::GetPixelMap()
34 {
35     return std::move(pixelMap_);
36 }
37 
GetColorBuffer()38 const std::vector<uint8_t>& Output::GetColorBuffer()
39 {
40     return colorBuffer_;
41 }
42 
DoProcess(ProcessData & data)43 void Output::DoProcess(ProcessData& data)
44 {
45     if (format_ == "image/jpeg" || format_ == "image/png") {
46         EncodeToFile(data);
47     } else if (format_ == "pixelMap") {
48         EncodeToPixelMap(data);
49     } else if (format_ == "buffer") {
50         WriteToBuffer(data);
51     } else {
52         LOGE("The format of Output is incorrect!!!");
53     }
54 }
55 
EncodeToFile(ProcessData & data)56 void Output::EncodeToFile(ProcessData& data)
57 {
58     EncodeToPixelMap(data);
59     OHOS::Media::ImagePacker imagePacker;
60     OHOS::Media::PackOption option;
61     option.format = format_;
62     std::set<std::string> formats;
63     uint32_t ret = imagePacker.GetSupportedFormats(formats);
64     if (ret != 0) {
65         return;
66     }
67     imagePacker.StartPacking(dstImagePath_, option);
68     if (pixelMap_ == nullptr) {
69         LOGE("The pixelMap is null.");
70         return;
71     }
72     imagePacker.AddImage(*pixelMap_);
73     int64_t packedSize = 0;
74     imagePacker.FinalizePacking(packedSize);
75 }
76 
EncodeToPixelMap(ProcessData & data)77 void Output::EncodeToPixelMap(ProcessData& data)
78 {
79     WriteToBuffer(data);
80     WriteToBuffer(data);
81     Media::InitializationOptions opts;
82     opts.size.width = std::ceil(data.textureWidth);
83     opts.size.height = std::ceil(data.textureHeight);
84     opts.editable = true;
85     pixelMap_ = Media::PixelMap::Create(opts);
86     if (pixelMap_ == nullptr) {
87         LOGE("The pixelMap create failed.");
88         return;
89     }
90     pixelMap_->WritePixels(colorBuffer_.data(), pixelMap_->GetByteCount());
91 }
92 
WriteToBuffer(ProcessData & data)93 void Output::WriteToBuffer(ProcessData& data)
94 {
95     uint32_t bufferSize = static_cast<uint32_t>(data.textureWidth * data.textureHeight * COLOR_CHANNEL);
96     colorBuffer_.resize(bufferSize);
97     glBindFramebuffer(GL_FRAMEBUFFER, data.frameBufferID);
98     glBindTexture(GL_TEXTURE_2D, data.dstTextureID);
99     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data.textureWidth, data.textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
100     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, data.dstTextureID, 0);
101     Use();
102     glViewport(0, 0, data.textureWidth, data.textureHeight);
103     glBindVertexArray(mesh_->VAO_);
104     glBindTexture(GL_TEXTURE_2D, data.srcTextureID);
105     glDrawElements(GL_TRIANGLES, AlgoFilter::DRAW_ELEMENTS_NUMBER, GL_UNSIGNED_INT, 0);
106     glPixelStorei(GL_PACK_ALIGNMENT, 1);
107     glReadPixels(0, 0, data.textureWidth, data.textureHeight, GL_RGBA, GL_UNSIGNED_BYTE, colorBuffer_.data());
108 }
109 
SetValue(const std::string & key,std::shared_ptr<void> value,int size)110 void Output::SetValue(const std::string& key, std::shared_ptr<void> value, int size)
111 {
112     if (key == "format" && size > 0) {
113         std::shared_ptr<std::string> format = std::static_pointer_cast<std::string>(value);
114         format_ = *(format.get());
115         if (format_ == "jpg" || format_ == "jpeg") {
116             format_ = "image/jpeg";
117         } else if (format_ == "png") {
118             format_ = "image/png";
119         }
120         LOGD("The output format is %{public}s.", format_.c_str());
121     } else if (key == "dst" && size > 0) {
122         if (format_ == "image/jpeg" || format_ == "image/png") {
123             std::shared_ptr<std::string> dstImagePath = std::static_pointer_cast<std::string>(value);
124             dstImagePath_ = *(dstImagePath.get());
125             LOGD("The ouput source image path is %{public}s.", dstImagePath_.c_str());
126         }
127     }
128 }
129 
GetVertexShader()130 std::string Output::GetVertexShader()
131 {
132     return R"SHADER(#version 320 es
133         precision mediump float;
134         layout (location = 0) in vec3 vertexCoord;
135         layout (location = 1) in vec2 inputTexCoord;
136         out vec2 texCoord;
137 
138         void main()
139         {
140             gl_Position = vec4(vertexCoord, 1.0);
141             texCoord = inputTexCoord;
142         }
143     )SHADER";
144 }
145 
GetFragmentShader()146 std::string Output::GetFragmentShader()
147 {
148     return R"SHADER(#version 320 es
149         precision mediump float;
150         in vec2 texCoord;
151         out vec4 fragColor;
152         uniform sampler2D uTexture;
153         void main()
154         {
155             fragColor = texture(uTexture, texCoord);
156         }
157     )SHADER";
158 }
159 } // namespcae Rosen
160 } // namespace OHOS