1. 程式人生 > >jpg實現影象縮放

jpg實現影象縮放

    jpg其實性質和bmp的差不多,但是jpg是經過壓縮的,所以在讀取jpg的影象資料時,不能像bmp影象那樣直接read了,而是有專門的動態庫函式支援,需要利用。這個動態庫中的函式其他都是按照流程來,這裡需要提一下jpeg_read_scanlines這個函式,jpg其實資料也是RGB 3個位元組的資料,但是他的順序是G B R,相對於bmp是反過來的,所以這裡需要注意一下。在讀取jpg影象時需要用到jpeg_read_scanlines,這個函式只能一次讀取一行,雖然函式說明它是支援多行讀取的,但是我改引數為多行會發生段錯誤,這裡原因不明,在程式中我用buffer申請讀取一行資料需要的記憶體大小,讀取每行資料到buffer,cinfo.output_scanline會自動加1。其他需要注意的是位元組匹配,一定要把所有的資料都讀到,不要忘記那三個位元組和讀取每列時應該乘以行的大小!

下面是實現程式碼:

    1 	#include "../inc/include.h"
    2 	
    3 	int show_jpg(const char *pathname)
    4 	{
    5 		unsigned char *buffer;
    6 		unsigned char *jpeg_buff;
    7 		unsigned char *pre_buff;
    8 		int x = 0;
    9 		FILE *infile; 
   10 	
   11 		/*1.為JPEG物件分配空間並初始化*/
   12 		struct jpeg_decompress_struct cinfo;
   13 		struct jpeg_error_mgr jerr;
   14 	
   15 		/*
   16 			將錯誤處理結構體物件繫結在JPEG物件上
   17 			jpeg_std_error在程式出現錯誤的時候自動執行exit退出
   18 		 */
   19 		cinfo.err = jpeg_std_error(&jerr);
   20 	
   21 		/*初始化cinfo結構*/
   22 		jpeg_create_decompress(&cinfo);
   23 	
   24 		/*2.指定解壓縮資料來源*/
   25 		if ((infile = fopen(pathname, "r")) == NULL)
   26 		{
   27 			perror("open fail");
   28 			return -1;
   29 		}
   30 		jpeg_stdio_src(&cinfo, infile);
   31 	
   32 		/*3.獲取檔案資訊*/
   33 		(void)jpeg_read_header(&cinfo, TRUE);
   34 		printf("width = %d, height = %d\n", cinfo.image_width, cinfo.image_height);
   35 		if ((cinfo.image_height != 480) || (cinfo.image_width != 800))
   36 		{
   37 			printf("This jpeg_image is not 800*480,I need change it\n");
   38 		}
   39 	
   40 		/*4.解壓圖片,以行為單位*/
   41 		jpeg_start_decompress(&cinfo);
   42 	
   43 		bzero(lcd, LCD_SIZE);
   44 		usleep(1000);
   45 	
   46 		/*5.取出資料*/
   47 		int row_stride = cinfo.output_width * cinfo.output_components; //計算每行影象所需的位元組大小
   48 		buffer = malloc(row_stride);
   49 		pre_buff = malloc(cinfo.output_width * cinfo.output_components * cinfo.output_height); //很關鍵,不能少
   50 	
   51 		while (cinfo.output_scanline < cinfo.output_height)
   52 		{
   53 			(void)jpeg_read_scanlines(&cinfo, (JSAMPARRAY)&buffer, 1);
   54 	
   55 			for (int i = 0; i < (cinfo.output_width * cinfo.output_components); ++i)
   56 			{
   57 				pre_buff[(cinfo.output_scanline - 1) * cinfo.output_width  * cinfo.output_components + i] = buffer[i];
   58 			}
   59 		}
   60 	
   61 		//利用最鄰近插值進行影象變換
   62 		jpeg_buff = insert_near(pre_buff, cinfo.image_width, cinfo.image_height, 800, 480);
   63 		
   64 		for (int i = 0; i < 480; ++i)
   65 		{
   66 			for (int j = 0, x = 0; j < 800; ++j)
   67 			{
   68 				*(pre_lcd[i] + j) = jpeg_buff[i*800*3 + x] << 16 | jpeg_buff[i*800*3 + x + 1] << 8 | jpeg_buff[i*800*3 + x + 2];
   69 				x += 3;
   70 			}
   71 		}
   72 		
   73 	
   74 		/*6.解壓縮完畢*/
   75 		(void)jpeg_finish_decompress(&cinfo);
   76 	
   77 		/*7.釋放資源*/
   78 		jpeg_destroy_decompress(&cinfo);
   79 		fclose(infile);
   80 	
   81 		/*8.退出程式*/
   82 		jpeg_destroy_decompress(&cinfo);
   83 	
   84 		return 0;
   85 	}