• mupdf实现常用图片转换为灰度图pnm


    我要实现的工作是使用mupdf库转换pdf、jpeg、tif等文件为灰度图,转换完成的灰度图存放到内存中,而不是存为文件,在读取到内存中,主要是嵌入式系统中使用。下面是example.c,我加了我理解的注释,以及自己修改的地方。example.c全文

    #include <mupdf/fitz.h>
    
    void
    render(char *filename, int pagenumber, int zoom, int rotation)
    {
    	// Create a context to hold the exception stack and various caches.
    
    	fz_context *ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
    
    	// set color to gray
    	
            //fz_device_gray(ctx);
    	
    	// Register the default file types.
    
    	fz_register_document_handlers(ctx);
    
    	// Open the PDF, XPS or CBZ document.
           //这里文件可以是任意mupdf识别的文件pdf、jpeg、tif、png等,打开文档函数实现了多态,会自动选择相应的文件处理函数来处理图像
    
    	fz_document *doc = fz_open_document(ctx, filename);
    
    	// Retrieve the number of pages (not used in this example).
           // 计算出文档的页数,相对pdf等多页文档来说的,这个例子暂时不用。
    
    	int pagecount = fz_count_pages(doc);
    
    	// Load the page we want. Page numbering starts from zero.
    
    	fz_page *page = fz_load_page(doc, pagenumber - 1);
    
    	// Calculate a transform to use when rendering. This transform
    	// contains the scale and rotation. Convert zoom percentage to a
    	// scaling factor. Without scaling the resolution is 72 dpi.
    
    	fz_matrix transform;
    	fz_rotate(&transform, rotation);
    	//fz_scale(&transform,2.0f,1.0f);	
    	fz_pre_scale(&transform, zoom / 100.0f, zoom / 100.0f);
    
    	// Take the page bounds and transform them by the same matrix that
    	// we will use to render the page.
    
    	fz_rect bounds;
    	fz_bound_page(doc, page, &bounds);
    	fz_transform_rect(&bounds, &transform);
    
    	// Create a blank pixmap to hold the result of rendering. The
    	// pixmap bounds used here are the same as the transformed page
    	// bounds, so it will contain the entire page. The page coordinate
    	// space has the origin at the top left corner and the x axis
    	// extends to the right and the y axis extends down.
    
    	fz_irect bbox;
    	fz_round_rect(&bbox, &bounds);
           // 这里修改了此函数的第三个参数为fz_device_rgb(..)为fz_device_grzy(..),将图像变为灰度图
    	fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), &bbox);
    	fz_clear_pixmap_with_value(ctx, pix, 0xff);
    
    	// A page consists of a series of objects (text, line art, images,
    	// gradients). These objects are passed to a device when the
    	// interpreter runs the page. There are several devices, used for
    	// different purposes:
    	//
    	//	draw device -- renders objects to a target pixmap.
    	//
    	//	text device -- extracts the text in reading order with styling
    	//	information. This text can be used to provide text search.
    	//
    	//	list device -- records the graphic objects in a list that can
    	//	be played back through another device. This is useful if you
    	//	need to run the same page through multiple devices, without
    	//	the overhead of parsing the page each time.
    
    	// Create a draw device with the pixmap as its target.
    	// Run the page with the transform.
    
    	fz_device *dev = fz_new_draw_device(ctx, pix);
    	fz_run_page(doc, page, dev, &transform, NULL);
    	fz_free_device(dev);
    
    	// Save the pixmap to a file.
           /*
           * 这里改动较大,首先用申请了一个fz_buffer,用来存放转换好的灰度图数据。申请过程以及销毁申请的内存以及内存扩充等工作均由mupdf来维护。后边介绍struct fz_buffer定义
           */
    	fz_buffer * buffer= fz_new_buffer(ctx,1916);
    
    	fz_write_png(ctx, pix, "out.png", 0);
           //这个函数我自己添加的,实现了内存存放位图数据到fz_buffer中
    	fz_write_pnm_buffer(ctx,pix,buffer,1);
    	
    	FILE * pgm_fd = fopen("3.pgm","w");
           // 将位图数据写到文件中,主要是为了测试用
    	fwrite(buffer->data,buffer->len,1,pgm_fd);
    	fclose(pgm_fd);
    	
    
    	// Clean up.
    
    	fz_drop_pixmap(ctx, pix);
    	fz_free_page(doc, page);
    	fz_close_document(doc);
    	fz_free_context(ctx);
    }
    
    int main(int argc, char **argv)
    {
    	char *filename = argc >= 2 ? argv[1] : "";
    	int pagenumber = argc > 2 ? atoi(argv[2]) : 1;
    	int zoom = argc > 3 ? atoi(argv[3]) : 100;
    	int rotation = argc > 4 ? atoi(argv[4]) : 0;
    
    	render(filename, pagenumber, zoom, rotation);
    	return 0;
    }

    fz_buffer在文件buffer.h中定义,如下:

    struct fz_buffer_s
    {
    	int refs;
    	unsigned char *data;
    	int cap, len;
    	int unused_bits;
    };

    另外我添加了一个函数void fz_write_pnm_buffer(fz_context *ctx, fz_pixmap *pixmap, fz_buffer *buffer,int head_flag),它的申明添加到output-pnm.h中,定义添加到pixmap.c中,定义如下

    void
    fz_write_pnm_buffer(fz_context *ctx, fz_pixmap *pixmap, fz_buffer *buffer,int head_flag)
    {
    	fz_output *out = fz_new_output_with_buffer(ctx, buffer);
    	if (head_flag == 1)
    		fz_output_pnm_header(out, pixmap->w, pixmap->h, pixmap->n);
    	fz_output_pnm_band(out, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples);
    	fz_close_output(out);
    }

    这里head_flag主要是为了选择是否将pnm的头添加到数据中。

    这样切换到编译好的mupdf源码目录下,编译好的库和可执行文件均存放在./bulid/debug/目录下。执行下边命令:

    gcc -g -o build/debug/example -Iinclude docs/example.c build/debug/libmupdf.a build/debug/libfreetype.a build/debug/libjbig2dec.a 
    build/debug/libjpeg.a build/debug/libopenjpeg.a build/debug/libz.a –lm
    生成的example可执行文件在bulid/debug目录下。这样可以使用如下命令
    ./example test.pdf 1 200 0
    ./example test.jpg 
    ./example test.tif
    均可生成对应的pnm图像,我们也可以对fz_buffer中的数据做其他处理,只要去修改example.c代码即可
  • 相关阅读:
    程序崩溃访问非法内存
    C# IP转换,时间转换
    _heap_alloc_dbg 崩溃
    TaskIcon 系统任务栏图标
    zlib 压缩使用
    桌面清理工具
    CMMI知识库(精简版)
    JAVA程序员面试题集合
    OracleDECODE用法
    Oracle索引重建
  • 原文地址:https://www.cnblogs.com/pang1567/p/4106803.html
Copyright © 2020-2023  润新知