fwt_software/tools/camera-bench/lossless_check.cpp

40 lines
2.4 KiB
C++

// Does the production encoder's distance-0 path succeed, and is the file lossless?
#include "fgc/JpegXlEncoder.h"
#include <jxl/decode.h>
#include <jxl/decode_cxx.h>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iterator>
#include <string>
#include <vector>
static std::vector<uint8_t> load(const char* p){std::ifstream f(p,std::ios::binary);return {std::istreambuf_iterator<char>(f),{}};}
static bool decode(const char* path, int ch, std::vector<uint8_t>& px, bool& lossy_flag){
auto data=load(path); if(data.empty()) return false;
auto dec=JxlDecoderMake(nullptr);
JxlDecoderSubscribeEvents(dec.get(), JXL_DEC_BASIC_INFO|JXL_DEC_FULL_IMAGE);
JxlDecoderSetInput(dec.get(), data.data(), data.size()); JxlDecoderCloseInput(dec.get());
JxlPixelFormat pf={(uint32_t)ch,JXL_TYPE_UINT8,JXL_NATIVE_ENDIAN,0};
for(;;){ auto s=JxlDecoderProcessInput(dec.get());
if(s==JXL_DEC_BASIC_INFO){JxlBasicInfo bi; JxlDecoderGetBasicInfo(dec.get(),&bi); lossy_flag=!bi.uses_original_profile;}
else if(s==JXL_DEC_NEED_IMAGE_OUT_BUFFER){size_t n; JxlDecoderImageOutBufferSize(dec.get(),&pf,&n); px.resize(n); JxlDecoderSetImageOutBuffer(dec.get(),&pf,px.data(),n);}
else if(s==JXL_DEC_FULL_IMAGE||s==JXL_DEC_SUCCESS) return true;
else return false; }
}
int main(){
std::ifstream j("frames/BayerRG8_0.json"); std::string t{std::istreambuf_iterator<char>(j),{}};
auto num=[&](const char* k){auto a=t.find(k); return a==std::string::npos?0:std::atoi(t.c_str()+t.find(':',a)+1);};
const int W=num("\"width\""),H=num("\"height\"");
struct T{const char* in; int ch;} ts[]={{"frames/BayerRG8_0.bin",1},{"frames/RGB8_0.bin",3}};
for(auto t:ts){
auto img=load(t.in); std::remove("check.jxl");
bool ok=fgc::JpegXlEncoder::encodeToFile("check.jxl",img.data(),W,H,t.ch,0.0f,1,3);
std::ifstream f("check.jxl",std::ios::binary|std::ios::ate); long long sz=f?(long long)f.tellg():-1;
std::vector<uint8_t> px; bool xyb=false; bool dok=sz>0&&decode("check.jxl",t.ch,px,xyb);
long long diff=0; int maxd=0;
if(dok) for(size_t i=0;i<img.size()&&i<px.size();++i){int d=std::abs(int(img[i])-int(px[i])); if(d){++diff; if(d>maxd)maxd=d;}}
std::printf("{\"input\":\"%s\",\"encode_returned\":%s,\"file_bytes\":%lld,\"decoded\":%s,\"xyb_lossy_colour\":%s,\"pixels_differing\":%lld,\"max_diff\":%d}\n",
t.in, ok?"true":"false", sz, dok?"true":"false", xyb?"true":"false", diff, maxd);
}
}