mirror of
https://github.com/simon987/libscan.git
synced 2025-04-05 12:23:00 +00:00
Save ebook renders as jpeg
This commit is contained in:
parent
0438c0e761
commit
e7eca2c90a
@ -1,9 +1,10 @@
|
||||
#include "ebook.h"
|
||||
#include "../util.h"
|
||||
#include <mupdf/fitz.h>
|
||||
#include <pthread.h>
|
||||
#include <tesseract/capi.h>
|
||||
|
||||
#include "../media/media.h"
|
||||
|
||||
#define MIN_OCR_SIZE 350
|
||||
#define MIN_OCR_LEN 10
|
||||
|
||||
@ -71,32 +72,61 @@ int render_cover(scan_ebook_ctx_t *ctx, fz_context *fzctx, document_t *doc, fz_d
|
||||
return -1;
|
||||
}
|
||||
|
||||
fz_buffer *fzbuf = NULL;
|
||||
fz_var(fzbuf);
|
||||
fz_var(err);
|
||||
|
||||
fz_try(fzctx)
|
||||
fzbuf = fz_new_buffer_from_pixmap_as_png(fzctx, pixmap, fz_default_color_params);
|
||||
fz_catch(fzctx)
|
||||
err = fzctx->error.errcode;
|
||||
|
||||
if (err == 0) {
|
||||
unsigned char *tn_buf;
|
||||
size_t tn_len = fz_buffer_storage(fzctx, fzbuf, &tn_buf);
|
||||
APPEND_TN_META(doc, pixmap->x, pixmap->y)
|
||||
ctx->store((char *) doc->uuid, sizeof(doc->uuid), (char *) tn_buf, tn_len);
|
||||
}
|
||||
|
||||
fz_drop_buffer(fzctx, fzbuf);
|
||||
fz_drop_pixmap(fzctx, pixmap);
|
||||
fz_drop_page(fzctx, cover);
|
||||
|
||||
if (err != 0) {
|
||||
CTX_LOG_WARNINGF(doc->filepath, "fz_new_buffer_from_pixmap_as_png() returned error code [%d] %s", err,
|
||||
fzctx->error.message)
|
||||
if (pixmap->n != 3) {
|
||||
CTX_LOG_ERRORF(doc->filepath, "Got unexpected pixmap depth: %d", pixmap->n)
|
||||
fz_drop_page(fzctx, cover);
|
||||
fz_drop_pixmap(fzctx, pixmap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// RGB24 -> YUV420p
|
||||
AVFrame *scaled_frame = av_frame_alloc();
|
||||
|
||||
struct SwsContext *sws_ctx= sws_getContext(
|
||||
pixmap->w, pixmap->h, AV_PIX_FMT_RGB24,
|
||||
pixmap->w, pixmap->h, AV_PIX_FMT_YUVJ420P,
|
||||
SIST_SWS_ALGO, 0, 0, 0
|
||||
);
|
||||
|
||||
int dst_buf_len = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pixmap->w, pixmap->h, 1);
|
||||
uint8_t *dst_buf = (uint8_t *) av_malloc(dst_buf_len);
|
||||
|
||||
av_image_fill_arrays(scaled_frame->data, scaled_frame->linesize, dst_buf, AV_PIX_FMT_YUV420P, pixmap->w, pixmap->h, 1);
|
||||
|
||||
const uint8_t *in_data[1] = {pixmap->samples};
|
||||
int in_line_size[1] = {3 * pixmap->w};
|
||||
|
||||
sws_scale(sws_ctx,
|
||||
in_data, in_line_size,
|
||||
0, pixmap->h,
|
||||
scaled_frame->data, scaled_frame->linesize
|
||||
);
|
||||
|
||||
scaled_frame->width = pixmap->w;
|
||||
scaled_frame->height = pixmap->h;
|
||||
scaled_frame->format = AV_PIX_FMT_YUV420P;
|
||||
|
||||
sws_freeContext(sws_ctx);
|
||||
|
||||
// YUV420p -> JPEG
|
||||
AVCodecContext *jpeg_encoder = alloc_jpeg_encoder(pixmap->w, pixmap->h, 1.0f);
|
||||
avcodec_send_frame(jpeg_encoder, scaled_frame);
|
||||
|
||||
AVPacket jpeg_packet;
|
||||
av_init_packet(&jpeg_packet);
|
||||
avcodec_receive_packet(jpeg_encoder, &jpeg_packet);
|
||||
|
||||
APPEND_TN_META(doc, pixmap->w, pixmap->h)
|
||||
ctx->store((char *) doc->uuid, sizeof(doc->uuid), (char *) jpeg_packet.data, jpeg_packet.size);
|
||||
|
||||
av_packet_unref(&jpeg_packet);
|
||||
av_free(*scaled_frame->data);
|
||||
av_frame_free(&scaled_frame);
|
||||
avcodec_free_context(&jpeg_encoder);
|
||||
|
||||
fz_drop_pixmap(fzctx, pixmap);
|
||||
fz_drop_page(fzctx, cover);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,6 @@
|
||||
|
||||
#include "../util.h"
|
||||
|
||||
#include "libavformat/avformat.h"
|
||||
#include "libswscale/swscale.h"
|
||||
#include "libswresample/swresample.h"
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
@ -15,28 +10,6 @@
|
||||
#define IS_VIDEO(fmt) (fmt->iformat->name && strcmp(fmt->iformat->name, "image2") != 0)
|
||||
|
||||
|
||||
__always_inline
|
||||
static AVCodecContext *alloc_jpeg_encoder(scan_media_ctx_t *ctx, int dstW, int dstH, float qscale) {
|
||||
|
||||
AVCodec *jpeg_codec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
|
||||
AVCodecContext *jpeg = avcodec_alloc_context3(jpeg_codec);
|
||||
jpeg->width = dstW;
|
||||
jpeg->height = dstH;
|
||||
jpeg->time_base.den = 1000000;
|
||||
jpeg->time_base.num = 1;
|
||||
jpeg->i_quant_factor = qscale;
|
||||
|
||||
jpeg->pix_fmt = AV_PIX_FMT_YUVJ420P;
|
||||
int ret = avcodec_open2(jpeg, jpeg_codec, NULL);
|
||||
|
||||
if (ret != 0) {
|
||||
CTX_LOG_WARNINGF("media.c", "Could not open jpeg encoder: %s!\n", av_err2str(ret));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return jpeg;
|
||||
}
|
||||
|
||||
__always_inline
|
||||
AVFrame *scale_frame(const AVCodecContext *decoder, const AVFrame *frame, int size) {
|
||||
|
||||
@ -362,7 +335,7 @@ void parse_media_format_ctx(scan_media_ctx_t *ctx, AVFormatContext *pFormatCtx,
|
||||
}
|
||||
|
||||
// Encode frame to jpeg
|
||||
AVCodecContext *jpeg_encoder = alloc_jpeg_encoder(ctx, scaled_frame->width, scaled_frame->height,
|
||||
AVCodecContext *jpeg_encoder = alloc_jpeg_encoder(scaled_frame->width, scaled_frame->height,
|
||||
ctx->tn_qscale);
|
||||
avcodec_send_frame(jpeg_encoder, scaled_frame);
|
||||
|
||||
@ -602,7 +575,7 @@ int store_image_thumbnail(scan_media_ctx_t *ctx, void* buf, size_t buf_len, docu
|
||||
}
|
||||
|
||||
// Encode frame to jpeg
|
||||
AVCodecContext *jpeg_encoder = alloc_jpeg_encoder(ctx, scaled_frame->width, scaled_frame->height, ctx->tn_qscale);
|
||||
AVCodecContext *jpeg_encoder = alloc_jpeg_encoder(scaled_frame->width, scaled_frame->height, ctx->tn_qscale);
|
||||
avcodec_send_frame(jpeg_encoder, scaled_frame);
|
||||
|
||||
AVPacket jpeg_packet;
|
||||
|
@ -4,6 +4,12 @@
|
||||
|
||||
#include "../scan.h"
|
||||
|
||||
#include "libavformat/avformat.h"
|
||||
#include "libswscale/swscale.h"
|
||||
#include "libswresample/swresample.h"
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
|
||||
typedef struct {
|
||||
log_callback_t log;
|
||||
logf_callback_t logf;
|
||||
@ -14,6 +20,28 @@ typedef struct {
|
||||
long max_media_buffer;
|
||||
} scan_media_ctx_t;
|
||||
|
||||
__always_inline
|
||||
static AVCodecContext *alloc_jpeg_encoder(int w, int h, float qscale) {
|
||||
|
||||
AVCodec *jpeg_codec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
|
||||
AVCodecContext *jpeg = avcodec_alloc_context3(jpeg_codec);
|
||||
jpeg->width = w;
|
||||
jpeg->height = h;
|
||||
jpeg->time_base.den = 1000000;
|
||||
jpeg->time_base.num = 1;
|
||||
jpeg->i_quant_factor = qscale;
|
||||
|
||||
jpeg->pix_fmt = AV_PIX_FMT_YUVJ420P;
|
||||
int ret = avcodec_open2(jpeg, jpeg_codec, NULL);
|
||||
|
||||
if (ret != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return jpeg;
|
||||
}
|
||||
|
||||
|
||||
void parse_media(scan_media_ctx_t *ctx, vfile_t *f, document_t *doc);
|
||||
void init_media();
|
||||
|
||||
|
@ -1,37 +1,8 @@
|
||||
#include "raw.h"
|
||||
#include <libraw/libraw.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "../media/media.h"
|
||||
|
||||
#include "libswscale/swscale.h"
|
||||
#include "libswresample/swresample.h"
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
|
||||
|
||||
|
||||
__always_inline
|
||||
static AVCodecContext *alloc_jpeg_encoder(scan_raw_ctx_t *ctx, int dstW, int dstH, float qscale) {
|
||||
|
||||
AVCodec *jpeg_codec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
|
||||
AVCodecContext *jpeg = avcodec_alloc_context3(jpeg_codec);
|
||||
jpeg->width = dstW;
|
||||
jpeg->height = dstH;
|
||||
jpeg->time_base.den = 1000000;
|
||||
jpeg->time_base.num = 1;
|
||||
jpeg->i_quant_factor = qscale;
|
||||
|
||||
jpeg->pix_fmt = AV_PIX_FMT_YUVJ420P;
|
||||
int ret = avcodec_open2(jpeg, jpeg_codec, NULL);
|
||||
|
||||
if (ret != 0) {
|
||||
CTX_LOG_WARNINGF("raw.c", "Could not open jpeg encoder: %s!\n", av_err2str(ret))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return jpeg;
|
||||
}
|
||||
|
||||
#define MIN_SIZE 32
|
||||
|
||||
@ -152,11 +123,11 @@ void parse_raw(scan_raw_ctx_t *ctx, vfile_t *f, document_t *doc) {
|
||||
|
||||
av_image_fill_arrays(scaled_frame->data, scaled_frame->linesize, dst_buf, AV_PIX_FMT_YUV420P, dstW, dstH, 1);
|
||||
|
||||
const uint8_t *inData[1] = {img->data};
|
||||
int inLinesize[1] = {3 * img->width};
|
||||
const uint8_t *in_data[1] = {img->data};
|
||||
int in_line_size[1] = {3 * img->width};
|
||||
|
||||
sws_scale(sws_ctx,
|
||||
inData, inLinesize,
|
||||
in_data, in_line_size,
|
||||
0, img->height,
|
||||
scaled_frame->data, scaled_frame->linesize
|
||||
);
|
||||
@ -167,7 +138,7 @@ void parse_raw(scan_raw_ctx_t *ctx, vfile_t *f, document_t *doc) {
|
||||
|
||||
sws_freeContext(sws_ctx);
|
||||
|
||||
AVCodecContext *jpeg_encoder = alloc_jpeg_encoder(ctx, scaled_frame->width, scaled_frame->height, 1.0f);
|
||||
AVCodecContext *jpeg_encoder = alloc_jpeg_encoder(scaled_frame->width, scaled_frame->height, 1.0f);
|
||||
avcodec_send_frame(jpeg_encoder, scaled_frame);
|
||||
|
||||
AVPacket jpeg_packet;
|
||||
|
@ -174,12 +174,16 @@ TEST(Ebook, CandlePdf) {
|
||||
document_t doc;
|
||||
load_doc_file("libscan-test-files/test_files/ebook/General_-_Candle_Making.pdf", &f, &doc);
|
||||
|
||||
size_t size_before = store_size;
|
||||
|
||||
parse_ebook(&ebook_500_ctx, &f, "application/pdf", &doc);
|
||||
|
||||
ASSERT_STREQ(get_meta(&doc, MetaTitle)->str_val, "Microsoft Word - A531 Candlemaking-01.doc");
|
||||
ASSERT_STREQ(get_meta(&doc, MetaAuthor)->str_val, "Dafydd Prichard");
|
||||
ASSERT_NEAR(strlen(get_meta(&doc, MetaContent)->str_val), 500, 4);
|
||||
ASSERT_NE(get_meta(&doc, MetaContent)->str_val[0], ' ');
|
||||
ASSERT_NE(size_before, store_size);
|
||||
|
||||
cleanup(&doc, &f);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user