imencode
imdecode
图片的编码与解码
void valueChanged(int changeCount) {
this->setAlgorithm([=](const QImage & arg)->QImage {
if (changeCount<1) { return arg; }
auto i=changeCount;
try {
QImage image=arg.copy();
const auto imageData=const_cast<uchar*>(image.constBits());
const auto lineStep=image.bytesPerLine();
const auto imageHeight=image.height();
const auto imageWidth3=image.width()*3;
const auto lineEnd=imageData+imageHeight*lineStep;
std::vector<std::uint8_t> buffer;
const std::vector<int> par={
CV_IMWRITE_JPEG_QUALITY,77,
};
cv::Mat input(imageHeight,image.width(),CV_8UC3,
imageData,lineStep);
/*opencv架构级错误,导致大量无用运算*/
cv::cvtColor(input,input,cv::COLOR_RGB2BGR);
/*参考:*/
/*view-source:https://m13253.github.io/JPEGreen/*/
auto clamp=[](const auto & x)->std::uint8_t {
return (x>=0)?(x<=255)?
std::uint8_t(x):std::uint8_t(255)
:std::uint8_t(0);
};
auto clampuv=[](const auto & x)->std::int8_t {
return (x>=-128)?(x<=127)?
std::int8_t(x):std::int8_t(127)
:std::int8_t(-128);
};
while ((--i)>=0) {
/*RGB 与 YUV 低精度转换*/
auto line=imageData;
for (; line<lineEnd; line+=lineStep) {
auto p=line; auto pend=p+imageWidth3;
for (; p<pend; p+=3) {
auto &b=p[0];
auto &g=p[1];
auto &r=p[2];
const auto y=clamp((77*r+150*g+29*b)>>8);
const auto u=clampuv(((-43*r-85*g+128*b)>>8)-1);
const auto v=clampuv(((128*r-107*g-21*b)>>8)-1);
r=clamp((65536*y+91881*v)>>16);
g=clamp((65536*y-22553*u-46802*v)>>16);
b=clamp((65536*y+116130*u)>>16);
}
}
/*opencv架构级别错误,导致大量无用运算,
尤其是save/load图片过程中,第三方库一般是按照rgb设计的,
于是opencv要先将bgr转rgb,浪费大量时间
可以自行查看opencv源代码验证*/
cv::imencode(".jpeg",input,buffer,par);
input=cv::imdecode(buffer,CV_LOAD_IMAGE_COLOR,&input);
assert(imageData==input.data);
}
/*opencv架构级错误,导致大量无用运算*/
cv::cvtColor(input,input,cv::COLOR_RGB2BGR);
return std::move(image);
}
catch (...) { CPLUSPLUS_EXCEPTION(false); }
return arg;
});
}