jpg實現影象縮放
阿新 • • 發佈:2018-12-11
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 }