Skip to content

Commit

Permalink
scan: enable high precision output
Browse files Browse the repository at this point in the history
scan now provides float image data to libavcodec for encoding instead of
rounding to 8 bit RGB, allowing for writing in full precision to formats
like portable floatmap.

Output bitdepths will now be higher by default for all formats that
support this; this may still be controlled by explicitly setting the
pixel format with e.g. --ff-opts pixel_format=rgb24
  • Loading branch information
0x09 committed Jul 6, 2024
1 parent d5d073d commit 6aa9538
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 14 deletions.
13 changes: 12 additions & 1 deletion include/ffapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <libavformat/avformat.h>
#include <libavutil/pixdesc.h>
#include <libavutil/parseutils.h>
#include <libavutil/intreadwrite.h>
#include <assert.h>
#include <stdbool.h>

Expand Down Expand Up @@ -49,7 +50,6 @@ size_t ffapi_seek_frame (FFContext*, size_t offset, void (*progress)(size_t))
int ffapi_write_frame(FFContext*, AVFrame*);
int ffapi_close(FFContext*);

// 8 bit only for now
#define FFA_PEL(frame,comp,x,y) frame->data[comp.plane][y*frame->linesize[comp.plane]+x*comp.step+comp.offset]
static inline void ffapi_setpel_direct(AVFrame* frame, size_t x, size_t y, AVComponentDescriptor comp, unsigned char val) {
assert(comp.depth == 8);
Expand All @@ -72,6 +72,17 @@ static inline void ffapi_setpell_direct(AVFrame* frame, size_t x, size_t y, AVCo
default: (ffapi_setpel_direct)(AVFrame,x,y,comp, val)\
)

static inline void ffapi_setpelf(FFContext* ctx, AVFrame* frame, size_t x, size_t y, int c, float val) {
AVComponentDescriptor comp = ctx->pixdesc->comp[c];
assert(comp.depth == 32 && (ctx->pixdesc->flags & AV_PIX_FMT_FLAG_FLOAT));
uint32_t valu = (union { float f; uint32_t u; }){val}.u;
uint8_t* data = &FFA_PEL(frame,comp,x,y);
if(ctx->pixdesc->flags & AV_PIX_FMT_FLAG_BE)
AV_WB32(data,valu);
else
AV_WL32(data,valu);
}

#define ffapi_setpel(FFContext,AVFrame,x,y,c,val) ffapi_setpel_direct(AVFrame,x,y,FFContext->pixdesc->comp[c],val)
#define ffapi_getpel(FFContext,AVFrame,x,y,c) ffapi_getpel_direct(AVFrame,x,y,FFContext->pixdesc->comp[c])
#define ffapi_setpixel(FFContext,AVFrame,x,y,val)\
Expand Down
24 changes: 11 additions & 13 deletions scan/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,10 @@ int main(int argc, char* argv[]) {
}
size_t width = MagickGetImageWidth(wand), height = MagickGetImageHeight(wand), channels = 3;

unsigned char blackpixel[channels];
memset(blackpixel,0,channels);

av_log_set_level(loglevel);
FFColorProperties color_props;
ffapi_parse_color_props(&color_props,"");
color_props.pix_fmt = AV_PIX_FMT_RGB24;
color_props.pix_fmt = AV_PIX_FMT_GBRPF32LE;
color_props.color_range = AVCOL_RANGE_JPEG;
int imagecolorspace = MagickGetImageColorspace(wand);
if(imagecolorspace == RGBColorspace)
Expand Down Expand Up @@ -375,8 +372,8 @@ int main(int argc, char* argv[]) {
if(visualize) {
intermediate normalization = spec_normalization_2d(x,y);
for(size_t z = 0; z < channels; z++) {
intermediate c = (spec ? spec_scale(sp,coeffs[(y*width+x)*channels+z]*normalization) : 1.0)*255;
ffapi_setpel(ffctx,frame,x+width,y,z,c);
intermediate c = spec ? spec_scale(sp,coeffs[(y*width+x)*channels+z]*normalization) : 1.0;
ffapi_setpelf(ffctx,frame,x+width,y,z,c);
}
}
}
Expand All @@ -390,7 +387,7 @@ int main(int argc, char* argv[]) {
intermediate pel = sum[(y*width+x)*channels+z];
if(trc_encode)
pel = trc_encode(pel);
ffapi_setpel(ffctx, frame, x, y, z, pel*255);
ffapi_setpelf(ffctx, frame, x, y, z, pel);
}
}

Expand All @@ -410,10 +407,10 @@ int main(int argc, char* argv[]) {
if(visualize) {
intermediate normalization = spec_normalization_2d(x,y);
for(size_t z = 0; z < channels; z++) {
intermediate c = (spec ? spec_scale(sp,coeffs[(y*width+x)*channels+z]*normalization) : 1.0)*255;
ffapi_setpel(ffctx,frame,x+width,y,z,c);
intermediate c = spec ? spec_scale(sp,coeffs[(y*width+x)*channels+z]*normalization) : 1.0;
ffapi_setpelf(ffctx,frame,x+width,y,z,c);
if(intermediates)
ffapi_setpel(ffctx,frame,x+width,y+height,z,c);
ffapi_setpelf(ffctx,frame,x+width,y+height,z,c);
}
}
}
Expand All @@ -432,7 +429,7 @@ int main(int argc, char* argv[]) {
intermediate pel = sum[(y*width+x)*channels+z];
if(trc_encode)
pel = trc_encode(pel);
ffapi_setpel(ffctx, frame, x, y, z, pel*255);
ffapi_setpelf(ffctx, frame, x, y, z, pel);
}

if(intermediates) {
Expand Down Expand Up @@ -463,7 +460,7 @@ int main(int argc, char* argv[]) {
intermediate pel = (((image[(y*width+x)*channels+z]+coeffs[z])-min[z])/(max[z]-min[z]));
if(trc_encode)
pel = trc_encode(pel);
ffapi_setpel(ffctx, frame, x, y+height, z, pel*255);
ffapi_setpelf(ffctx, frame, x, y+height, z, pel);
}
}

Expand All @@ -474,7 +471,8 @@ int main(int argc, char* argv[]) {
// just clear intermediate coords instead of wiping the entire frame
if(intermediates && visualize)
for(size_t ci = 0; ci < ncoords; ci++)
ffapi_setpixel(ffctx, frame, coords[ci][1]+width, coords[ci][0]+height, blackpixel);
for(size_t z = 0; z < channels; z++)
ffapi_setpelf(ffctx, frame, coords[ci][1]+width, coords[ci][0]+height, z, 0);
}
if(!quiet)
fprintf(stderr,"\n");
Expand Down

0 comments on commit 6aa9538

Please sign in to comment.