├── Makefile ├── Makefile.build ├── config └── config.h ├── convert ├── Makefile ├── color.c ├── color.h ├── convert_manager.c ├── jdatasrc-tj.c ├── jerror.h ├── jinclude.h ├── jpeglib.h ├── mjpeg2rgb.c ├── rgb2rgb.c └── yuv_2_rgb.c ├── display ├── Makefile ├── disp_manager.c └── framebuffer.c ├── inc ├── convert_manager.h ├── disp_manager.h ├── picfmt_manage.h ├── picture_ops.h ├── render.h └── video_manager.h ├── main.c ├── netprint_client.c ├── readme.md ├── render ├── Makefile └── operation │ ├── Makefile │ ├── merge.c │ └── zoom.c └── video ├── Makefile ├── v412.c └── video_manager.c /Makefile: -------------------------------------------------------------------------------- 1 | 2 | CROSS_COMPILE = arm-linux- 3 | AS = $(CROSS_COMPILE)as 4 | LD = $(CROSS_COMPILE)ld 5 | CC = $(CROSS_COMPILE)gcc 6 | CPP = $(CC) -E 7 | AR = $(CROSS_COMPILE)ar 8 | NM = $(CROSS_COMPILE)nm 9 | 10 | STRIP = $(CROSS_COMPILE)strip 11 | OBJCOPY = $(CROSS_COMPILE)objcopy 12 | OBJDUMP = $(CROSS_COMPILE)objdump 13 | 14 | export AS LD CC CPP AR NM 15 | export STRIP OBJCOPY OBJDUMP 16 | 17 | CFLAGS := -Wall -O2 -g 18 | CFLAGS += -I $(shell pwd)/include 19 | 20 | LDFLAGS := -lm -ljpeg 21 | 22 | export CFLAGS LDFLAGS 23 | 24 | TOPDIR := $(shell pwd) 25 | export TOPDIR 26 | 27 | TARGET := video2lcd 28 | 29 | 30 | obj-y += main.o 31 | obj-y += convert/ 32 | obj-y += display/ 33 | obj-y += render/ 34 | obj-y += video/ 35 | 36 | all : start_recursive_build $(TARGET) 37 | @echo $(TARGET) has been built! 38 | 39 | start_recursive_build: 40 | make -C ./ -f $(TOPDIR)/Makefile.build 41 | 42 | $(TARGET) : start_recursive_build 43 | $(CC) -o $(TARGET) built-in.o $(LDFLAGS) 44 | 45 | clean: 46 | rm -f $(shell find -name "*.o") 47 | rm -f $(TARGET) 48 | 49 | distclean: 50 | rm -f $(shell find -name "*.o") 51 | rm -f $(shell find -name "*.d") 52 | rm -f $(TARGET) 53 | 54 | -------------------------------------------------------------------------------- /Makefile.build: -------------------------------------------------------------------------------- 1 | PHONY := __build 2 | __build: 3 | 4 | 5 | obj-y := 6 | subdir-y := 7 | 8 | include Makefile 9 | 10 | # obj-y := a.o b.o c/ d/ 11 | # $(filter %/, $(obj-y)) : c/ d/ 12 | # __subdir-y : c d 13 | # subdir-y : c d 14 | __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) 15 | subdir-y += $(__subdir-y) 16 | 17 | # c/built-in.o d/built-in.o 18 | subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o) 19 | 20 | # a.o b.o 21 | cur_objs := $(filter-out %/, $(obj-y)) 22 | dep_files := $(foreach f,$(cur_objs),.$(f).d) 23 | dep_files := $(wildcard $(dep_files)) 24 | 25 | ifneq ($(dep_files),) 26 | include $(dep_files) 27 | endif 28 | 29 | 30 | PHONY += $(subdir-y) 31 | 32 | 33 | __build : $(subdir-y) built-in.o 34 | 35 | $(subdir-y): 36 | make -C $@ -f $(TOPDIR)/Makefile.build 37 | 38 | built-in.o : $(cur_objs) $(subdir_objs) 39 | $(LD) -r -o $@ $^ 40 | 41 | dep_file = .$@.d 42 | 43 | %.o : %.c 44 | $(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $< 45 | 46 | .PHONY : $(PHONY) -------------------------------------------------------------------------------- /config/config.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _CONFIG_H 3 | #define _CONFIG_H 4 | 5 | #include 6 | 7 | 8 | //#define DBG_PRINTF(...) 9 | #define DBG_PRINTF printf 10 | 11 | #define FB_DEVICE_NAME "/dev/fb0" 12 | 13 | #endif /* _CONFIG_H */ 14 | -------------------------------------------------------------------------------- /convert/Makefile: -------------------------------------------------------------------------------- 1 | obj-y += convert_manager.o 2 | obj-y += yuv2rgb.o 3 | obj-y += color.o 4 | obj-y += mjpeg2rgb.o 5 | obj-y += jdatasrc-tj.o 6 | obj-y += rgb2rgb.o 7 | -------------------------------------------------------------------------------- /convert/color.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | # GspcaGui: Gspca/Spca5xx Grabber # 3 | # Copyright (C) 2004 2005 2006 Michel Xhaard # 4 | # # 5 | # This program is free software; you can redistribute it and/or modify # 6 | # it under the terms of the GNU General Public License as published by # 7 | # the Free Software Foundation; either version 2 of the License, or # 8 | # (at your option) any later version. # 9 | # # 10 | # This program is distributed in the hope that it will be useful, # 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # 13 | # GNU General Public License for more details. # 14 | # # 15 | # You should have received a copy of the GNU General Public License # 16 | # along with this program; if not, write to the Free Software # 17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # 18 | # # 19 | ****************************************************************************/ 20 | #include 21 | #include 22 | #include 23 | #include "color.h" 24 | 25 | static int *LutYr = NULL; 26 | static int *LutYg = NULL;; 27 | static int *LutYb = NULL;; 28 | static int *LutVr = NULL;; 29 | static int *LutVrY = NULL;; 30 | static int *LutUb = NULL;; 31 | static int *LutUbY = NULL;; 32 | static int *LutRv = NULL; 33 | static int *LutGu = NULL; 34 | static int *LutGv = NULL; 35 | static int *LutBu = NULL; 36 | 37 | #if 0 38 | #define RGB24_TO_Y(r,g,b) LutYr[(r)] + LutYg[(g)] + LutYb[(b)] 39 | #define YR_TO_V(r,y) LutVr[(r)] + LutVrY[(y)] 40 | #define YB_TO_U(b,y) LutUb[(b)] + LutUbY[(y)] 41 | 42 | #define R_FROMYV(y,v) CLIP((y) + LutRv[(v)]) 43 | #define G_FROMYUV(y,u,v) CLIP((y) + LutGu[(u)] + LutGv[(v)]) 44 | #define B_FROMYU(y,u) CLIP((y) + LutBu[(u)]) 45 | #endif 46 | 47 | unsigned char 48 | RGB24_TO_Y(unsigned char r, unsigned char g, unsigned char b) 49 | { 50 | return (LutYr[(r)] + LutYg[(g)] + LutYb[(b)]); 51 | } 52 | unsigned char 53 | YR_TO_V(unsigned char r, unsigned char y) 54 | { 55 | return (LutVr[(r)] + LutVrY[(y)]); 56 | } 57 | unsigned char 58 | YB_TO_U(unsigned char b, unsigned char y) 59 | { 60 | return (LutUb[(b)] + LutUbY[(y)]); 61 | } 62 | unsigned char 63 | R_FROMYV(unsigned char y, unsigned char v) 64 | { 65 | return CLIP((y) + LutRv[(v)]); 66 | } 67 | unsigned char 68 | G_FROMYUV(unsigned char y, unsigned char u, unsigned char v) 69 | { 70 | return CLIP((y) + LutGu[(u)] + LutGv[(v)]); 71 | } 72 | unsigned char 73 | B_FROMYU(unsigned char y, unsigned char u) 74 | { 75 | return CLIP((y) + LutBu[(u)]); 76 | } 77 | 78 | void initLut(void) 79 | { 80 | int i; 81 | #define Rcoef 299 82 | #define Gcoef 587 83 | #define Bcoef 114 84 | #define Vrcoef 711 //656 //877 85 | #define Ubcoef 560 //500 //493 564 86 | 87 | #define CoefRv 1402 88 | #define CoefGu 714 // 344 89 | #define CoefGv 344 // 714 90 | #define CoefBu 1772 91 | 92 | LutYr = malloc(256*sizeof(int)); 93 | LutYg = malloc(256*sizeof(int)); 94 | LutYb = malloc(256*sizeof(int)); 95 | LutVr = malloc(256*sizeof(int)); 96 | LutVrY = malloc(256*sizeof(int)); 97 | LutUb = malloc(256*sizeof(int)); 98 | LutUbY = malloc(256*sizeof(int)); 99 | 100 | LutRv = malloc(256*sizeof(int)); 101 | LutGu = malloc(256*sizeof(int)); 102 | LutGv = malloc(256*sizeof(int)); 103 | LutBu = malloc(256*sizeof(int)); 104 | for (i= 0;i < 256;i++){ 105 | LutYr[i] = i*Rcoef/1000 ; 106 | LutYg[i] = i*Gcoef/1000 ; 107 | LutYb[i] = i*Bcoef/1000 ; 108 | LutVr[i] = i*Vrcoef/1000; 109 | LutUb[i] = i*Ubcoef/1000; 110 | LutVrY[i] = 128 -(i*Vrcoef/1000); 111 | LutUbY[i] = 128 -(i*Ubcoef/1000); 112 | LutRv[i] = (i-128)*CoefRv/1000; 113 | LutBu[i] = (i-128)*CoefBu/1000; 114 | LutGu[i] = (128-i)*CoefGu/1000; 115 | LutGv[i] = (128-i)*CoefGv/1000; 116 | } 117 | } 118 | 119 | 120 | void freeLut(void){ 121 | free(LutYr); 122 | free(LutYg); 123 | free(LutYb); 124 | free(LutVr); 125 | free(LutVrY); 126 | free(LutUb); 127 | free(LutUbY); 128 | 129 | free(LutRv); 130 | free(LutGu); 131 | free(LutGv); 132 | free(LutBu); 133 | } 134 | 135 | -------------------------------------------------------------------------------- /convert/color.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | # GspcaGui: Gspca/Spca5xx Grabber # 3 | # Copyright (C) 2004 2005 2006 Michel Xhaard # 4 | # # 5 | # This program is free software; you can redistribute it and/or modify # 6 | # it under the terms of the GNU General Public License as published by # 7 | # the Free Software Foundation; either version 2 of the License, or # 8 | # (at your option) any later version. # 9 | # # 10 | # This program is distributed in the hope that it will be useful, # 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # 13 | # GNU General Public License for more details. # 14 | # # 15 | # You should have received a copy of the GNU General Public License # 16 | # along with this program; if not, write to the Free Software # 17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # 18 | # # 19 | ****************************************************************************/ 20 | typedef struct Myrgb16 { 21 | unsigned short blue:5; 22 | unsigned short green:6; 23 | unsigned short red:5; 24 | } Myrgb16; 25 | typedef struct Myrgb24 { 26 | unsigned char blue; 27 | unsigned char green; 28 | unsigned char red; 29 | } Myrgb24; 30 | typedef struct Myrgb32 { 31 | unsigned char blue; 32 | unsigned char green; 33 | unsigned char red; 34 | unsigned char alpha; 35 | } Myrgb32; 36 | 37 | typedef struct MyYUV422 { 38 | unsigned char y0; 39 | unsigned char u; 40 | unsigned char y1; 41 | unsigned char v; 42 | } MyYUV422; 43 | 44 | typedef struct MyYUV444 { 45 | unsigned char y; 46 | unsigned char u; 47 | unsigned char v; 48 | } MyYUV444; 49 | 50 | #define CLIP(color) (unsigned char)(((color)>0xFF)?0xff:(((color)<0)?0:(color))) 51 | 52 | unsigned char 53 | RGB24_TO_Y(unsigned char r, unsigned char g, unsigned char b); 54 | 55 | unsigned char 56 | YR_TO_V(unsigned char r, unsigned char y); 57 | 58 | unsigned char 59 | YB_TO_U(unsigned char b, unsigned char y); 60 | 61 | unsigned char 62 | R_FROMYV(unsigned char y, unsigned char v); 63 | 64 | unsigned char 65 | G_FROMYUV(unsigned char y, unsigned char u, unsigned char v); 66 | 67 | unsigned char 68 | B_FROMYU(unsigned char y, unsigned char u); 69 | 70 | #define YfromRGB(r,g,b) CLIP((77*(r)+150*(g)+29*(b))>>8) 71 | #define UfromRGB(r,g,b) CLIP(((128*(b)-85*(g)-43*(r))>>8 )+128) 72 | #define VfromRGB(r,g,b) CLIP(((128*(r)-107*(g)-21*(b))>>8) +128) 73 | 74 | #define PACKRGB16(r,g,b) (__u16) ((((b) & 0xF8) << 8 ) | (((g) & 0xFC) << 3 ) | (((r) & 0xF8) >> 3 )) 75 | #define UNPACK16(pixel,r,g,b) r=((pixel)&0xf800) >> 8; g=((pixel)&0x07e0) >> 3; b=(((pixel)&0x001f) << 3) 76 | 77 | void initLut(void); 78 | void freeLut(void); 79 | -------------------------------------------------------------------------------- /convert/convert_manager.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static PT_VideoConvert g_ptVideoConvertHead = NULL; 6 | 7 | 8 | int VideoConvertInit(void) 9 | { 10 | int iError; 11 | 12 | iError = Yuv2RgbInit(); 13 | iError |= Mjpeg2RgbInit(); 14 | iError |= Rgb2RgbInit(); 15 | 16 | return iError; 17 | } 18 | 19 | 20 | //注册结构体 21 | int RegisterVideoConvert(PT_VideoConvert ptVideoConvert) 22 | { 23 | PT_VideoConvert ptTmp; 24 | 25 | if (!g_ptVideoConvertHead) 26 | { 27 | g_ptVideoConvertHead = ptVideoConvert; 28 | ptVideoConvert->ptNext = NULL; 29 | } 30 | else 31 | { 32 | ptTmp = g_ptVideoConvertHead; 33 | while (ptTmp->ptNext) 34 | { 35 | ptTmp = ptTmp->ptNext; 36 | } 37 | ptTmp->ptNext = ptVideoConvert; 38 | ptVideoConvert->ptNext = NULL; 39 | } 40 | 41 | return 0; 42 | } 43 | 44 | 45 | PT_VideoConvert GetVideoConvertForFormats(int iPixelFormatIn, int iPixelFormatOut) 46 | { 47 | PT_VideoConvert ptTmp = g_ptVideoConvertHead; 48 | 49 | while (ptTmp) 50 | { 51 | if (ptTmp->isSupport(iPixelFormatIn, iPixelFormatOut)) 52 | { 53 | return ptTmp; 54 | } 55 | ptTmp = ptTmp->ptNext; 56 | } 57 | return NULL; 58 | } 59 | 60 | void ShowVideoConvert(void) 61 | { 62 | int i = 0; 63 | PT_VideoConvert ptTmp = g_ptVideoConvertHead; 64 | 65 | while (ptTmp) 66 | { 67 | printf("%02d %s\n", i++, ptTmp->name); 68 | ptTmp = ptTmp->ptNext; 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /convert/jdatasrc-tj.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jdatasrc.c 3 | * 4 | * Copyright (C) 1994-1996, Thomas G. Lane. 5 | * Modified 2009-2010 by Guido Vollbeding. 6 | * This file is part of the Independent JPEG Group's software. 7 | * For conditions of distribution and use, see the accompanying README file. 8 | * 9 | * This file contains decompression data source routines for the case of 10 | * reading JPEG data from memory or from a file (or any stdio stream). 11 | * While these routines are sufficient for most applications, 12 | * some will want to use a different source manager. 13 | * IMPORTANT: we assume that fread() will correctly transcribe an array of 14 | * JOCTETs from 8-bit-wide elements on external storage. If char is wider 15 | * than 8 bits on your machine, you may need to do some tweaking. 16 | */ 17 | 18 | /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ 19 | #include "jinclude.h" 20 | #include "jpeglib.h" 21 | #include "jerror.h" 22 | 23 | 24 | /* 25 | * Initialize source --- called by jpeg_read_header 26 | * before any data is actually read. 27 | */ 28 | 29 | METHODDEF(void) 30 | init_mem_source (j_decompress_ptr cinfo) 31 | { 32 | /* no work necessary here */ 33 | } 34 | 35 | 36 | /* 37 | * Fill the input buffer --- called whenever buffer is emptied. 38 | * 39 | * In typical applications, this should read fresh data into the buffer 40 | * (ignoring the current state of next_input_byte & bytes_in_buffer), 41 | * reset the pointer & count to the start of the buffer, and return TRUE 42 | * indicating that the buffer has been reloaded. It is not necessary to 43 | * fill the buffer entirely, only to obtain at least one more byte. 44 | * 45 | * There is no such thing as an EOF return. If the end of the file has been 46 | * reached, the routine has a choice of ERREXIT() or inserting fake data into 47 | * the buffer. In most cases, generating a warning message and inserting a 48 | * fake EOI marker is the best course of action --- this will allow the 49 | * decompressor to output however much of the image is there. However, 50 | * the resulting error message is misleading if the real problem is an empty 51 | * input file, so we handle that case specially. 52 | * 53 | * In applications that need to be able to suspend compression due to input 54 | * not being available yet, a FALSE return indicates that no more data can be 55 | * obtained right now, but more may be forthcoming later. In this situation, 56 | * the decompressor will return to its caller (with an indication of the 57 | * number of scanlines it has read, if any). The application should resume 58 | * decompression after it has loaded more data into the input buffer. Note 59 | * that there are substantial restrictions on the use of suspension --- see 60 | * the documentation. 61 | * 62 | * When suspending, the decompressor will back up to a convenient restart point 63 | * (typically the start of the current MCU). next_input_byte & bytes_in_buffer 64 | * indicate where the restart point will be if the current call returns FALSE. 65 | * Data beyond this point must be rescanned after resumption, so move it to 66 | * the front of the buffer rather than discarding it. 67 | */ 68 | 69 | METHODDEF(boolean) 70 | fill_mem_input_buffer (j_decompress_ptr cinfo) 71 | { 72 | static JOCTET mybuffer[4]; 73 | 74 | /* The whole JPEG data is expected to reside in the supplied memory 75 | * buffer, so any request for more data beyond the given buffer size 76 | * is treated as an error. 77 | */ 78 | WARNMS(cinfo, JWRN_JPEG_EOF); 79 | /* Insert a fake EOI marker */ 80 | mybuffer[0] = (JOCTET) 0xFF; 81 | mybuffer[1] = (JOCTET) JPEG_EOI; 82 | 83 | cinfo->src->next_input_byte = mybuffer; 84 | cinfo->src->bytes_in_buffer = 2; 85 | 86 | return TRUE; 87 | } 88 | 89 | 90 | /* 91 | * Skip data --- used to skip over a potentially large amount of 92 | * uninteresting data (such as an APPn marker). 93 | * 94 | * Writers of suspendable-input applications must note that skip_input_data 95 | * is not granted the right to give a suspension return. If the skip extends 96 | * beyond the data currently in the buffer, the buffer can be marked empty so 97 | * that the next read will cause a fill_input_buffer call that can suspend. 98 | * Arranging for additional bytes to be discarded before reloading the input 99 | * buffer is the application writer's problem. 100 | */ 101 | 102 | METHODDEF(void) 103 | skip_input_data (j_decompress_ptr cinfo, long num_bytes) 104 | { 105 | struct jpeg_source_mgr * src = cinfo->src; 106 | 107 | /* Just a dumb implementation for now. Could use fseek() except 108 | * it doesn't work on pipes. Not clear that being smart is worth 109 | * any trouble anyway --- large skips are infrequent. 110 | */ 111 | if (num_bytes > 0) { 112 | while (num_bytes > (long) src->bytes_in_buffer) { 113 | num_bytes -= (long) src->bytes_in_buffer; 114 | (void) (*src->fill_input_buffer) (cinfo); 115 | /* note we assume that fill_input_buffer will never return FALSE, 116 | * so suspension need not be handled. 117 | */ 118 | } 119 | src->next_input_byte += (size_t) num_bytes; 120 | src->bytes_in_buffer -= (size_t) num_bytes; 121 | } 122 | } 123 | 124 | 125 | /* 126 | * An additional method that can be provided by data source modules is the 127 | * resync_to_restart method for error recovery in the presence of RST markers. 128 | * For the moment, this source module just uses the default resync method 129 | * provided by the JPEG library. That method assumes that no backtracking 130 | * is possible. 131 | */ 132 | 133 | 134 | /* 135 | * Terminate source --- called by jpeg_finish_decompress 136 | * after all data has been read. Often a no-op. 137 | * 138 | * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding 139 | * application must deal with any cleanup that should happen even 140 | * for error exit. 141 | */ 142 | 143 | METHODDEF(void) 144 | term_source (j_decompress_ptr cinfo) 145 | { 146 | /* no work necessary here */ 147 | } 148 | 149 | 150 | /* 151 | * Prepare for input from a supplied memory buffer. 152 | * The buffer must contain the whole JPEG data. 153 | */ 154 | 155 | GLOBAL(void) 156 | jpeg_mem_src_tj (j_decompress_ptr cinfo, 157 | unsigned char * inbuffer, unsigned long insize) 158 | { 159 | struct jpeg_source_mgr * src; 160 | 161 | if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */ 162 | ERREXIT(cinfo, JERR_INPUT_EMPTY); 163 | 164 | /* The source object is made permanent so that a series of JPEG images 165 | * can be read from the same buffer by calling jpeg_mem_src only before 166 | * the first one. 167 | */ 168 | if (cinfo->src == NULL) { /* first time for this JPEG object? */ 169 | cinfo->src = (struct jpeg_source_mgr *) 170 | (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, 171 | SIZEOF(struct jpeg_source_mgr)); 172 | } 173 | 174 | src = cinfo->src; 175 | src->init_source = init_mem_source; 176 | src->fill_input_buffer = fill_mem_input_buffer; 177 | src->skip_input_data = skip_input_data; 178 | src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ 179 | src->term_source = term_source; 180 | src->bytes_in_buffer = (size_t) insize; 181 | src->next_input_byte = (JOCTET *) inbuffer; 182 | } 183 | -------------------------------------------------------------------------------- /convert/jerror.h: -------------------------------------------------------------------------------- 1 | /* 2 | * jerror.h 3 | * 4 | * Copyright (C) 1994-1997, Thomas G. Lane. 5 | * Modified 1997-2009 by Guido Vollbeding. 6 | * This file is part of the Independent JPEG Group's software. 7 | * For conditions of distribution and use, see the accompanying README file. 8 | * 9 | * This file defines the error and message codes for the JPEG library. 10 | * Edit this file to add new codes, or to translate the message strings to 11 | * some other language. 12 | * A set of error-reporting macros are defined too. Some applications using 13 | * the JPEG library may wish to include this file to get the error codes 14 | * and/or the macros. 15 | */ 16 | 17 | /* 18 | * To define the enum list of message codes, include this file without 19 | * defining macro JMESSAGE. To create a message string table, include it 20 | * again with a suitable JMESSAGE definition (see jerror.c for an example). 21 | */ 22 | #ifndef JMESSAGE 23 | #ifndef JERROR_H 24 | /* First time through, define the enum list */ 25 | #define JMAKE_ENUM_LIST 26 | #else 27 | /* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ 28 | #define JMESSAGE(code,string) 29 | #endif /* JERROR_H */ 30 | #endif /* JMESSAGE */ 31 | 32 | #ifdef JMAKE_ENUM_LIST 33 | 34 | typedef enum { 35 | 36 | #define JMESSAGE(code,string) code , 37 | 38 | #endif /* JMAKE_ENUM_LIST */ 39 | 40 | JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ 41 | 42 | /* For maintenance convenience, list is alphabetical by message code name */ 43 | #if JPEG_LIB_VERSION < 70 44 | JMESSAGE(JERR_ARITH_NOTIMPL, 45 | "Sorry, arithmetic coding is not implemented") 46 | #endif 47 | JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") 48 | JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") 49 | JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") 50 | JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") 51 | #if JPEG_LIB_VERSION >= 70 52 | JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") 53 | #endif 54 | JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") 55 | JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") 56 | #if JPEG_LIB_VERSION >= 70 57 | JMESSAGE(JERR_BAD_DROP_SAMPLING, 58 | "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") 59 | #endif 60 | JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") 61 | JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") 62 | JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") 63 | JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") 64 | JMESSAGE(JERR_BAD_LIB_VERSION, 65 | "Wrong JPEG library version: library is %d, caller expects %d") 66 | JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") 67 | JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") 68 | JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") 69 | JMESSAGE(JERR_BAD_PROGRESSION, 70 | "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") 71 | JMESSAGE(JERR_BAD_PROG_SCRIPT, 72 | "Invalid progressive parameters at scan script entry %d") 73 | JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") 74 | JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") 75 | JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") 76 | JMESSAGE(JERR_BAD_STRUCT_SIZE, 77 | "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") 78 | JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") 79 | JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") 80 | JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") 81 | JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") 82 | JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") 83 | JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") 84 | JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") 85 | JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") 86 | JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") 87 | JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") 88 | JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") 89 | JMESSAGE(JERR_EMS_READ, "Read from EMS failed") 90 | JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") 91 | JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") 92 | JMESSAGE(JERR_FILE_READ, "Input file read error") 93 | JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") 94 | JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") 95 | JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") 96 | JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") 97 | JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") 98 | JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") 99 | JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") 100 | JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, 101 | "Cannot transcode due to multiple use of quantization table %d") 102 | JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") 103 | JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") 104 | JMESSAGE(JERR_NOTIMPL, "Not implemented yet") 105 | JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") 106 | #if JPEG_LIB_VERSION >= 70 107 | JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") 108 | #endif 109 | JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") 110 | JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") 111 | JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") 112 | JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") 113 | JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") 114 | JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") 115 | JMESSAGE(JERR_QUANT_COMPONENTS, 116 | "Cannot quantize more than %d color components") 117 | JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") 118 | JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") 119 | JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") 120 | JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") 121 | JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") 122 | JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") 123 | JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") 124 | JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") 125 | JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") 126 | JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") 127 | JMESSAGE(JERR_TFILE_WRITE, 128 | "Write failed on temporary file --- out of disk space?") 129 | JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") 130 | JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") 131 | JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") 132 | JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") 133 | JMESSAGE(JERR_XMS_READ, "Read from XMS failed") 134 | JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") 135 | JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) 136 | JMESSAGE(JMSG_VERSION, JVERSION) 137 | JMESSAGE(JTRC_16BIT_TABLES, 138 | "Caution: quantization tables are too coarse for baseline JPEG") 139 | JMESSAGE(JTRC_ADOBE, 140 | "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") 141 | JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") 142 | JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") 143 | JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") 144 | JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") 145 | JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") 146 | JMESSAGE(JTRC_DRI, "Define Restart Interval %u") 147 | JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") 148 | JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") 149 | JMESSAGE(JTRC_EOI, "End Of Image") 150 | JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") 151 | JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") 152 | JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, 153 | "Warning: thumbnail image size does not match data length %u") 154 | JMESSAGE(JTRC_JFIF_EXTENSION, 155 | "JFIF extension marker: type 0x%02x, length %u") 156 | JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") 157 | JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") 158 | JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") 159 | JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") 160 | JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") 161 | JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") 162 | JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") 163 | JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") 164 | JMESSAGE(JTRC_RST, "RST%d") 165 | JMESSAGE(JTRC_SMOOTH_NOTIMPL, 166 | "Smoothing not supported with nonstandard sampling ratios") 167 | JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") 168 | JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") 169 | JMESSAGE(JTRC_SOI, "Start of Image") 170 | JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") 171 | JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") 172 | JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") 173 | JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") 174 | JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") 175 | JMESSAGE(JTRC_THUMB_JPEG, 176 | "JFIF extension marker: JPEG-compressed thumbnail image, length %u") 177 | JMESSAGE(JTRC_THUMB_PALETTE, 178 | "JFIF extension marker: palette thumbnail image, length %u") 179 | JMESSAGE(JTRC_THUMB_RGB, 180 | "JFIF extension marker: RGB thumbnail image, length %u") 181 | JMESSAGE(JTRC_UNKNOWN_IDS, 182 | "Unrecognized component IDs %d %d %d, assuming YCbCr") 183 | JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") 184 | JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") 185 | JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") 186 | #if JPEG_LIB_VERSION >= 70 187 | JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") 188 | #endif 189 | JMESSAGE(JWRN_BOGUS_PROGRESSION, 190 | "Inconsistent progression sequence for component %d coefficient %d") 191 | JMESSAGE(JWRN_EXTRANEOUS_DATA, 192 | "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") 193 | JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") 194 | JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") 195 | JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") 196 | JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") 197 | JMESSAGE(JWRN_MUST_RESYNC, 198 | "Corrupt JPEG data: found marker 0x%02x instead of RST%d") 199 | JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") 200 | JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") 201 | #if JPEG_LIB_VERSION < 70 202 | JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") 203 | #if defined(C_ARITH_CODING_SUPPORTED) || defined(D_ARITH_CODING_SUPPORTED) 204 | JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") 205 | JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") 206 | #endif 207 | #endif 208 | 209 | #ifdef JMAKE_ENUM_LIST 210 | 211 | JMSG_LASTMSGCODE 212 | } J_MESSAGE_CODE; 213 | 214 | #undef JMAKE_ENUM_LIST 215 | #endif /* JMAKE_ENUM_LIST */ 216 | 217 | /* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ 218 | #undef JMESSAGE 219 | 220 | 221 | #ifndef JERROR_H 222 | #define JERROR_H 223 | 224 | /* Macros to simplify using the error and trace message stuff */ 225 | /* The first parameter is either type of cinfo pointer */ 226 | 227 | /* Fatal errors (print message and exit) */ 228 | #define ERREXIT(cinfo,code) \ 229 | ((cinfo)->err->msg_code = (code), \ 230 | (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) 231 | #define ERREXIT1(cinfo,code,p1) \ 232 | ((cinfo)->err->msg_code = (code), \ 233 | (cinfo)->err->msg_parm.i[0] = (p1), \ 234 | (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) 235 | #define ERREXIT2(cinfo,code,p1,p2) \ 236 | ((cinfo)->err->msg_code = (code), \ 237 | (cinfo)->err->msg_parm.i[0] = (p1), \ 238 | (cinfo)->err->msg_parm.i[1] = (p2), \ 239 | (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) 240 | #define ERREXIT3(cinfo,code,p1,p2,p3) \ 241 | ((cinfo)->err->msg_code = (code), \ 242 | (cinfo)->err->msg_parm.i[0] = (p1), \ 243 | (cinfo)->err->msg_parm.i[1] = (p2), \ 244 | (cinfo)->err->msg_parm.i[2] = (p3), \ 245 | (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) 246 | #define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ 247 | ((cinfo)->err->msg_code = (code), \ 248 | (cinfo)->err->msg_parm.i[0] = (p1), \ 249 | (cinfo)->err->msg_parm.i[1] = (p2), \ 250 | (cinfo)->err->msg_parm.i[2] = (p3), \ 251 | (cinfo)->err->msg_parm.i[3] = (p4), \ 252 | (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) 253 | #define ERREXITS(cinfo,code,str) \ 254 | ((cinfo)->err->msg_code = (code), \ 255 | strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ 256 | (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) 257 | 258 | #define MAKESTMT(stuff) do { stuff } while (0) 259 | 260 | /* Nonfatal errors (we can keep going, but the data is probably corrupt) */ 261 | #define WARNMS(cinfo,code) \ 262 | ((cinfo)->err->msg_code = (code), \ 263 | (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) 264 | #define WARNMS1(cinfo,code,p1) \ 265 | ((cinfo)->err->msg_code = (code), \ 266 | (cinfo)->err->msg_parm.i[0] = (p1), \ 267 | (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) 268 | #define WARNMS2(cinfo,code,p1,p2) \ 269 | ((cinfo)->err->msg_code = (code), \ 270 | (cinfo)->err->msg_parm.i[0] = (p1), \ 271 | (cinfo)->err->msg_parm.i[1] = (p2), \ 272 | (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) 273 | 274 | /* Informational/debugging messages */ 275 | #define TRACEMS(cinfo,lvl,code) \ 276 | ((cinfo)->err->msg_code = (code), \ 277 | (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) 278 | #define TRACEMS1(cinfo,lvl,code,p1) \ 279 | ((cinfo)->err->msg_code = (code), \ 280 | (cinfo)->err->msg_parm.i[0] = (p1), \ 281 | (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) 282 | #define TRACEMS2(cinfo,lvl,code,p1,p2) \ 283 | ((cinfo)->err->msg_code = (code), \ 284 | (cinfo)->err->msg_parm.i[0] = (p1), \ 285 | (cinfo)->err->msg_parm.i[1] = (p2), \ 286 | (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) 287 | #define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ 288 | MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ 289 | _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ 290 | (cinfo)->err->msg_code = (code); \ 291 | (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) 292 | #define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ 293 | MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ 294 | _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ 295 | (cinfo)->err->msg_code = (code); \ 296 | (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) 297 | #define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ 298 | MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ 299 | _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ 300 | _mp[4] = (p5); \ 301 | (cinfo)->err->msg_code = (code); \ 302 | (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) 303 | #define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ 304 | MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ 305 | _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ 306 | _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ 307 | (cinfo)->err->msg_code = (code); \ 308 | (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) 309 | #define TRACEMSS(cinfo,lvl,code,str) \ 310 | ((cinfo)->err->msg_code = (code), \ 311 | strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ 312 | (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) 313 | 314 | #endif /* JERROR_H */ 315 | -------------------------------------------------------------------------------- /convert/jinclude.h: -------------------------------------------------------------------------------- 1 | /* 2 | * jinclude.h 3 | * 4 | * Copyright (C) 1991-1994, Thomas G. Lane. 5 | * This file is part of the Independent JPEG Group's software. 6 | * For conditions of distribution and use, see the accompanying README file. 7 | * 8 | * This file exists to provide a single place to fix any problems with 9 | * including the wrong system include files. (Common problems are taken 10 | * care of by the standard jconfig symbols, but on really weird systems 11 | * you may have to edit this file.) 12 | * 13 | * NOTE: this file is NOT intended to be included by applications using the 14 | * JPEG library. Most applications need only include jpeglib.h. 15 | */ 16 | 17 | 18 | /* Include auto-config file to find out which system include files we need. */ 19 | 20 | #include "jconfig.h" /* auto configuration options */ 21 | #define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ 22 | 23 | /* 24 | * We need the NULL macro and size_t typedef. 25 | * On an ANSI-conforming system it is sufficient to include . 26 | * Otherwise, we get them from or ; we may have to 27 | * pull in as well. 28 | * Note that the core JPEG library does not require ; 29 | * only the default error handler and data source/destination modules do. 30 | * But we must pull it in because of the references to FILE in jpeglib.h. 31 | * You can remove those references if you want to compile without . 32 | */ 33 | 34 | #ifdef HAVE_STDDEF_H 35 | #include 36 | #endif 37 | 38 | #ifdef HAVE_STDLIB_H 39 | #include 40 | #endif 41 | 42 | #ifdef NEED_SYS_TYPES_H 43 | #include 44 | #endif 45 | 46 | #include 47 | 48 | /* 49 | * We need memory copying and zeroing functions, plus strncpy(). 50 | * ANSI and System V implementations declare these in . 51 | * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). 52 | * Some systems may declare memset and memcpy in . 53 | * 54 | * NOTE: we assume the size parameters to these functions are of type size_t. 55 | * Change the casts in these macros if not! 56 | */ 57 | 58 | #ifdef NEED_BSD_STRINGS 59 | 60 | #include 61 | #define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) 62 | #define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) 63 | 64 | #else /* not BSD, assume ANSI/SysV string lib */ 65 | 66 | #include 67 | #define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) 68 | #define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) 69 | 70 | #endif 71 | 72 | /* 73 | * In ANSI C, and indeed any rational implementation, size_t is also the 74 | * type returned by sizeof(). However, it seems there are some irrational 75 | * implementations out there, in which sizeof() returns an int even though 76 | * size_t is defined as long or unsigned long. To ensure consistent results 77 | * we always use this SIZEOF() macro in place of using sizeof() directly. 78 | */ 79 | 80 | #define SIZEOF(object) ((size_t) sizeof(object)) 81 | 82 | /* 83 | * The modules that use fread() and fwrite() always invoke them through 84 | * these macros. On some systems you may need to twiddle the argument casts. 85 | * CAUTION: argument order is different from underlying functions! 86 | */ 87 | 88 | #define JFREAD(file,buf,sizeofbuf) \ 89 | ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) 90 | #define JFWRITE(file,buf,sizeofbuf) \ 91 | ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) 92 | -------------------------------------------------------------------------------- /convert/jpeglib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * jpeglib.h 3 | * 4 | * Copyright (C) 1991-1998, Thomas G. Lane. 5 | * Modified 2002-2009 by Guido Vollbeding. 6 | * Copyright (C) 2009-2011, D. R. Commander. 7 | * This file is part of the Independent JPEG Group's software. 8 | * For conditions of distribution and use, see the accompanying README file. 9 | * 10 | * This file defines the application interface for the JPEG library. 11 | * Most applications using the library need only include this file, 12 | * and perhaps jerror.h if they want to know the exact error codes. 13 | */ 14 | 15 | #ifndef JPEGLIB_H 16 | #define JPEGLIB_H 17 | 18 | /* 19 | * First we include the configuration files that record how this 20 | * installation of the JPEG library is set up. jconfig.h can be 21 | * generated automatically for many systems. jmorecfg.h contains 22 | * manual configuration options that most people need not worry about. 23 | */ 24 | 25 | #ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ 26 | #include "jconfig.h" /* widely used configuration options */ 27 | #endif 28 | #include "jmorecfg.h" /* seldom changed options */ 29 | 30 | 31 | #ifdef __cplusplus 32 | #ifndef DONT_USE_EXTERN_C 33 | extern "C" { 34 | #endif 35 | #endif 36 | 37 | 38 | /* Various constants determining the sizes of things. 39 | * All of these are specified by the JPEG standard, so don't change them 40 | * if you want to be compatible. 41 | */ 42 | 43 | #define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ 44 | #define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ 45 | #define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ 46 | #define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ 47 | #define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ 48 | #define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ 49 | #define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ 50 | /* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; 51 | * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. 52 | * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU 53 | * to handle it. We even let you do this from the jconfig.h file. However, 54 | * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe 55 | * sometimes emits noncompliant files doesn't mean you should too. 56 | */ 57 | #define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ 58 | #ifndef D_MAX_BLOCKS_IN_MCU 59 | #define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ 60 | #endif 61 | 62 | 63 | /* Data structures for images (arrays of samples and of DCT coefficients). 64 | * On 80x86 machines, the image arrays are too big for near pointers, 65 | * but the pointer arrays can fit in near memory. 66 | */ 67 | 68 | typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ 69 | typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ 70 | typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ 71 | 72 | typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ 73 | typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ 74 | typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ 75 | typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ 76 | 77 | typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ 78 | 79 | 80 | /* Types for JPEG compression parameters and working tables. */ 81 | 82 | 83 | /* DCT coefficient quantization tables. */ 84 | 85 | typedef struct { 86 | /* This array gives the coefficient quantizers in natural array order 87 | * (not the zigzag order in which they are stored in a JPEG DQT marker). 88 | * CAUTION: IJG versions prior to v6a kept this array in zigzag order. 89 | */ 90 | UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ 91 | /* This field is used only during compression. It's initialized FALSE when 92 | * the table is created, and set TRUE when it's been output to the file. 93 | * You could suppress output of a table by setting this to TRUE. 94 | * (See jpeg_suppress_tables for an example.) 95 | */ 96 | boolean sent_table; /* TRUE when table has been output */ 97 | } JQUANT_TBL; 98 | 99 | 100 | /* Huffman coding tables. */ 101 | 102 | typedef struct { 103 | /* These two fields directly represent the contents of a JPEG DHT marker */ 104 | UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ 105 | /* length k bits; bits[0] is unused */ 106 | UINT8 huffval[256]; /* The symbols, in order of incr code length */ 107 | /* This field is used only during compression. It's initialized FALSE when 108 | * the table is created, and set TRUE when it's been output to the file. 109 | * You could suppress output of a table by setting this to TRUE. 110 | * (See jpeg_suppress_tables for an example.) 111 | */ 112 | boolean sent_table; /* TRUE when table has been output */ 113 | } JHUFF_TBL; 114 | 115 | 116 | /* Basic info about one component (color channel). */ 117 | 118 | typedef struct { 119 | /* These values are fixed over the whole image. */ 120 | /* For compression, they must be supplied by parameter setup; */ 121 | /* for decompression, they are read from the SOF marker. */ 122 | int component_id; /* identifier for this component (0..255) */ 123 | int component_index; /* its index in SOF or cinfo->comp_info[] */ 124 | int h_samp_factor; /* horizontal sampling factor (1..4) */ 125 | int v_samp_factor; /* vertical sampling factor (1..4) */ 126 | int quant_tbl_no; /* quantization table selector (0..3) */ 127 | /* These values may vary between scans. */ 128 | /* For compression, they must be supplied by parameter setup; */ 129 | /* for decompression, they are read from the SOS marker. */ 130 | /* The decompressor output side may not use these variables. */ 131 | int dc_tbl_no; /* DC entropy table selector (0..3) */ 132 | int ac_tbl_no; /* AC entropy table selector (0..3) */ 133 | 134 | /* Remaining fields should be treated as private by applications. */ 135 | 136 | /* These values are computed during compression or decompression startup: */ 137 | /* Component's size in DCT blocks. 138 | * Any dummy blocks added to complete an MCU are not counted; therefore 139 | * these values do not depend on whether a scan is interleaved or not. 140 | */ 141 | JDIMENSION width_in_blocks; 142 | JDIMENSION height_in_blocks; 143 | /* Size of a DCT block in samples. Always DCTSIZE for compression. 144 | * For decompression this is the size of the output from one DCT block, 145 | * reflecting any scaling we choose to apply during the IDCT step. 146 | * Values of 1,2,4,8 are likely to be supported. Note that different 147 | * components may receive different IDCT scalings. 148 | */ 149 | #if JPEG_LIB_VERSION >= 70 150 | int DCT_h_scaled_size; 151 | int DCT_v_scaled_size; 152 | #else 153 | int DCT_scaled_size; 154 | #endif 155 | /* The downsampled dimensions are the component's actual, unpadded number 156 | * of samples at the main buffer (preprocessing/compression interface), thus 157 | * downsampled_width = ceil(image_width * Hi/Hmax) 158 | * and similarly for height. For decompression, IDCT scaling is included, so 159 | * downsampled_width = ceil(image_width * Hi/Hmax * DCT_[h_]scaled_size/DCTSIZE) 160 | */ 161 | JDIMENSION downsampled_width; /* actual width in samples */ 162 | JDIMENSION downsampled_height; /* actual height in samples */ 163 | /* This flag is used only for decompression. In cases where some of the 164 | * components will be ignored (eg grayscale output from YCbCr image), 165 | * we can skip most computations for the unused components. 166 | */ 167 | boolean component_needed; /* do we need the value of this component? */ 168 | 169 | /* These values are computed before starting a scan of the component. */ 170 | /* The decompressor output side may not use these variables. */ 171 | int MCU_width; /* number of blocks per MCU, horizontally */ 172 | int MCU_height; /* number of blocks per MCU, vertically */ 173 | int MCU_blocks; /* MCU_width * MCU_height */ 174 | int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_[h_]scaled_size */ 175 | int last_col_width; /* # of non-dummy blocks across in last MCU */ 176 | int last_row_height; /* # of non-dummy blocks down in last MCU */ 177 | 178 | /* Saved quantization table for component; NULL if none yet saved. 179 | * See jdinput.c comments about the need for this information. 180 | * This field is currently used only for decompression. 181 | */ 182 | JQUANT_TBL * quant_table; 183 | 184 | /* Private per-component storage for DCT or IDCT subsystem. */ 185 | void * dct_table; 186 | } jpeg_component_info; 187 | 188 | 189 | /* The script for encoding a multiple-scan file is an array of these: */ 190 | 191 | typedef struct { 192 | int comps_in_scan; /* number of components encoded in this scan */ 193 | int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ 194 | int Ss, Se; /* progressive JPEG spectral selection parms */ 195 | int Ah, Al; /* progressive JPEG successive approx. parms */ 196 | } jpeg_scan_info; 197 | 198 | /* The decompressor can save APPn and COM markers in a list of these: */ 199 | 200 | typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; 201 | 202 | struct jpeg_marker_struct { 203 | jpeg_saved_marker_ptr next; /* next in list, or NULL */ 204 | UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ 205 | unsigned int original_length; /* # bytes of data in the file */ 206 | unsigned int data_length; /* # bytes of data saved at data[] */ 207 | JOCTET FAR * data; /* the data contained in the marker */ 208 | /* the marker length word is not counted in data_length or original_length */ 209 | }; 210 | 211 | /* Known color spaces. */ 212 | 213 | #define JCS_EXTENSIONS 1 214 | #define JCS_ALPHA_EXTENSIONS 1 215 | 216 | typedef enum { 217 | JCS_UNKNOWN, /* error/unspecified */ 218 | JCS_GRAYSCALE, /* monochrome */ 219 | JCS_RGB, /* red/green/blue as specified by the RGB_RED, RGB_GREEN, 220 | RGB_BLUE, and RGB_PIXELSIZE macros */ 221 | JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ 222 | JCS_CMYK, /* C/M/Y/K */ 223 | JCS_YCCK, /* Y/Cb/Cr/K */ 224 | JCS_EXT_RGB, /* red/green/blue */ 225 | JCS_EXT_RGBX, /* red/green/blue/x */ 226 | JCS_EXT_BGR, /* blue/green/red */ 227 | JCS_EXT_BGRX, /* blue/green/red/x */ 228 | JCS_EXT_XBGR, /* x/blue/green/red */ 229 | JCS_EXT_XRGB, /* x/red/green/blue */ 230 | /* When out_color_space it set to JCS_EXT_RGBX, JCS_EXT_BGRX, 231 | JCS_EXT_XBGR, or JCS_EXT_XRGB during decompression, the X byte is 232 | undefined, and in order to ensure the best performance, 233 | libjpeg-turbo can set that byte to whatever value it wishes. Use 234 | the following colorspace constants to ensure that the X byte is set 235 | to 0xFF, so that it can be interpreted as an opaque alpha 236 | channel. */ 237 | JCS_EXT_RGBA, /* red/green/blue/alpha */ 238 | JCS_EXT_BGRA, /* blue/green/red/alpha */ 239 | JCS_EXT_ABGR, /* alpha/blue/green/red */ 240 | JCS_EXT_ARGB /* alpha/red/green/blue */ 241 | } J_COLOR_SPACE; 242 | 243 | /* DCT/IDCT algorithm options. */ 244 | 245 | typedef enum { 246 | JDCT_ISLOW, /* slow but accurate integer algorithm */ 247 | JDCT_IFAST, /* faster, less accurate integer method */ 248 | JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ 249 | } J_DCT_METHOD; 250 | 251 | #ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ 252 | #define JDCT_DEFAULT JDCT_ISLOW 253 | #endif 254 | #ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ 255 | #define JDCT_FASTEST JDCT_IFAST 256 | #endif 257 | 258 | /* Dithering options for decompression. */ 259 | 260 | typedef enum { 261 | JDITHER_NONE, /* no dithering */ 262 | JDITHER_ORDERED, /* simple ordered dither */ 263 | JDITHER_FS /* Floyd-Steinberg error diffusion dither */ 264 | } J_DITHER_MODE; 265 | 266 | 267 | /* Common fields between JPEG compression and decompression master structs. */ 268 | 269 | #define jpeg_common_fields \ 270 | struct jpeg_error_mgr * err; /* Error handler module */\ 271 | struct jpeg_memory_mgr * mem; /* Memory manager module */\ 272 | struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ 273 | void * client_data; /* Available for use by application */\ 274 | boolean is_decompressor; /* So common code can tell which is which */\ 275 | int global_state /* For checking call sequence validity */ 276 | 277 | /* Routines that are to be used by both halves of the library are declared 278 | * to receive a pointer to this structure. There are no actual instances of 279 | * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. 280 | */ 281 | struct jpeg_common_struct { 282 | jpeg_common_fields; /* Fields common to both master struct types */ 283 | /* Additional fields follow in an actual jpeg_compress_struct or 284 | * jpeg_decompress_struct. All three structs must agree on these 285 | * initial fields! (This would be a lot cleaner in C++.) 286 | */ 287 | }; 288 | 289 | typedef struct jpeg_common_struct * j_common_ptr; 290 | typedef struct jpeg_compress_struct * j_compress_ptr; 291 | typedef struct jpeg_decompress_struct * j_decompress_ptr; 292 | 293 | 294 | /* Master record for a compression instance */ 295 | 296 | struct jpeg_compress_struct { 297 | jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ 298 | 299 | /* Destination for compressed data */ 300 | struct jpeg_destination_mgr * dest; 301 | 302 | /* Description of source image --- these fields must be filled in by 303 | * outer application before starting compression. in_color_space must 304 | * be correct before you can even call jpeg_set_defaults(). 305 | */ 306 | 307 | JDIMENSION image_width; /* input image width */ 308 | JDIMENSION image_height; /* input image height */ 309 | int input_components; /* # of color components in input image */ 310 | J_COLOR_SPACE in_color_space; /* colorspace of input image */ 311 | 312 | double input_gamma; /* image gamma of input image */ 313 | 314 | /* Compression parameters --- these fields must be set before calling 315 | * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to 316 | * initialize everything to reasonable defaults, then changing anything 317 | * the application specifically wants to change. That way you won't get 318 | * burnt when new parameters are added. Also note that there are several 319 | * helper routines to simplify changing parameters. 320 | */ 321 | 322 | #if JPEG_LIB_VERSION >= 70 323 | unsigned int scale_num, scale_denom; /* fraction by which to scale image */ 324 | 325 | JDIMENSION jpeg_width; /* scaled JPEG image width */ 326 | JDIMENSION jpeg_height; /* scaled JPEG image height */ 327 | /* Dimensions of actual JPEG image that will be written to file, 328 | * derived from input dimensions by scaling factors above. 329 | * These fields are computed by jpeg_start_compress(). 330 | * You can also use jpeg_calc_jpeg_dimensions() to determine these values 331 | * in advance of calling jpeg_start_compress(). 332 | */ 333 | #endif 334 | 335 | int data_precision; /* bits of precision in image data */ 336 | 337 | int num_components; /* # of color components in JPEG image */ 338 | J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ 339 | 340 | jpeg_component_info * comp_info; 341 | /* comp_info[i] describes component that appears i'th in SOF */ 342 | 343 | JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; 344 | #if JPEG_LIB_VERSION >= 70 345 | int q_scale_factor[NUM_QUANT_TBLS]; 346 | #endif 347 | /* ptrs to coefficient quantization tables, or NULL if not defined, 348 | * and corresponding scale factors (percentage, initialized 100). 349 | */ 350 | 351 | JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; 352 | JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; 353 | /* ptrs to Huffman coding tables, or NULL if not defined */ 354 | 355 | UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ 356 | UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ 357 | UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ 358 | 359 | int num_scans; /* # of entries in scan_info array */ 360 | const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ 361 | /* The default value of scan_info is NULL, which causes a single-scan 362 | * sequential JPEG file to be emitted. To create a multi-scan file, 363 | * set num_scans and scan_info to point to an array of scan definitions. 364 | */ 365 | 366 | boolean raw_data_in; /* TRUE=caller supplies downsampled data */ 367 | boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ 368 | boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ 369 | boolean CCIR601_sampling; /* TRUE=first samples are cosited */ 370 | #if JPEG_LIB_VERSION >= 70 371 | boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ 372 | #endif 373 | int smoothing_factor; /* 1..100, or 0 for no input smoothing */ 374 | J_DCT_METHOD dct_method; /* DCT algorithm selector */ 375 | 376 | /* The restart interval can be specified in absolute MCUs by setting 377 | * restart_interval, or in MCU rows by setting restart_in_rows 378 | * (in which case the correct restart_interval will be figured 379 | * for each scan). 380 | */ 381 | unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ 382 | int restart_in_rows; /* if > 0, MCU rows per restart interval */ 383 | 384 | /* Parameters controlling emission of special markers. */ 385 | 386 | boolean write_JFIF_header; /* should a JFIF marker be written? */ 387 | UINT8 JFIF_major_version; /* What to write for the JFIF version number */ 388 | UINT8 JFIF_minor_version; 389 | /* These three values are not used by the JPEG code, merely copied */ 390 | /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ 391 | /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ 392 | /* ratio is defined by X_density/Y_density even when density_unit=0. */ 393 | UINT8 density_unit; /* JFIF code for pixel size units */ 394 | UINT16 X_density; /* Horizontal pixel density */ 395 | UINT16 Y_density; /* Vertical pixel density */ 396 | boolean write_Adobe_marker; /* should an Adobe marker be written? */ 397 | 398 | /* State variable: index of next scanline to be written to 399 | * jpeg_write_scanlines(). Application may use this to control its 400 | * processing loop, e.g., "while (next_scanline < image_height)". 401 | */ 402 | 403 | JDIMENSION next_scanline; /* 0 .. image_height-1 */ 404 | 405 | /* Remaining fields are known throughout compressor, but generally 406 | * should not be touched by a surrounding application. 407 | */ 408 | 409 | /* 410 | * These fields are computed during compression startup 411 | */ 412 | boolean progressive_mode; /* TRUE if scan script uses progressive mode */ 413 | int max_h_samp_factor; /* largest h_samp_factor */ 414 | int max_v_samp_factor; /* largest v_samp_factor */ 415 | 416 | #if JPEG_LIB_VERSION >= 70 417 | int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ 418 | int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ 419 | #endif 420 | 421 | JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ 422 | /* The coefficient controller receives data in units of MCU rows as defined 423 | * for fully interleaved scans (whether the JPEG file is interleaved or not). 424 | * There are v_samp_factor * DCTSIZE sample rows of each component in an 425 | * "iMCU" (interleaved MCU) row. 426 | */ 427 | 428 | /* 429 | * These fields are valid during any one scan. 430 | * They describe the components and MCUs actually appearing in the scan. 431 | */ 432 | int comps_in_scan; /* # of JPEG components in this scan */ 433 | jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; 434 | /* *cur_comp_info[i] describes component that appears i'th in SOS */ 435 | 436 | JDIMENSION MCUs_per_row; /* # of MCUs across the image */ 437 | JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ 438 | 439 | int blocks_in_MCU; /* # of DCT blocks per MCU */ 440 | int MCU_membership[C_MAX_BLOCKS_IN_MCU]; 441 | /* MCU_membership[i] is index in cur_comp_info of component owning */ 442 | /* i'th block in an MCU */ 443 | 444 | int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ 445 | 446 | #if JPEG_LIB_VERSION >= 80 447 | int block_size; /* the basic DCT block size: 1..16 */ 448 | const int * natural_order; /* natural-order position array */ 449 | int lim_Se; /* min( Se, DCTSIZE2-1 ) */ 450 | #endif 451 | 452 | /* 453 | * Links to compression subobjects (methods and private variables of modules) 454 | */ 455 | struct jpeg_comp_master * master; 456 | struct jpeg_c_main_controller * main; 457 | struct jpeg_c_prep_controller * prep; 458 | struct jpeg_c_coef_controller * coef; 459 | struct jpeg_marker_writer * marker; 460 | struct jpeg_color_converter * cconvert; 461 | struct jpeg_downsampler * downsample; 462 | struct jpeg_forward_dct * fdct; 463 | struct jpeg_entropy_encoder * entropy; 464 | jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ 465 | int script_space_size; 466 | }; 467 | 468 | 469 | /* Master record for a decompression instance */ 470 | 471 | struct jpeg_decompress_struct { 472 | jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ 473 | 474 | /* Source of compressed data */ 475 | struct jpeg_source_mgr * src; 476 | 477 | /* Basic description of image --- filled in by jpeg_read_header(). */ 478 | /* Application may inspect these values to decide how to process image. */ 479 | 480 | JDIMENSION image_width; /* nominal image width (from SOF marker) */ 481 | JDIMENSION image_height; /* nominal image height */ 482 | int num_components; /* # of color components in JPEG image */ 483 | J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ 484 | 485 | /* Decompression processing parameters --- these fields must be set before 486 | * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes 487 | * them to default values. 488 | */ 489 | 490 | J_COLOR_SPACE out_color_space; /* colorspace for output */ 491 | 492 | unsigned int scale_num, scale_denom; /* fraction by which to scale image */ 493 | 494 | double output_gamma; /* image gamma wanted in output */ 495 | 496 | boolean buffered_image; /* TRUE=multiple output passes */ 497 | boolean raw_data_out; /* TRUE=downsampled data wanted */ 498 | 499 | J_DCT_METHOD dct_method; /* IDCT algorithm selector */ 500 | boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ 501 | boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ 502 | 503 | boolean quantize_colors; /* TRUE=colormapped output wanted */ 504 | /* the following are ignored if not quantize_colors: */ 505 | J_DITHER_MODE dither_mode; /* type of color dithering to use */ 506 | boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ 507 | int desired_number_of_colors; /* max # colors to use in created colormap */ 508 | /* these are significant only in buffered-image mode: */ 509 | boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ 510 | boolean enable_external_quant;/* enable future use of external colormap */ 511 | boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ 512 | 513 | /* Description of actual output image that will be returned to application. 514 | * These fields are computed by jpeg_start_decompress(). 515 | * You can also use jpeg_calc_output_dimensions() to determine these values 516 | * in advance of calling jpeg_start_decompress(). 517 | */ 518 | 519 | JDIMENSION output_width; /* scaled image width */ 520 | JDIMENSION output_height; /* scaled image height */ 521 | int out_color_components; /* # of color components in out_color_space */ 522 | int output_components; /* # of color components returned */ 523 | /* output_components is 1 (a colormap index) when quantizing colors; 524 | * otherwise it equals out_color_components. 525 | */ 526 | int rec_outbuf_height; /* min recommended height of scanline buffer */ 527 | /* If the buffer passed to jpeg_read_scanlines() is less than this many rows 528 | * high, space and time will be wasted due to unnecessary data copying. 529 | * Usually rec_outbuf_height will be 1 or 2, at most 4. 530 | */ 531 | 532 | /* When quantizing colors, the output colormap is described by these fields. 533 | * The application can supply a colormap by setting colormap non-NULL before 534 | * calling jpeg_start_decompress; otherwise a colormap is created during 535 | * jpeg_start_decompress or jpeg_start_output. 536 | * The map has out_color_components rows and actual_number_of_colors columns. 537 | */ 538 | int actual_number_of_colors; /* number of entries in use */ 539 | JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ 540 | 541 | /* State variables: these variables indicate the progress of decompression. 542 | * The application may examine these but must not modify them. 543 | */ 544 | 545 | /* Row index of next scanline to be read from jpeg_read_scanlines(). 546 | * Application may use this to control its processing loop, e.g., 547 | * "while (output_scanline < output_height)". 548 | */ 549 | JDIMENSION output_scanline; /* 0 .. output_height-1 */ 550 | 551 | /* Current input scan number and number of iMCU rows completed in scan. 552 | * These indicate the progress of the decompressor input side. 553 | */ 554 | int input_scan_number; /* Number of SOS markers seen so far */ 555 | JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ 556 | 557 | /* The "output scan number" is the notional scan being displayed by the 558 | * output side. The decompressor will not allow output scan/row number 559 | * to get ahead of input scan/row, but it can fall arbitrarily far behind. 560 | */ 561 | int output_scan_number; /* Nominal scan number being displayed */ 562 | JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ 563 | 564 | /* Current progression status. coef_bits[c][i] indicates the precision 565 | * with which component c's DCT coefficient i (in zigzag order) is known. 566 | * It is -1 when no data has yet been received, otherwise it is the point 567 | * transform (shift) value for the most recent scan of the coefficient 568 | * (thus, 0 at completion of the progression). 569 | * This pointer is NULL when reading a non-progressive file. 570 | */ 571 | int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ 572 | 573 | /* Internal JPEG parameters --- the application usually need not look at 574 | * these fields. Note that the decompressor output side may not use 575 | * any parameters that can change between scans. 576 | */ 577 | 578 | /* Quantization and Huffman tables are carried forward across input 579 | * datastreams when processing abbreviated JPEG datastreams. 580 | */ 581 | 582 | JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; 583 | /* ptrs to coefficient quantization tables, or NULL if not defined */ 584 | 585 | JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; 586 | JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; 587 | /* ptrs to Huffman coding tables, or NULL if not defined */ 588 | 589 | /* These parameters are never carried across datastreams, since they 590 | * are given in SOF/SOS markers or defined to be reset by SOI. 591 | */ 592 | 593 | int data_precision; /* bits of precision in image data */ 594 | 595 | jpeg_component_info * comp_info; 596 | /* comp_info[i] describes component that appears i'th in SOF */ 597 | 598 | #if JPEG_LIB_VERSION >= 80 599 | boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ 600 | #endif 601 | boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ 602 | boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ 603 | 604 | UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ 605 | UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ 606 | UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ 607 | 608 | unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ 609 | 610 | /* These fields record data obtained from optional markers recognized by 611 | * the JPEG library. 612 | */ 613 | boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ 614 | /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ 615 | UINT8 JFIF_major_version; /* JFIF version number */ 616 | UINT8 JFIF_minor_version; 617 | UINT8 density_unit; /* JFIF code for pixel size units */ 618 | UINT16 X_density; /* Horizontal pixel density */ 619 | UINT16 Y_density; /* Vertical pixel density */ 620 | boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ 621 | UINT8 Adobe_transform; /* Color transform code from Adobe marker */ 622 | 623 | boolean CCIR601_sampling; /* TRUE=first samples are cosited */ 624 | 625 | /* Aside from the specific data retained from APPn markers known to the 626 | * library, the uninterpreted contents of any or all APPn and COM markers 627 | * can be saved in a list for examination by the application. 628 | */ 629 | jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ 630 | 631 | /* Remaining fields are known throughout decompressor, but generally 632 | * should not be touched by a surrounding application. 633 | */ 634 | 635 | /* 636 | * These fields are computed during decompression startup 637 | */ 638 | int max_h_samp_factor; /* largest h_samp_factor */ 639 | int max_v_samp_factor; /* largest v_samp_factor */ 640 | 641 | #if JPEG_LIB_VERSION >= 70 642 | int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ 643 | int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ 644 | #else 645 | int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ 646 | #endif 647 | 648 | JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ 649 | /* The coefficient controller's input and output progress is measured in 650 | * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows 651 | * in fully interleaved JPEG scans, but are used whether the scan is 652 | * interleaved or not. We define an iMCU row as v_samp_factor DCT block 653 | * rows of each component. Therefore, the IDCT output contains 654 | * v_samp_factor*DCT_[v_]scaled_size sample rows of a component per iMCU row. 655 | */ 656 | 657 | JSAMPLE * sample_range_limit; /* table for fast range-limiting */ 658 | 659 | /* 660 | * These fields are valid during any one scan. 661 | * They describe the components and MCUs actually appearing in the scan. 662 | * Note that the decompressor output side must not use these fields. 663 | */ 664 | int comps_in_scan; /* # of JPEG components in this scan */ 665 | jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; 666 | /* *cur_comp_info[i] describes component that appears i'th in SOS */ 667 | 668 | JDIMENSION MCUs_per_row; /* # of MCUs across the image */ 669 | JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ 670 | 671 | int blocks_in_MCU; /* # of DCT blocks per MCU */ 672 | int MCU_membership[D_MAX_BLOCKS_IN_MCU]; 673 | /* MCU_membership[i] is index in cur_comp_info of component owning */ 674 | /* i'th block in an MCU */ 675 | 676 | int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ 677 | 678 | #if JPEG_LIB_VERSION >= 80 679 | /* These fields are derived from Se of first SOS marker. 680 | */ 681 | int block_size; /* the basic DCT block size: 1..16 */ 682 | const int * natural_order; /* natural-order position array for entropy decode */ 683 | int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ 684 | #endif 685 | 686 | /* This field is shared between entropy decoder and marker parser. 687 | * It is either zero or the code of a JPEG marker that has been 688 | * read from the data source, but has not yet been processed. 689 | */ 690 | int unread_marker; 691 | 692 | /* 693 | * Links to decompression subobjects (methods, private variables of modules) 694 | */ 695 | struct jpeg_decomp_master * master; 696 | struct jpeg_d_main_controller * main; 697 | struct jpeg_d_coef_controller * coef; 698 | struct jpeg_d_post_controller * post; 699 | struct jpeg_input_controller * inputctl; 700 | struct jpeg_marker_reader * marker; 701 | struct jpeg_entropy_decoder * entropy; 702 | struct jpeg_inverse_dct * idct; 703 | struct jpeg_upsampler * upsample; 704 | struct jpeg_color_deconverter * cconvert; 705 | struct jpeg_color_quantizer * cquantize; 706 | }; 707 | 708 | 709 | /* "Object" declarations for JPEG modules that may be supplied or called 710 | * directly by the surrounding application. 711 | * As with all objects in the JPEG library, these structs only define the 712 | * publicly visible methods and state variables of a module. Additional 713 | * private fields may exist after the public ones. 714 | */ 715 | 716 | 717 | /* Error handler object */ 718 | 719 | struct jpeg_error_mgr { 720 | /* Error exit handler: does not return to caller */ 721 | JMETHOD(void, error_exit, (j_common_ptr cinfo)); 722 | /* Conditionally emit a trace or warning message */ 723 | JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); 724 | /* Routine that actually outputs a trace or error message */ 725 | JMETHOD(void, output_message, (j_common_ptr cinfo)); 726 | /* Format a message string for the most recent JPEG error or message */ 727 | JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); 728 | #define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ 729 | /* Reset error state variables at start of a new image */ 730 | JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); 731 | 732 | /* The message ID code and any parameters are saved here. 733 | * A message can have one string parameter or up to 8 int parameters. 734 | */ 735 | int msg_code; 736 | #define JMSG_STR_PARM_MAX 80 737 | union { 738 | int i[8]; 739 | char s[JMSG_STR_PARM_MAX]; 740 | } msg_parm; 741 | 742 | /* Standard state variables for error facility */ 743 | 744 | int trace_level; /* max msg_level that will be displayed */ 745 | 746 | /* For recoverable corrupt-data errors, we emit a warning message, 747 | * but keep going unless emit_message chooses to abort. emit_message 748 | * should count warnings in num_warnings. The surrounding application 749 | * can check for bad data by seeing if num_warnings is nonzero at the 750 | * end of processing. 751 | */ 752 | long num_warnings; /* number of corrupt-data warnings */ 753 | 754 | /* These fields point to the table(s) of error message strings. 755 | * An application can change the table pointer to switch to a different 756 | * message list (typically, to change the language in which errors are 757 | * reported). Some applications may wish to add additional error codes 758 | * that will be handled by the JPEG library error mechanism; the second 759 | * table pointer is used for this purpose. 760 | * 761 | * First table includes all errors generated by JPEG library itself. 762 | * Error code 0 is reserved for a "no such error string" message. 763 | */ 764 | const char * const * jpeg_message_table; /* Library errors */ 765 | int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ 766 | /* Second table can be added by application (see cjpeg/djpeg for example). 767 | * It contains strings numbered first_addon_message..last_addon_message. 768 | */ 769 | const char * const * addon_message_table; /* Non-library errors */ 770 | int first_addon_message; /* code for first string in addon table */ 771 | int last_addon_message; /* code for last string in addon table */ 772 | }; 773 | 774 | 775 | /* Progress monitor object */ 776 | 777 | struct jpeg_progress_mgr { 778 | JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); 779 | 780 | long pass_counter; /* work units completed in this pass */ 781 | long pass_limit; /* total number of work units in this pass */ 782 | int completed_passes; /* passes completed so far */ 783 | int total_passes; /* total number of passes expected */ 784 | }; 785 | 786 | 787 | /* Data destination object for compression */ 788 | 789 | struct jpeg_destination_mgr { 790 | JOCTET * next_output_byte; /* => next byte to write in buffer */ 791 | size_t free_in_buffer; /* # of byte spaces remaining in buffer */ 792 | 793 | JMETHOD(void, init_destination, (j_compress_ptr cinfo)); 794 | JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); 795 | JMETHOD(void, term_destination, (j_compress_ptr cinfo)); 796 | }; 797 | 798 | 799 | /* Data source object for decompression */ 800 | 801 | struct jpeg_source_mgr { 802 | const JOCTET * next_input_byte; /* => next byte to read from buffer */ 803 | size_t bytes_in_buffer; /* # of bytes remaining in buffer */ 804 | 805 | JMETHOD(void, init_source, (j_decompress_ptr cinfo)); 806 | JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); 807 | JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); 808 | JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); 809 | JMETHOD(void, term_source, (j_decompress_ptr cinfo)); 810 | }; 811 | 812 | 813 | /* Memory manager object. 814 | * Allocates "small" objects (a few K total), "large" objects (tens of K), 815 | * and "really big" objects (virtual arrays with backing store if needed). 816 | * The memory manager does not allow individual objects to be freed; rather, 817 | * each created object is assigned to a pool, and whole pools can be freed 818 | * at once. This is faster and more convenient than remembering exactly what 819 | * to free, especially where malloc()/free() are not too speedy. 820 | * NB: alloc routines never return NULL. They exit to error_exit if not 821 | * successful. 822 | */ 823 | 824 | #define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ 825 | #define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ 826 | #define JPOOL_NUMPOOLS 2 827 | 828 | typedef struct jvirt_sarray_control * jvirt_sarray_ptr; 829 | typedef struct jvirt_barray_control * jvirt_barray_ptr; 830 | 831 | 832 | struct jpeg_memory_mgr { 833 | /* Method pointers */ 834 | JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, 835 | size_t sizeofobject)); 836 | JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, 837 | size_t sizeofobject)); 838 | JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, 839 | JDIMENSION samplesperrow, 840 | JDIMENSION numrows)); 841 | JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, 842 | JDIMENSION blocksperrow, 843 | JDIMENSION numrows)); 844 | JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, 845 | int pool_id, 846 | boolean pre_zero, 847 | JDIMENSION samplesperrow, 848 | JDIMENSION numrows, 849 | JDIMENSION maxaccess)); 850 | JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, 851 | int pool_id, 852 | boolean pre_zero, 853 | JDIMENSION blocksperrow, 854 | JDIMENSION numrows, 855 | JDIMENSION maxaccess)); 856 | JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); 857 | JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, 858 | jvirt_sarray_ptr ptr, 859 | JDIMENSION start_row, 860 | JDIMENSION num_rows, 861 | boolean writable)); 862 | JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, 863 | jvirt_barray_ptr ptr, 864 | JDIMENSION start_row, 865 | JDIMENSION num_rows, 866 | boolean writable)); 867 | JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); 868 | JMETHOD(void, self_destruct, (j_common_ptr cinfo)); 869 | 870 | /* Limit on memory allocation for this JPEG object. (Note that this is 871 | * merely advisory, not a guaranteed maximum; it only affects the space 872 | * used for virtual-array buffers.) May be changed by outer application 873 | * after creating the JPEG object. 874 | */ 875 | long max_memory_to_use; 876 | 877 | /* Maximum allocation request accepted by alloc_large. */ 878 | long max_alloc_chunk; 879 | }; 880 | 881 | 882 | /* Routine signature for application-supplied marker processing methods. 883 | * Need not pass marker code since it is stored in cinfo->unread_marker. 884 | */ 885 | typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); 886 | 887 | 888 | /* Declarations for routines called by application. 889 | * The JPP macro hides prototype parameters from compilers that can't cope. 890 | * Note JPP requires double parentheses. 891 | */ 892 | 893 | #ifdef HAVE_PROTOTYPES 894 | #define JPP(arglist) arglist 895 | #else 896 | #define JPP(arglist) () 897 | #endif 898 | 899 | 900 | /* Short forms of external names for systems with brain-damaged linkers. 901 | * We shorten external names to be unique in the first six letters, which 902 | * is good enough for all known systems. 903 | * (If your compiler itself needs names to be unique in less than 15 904 | * characters, you are out of luck. Get a better compiler.) 905 | */ 906 | 907 | #ifdef NEED_SHORT_EXTERNAL_NAMES 908 | #define jpeg_std_error jStdError 909 | #define jpeg_CreateCompress jCreaCompress 910 | #define jpeg_CreateDecompress jCreaDecompress 911 | #define jpeg_destroy_compress jDestCompress 912 | #define jpeg_destroy_decompress jDestDecompress 913 | #define jpeg_stdio_dest jStdDest 914 | #define jpeg_stdio_src jStdSrc 915 | #if JPEG_LIB_VERSION >= 80 916 | #define jpeg_mem_dest jMemDest 917 | #define jpeg_mem_src jMemSrc 918 | #endif 919 | #define jpeg_set_defaults jSetDefaults 920 | #define jpeg_set_colorspace jSetColorspace 921 | #define jpeg_default_colorspace jDefColorspace 922 | #define jpeg_set_quality jSetQuality 923 | #define jpeg_set_linear_quality jSetLQuality 924 | #if JPEG_LIB_VERSION >= 70 925 | #define jpeg_default_qtables jDefQTables 926 | #endif 927 | #define jpeg_add_quant_table jAddQuantTable 928 | #define jpeg_quality_scaling jQualityScaling 929 | #define jpeg_simple_progression jSimProgress 930 | #define jpeg_suppress_tables jSuppressTables 931 | #define jpeg_alloc_quant_table jAlcQTable 932 | #define jpeg_alloc_huff_table jAlcHTable 933 | #define jpeg_start_compress jStrtCompress 934 | #define jpeg_write_scanlines jWrtScanlines 935 | #define jpeg_finish_compress jFinCompress 936 | #if JPEG_LIB_VERSION >= 70 937 | #define jpeg_calc_jpeg_dimensions jCjpegDimensions 938 | #endif 939 | #define jpeg_write_raw_data jWrtRawData 940 | #define jpeg_write_marker jWrtMarker 941 | #define jpeg_write_m_header jWrtMHeader 942 | #define jpeg_write_m_byte jWrtMByte 943 | #define jpeg_write_tables jWrtTables 944 | #define jpeg_read_header jReadHeader 945 | #define jpeg_start_decompress jStrtDecompress 946 | #define jpeg_read_scanlines jReadScanlines 947 | #define jpeg_finish_decompress jFinDecompress 948 | #define jpeg_read_raw_data jReadRawData 949 | #define jpeg_has_multiple_scans jHasMultScn 950 | #define jpeg_start_output jStrtOutput 951 | #define jpeg_finish_output jFinOutput 952 | #define jpeg_input_complete jInComplete 953 | #define jpeg_new_colormap jNewCMap 954 | #define jpeg_consume_input jConsumeInput 955 | #if JPEG_LIB_VERSION >= 80 956 | #define jpeg_core_output_dimensions jCoreDimensions 957 | #endif 958 | #define jpeg_calc_output_dimensions jCalcDimensions 959 | #define jpeg_save_markers jSaveMarkers 960 | #define jpeg_set_marker_processor jSetMarker 961 | #define jpeg_read_coefficients jReadCoefs 962 | #define jpeg_write_coefficients jWrtCoefs 963 | #define jpeg_copy_critical_parameters jCopyCrit 964 | #define jpeg_abort_compress jAbrtCompress 965 | #define jpeg_abort_decompress jAbrtDecompress 966 | #define jpeg_abort jAbort 967 | #define jpeg_destroy jDestroy 968 | #define jpeg_resync_to_restart jResyncRestart 969 | #endif /* NEED_SHORT_EXTERNAL_NAMES */ 970 | 971 | 972 | /* Default error-management setup */ 973 | EXTERN(struct jpeg_error_mgr *) jpeg_std_error 974 | JPP((struct jpeg_error_mgr * err)); 975 | 976 | /* Initialization of JPEG compression objects. 977 | * jpeg_create_compress() and jpeg_create_decompress() are the exported 978 | * names that applications should call. These expand to calls on 979 | * jpeg_CreateCompress and jpeg_CreateDecompress with additional information 980 | * passed for version mismatch checking. 981 | * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. 982 | */ 983 | #define jpeg_create_compress(cinfo) \ 984 | jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ 985 | (size_t) sizeof(struct jpeg_compress_struct)) 986 | #define jpeg_create_decompress(cinfo) \ 987 | jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ 988 | (size_t) sizeof(struct jpeg_decompress_struct)) 989 | EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, 990 | int version, size_t structsize)); 991 | EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, 992 | int version, size_t structsize)); 993 | /* Destruction of JPEG compression objects */ 994 | EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); 995 | EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); 996 | 997 | /* Standard data source and destination managers: stdio streams. */ 998 | /* Caller is responsible for opening the file before and closing after. */ 999 | EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); 1000 | EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); 1001 | 1002 | #if JPEG_LIB_VERSION >= 80 1003 | /* Data source and destination managers: memory buffers. */ 1004 | EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, 1005 | unsigned char ** outbuffer, 1006 | unsigned long * outsize)); 1007 | EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, 1008 | unsigned char * inbuffer, 1009 | unsigned long insize)); 1010 | #endif 1011 | 1012 | /* Default parameter setup for compression */ 1013 | EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); 1014 | /* Compression parameter setup aids */ 1015 | EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, 1016 | J_COLOR_SPACE colorspace)); 1017 | EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); 1018 | EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, 1019 | boolean force_baseline)); 1020 | EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, 1021 | int scale_factor, 1022 | boolean force_baseline)); 1023 | #if JPEG_LIB_VERSION >= 70 1024 | EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, 1025 | boolean force_baseline)); 1026 | #endif 1027 | EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, 1028 | const unsigned int *basic_table, 1029 | int scale_factor, 1030 | boolean force_baseline)); 1031 | EXTERN(int) jpeg_quality_scaling JPP((int quality)); 1032 | EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); 1033 | EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, 1034 | boolean suppress)); 1035 | EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); 1036 | EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); 1037 | 1038 | /* Main entry points for compression */ 1039 | EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, 1040 | boolean write_all_tables)); 1041 | EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, 1042 | JSAMPARRAY scanlines, 1043 | JDIMENSION num_lines)); 1044 | EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); 1045 | 1046 | #if JPEG_LIB_VERSION >= 70 1047 | /* Precalculate JPEG dimensions for current compression parameters. */ 1048 | EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); 1049 | #endif 1050 | 1051 | /* Replaces jpeg_write_scanlines when writing raw downsampled data. */ 1052 | EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, 1053 | JSAMPIMAGE data, 1054 | JDIMENSION num_lines)); 1055 | 1056 | /* Write a special marker. See libjpeg.txt concerning safe usage. */ 1057 | EXTERN(void) jpeg_write_marker 1058 | JPP((j_compress_ptr cinfo, int marker, 1059 | const JOCTET * dataptr, unsigned int datalen)); 1060 | /* Same, but piecemeal. */ 1061 | EXTERN(void) jpeg_write_m_header 1062 | JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); 1063 | EXTERN(void) jpeg_write_m_byte 1064 | JPP((j_compress_ptr cinfo, int val)); 1065 | 1066 | /* Alternate compression function: just write an abbreviated table file */ 1067 | EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); 1068 | 1069 | /* Decompression startup: read start of JPEG datastream to see what's there */ 1070 | EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, 1071 | boolean require_image)); 1072 | /* Return value is one of: */ 1073 | #define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ 1074 | #define JPEG_HEADER_OK 1 /* Found valid image datastream */ 1075 | #define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ 1076 | /* If you pass require_image = TRUE (normal case), you need not check for 1077 | * a TABLES_ONLY return code; an abbreviated file will cause an error exit. 1078 | * JPEG_SUSPENDED is only possible if you use a data source module that can 1079 | * give a suspension return (the stdio source module doesn't). 1080 | */ 1081 | 1082 | /* Main entry points for decompression */ 1083 | EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); 1084 | EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, 1085 | JSAMPARRAY scanlines, 1086 | JDIMENSION max_lines)); 1087 | EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); 1088 | 1089 | /* Replaces jpeg_read_scanlines when reading raw downsampled data. */ 1090 | EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, 1091 | JSAMPIMAGE data, 1092 | JDIMENSION max_lines)); 1093 | 1094 | /* Additional entry points for buffered-image mode. */ 1095 | EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); 1096 | EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, 1097 | int scan_number)); 1098 | EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); 1099 | EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); 1100 | EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); 1101 | EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); 1102 | /* Return value is one of: */ 1103 | /* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ 1104 | #define JPEG_REACHED_SOS 1 /* Reached start of new scan */ 1105 | #define JPEG_REACHED_EOI 2 /* Reached end of image */ 1106 | #define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ 1107 | #define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ 1108 | 1109 | /* Precalculate output dimensions for current decompression parameters. */ 1110 | #if JPEG_LIB_VERSION >= 80 1111 | EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); 1112 | #endif 1113 | EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); 1114 | 1115 | /* Control saving of COM and APPn markers into marker_list. */ 1116 | EXTERN(void) jpeg_save_markers 1117 | JPP((j_decompress_ptr cinfo, int marker_code, 1118 | unsigned int length_limit)); 1119 | 1120 | /* Install a special processing method for COM or APPn markers. */ 1121 | EXTERN(void) jpeg_set_marker_processor 1122 | JPP((j_decompress_ptr cinfo, int marker_code, 1123 | jpeg_marker_parser_method routine)); 1124 | 1125 | /* Read or write raw DCT coefficients --- useful for lossless transcoding. */ 1126 | EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); 1127 | EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, 1128 | jvirt_barray_ptr * coef_arrays)); 1129 | EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, 1130 | j_compress_ptr dstinfo)); 1131 | 1132 | /* If you choose to abort compression or decompression before completing 1133 | * jpeg_finish_(de)compress, then you need to clean up to release memory, 1134 | * temporary files, etc. You can just call jpeg_destroy_(de)compress 1135 | * if you're done with the JPEG object, but if you want to clean it up and 1136 | * reuse it, call this: 1137 | */ 1138 | EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); 1139 | EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); 1140 | 1141 | /* Generic versions of jpeg_abort and jpeg_destroy that work on either 1142 | * flavor of JPEG object. These may be more convenient in some places. 1143 | */ 1144 | EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); 1145 | EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); 1146 | 1147 | /* Default restart-marker-resync procedure for use by data source modules */ 1148 | EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, 1149 | int desired)); 1150 | 1151 | 1152 | /* These marker codes are exported since applications and data source modules 1153 | * are likely to want to use them. 1154 | */ 1155 | 1156 | #define JPEG_RST0 0xD0 /* RST0 marker code */ 1157 | #define JPEG_EOI 0xD9 /* EOI marker code */ 1158 | #define JPEG_APP0 0xE0 /* APP0 marker code */ 1159 | #define JPEG_COM 0xFE /* COM marker code */ 1160 | 1161 | 1162 | /* If we have a brain-damaged compiler that emits warnings (or worse, errors) 1163 | * for structure definitions that are never filled in, keep it quiet by 1164 | * supplying dummy definitions for the various substructures. 1165 | */ 1166 | 1167 | #ifdef INCOMPLETE_TYPES_BROKEN 1168 | #ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ 1169 | struct jvirt_sarray_control { long dummy; }; 1170 | struct jvirt_barray_control { long dummy; }; 1171 | struct jpeg_comp_master { long dummy; }; 1172 | struct jpeg_c_main_controller { long dummy; }; 1173 | struct jpeg_c_prep_controller { long dummy; }; 1174 | struct jpeg_c_coef_controller { long dummy; }; 1175 | struct jpeg_marker_writer { long dummy; }; 1176 | struct jpeg_color_converter { long dummy; }; 1177 | struct jpeg_downsampler { long dummy; }; 1178 | struct jpeg_forward_dct { long dummy; }; 1179 | struct jpeg_entropy_encoder { long dummy; }; 1180 | struct jpeg_decomp_master { long dummy; }; 1181 | struct jpeg_d_main_controller { long dummy; }; 1182 | struct jpeg_d_coef_controller { long dummy; }; 1183 | struct jpeg_d_post_controller { long dummy; }; 1184 | struct jpeg_input_controller { long dummy; }; 1185 | struct jpeg_marker_reader { long dummy; }; 1186 | struct jpeg_entropy_decoder { long dummy; }; 1187 | struct jpeg_inverse_dct { long dummy; }; 1188 | struct jpeg_upsampler { long dummy; }; 1189 | struct jpeg_color_deconverter { long dummy; }; 1190 | struct jpeg_color_quantizer { long dummy; }; 1191 | #endif /* JPEG_INTERNALS */ 1192 | #endif /* INCOMPLETE_TYPES_BROKEN */ 1193 | 1194 | 1195 | /* 1196 | * The JPEG library modules define JPEG_INTERNALS before including this file. 1197 | * The internal structure declarations are read only when that is true. 1198 | * Applications using the library should not include jpegint.h, but may wish 1199 | * to include jerror.h. 1200 | */ 1201 | 1202 | #ifdef JPEG_INTERNALS 1203 | #include "jpegint.h" /* fetch private declarations */ 1204 | #include "jerror.h" /* fetch error codes too */ 1205 | #endif 1206 | 1207 | #ifdef __cplusplus 1208 | #ifndef DONT_USE_EXTERN_C 1209 | } 1210 | #endif 1211 | #endif 1212 | 1213 | #endif /* JPEGLIB_H */ 1214 | -------------------------------------------------------------------------------- /convert/mjpeg2rgb.c: -------------------------------------------------------------------------------- 1 | /* MJPEG : 实质上每一帧数据都是一个完整的JPEG文件 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef struct MyErrorMgr 10 | { 11 | struct jpeg_error_mgr pub; 12 | jmp_buf setjmp_buffer; 13 | }T_MyErrorMgr, *PT_MyErrorMgr; 14 | 15 | extern void jpeg_mem_src_tj(j_decompress_ptr, unsigned char *, unsigned long); 16 | 17 | 18 | 19 | 20 | 21 | static int isSupportMjpeg2Rgb(int iPixelFormatIn, int iPixelFormatOut) 22 | { 23 | if (iPixelFormatIn != V4L2_PIX_FMT_MJPEG) 24 | return 0; 25 | if ((iPixelFormatOut != V4L2_PIX_FMT_RGB565) && (iPixelFormatOut != V4L2_PIX_FMT_RGB32)) 26 | { 27 | return 0; 28 | } 29 | return 1; 30 | } 31 | 32 | 33 | 34 | 35 | 36 | /********************************************************************** 37 | * 函数名称: GetPixelDatasFrmJPG 38 | * 功能描述: 把JPG文件中的图像数据,取出并转换为能在显示设备上使用的格式 39 | * 输入参数: ptFileMap - 内含文件信息 40 | * 输出参数: ptPixelDatas - 内含象素数据 41 | * ptPixelDatas->iBpp 是输入的参数, 它确定从JPG文件得到的数据要转换为该BPP 42 | * 返 回 值: 0 - 成功, 其他值 - 失败 43 | * 修改日期 版本号 修改人 修改内容 44 | * ----------------------------------------------- 45 | * 2013/02/08 V1.0 韦东山 创建 46 | ***********************************************************************/ 47 | //static int GetPixelDatasFrmJPG(PT_FileMap ptFileMap, PT_PixelDatas ptPixelDatas) 48 | /* 把内存里的JPEG图像转换为RGB图像 */ 49 | static int Mjpeg2RgbConvert(PT_VideoBuf ptVideoBufIn, PT_VideoBuf ptVideoBufOut) 50 | { 51 | struct jpeg_decompress_struct tDInfo; 52 | //struct jpeg_error_mgr tJErr; 53 | int iRet; 54 | int iRowStride; 55 | unsigned char *aucLineBuffer = NULL; 56 | unsigned char *pucDest; 57 | T_MyErrorMgr tJerr; 58 | PT_PixelDatas ptPixelDatas = &ptVideoBufOut->tPixelDatas; 59 | 60 | // 分配和初始化一个decompression结构体 61 | //tDInfo.err = jpeg_std_error(&tJErr); 62 | 63 | tDInfo.err = jpeg_std_error(&tJerr.pub); 64 | tJerr.pub.error_exit = MyErrorExit; 65 | 66 | if(setjmp(tJerr.setjmp_buffer)) 67 | { 68 | /* 如果程序能运行到这里, 表示JPEG解码出错 */ 69 | jpeg_destroy_decompress(&tDInfo); 70 | if (aucLineBuffer) 71 | { 72 | free(aucLineBuffer); 73 | } 74 | if (ptPixelDatas->aucPixelDatas) 75 | { 76 | free(ptPixelDatas->aucPixelDatas); 77 | } 78 | return -1; 79 | } 80 | 81 | jpeg_create_decompress(&tDInfo); 82 | 83 | // 用jpeg_read_header获得jpg信息 84 | //jpeg_stdio_src(&tDInfo, ptFileMap->tFp); 85 | /* 把数据设为内存中的数据 */ 86 | jpeg_mem_src_tj (&tDInfo, ptVideoBufIn->tPixelDatas.aucPixelDatas, ptVideoBufIn->tPixelDatas.iTotalBytes); 87 | 88 | 89 | iRet = jpeg_read_header(&tDInfo, TRUE); 90 | 91 | // 设置解压参数,比如放大、缩小 92 | tDInfo.scale_num = tDInfo.scale_denom = 1; 93 | 94 | // 启动解压:jpeg_start_decompress 95 | jpeg_start_decompress(&tDInfo); 96 | 97 | // 一行的数据长度 98 | iRowStride = tDInfo.output_width * tDInfo.output_components; 99 | aucLineBuffer = malloc(iRowStride); 100 | 101 | if (NULL == aucLineBuffer) 102 | { 103 | return -1; 104 | } 105 | 106 | ptPixelDatas->iWidth = tDInfo.output_width; 107 | ptPixelDatas->iHeight = tDInfo.output_height; 108 | //ptPixelDatas->iBpp = iBpp; 109 | ptPixelDatas->iLineBytes = ptPixelDatas->iWidth * ptPixelDatas->iBpp / 8; 110 | ptPixelDatas->iTotalBytes = ptPixelDatas->iHeight * ptPixelDatas->iLineBytes; 111 | if (NULL == ptPixelDatas->aucPixelDatas) 112 | { 113 | ptPixelDatas->aucPixelDatas = malloc(ptPixelDatas->iTotalBytes); 114 | } 115 | 116 | pucDest = ptPixelDatas->aucPixelDatas; 117 | 118 | // 循环调用jpeg_read_scanlines来一行一行地获得解压的数据 119 | while (tDInfo.output_scanline < tDInfo.output_height) 120 | { 121 | /* 得到一行数据,里面的颜色格式为0xRR, 0xGG, 0xBB */ 122 | (void) jpeg_read_scanlines(&tDInfo, &aucLineBuffer, 1); 123 | 124 | // 转到ptPixelDatas去 125 | CovertOneLine(ptPixelDatas->iWidth, 24, ptPixelDatas->iBpp, aucLineBuffer, pucDest); 126 | pucDest += ptPixelDatas->iLineBytes; 127 | } 128 | 129 | free(aucLineBuffer); 130 | jpeg_finish_decompress(&tDInfo); 131 | jpeg_destroy_decompress(&tDInfo); 132 | 133 | return 0; 134 | } 135 | 136 | 137 | 138 | static int Mjpeg2RgbConvertExit(PT_VideoBuf ptVideoBufOut) 139 | { 140 | if (ptVideoBufOut->tPixelDatas.aucPixelDatas) 141 | { 142 | free(ptVideoBufOut->tPixelDatas.aucPixelDatas); 143 | ptVideoBufOut->tPixelDatas.aucPixelDatas = NULL; 144 | } 145 | return 0; 146 | } 147 | 148 | 149 | 150 | 151 | /* 构造 */ 152 | static T_VideoConvert g_tMjpeg2RgbConvert = { 153 | .name = "mjpeg2rgb", 154 | .isSupport = isSupportMjpeg2Rgb, 155 | .Convert = Mjpeg2RgbConvert, 156 | .ConvertExit = Mjpeg2RgbConvertExit, 157 | }; 158 | 159 | 160 | /* 注册 */ 161 | int Mjpeg2RgbInit(void) 162 | { 163 | return RegisterVideoConvert(&g_tMjpeg2RgbConvert); 164 | } 165 | 166 | 167 | 168 | 169 | /********************************************************************** 170 | * 函数名称: MyErrorExit 171 | * 功能描述: 自定义的libjpeg库出错处理函数 172 | * 默认的错误处理函数是让程序退出,我们当然不会使用它 173 | * 参考libjpeg里的bmp.c编写了这个错误处理函数 174 | * 输入参数: ptCInfo - libjpeg库抽象出来的通用结构体 175 | * 输出参数: 无 176 | * 返 回 值: 无 177 | * 修改日期 版本号 修改人 修改内容 178 | * ----------------------------------------------- 179 | * 2013/02/08 V1.0 韦东山 创建 180 | ***********************************************************************/ 181 | static void MyErrorExit(j_common_ptr ptCInfo) 182 | { 183 | static char errStr[JMSG_LENGTH_MAX]; 184 | 185 | PT_MyErrorMgr ptMyErr = (PT_MyErrorMgr)ptCInfo->err; 186 | 187 | /* Create the message */ 188 | (*ptCInfo->err->format_message) (ptCInfo, errStr); 189 | DBG_PRINTF("%s\n", errStr); 190 | 191 | longjmp(ptMyErr->setjmp_buffer, 1); 192 | } 193 | 194 | /********************************************************************** 195 | * 函数名称: CovertOneLine 196 | * 功能描述: 把已经从JPG文件取出的一行象素数据,转换为能在显示设备上使用的格式 197 | * 输入参数: iWidth - 宽度,即多少个象素 198 | * iSrcBpp - 已经从JPG文件取出的一行象素数据里面,一个象素用多少位来表示 199 | * iDstBpp - 显示设备上一个象素用多少位来表示 200 | * pudSrcDatas - 已经从JPG文件取出的一行象素数所存储的位置 201 | * pudDstDatas - 转换所得数据存储的位置 202 | * 输出参数: 无 203 | * 返 回 值: 0 - 成功, 其他值 - 失败 204 | * 修改日期 版本号 修改人 修改内容 205 | * ----------------------------------------------- 206 | * 2013/02/08 V1.0 韦东山 创建 207 | ***********************************************************************/ 208 | static int CovertOneLine(int iWidth, int iSrcBpp, int iDstBpp, unsigned char *pudSrcDatas, unsigned char *pudDstDatas) 209 | { 210 | unsigned int dwRed; 211 | unsigned int dwGreen; 212 | unsigned int dwBlue; 213 | unsigned int dwColor; 214 | 215 | unsigned short *pwDstDatas16bpp = (unsigned short *)pudDstDatas; 216 | unsigned int *pwDstDatas32bpp = (unsigned int *)pudDstDatas; 217 | 218 | int i; 219 | int pos = 0; 220 | 221 | if (iSrcBpp != 24) 222 | { 223 | return -1; 224 | } 225 | 226 | if (iDstBpp == 24) 227 | { 228 | memcpy(pudDstDatas, pudSrcDatas, iWidth*3); 229 | } 230 | else 231 | { 232 | for (i = 0; i < iWidth; i++) 233 | { 234 | dwRed = pudSrcDatas[pos++]; 235 | dwGreen = pudSrcDatas[pos++]; 236 | dwBlue = pudSrcDatas[pos++]; 237 | if (iDstBpp == 32) 238 | { 239 | dwColor = (dwRed << 16) | (dwGreen << 8) | dwBlue; 240 | *pwDstDatas32bpp = dwColor; 241 | pwDstDatas32bpp++; 242 | } 243 | else if (iDstBpp == 16) 244 | { 245 | /* 565 */ 246 | dwRed = dwRed >> 3; 247 | dwGreen = dwGreen >> 2; 248 | dwBlue = dwBlue >> 3; 249 | dwColor = (dwRed << 11) | (dwGreen << 5) | (dwBlue); 250 | *pwDstDatas16bpp = dwColor; 251 | pwDstDatas16bpp++; 252 | } 253 | } 254 | } 255 | return 0; 256 | } -------------------------------------------------------------------------------- /convert/rgb2rgb.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | static int isSupportRgb2Rgb(int iPixelFormatIn, int iPixelFormatOut) 7 | { 8 | if (iPixelFormatIn != V4L2_PIX_FMT_RGB565) 9 | return 0; 10 | if ((iPixelFormatOut != V4L2_PIX_FMT_RGB565) && (iPixelFormatOut != V4L2_PIX_FMT_RGB32)) 11 | { 12 | return 0; 13 | } 14 | return 1; 15 | } 16 | 17 | static int Rgb2RgbConvert(PT_VideoBuf ptVideoBufIn, PT_VideoBuf ptVideoBufOut) 18 | { 19 | PT_PixelDatas ptPixelDatasIn = &ptVideoBufIn->tPixelDatas; 20 | PT_PixelDatas ptPixelDatasOut = &ptVideoBufOut->tPixelDatas; 21 | 22 | int x, y; 23 | int r, g, b; 24 | int color; 25 | unsigned short *pwSrc = (unsigned short *)ptPixelDatasIn->aucPixelDatas; 26 | unsigned int *pdwDest; 27 | 28 | if (ptVideoBufIn->iPixelFormat != V4L2_PIX_FMT_RGB565) 29 | { 30 | return -1; 31 | } 32 | 33 | if (ptVideoBufOut->iPixelFormat == V4L2_PIX_FMT_RGB565) 34 | { 35 | ptPixelDatasOut->iWidth = ptPixelDatasIn->iWidth; 36 | ptPixelDatasOut->iHeight = ptPixelDatasIn->iHeight; 37 | ptPixelDatasOut->iBpp = 16; 38 | ptPixelDatasOut->iLineBytes = ptPixelDatasOut->iWidth * ptPixelDatasOut->iBpp / 8; 39 | ptPixelDatasOut->iTotalBytes = ptPixelDatasOut->iLineBytes * ptPixelDatasOut->iHeight; 40 | if (!ptPixelDatasOut->aucPixelDatas) 41 | { 42 | ptPixelDatasOut->aucPixelDatas = malloc(ptPixelDatasOut->iTotalBytes); 43 | } 44 | 45 | memcpy(ptPixelDatasOut->aucPixelDatas, ptPixelDatasIn->aucPixelDatas, ptPixelDatasOut->iTotalBytes); 46 | return 0; 47 | } 48 | else if (ptVideoBufOut->iPixelFormat == V4L2_PIX_FMT_RGB32) 49 | { 50 | ptPixelDatasOut->iWidth = ptPixelDatasIn->iWidth; 51 | ptPixelDatasOut->iHeight = ptPixelDatasIn->iHeight; 52 | ptPixelDatasOut->iBpp = 32; 53 | ptPixelDatasOut->iLineBytes = ptPixelDatasOut->iWidth * ptPixelDatasOut->iBpp / 8; 54 | ptPixelDatasOut->iTotalBytes = ptPixelDatasOut->iLineBytes * ptPixelDatasOut->iHeight; 55 | if (!ptPixelDatasOut->aucPixelDatas) 56 | { 57 | ptPixelDatasOut->aucPixelDatas = malloc(ptPixelDatasOut->iTotalBytes); 58 | } 59 | 60 | pdwDest = (unsigned int *)ptPixelDatasOut->aucPixelDatas; 61 | 62 | for (y = 0; y < ptPixelDatasOut->iHeight; y++) 63 | { 64 | for (x = 0; x < ptPixelDatasOut->iWidth; x++) 65 | { 66 | color = *pwSrc++; 67 | /* 从RGB565格式的数据中提取出R,G,B */ 68 | r = color >> 11; 69 | g = (color >> 5) & (0x3f); 70 | b = color & 0x1f; 71 | 72 | /* 把r,g,b转为0x00RRGGBB的32位数据 */ 73 | color = ((r << 3) << 16) | ((g << 2) << 8) | (b << 3); 74 | 75 | *pdwDest = color; 76 | pdwDest++; 77 | } 78 | } 79 | return 0; 80 | } 81 | 82 | return -1; 83 | } 84 | 85 | static int Rgb2RgbConvertExit(PT_VideoBuf ptVideoBufOut) 86 | { 87 | if (ptVideoBufOut->tPixelDatas.aucPixelDatas) 88 | { 89 | free(ptVideoBufOut->tPixelDatas.aucPixelDatas); 90 | ptVideoBufOut->tPixelDatas.aucPixelDatas = NULL; 91 | } 92 | return 0; 93 | } 94 | 95 | /* 构造 */ 96 | static T_VideoConvert g_tRgb2RgbConvert = { 97 | .name = "rgb2rgb", 98 | .isSupport = isSupportRgb2Rgb, 99 | .Convert = Rgb2RgbConvert, 100 | .ConvertExit = Rgb2RgbConvertExit, 101 | }; 102 | 103 | 104 | /* 注册 */ 105 | int Rgb2RgbInit(void) 106 | { 107 | return RegisterVideoConvert(&g_tRgb2RgbConvert); 108 | } 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /convert/yuv_2_rgb.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "color.h" 5 | 6 | static int isSupportYuv2Rgb(int iPixelFormatIn, int iPixelFormatOut) 7 | { 8 | if (iPixelFormatIn != V4L2_PIX_FMT_YUYV) 9 | return 0; 10 | if ((iPixelFormatOut != V4L2_PIX_FMT_RGB565) && (iPixelFormatOut != V4L2_PIX_FMT_RGB32)) 11 | { 12 | return 0; 13 | } 14 | return 1; 15 | } 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | /* 参考luvcview */ 24 | static int Yuv2RgbConvert(PT_VideoBuf ptVideoBufIn, PT_VideoBuf ptVideoBufOut) 25 | { 26 | PT_PixelDatas ptPixelDatasIn = &ptVideoBufIn->tPixelDatas; 27 | PT_PixelDatas ptPixelDatasOut = &ptVideoBufOut->tPixelDatas; 28 | 29 | ptPixelDatasOut->iWidth = ptPixelDatasIn->iWidth; 30 | ptPixelDatasOut->iHeight = ptPixelDatasIn->iHeight; 31 | 32 | if (ptVideoBufOut->iPixelFormat == V4L2_PIX_FMT_RGB565) 33 | { 34 | ptPixelDatasOut->iBpp = 16; 35 | ptPixelDatasOut->iLineBytes = ptPixelDatasOut->iWidth * ptPixelDatasOut->iBpp / 8; 36 | ptPixelDatasOut->iTotalBytes = ptPixelDatasOut->iLineBytes * ptPixelDatasOut->iHeight; 37 | 38 | if (!ptPixelDatasOut->aucPixelDatas) 39 | { 40 | ptPixelDatasOut->aucPixelDatas = malloc(ptPixelDatasOut->iTotalBytes); 41 | } 42 | 43 | Pyuv422torgb565(ptPixelDatasIn->aucPixelDatas, ptPixelDatasOut->aucPixelDatas, ptPixelDatasOut->iWidth, ptPixelDatasOut->iHeight); 44 | return 0; 45 | } 46 | else if (ptVideoBufOut->iPixelFormat == V4L2_PIX_FMT_RGB32) 47 | { 48 | ptPixelDatasOut->iBpp = 32; 49 | ptPixelDatasOut->iLineBytes = ptPixelDatasOut->iWidth * ptPixelDatasOut->iBpp / 8; 50 | ptPixelDatasOut->iTotalBytes = ptPixelDatasOut->iLineBytes * ptPixelDatasOut->iHeight; 51 | 52 | if (!ptPixelDatasOut->aucPixelDatas) 53 | { 54 | ptPixelDatasOut->aucPixelDatas = malloc(ptPixelDatasOut->iTotalBytes); 55 | } 56 | 57 | Pyuv422torgb32(ptPixelDatasIn->aucPixelDatas, ptPixelDatasOut->aucPixelDatas, ptPixelDatasOut->iWidth, ptPixelDatasOut->iHeight); 58 | return 0; 59 | } 60 | 61 | return -1; 62 | } 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | static int Yuv2RgbConvertExit(PT_VideoBuf ptVideoBufOut) 71 | { 72 | if (ptVideoBufOut->tPixelDatas.aucPixelDatas) 73 | { 74 | free(ptVideoBufOut->tPixelDatas.aucPixelDatas); 75 | ptVideoBufOut->tPixelDatas.aucPixelDatas = NULL; 76 | } 77 | return 0; 78 | } 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | /* 构造 */ 88 | static T_VideoConvert g_tYuv2RgbConvert = { 89 | .name = "yuv2rgb", 90 | .isSupport = isSupportYuv2Rgb, 91 | .Convert = Yuv2RgbConvert, 92 | .ConvertExit = Yuv2RgbConvertExit, 93 | }; 94 | 95 | /* 注册 */ 96 | int Yuv2RgbInit(void) 97 | { 98 | //初始化xxx 99 | initLut(); 100 | //注册视频转换 101 | return RegisterVideoConvert(&g_tYuv2RgbConvert); 102 | } 103 | 104 | 105 | 106 | 107 | 108 | 109 | /* translate YUV422Packed to rgb24 */ 110 | 111 | static unsigned int 112 | Pyuv422torgb565(unsigned char * input_ptr, unsigned char * output_ptr, unsigned int image_width, unsigned int image_height) 113 | { 114 | unsigned int i, size; 115 | unsigned char Y, Y1, U, V; 116 | unsigned char *buff = input_ptr; 117 | unsigned char *output_pt = output_ptr; 118 | 119 | unsigned int r, g, b; 120 | unsigned int color; 121 | 122 | size = image_width * image_height /2; 123 | for (i = size; i > 0; i--) { 124 | /* bgr instead rgb ?? */ 125 | Y = buff[0] ; 126 | U = buff[1] ; 127 | Y1 = buff[2]; 128 | V = buff[3]; 129 | buff += 4; 130 | r = R_FROMYV(Y,V); 131 | g = G_FROMYUV(Y,U,V); //b 132 | b = B_FROMYU(Y,U); //v 133 | 134 | /* 把r,g,b三色构造为rgb565的16位值 */ 135 | r = r >> 3; 136 | g = g >> 2; 137 | b = b >> 3; 138 | color = (r << 11) | (g << 5) | b; 139 | *output_pt++ = color & 0xff; 140 | *output_pt++ = (color >> 8) & 0xff; 141 | 142 | r = R_FROMYV(Y1,V); 143 | g = G_FROMYUV(Y1,U,V); //b 144 | b = B_FROMYU(Y1,U); //v 145 | 146 | /* 把r,g,b三色构造为rgb565的16位值 */ 147 | r = r >> 3; 148 | g = g >> 2; 149 | b = b >> 3; 150 | color = (r << 11) | (g << 5) | b; 151 | *output_pt++ = color & 0xff; 152 | *output_pt++ = (color >> 8) & 0xff; 153 | } 154 | 155 | return 0; 156 | } 157 | 158 | 159 | 160 | 161 | /* translate YUV422Packed to rgb24 */ 162 | 163 | static unsigned int 164 | Pyuv422torgb32(unsigned char * input_ptr, unsigned char * output_ptr, unsigned int image_width, unsigned int image_height) 165 | { 166 | unsigned int i, size; 167 | unsigned char Y, Y1, U, V; 168 | unsigned char *buff = input_ptr; 169 | unsigned int *output_pt = (unsigned int *)output_ptr; 170 | 171 | unsigned int r, g, b; 172 | unsigned int color; 173 | 174 | size = image_width * image_height /2; 175 | for (i = size; i > 0; i--) { 176 | /* bgr instead rgb ?? */ 177 | Y = buff[0] ; 178 | U = buff[1] ; 179 | Y1 = buff[2]; 180 | V = buff[3]; 181 | buff += 4; 182 | 183 | r = R_FROMYV(Y,V); 184 | g = G_FROMYUV(Y,U,V); //b 185 | b = B_FROMYU(Y,U); //v 186 | /* rgb888 */ 187 | color = (r << 16) | (g << 8) | b; 188 | *output_pt++ = color; 189 | 190 | r = R_FROMYV(Y1,V); 191 | g = G_FROMYUV(Y1,U,V); //b 192 | b = B_FROMYU(Y1,U); //v 193 | color = (r << 16) | (g << 8) | b; 194 | *output_pt++ = color; 195 | } 196 | 197 | return 0; 198 | } -------------------------------------------------------------------------------- /display/Makefile: -------------------------------------------------------------------------------- 1 | obj-y += disp_manager.o 2 | obj-y += framebuffer.o -------------------------------------------------------------------------------- /display/disp_manager.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | static PT_DispOpr g_ptDispOprHead; 7 | static PT_DispOpr g_ptDefaultDispOpr; 8 | static PT_VideoMem g_ptVideoMemHead; 9 | 10 | 11 | 12 | 13 | 14 | void ShowDispOpr(void) 15 | { 16 | int i = 0; 17 | PT_DispOpr ptTmp = g_ptDispOprHead; 18 | 19 | while (ptTmp) 20 | { 21 | printf("%02d %s\n", i++, ptTmp->name); 22 | ptTmp = ptTmp->ptNext; 23 | } 24 | } 25 | 26 | 27 | PT_DispOpr GetDispOpr(char *pcName) 28 | { 29 | PT_DispOpr ptTmp = g_ptDispOprHead; 30 | 31 | while (ptTmp) 32 | { 33 | if (strcmp(ptTmp->name, pcName) == 0) 34 | { 35 | return ptTmp; 36 | } 37 | ptTmp = ptTmp->ptNext; 38 | } 39 | return NULL; 40 | } 41 | 42 | void SelectAndInitDefaultDispDev(char *name) 43 | { 44 | g_ptDefaultDispOpr = GetDispOpr(name); 45 | if (g_ptDefaultDispOpr) 46 | { 47 | g_ptDefaultDispOpr->DeviceInit(); 48 | g_ptDefaultDispOpr->CleanScreen(0); 49 | } 50 | } 51 | 52 | 53 | 54 | PT_DispOpr GetDefaultDispDev(void) 55 | { 56 | return g_ptDefaultDispOpr; 57 | } 58 | 59 | int GetDispResolution(int *piXres, int *piYres, int *piBpp) 60 | { 61 | if (g_ptDefaultDispOpr) 62 | { 63 | *piXres = g_ptDefaultDispOpr->iXres; 64 | *piYres = g_ptDefaultDispOpr->iYres; 65 | *piBpp = g_ptDefaultDispOpr->iBpp; 66 | return 0; 67 | } 68 | else 69 | { 70 | return -1; 71 | } 72 | } 73 | 74 | int GetVideoBufForDisplay(PT_VideoBuf ptFrameBuf) 75 | { 76 | ptFrameBuf->iPixelFormat = (g_ptDefaultDispOpr->iBpp == 16) ? V4L2_PIX_FMT_RGB565 : \ 77 | (g_ptDefaultDispOpr->iBpp == 32) ? V4L2_PIX_FMT_RGB32 : \ 78 | 0; 79 | ptFrameBuf->tPixelDatas.iWidth = g_ptDefaultDispOpr->iXres; 80 | ptFrameBuf->tPixelDatas.iHeight = g_ptDefaultDispOpr->iYres; 81 | ptFrameBuf->tPixelDatas.iBpp = g_ptDefaultDispOpr->iBpp; 82 | ptFrameBuf->tPixelDatas.iLineBytes = g_ptDefaultDispOpr->iLineWidth; 83 | ptFrameBuf->tPixelDatas.iTotalBytes = ptFrameBuf->tPixelDatas.iLineBytes * ptFrameBuf->tPixelDatas.iHeight; 84 | ptFrameBuf->tPixelDatas.aucPixelDatas = g_ptDefaultDispOpr->pucDispMem; 85 | return 0; 86 | } 87 | 88 | void FlushPixelDatasToDev(PT_PixelDatas ptPixelDatas) 89 | { 90 | g_ptDefaultDispOpr->ShowPage(ptPixelDatas); 91 | } 92 | 93 | 94 | 95 | int AllocVideoMem(int iNum) 96 | { 97 | int i; 98 | 99 | int iXres = 0; 100 | int iYres = 0; 101 | int iBpp = 0; 102 | 103 | int iVMSize; 104 | int iLineBytes; 105 | 106 | PT_VideoMem ptNew; 107 | 108 | /* 确定VideoMem的大小 109 | */ 110 | GetDispResolution(&iXres, &iYres, &iBpp); 111 | iVMSize = iXres * iYres * iBpp / 8; 112 | iLineBytes = iXres * iBpp / 8; 113 | 114 | /* 先把设备本身的framebuffer放入链表 115 | * 分配一个T_VideoMem结构体, 注意我们没有分配里面的tPixelDatas.aucPixelDatas 116 | * 而是让tPixelDatas.aucPixelDatas指向显示设备的framebuffer 117 | */ 118 | ptNew = malloc(sizeof(T_VideoMem)); 119 | if (ptNew == NULL) 120 | { 121 | return -1; 122 | } 123 | 124 | /* 指向framebuffer */ 125 | ptNew->tPixelDatas.aucPixelDatas = g_ptDefaultDispOpr->pucDispMem; 126 | 127 | ptNew->iID = 0; 128 | ptNew->bDevFrameBuffer = 1; /* 表示这个VideoMem是设备本身的framebuffer, 而不是用作缓存作用的VideoMem */ 129 | ptNew->eVideoMemState = VMS_FREE; 130 | ptNew->ePicState = PS_BLANK; 131 | ptNew->tPixelDatas.iWidth = iXres; 132 | ptNew->tPixelDatas.iHeight = iYres; 133 | ptNew->tPixelDatas.iBpp = iBpp; 134 | ptNew->tPixelDatas.iLineBytes = iLineBytes; 135 | ptNew->tPixelDatas.iTotalBytes = iVMSize; 136 | 137 | if (iNum != 0) 138 | { 139 | /* 如果下面要分配用于缓存的VideoMem, 140 | * 把设备本身framebuffer对应的VideoMem状态设置为VMS_USED_FOR_CUR, 141 | * 表示这个VideoMem不会被作为缓存分配出去 142 | */ 143 | ptNew->eVideoMemState = VMS_USED_FOR_CUR; 144 | } 145 | 146 | /* 放入链表 */ 147 | ptNew->ptNext = g_ptVideoMemHead; 148 | g_ptVideoMemHead = ptNew; 149 | 150 | 151 | /* 152 | * 分配用于缓存的VideoMem 153 | */ 154 | for (i = 0; i < iNum; i++) 155 | { 156 | /* 分配T_VideoMem结构体本身和"跟framebuffer同样大小的缓存" */ 157 | ptNew = malloc(sizeof(T_VideoMem) + iVMSize); 158 | if (ptNew == NULL) 159 | { 160 | return -1; 161 | } 162 | /* 在T_VideoMem结构体里记录上面分配的"跟framebuffer同样大小的缓存" */ 163 | ptNew->tPixelDatas.aucPixelDatas = (unsigned char *)(ptNew + 1); 164 | 165 | ptNew->iID = 0; 166 | ptNew->bDevFrameBuffer = 0; 167 | ptNew->eVideoMemState = VMS_FREE; 168 | ptNew->ePicState = PS_BLANK; 169 | ptNew->tPixelDatas.iWidth = iXres; 170 | ptNew->tPixelDatas.iHeight = iYres; 171 | ptNew->tPixelDatas.iBpp = iBpp; 172 | ptNew->tPixelDatas.iLineBytes = iLineBytes; 173 | ptNew->tPixelDatas.iTotalBytes = iVMSize; 174 | 175 | /* 放入链表 */ 176 | ptNew->ptNext = g_ptVideoMemHead; 177 | g_ptVideoMemHead = ptNew; 178 | } 179 | 180 | return 0; 181 | } 182 | 183 | 184 | PT_VideoMem GetVideoMem(int iID, int bCur) 185 | { 186 | PT_VideoMem ptTmp = g_ptVideoMemHead; 187 | 188 | /* 1. 优先: 取出空闲的、ID相同的videomem */ 189 | while (ptTmp) 190 | { 191 | if ((ptTmp->eVideoMemState == VMS_FREE) && (ptTmp->iID == iID)) 192 | { 193 | ptTmp->eVideoMemState = bCur ? VMS_USED_FOR_CUR : VMS_USED_FOR_PREPARE; 194 | return ptTmp; 195 | } 196 | ptTmp = ptTmp->ptNext; 197 | } 198 | 199 | /* 2. 如果前面不成功, 取出一个空闲的并且里面没有数据(ptVideoMem->ePicState = PS_BLANK)的VideoMem */ 200 | ptTmp = g_ptVideoMemHead; 201 | while (ptTmp) 202 | { 203 | if ((ptTmp->eVideoMemState == VMS_FREE) && (ptTmp->ePicState == PS_BLANK)) 204 | { 205 | ptTmp->iID = iID; 206 | ptTmp->eVideoMemState = bCur ? VMS_USED_FOR_CUR : VMS_USED_FOR_PREPARE; 207 | return ptTmp; 208 | } 209 | ptTmp = ptTmp->ptNext; 210 | } 211 | 212 | /* 3. 如果前面不成功: 取出任意一个空闲的VideoMem */ 213 | ptTmp = g_ptVideoMemHead; 214 | while (ptTmp) 215 | { 216 | if (ptTmp->eVideoMemState == VMS_FREE) 217 | { 218 | ptTmp->iID = iID; 219 | ptTmp->ePicState = PS_BLANK; 220 | ptTmp->eVideoMemState = bCur ? VMS_USED_FOR_CUR : VMS_USED_FOR_PREPARE; 221 | return ptTmp; 222 | } 223 | ptTmp = ptTmp->ptNext; 224 | } 225 | 226 | /* 4. 如果没有空闲的VideoMem并且bCur为1, 则取出任意一个VideoMem(不管它是否空闲) */ 227 | if (bCur) 228 | { 229 | ptTmp = g_ptVideoMemHead; 230 | ptTmp->iID = iID; 231 | ptTmp->ePicState = PS_BLANK; 232 | ptTmp->eVideoMemState = bCur ? VMS_USED_FOR_CUR : VMS_USED_FOR_PREPARE; 233 | return ptTmp; 234 | } 235 | 236 | return NULL; 237 | } 238 | 239 | 240 | 241 | void PutVideoMem(PT_VideoMem ptVideoMem) 242 | { 243 | ptVideoMem->eVideoMemState = VMS_FREE; /* 设置VideoMem状态为空闲 */ 244 | if (ptVideoMem->iID == -1) 245 | { 246 | ptVideoMem->ePicState = PS_BLANK; /* 表示里面的数据没有用了 */ 247 | } 248 | } 249 | 250 | 251 | PT_VideoMem GetDevVideoMem(void) 252 | { 253 | PT_VideoMem ptTmp = g_ptVideoMemHead; 254 | 255 | while (ptTmp) 256 | { 257 | if (ptTmp->bDevFrameBuffer) 258 | { 259 | return ptTmp; 260 | } 261 | ptTmp = ptTmp->ptNext; 262 | } 263 | return NULL; 264 | } 265 | 266 | 267 | 268 | void ClearVideoMem(PT_VideoMem ptVideoMem, unsigned int dwColor) 269 | { 270 | unsigned char *pucVM; 271 | unsigned short *pwVM16bpp; 272 | unsigned int *pdwVM32bpp; 273 | unsigned short wColor16bpp; /* 565 */ 274 | int iRed; 275 | int iGreen; 276 | int iBlue; 277 | int i = 0; 278 | 279 | pucVM = ptVideoMem->tPixelDatas.aucPixelDatas; 280 | pwVM16bpp = (unsigned short *)pucVM; 281 | pdwVM32bpp = (unsigned int *)pucVM; 282 | 283 | switch (ptVideoMem->tPixelDatas.iBpp) 284 | { 285 | case 8: 286 | { 287 | memset(pucVM, dwColor, ptVideoMem->tPixelDatas.iTotalBytes); 288 | break; 289 | } 290 | case 16: 291 | { 292 | /* 先根据32位的dwColor构造出16位的wColor16bpp */ 293 | iRed = (dwColor >> (16+3)) & 0x1f; 294 | iGreen = (dwColor >> (8+2)) & 0x3f; 295 | iBlue = (dwColor >> 3) & 0x1f; 296 | wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue; 297 | while (i < ptVideoMem->tPixelDatas.iTotalBytes) 298 | { 299 | *pwVM16bpp = wColor16bpp; 300 | pwVM16bpp++; 301 | i += 2; 302 | } 303 | break; 304 | } 305 | case 32: 306 | { 307 | while (i < ptVideoMem->tPixelDatas.iTotalBytes) 308 | { 309 | *pdwVM32bpp = dwColor; 310 | pdwVM32bpp++; 311 | i += 4; 312 | } 313 | break; 314 | } 315 | default : 316 | { 317 | DBG_PRINTF("can't support %d bpp\n", ptVideoMem->tPixelDatas.iBpp); 318 | return; 319 | } 320 | } 321 | 322 | } 323 | 324 | 325 | 326 | void ClearVideoMemRegion(PT_VideoMem ptVideoMem, PT_Layout ptLayout, unsigned int dwColor) 327 | { 328 | unsigned char *pucVM; 329 | unsigned short *pwVM16bpp; 330 | unsigned int *pdwVM32bpp; 331 | unsigned short wColor16bpp; /* 565 */ 332 | int iRed; 333 | int iGreen; 334 | int iBlue; 335 | int iX; 336 | int iY; 337 | int iLineBytesClear; 338 | int i; 339 | 340 | pucVM = ptVideoMem->tPixelDatas.aucPixelDatas + ptLayout->iTopLeftY * ptVideoMem->tPixelDatas.iLineBytes + ptLayout->iTopLeftX * ptVideoMem->tPixelDatas.iBpp / 8; 341 | pwVM16bpp = (unsigned short *)pucVM; 342 | pdwVM32bpp = (unsigned int *)pucVM; 343 | 344 | iLineBytesClear = (ptLayout->iBotRightX - ptLayout->iTopLeftX + 1) * ptVideoMem->tPixelDatas.iBpp / 8; 345 | 346 | switch (ptVideoMem->tPixelDatas.iBpp) 347 | { 348 | case 8: 349 | { 350 | for (iY = ptLayout->iTopLeftY; iY <= ptLayout->iBotRightY; iY++) 351 | { 352 | memset(pucVM, dwColor, iLineBytesClear); 353 | pucVM += ptVideoMem->tPixelDatas.iLineBytes; 354 | } 355 | break; 356 | } 357 | case 16: 358 | { 359 | /* 先根据32位的dwColor构造出16位的wColor16bpp */ 360 | iRed = (dwColor >> (16+3)) & 0x1f; 361 | iGreen = (dwColor >> (8+2)) & 0x3f; 362 | iBlue = (dwColor >> 3) & 0x1f; 363 | wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue; 364 | for (iY = ptLayout->iTopLeftY; iY <= ptLayout->iBotRightY; iY++) 365 | { 366 | i = 0; 367 | for (iX = ptLayout->iTopLeftX; iX <= ptLayout->iBotRightX; iX++) 368 | { 369 | pwVM16bpp[i++] = wColor16bpp; 370 | } 371 | pwVM16bpp = (unsigned short *)((unsigned int)pwVM16bpp + ptVideoMem->tPixelDatas.iLineBytes); 372 | } 373 | break; 374 | } 375 | case 32: 376 | { 377 | for (iY = ptLayout->iTopLeftY; iY <= ptLayout->iBotRightY; iY++) 378 | { 379 | i = 0; 380 | for (iX = ptLayout->iTopLeftX; iX <= ptLayout->iBotRightX; iX++) 381 | { 382 | pdwVM32bpp[i++] = dwColor; 383 | } 384 | pdwVM32bpp = (unsigned int *)((unsigned int)pdwVM32bpp + ptVideoMem->tPixelDatas.iLineBytes); 385 | } 386 | break; 387 | } 388 | default : 389 | { 390 | DBG_PRINTF("can't support %d bpp\n", ptVideoMem->tPixelDatas.iBpp); 391 | return; 392 | } 393 | } 394 | 395 | } 396 | 397 | 398 | int DisplayInit(void) 399 | { 400 | int iError; 401 | 402 | iError = FBInit(); 403 | 404 | return iError; 405 | } 406 | 407 | -------------------------------------------------------------------------------- /display/framebuffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | 13 | // 在函数声明前加上static关键字,表示该函数具有静态的存储类别。 14 | // 静态函数只能在当前源文件中使用,不能被其他源文件调用。这样做的目的是限制函数的作用域; 15 | // 使其只能在当前源文件中访问,避免函数被其他源文件意外调用或修改。 16 | static int FBDeviceInit(void);//"framebuffer显示设备"的初始化函数 17 | static int FBShowPixel(int iX, int iY, unsigned int dwColor);//设置FrameBuffer的指定象素为某颜色 18 | static int FBCleanScreen(unsigned int dwBackColor);// "framebuffer显示设备"的清屏函数 19 | static int FBShowPage(PT_PixelDatas ptPixelDatas);// 把PT_VideoMem中的颜色数据在FrameBuffer上显示出来 20 | 21 | 22 | static T_DispOpr g_tFBOpr = { 23 | .name = "framebuffer", 24 | .DeviceInit = FBDeviceInit, 25 | .ShowPixel = FBShowPixel, 26 | .CleanScreen = FBCleanScreen, 27 | .ShowPage = FBShowPage, 28 | }; 29 | 30 | 31 | int FBInit(void) 32 | { 33 | return RegisterDispOpr(&g_tFBOpr); 34 | } 35 | 36 | 37 | static int g_fd; 38 | static struct fb_var_screeninfo g_tFBVar;//这个数据结构由驱动程序定义 39 | static struct fb_fix_screeninfo g_tFBFix;//驱动数据结构 40 | static unsigned int g_dwScreenSize; 41 | static unsigned char *g_pucFBMem; 42 | 43 | static unsigned int g_dwLineWidth; 44 | static unsigned int g_dwPixelWidth; 45 | 46 | 47 | //"framebuffer显示设备"的初始化函数,打开屏幕读取参数,放到两个BUFFER中,并构建了一个链表结构的结构体,并赋初值 48 | static int FBDeviceInit(void) 49 | { 50 | int ret; 51 | //打开设备节点"/dev/fb0" 52 | g_fd = open(FB_DEVICE_NAME,O_RDWR); 53 | if (0 > g_fd) 54 | { 55 | DBG_PRINTF("can't open %s\n", FB_DEVICE_NAME); 56 | } 57 | //发送控制请求,由驱动程序定义 58 | ret = ioctl(g_fd,FBIOGET_VSCREENINFO,&g_tFBVar);//传出参数 59 | if (ret < 0) 60 | { 61 | DBG_PRINTF("can't get fb's var\n"); 62 | return -1; 63 | } 64 | //发送控制请求,由驱动程序定义 65 | ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);//传出参数 66 | if (ret < 0) 67 | { 68 | DBG_PRINTF("can't get fb's fix\n"); 69 | return -1; 70 | } 71 | //获得屏幕尺寸,并且mmap开辟虚拟内存映射空间,增快传输速度 72 | g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8; 73 | g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);//调用驱动mmap的函数,来实现虚拟内存映射 74 | 75 | // mmap()是一个系统调用函数,用于将文件或设备的一块内存映射到进程的虚拟地址空间中。它的原型如下: 76 | // void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 77 | 78 | // 参数说明: 79 | // addr:指定映射的起始地址,通常设为NULL,由系统自动分配。 80 | // length:映射的长度,以字节为单位。 81 | // prot:映射区域的保护方式,指定内存区域的可读、可写、可执行等属性。 82 | // flags:指定映射区域的一些特性,如映射区域是否可以共享、是否可以修改等。 83 | // fd:要映射的文件描述符,如果映射的是文件,则该参数为文件描述符;如果映射的是设备,则该参数为设备的文件描述符。 84 | // offset:映射的起始位置,对于文件映射,通常为0;对于设备映射,通常为设备的偏移量。 85 | // 返回值: 86 | 87 | // 成功时,返回映射区域的起始地址;失败时,返回MAP_FAILED(-1)。 88 | // mmap()函数的作用是将一个文件或设备的内容映射到进程的地址空间中,使得进程可以直接访问该文件或设备的数据。通过对映射区域进行读写操作,可以实现对文件或设备的直接操作,而无需使用read()和write()等系统调用。 89 | // 需要注意的是,使用mmap()函数映射的内存区域必须按照页对齐,即起始地址和长度必须是页大小的整数倍。另外,对映射区域的读写操作可能会触发页错误,需要使用mprotect()函数设置合适的保护属性。 90 | // 使用mmap()函数时,需要注意对返回的映射地址的合法性和正确性进行判断和处理,以及在不再需要映射区域时使用munmap()函数释放映射的内存。 91 | 92 | 93 | 94 | if (0 > g_pucFBMem) 95 | { 96 | DBG_PRINTF("can't mmap\n"); 97 | return -1; 98 | } 99 | 100 | 101 | g_tFBOpr.iXres = g_tFBVar.xres; 102 | g_tFBOpr.iYres = g_tFBVar.yres; 103 | g_tFBOpr.iBpp = g_tFBVar.bits_per_pixel; 104 | g_tFBOpr.iLineWidth = g_tFBVar.xres * g_tFBOpr.iBpp / 8; 105 | g_tFBOpr.pucDispMem = g_pucFBMem; 106 | 107 | g_dwLineWidth = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8; 108 | g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8; 109 | 110 | return 0; 111 | } 112 | 113 | //设置FrameBuffer的指定象素为某颜色 114 | static int FBShowPixel(int iX, int iY, unsigned int dwColor) 115 | { 116 | 117 | int iRed; 118 | int iGreen; 119 | int iBlue; 120 | 121 | if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres)) 122 | { 123 | DBG_PRINTF("out of region\n"); 124 | return -1; 125 | } 126 | unsigned char *pucFB; 127 | unsigned short *pwFB16bpp; 128 | unsigned int *pdwFB32bpp; 129 | unsigned short wColor16bpp; /* 565 */ 130 | pucFB = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX; 131 | pwFB16bpp = (unsigned short *)pucFB; 132 | pdwFB32bpp = (unsigned int *)pucFB; 133 | 134 | switch (g_tFBVar.bits_per_pixel)//一个像素多少位 135 | { 136 | case 8: 137 | { 138 | *pucFB = (unsigned char)dwColor; 139 | break; 140 | } 141 | 142 | case 16: 143 | { 144 | /* 从dwBackColor中取出红绿蓝三原色, 145 | * 构造为16Bpp的颜色 146 | */ 147 | iRed = (dwColor >> (16+3)) & 0x1f; 148 | iGreen = (dwColor >> (8+2)) & 0x3f; 149 | iBlue = (dwColor >> 3) & 0x1f; 150 | wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue; 151 | *pwFB16bpp = wColor16bpp; 152 | 153 | } 154 | 155 | case 32; 156 | { 157 | *pdwFB32bpp = dwColor; 158 | break; 159 | } 160 | 161 | default: 162 | { 163 | DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel); 164 | return -1; 165 | } 166 | 167 | } 168 | return 0; 169 | 170 | } 171 | 172 | // "framebuffer显示设备"的清屏函数 173 | static int FBCleanScreen(unsigned int dwBackColor) 174 | { 175 | 176 | unsigned short *pwFB16bpp; 177 | unsigned int *pdwFB32bpp; 178 | unsigned short wColor16bpp; /* 565 */ 179 | int iRed; 180 | int iGreen; 181 | int iBlue; 182 | int i = 0; 183 | 184 | unsigned char *pucFB; 185 | pucFB = g_pucFBMem; //虚拟内存映射的地址 186 | pwFB16bpp = (unsigned short *)pucFB; 187 | pdwFB32bpp = (unsigned int *)pucFB; 188 | 189 | switch (g_tFBVar.bits_per_pixel) 190 | { 191 | case 8: 192 | { 193 | memset(g_pucFBMem, dwBackColor, g_dwScreenSize); 194 | break; 195 | // memset函数是C语言中的一个库函数,用于将一块内存区域的内容设置为指定的值。 196 | // 函数原型如下: 197 | // void *memset(void *s, int c, size_t n); 198 | 199 | // 参数说明: 200 | // s:指向要设置的内存区域的指针。 201 | // c:要设置的值,通常是一个整数。 202 | // n:要设置的字节数。 203 | // 函数功能: 204 | // memset函数将指定的值c复制到s所指向的内存区域的前n个字节中。 205 | // 使用示例: 206 | 207 | } 208 | 209 | case 16: 210 | { 211 | /* 从dwBackColor中取出红绿蓝三原色, 212 | * 构造为16Bpp的颜色 213 | */ 214 | iRed = (dwBackColor >> (16+3)) & 0x1f; 215 | iGreen = (dwBackColor >> (8+2)) & 0x3f; 216 | iBlue = (dwBackColor >> 3) & 0x1f; 217 | wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue; 218 | while (i < g_dwScreenSize) 219 | { 220 | *pwFB16bpp = wColor16bpp; 221 | pwFB16bpp++; 222 | i += 2; 223 | } 224 | break; 225 | 226 | } 227 | 228 | case 32: 229 | { 230 | while (i < g_dwScreenSize) 231 | { 232 | *pdwFB32bpp = dwBackColor; 233 | pdwFB32bpp++; 234 | i += 4; 235 | } 236 | break; 237 | } 238 | 239 | default: 240 | { 241 | DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel); 242 | return -1; 243 | } 244 | } 245 | 246 | return 0; 247 | 248 | } 249 | 250 | 251 | 252 | 253 | // /* 图片的象素数据 */ 254 | // typedef struct PixelDatas { 255 | // int iWidth; /* 宽度: 一行有多少个象素 */ 256 | // int iHeight; /* 高度: 一列有多少个象素 */ 257 | // int iBpp; /* 一个象素用多少位来表示 */ 258 | // int iLineBytes; /* 一行数据有多少字节 */ 259 | // int iTotalBytes; /* 所有字节数 */ 260 | // unsigned char *aucPixelDatas; /* 象素数据存储的地方 */ 261 | // }T_PixelDatas, *PT_PixelDatas; 262 | 263 | // 把PT_VideoMem中的颜色数据在FrameBuffer上显示出来 264 | static int FBShowPage(PT_PixelDatas ptPixelDatas) 265 | { 266 | if (g_tFBOpr.pucDispMem != ptPixelDatas->aucPixelDatas) 267 | { 268 | //把图片的源数据赋值到共享虚拟内存映射中去 269 | memcpy(g_tFBOpr.pucDispMem, ptPixelDatas->aucPixelDatas, ptPixelDatas->iTotalBytes); 270 | // memcpy是C语言中的一个库函数,用于将一块内存区域的内容复制到另一块内存区域。 271 | // 函数原型如下: 272 | // void *memcpy(void *dest, const void *src, size_t n); 273 | 274 | // 参数说明: 275 | // dest:目标内存区域的起始地址,即要将数据复制到的位置。 276 | // src:源内存区域的起始地址,即要复制的数据的位置。 277 | // n:要复制的字节数。 278 | 279 | // 函数功能: 280 | // memcpy函数将src所指向的内存区域的前n个字节复制到dest所指向的内存区域中。如果源和目标区域有重叠,复制行为是未定义的。 281 | } 282 | return 0; 283 | } 284 | -------------------------------------------------------------------------------- /inc/convert_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONVERT_MANAGER_H 2 | #define _CONVERT_MANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct VideoConvert { 9 | char *name; 10 | int (*isSupport)(int iPixelFormatIn, int iPixelFormatOut); 11 | int (*Convert)(PT_VideoBuf ptVideoBufIn, PT_VideoBuf ptVideoBufOut); 12 | int (*ConvertExit)(PT_VideoBuf ptVideoBufOut); 13 | struct VideoConvert *ptNext; 14 | }T_VideoConvert, *PT_VideoConvert; 15 | 16 | PT_VideoConvert GetVideoConvertForFormats(int iPixelFormatIn, int iPixelFormatOut); 17 | int VideoConvertInit(void); 18 | 19 | int Yuv2RgbInit(void); 20 | int Mjpeg2RgbInit(void); 21 | int Rgb2RgbInit(void); 22 | int RegisterVideoConvert(PT_VideoConvert ptVideoConvert); 23 | 24 | 25 | #endif /* _CONVERT_MANAGER_H */ 26 | 27 | -------------------------------------------------------------------------------- /inc/disp_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef _DISP_MANAGER_H 2 | #define _DISP_MANAGER_H 3 | 4 | #include 5 | #include 6 | 7 | /* 显示区域,含该区域的左上角/右下角座标 8 | * 如果是图标,还含有图标的文件名 9 | */ 10 | // typedef struct Layout { 11 | // int iTopLeftX; 12 | // int iTopLeftY; 13 | // int iBotRightX; 14 | // int iBotRightY; 15 | // char *strIconName; 16 | // }T_Layout, *PT_Layout; 17 | 18 | 19 | // /* VideoMem的状态: 20 | // * 空闲/用于预先准备显示内容/用于当前线程 21 | // */ 22 | // typedef enum { 23 | // VMS_FREE = 0, 24 | // VMS_USED_FOR_PREPARE, 25 | // VMS_USED_FOR_CUR, 26 | // }E_VideoMemState; 27 | 28 | // /* VideoMem中内存里图片的状态: 29 | // * 空白/正在生成/已经生成 30 | // */ 31 | // typedef enum { 32 | // PS_BLANK = 0, 33 | // PS_GENERATING, 34 | // PS_GENERATED, 35 | // }E_PicState; 36 | 37 | 38 | // typedef struct VideoMem { 39 | // int iID; /* ID值,用于标识不同的页面 */ 40 | // int bDevFrameBuffer; /* 1: 这个VideoMem是显示设备的显存; 0: 只是一个普通缓存 */ 41 | // E_VideoMemState eVideoMemState; /* 这个VideoMem的状态 */ 42 | // E_PicState ePicState; /* VideoMem中内存里图片的状态 */ 43 | // T_PixelDatas tPixelDatas; /* 内存: 用来存储图像 */ 44 | // struct VideoMem *ptNext; /* 链表 */ 45 | // }T_VideoMem, *PT_VideoMem; 46 | 47 | typedef struct DispOpr { 48 | char *name; /* 显示模块的名字 */ 49 | int iXres; /* X分辨率 */ 50 | int iYres; /* Y分辨率 */ 51 | int iBpp; /* 一个象素用多少位来表示 */ 52 | int iLineWidth; /* 一行数据占据多少字节 */ 53 | unsigned char *pucDispMem; /* 显存地址 */ 54 | int (*DeviceInit)(void); /* 设备初始化函数 */ 55 | int (*ShowPixel)(int iPenX, int iPenY, unsigned int dwColor); /* 把指定座标的象素设为某颜色 */ 56 | int (*CleanScreen)(unsigned int dwBackColor); /* 清屏为某颜色 */ 57 | int (*ShowPage)(PT_PixelDatas ptPixelDatas); /* 显示一页,数据源自ptVideoMem */ 58 | struct DispOpr *ptNext; /* 链表 */ 59 | }T_DispOpr, *PT_DispOpr; 60 | 61 | 62 | //注册"显示模块", 把所能支持的显示设备的操作函数放入链表 63 | int RegisterDispOpr(PT_DispOpr ptDispOpr); 64 | 65 | 66 | // void ShowDispOpr(void); 67 | 68 | int DisplayInit(void); 69 | 70 | //根据名字取出指定的"显示模块", 调用它的初始化函数, 并且清屏 71 | void SelectAndInitDefaultDispDev(char *name); 72 | 73 | //匹配链表中适合的屏幕的结构体 74 | PT_DispOpr GetDispOpr(char *pcName); 75 | 76 | // PT_DispOpr GetDefaultDispDev(void); 77 | 78 | 79 | //获得所使用的显示设备的分辨率和BPP 80 | int GetDispResolution(int *piXres, int *piYres, int *piBpp); 81 | 82 | 83 | // int AllocVideoMem(int iNum); 84 | 85 | 86 | // PT_VideoMem GetDevVideoMem(void); 87 | 88 | 89 | // PT_VideoMem GetVideoMem(int iID, int bCur); 90 | 91 | 92 | // void PutVideoMem(PT_VideoMem ptVideoMem); 93 | 94 | // void ClearVideoMem(PT_VideoMem ptVideoMem, unsigned int dwColor); 95 | 96 | // void ClearVideoMemRegion(PT_VideoMem ptVideoMem, PT_Layout ptLayout, unsigned int dwColor); 97 | 98 | //framebuffer注册 99 | int FBInit(void); 100 | 101 | int GetVideoBufForDisplay(PT_VideoBuf ptFrameBuf); 102 | // void FlushPixelDatasToDev(PT_PixelDatas ptPixelDatas); 103 | 104 | #endif /* _DISP_MANAGER_H */ 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /inc/picfmt_manage.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _PIC_MANAGER_H 3 | #define _PIC_MANAGER_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int RegisterPicFileParser(PT_PicFileParser ptPicFileParser); 11 | 12 | 13 | void ShowPicFmts(void); 14 | 15 | int PicFmtsInit(void); 16 | 17 | int JPGParserInit(void); 18 | 19 | int BMPParserInit(void); 20 | 21 | PT_PicFileParser Parser(char *pcName); 22 | 23 | PT_PicFileParser GetParser(PT_FileMap ptFileMap); 24 | 25 | #endif /* _PIC_MANAGER_H */ 26 | 27 | -------------------------------------------------------------------------------- /inc/picture_ops.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _PIC_OPERATION_H 3 | #define _PIC_OPERATION_H 4 | 5 | /* 图片的象素数据 */ 6 | typedef struct PixelDatas { 7 | int iWidth; /* 宽度: 一行有多少个象素 */ 8 | int iHeight; /* 高度: 一列有多少个象素 */ 9 | int iBpp; /* 一个象素用多少位来表示 */ 10 | int iLineBytes; /* 一行数据有多少字节 */ 11 | int iTotalBytes; /* 所有字节数 */ 12 | unsigned char *aucPixelDatas; /* 象素数据存储的地方 */ 13 | }T_PixelDatas, *PT_PixelDatas; 14 | 15 | 16 | #endif /* _PIC_OPERATION_H */ 17 | 18 | -------------------------------------------------------------------------------- /inc/render.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _RENDER_H 3 | #define _RENDER_H 4 | 5 | #include 6 | #include 7 | 8 | 9 | // * 函数名称: PicZoom 10 | // * 功能描述: 近邻取样插值方法缩放图片 11 | // * 注意该函数会分配内存来存放缩放后的图片,用完后要用free函数释放掉 12 | // * "近邻取样插值"的原理请参考网友"lantianyu520"所著的"图像缩放算法" 13 | // * 输入参数: ptOriginPic - 内含原始图片的象素数据 14 | // * ptBigPic - 内含缩放后的图片的象素数据 15 | 16 | int PicZoom(PT_PixelDatas ptOriginPic, PT_PixelDatas ptZoomPic); 17 | 18 | // * 函数名称: PicMerge 19 | // * 功能描述: 把小图片合并入大图片里 20 | // * 输入参数: iX,iY - 小图片合并入大图片的某个区域, iX/iY确定这个区域的左上角座标 21 | // * ptSmallPic - 内含小图片的象素数据 22 | // * ptBigPic - 内含大图片的象素数据 23 | // * 输出参数: 无 24 | 25 | int PicMerge(int iX, int iY, PT_PixelDatas ptSmallPic, PT_PixelDatas ptBigPic); 26 | 27 | 28 | #endif /* _RENDER_H */ 29 | 30 | -------------------------------------------------------------------------------- /inc/video_manager.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _VIDEO_MANAGER_H 3 | #define _VIDEO_MANAGER_H 4 | 5 | 6 | 7 | #define NB_BUFFER 4 8 | 9 | struct VideoDevice; 10 | struct VideoOpr; 11 | typedef struct VideoDevice T_VideoDevice, *PT_VideoDevice; 12 | typedef struct VideoOpr T_VideoOpr, *PT_VideoOpr; 13 | 14 | struct VideoDevice { 15 | int iFd; 16 | int iPixelFormat; 17 | int iWidth; 18 | int iHeight; 19 | 20 | int iVideoBufCnt; 21 | int iVideoBufMaxLen; 22 | int iVideoBufCurIndex; 23 | unsigned char *pucVideBuf[NB_BUFFER]; 24 | 25 | /* 函数 */ 26 | PT_VideoOpr ptOPr; 27 | }; 28 | 29 | 30 | 31 | typedef struct VideoBuf 32 | { 33 | T_PixelDatas tPixelDatas; 34 | int iPixelFormat; 35 | }T_VideoBuf, *PT_VideoBuf; 36 | 37 | 38 | 39 | struct VideoOpr { 40 | char *name; 41 | int (*InitDevice)(char *strDevName, PT_VideoDevice ptVideoDevice); 42 | int (*ExitDevice)(PT_VideoDevice ptVideoDevice); 43 | int (*GetFrame)(PT_VideoDevice ptVideoDevice, PT_VideoBuf ptVideoBuf); 44 | int (*GetFormat)(PT_VideoDevice ptVideoDevice); 45 | int (*PutFrame)(PT_VideoDevice ptVideoDevice, PT_VideoBuf ptVideoBuf); 46 | int (*StartDevice)(PT_VideoDevice ptVideoDevice); 47 | int (*StopDevice)(PT_VideoDevice ptVideoDevice); 48 | struct VideoOpr *ptNext; 49 | }; 50 | 51 | int VideoConvertInit(void); 52 | int VideoInit(void); 53 | int V4l2Init(void); 54 | int RegisterVideoOpr(PT_VideoOpr ptVideoOpr); 55 | int VideoDeviceInit(char *strDevName, PT_VideoDevice ptVideoDevice); 56 | #endif /* _VIDEO_MANAGER_H */ -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | int main(int argc, char const *argv[]) 21 | { 22 | int iLcdWidth; 23 | int iLcdHeigt; 24 | int iLcdBpp; 25 | 26 | int iTopLeftX; 27 | int iTopLeftY; 28 | 29 | float k; 30 | int iError; 31 | T_VideoDevice tVideoDevice; 32 | PT_VideoConvert ptVideoConvert; 33 | int iPixelFormatOfVideo; 34 | int iPixelFormatOfDisp; 35 | 36 | 37 | PT_VideoBuf ptVideoBufCur; 38 | T_VideoBuf tVideoBuf; 39 | T_VideoBuf tConvertBuf; 40 | T_VideoBuf tZoomBuf; 41 | T_VideoBuf tFrameBuf; 42 | 43 | if (argc != 2) 44 | { 45 | printf("Usage:\n"); 46 | printf("%s \n", argv[0]); 47 | return -1; 48 | } 49 | 50 | 51 | /*1.初始化显示屏的相关信息放到构造的结构体链表中*/ 52 | //1.1 注册framebuffer设备显示屏 53 | DisplayInit(); 54 | //1.2可能可支持多个显示设备: 选择和初始化指定的显示设备:frambuffer 55 | SelectAndInitDefaultDispDev("framebuffer"); 56 | //1.3 取出参数显示屏的参数信息 57 | GetDispResolution(&iLcdWidth, &iLcdHeigt, &iLcdBpp); 58 | 59 | //1.4 取出构造T_VideoBuf结构体:来源于显示屏的参数信息 60 | GetVideoBufForDisplay(&tFrameBuf); 61 | //1.5获得显示屏的像素 62 | iPixelFormatOfDisp = tFrameBuf.iPixelFormat; 63 | 64 | 65 | 66 | /*2. 初始化摄像头相关*/ 67 | //2.1.注册摄像头 68 | VideoInit(); 69 | 70 | //2.2.摄像头匹配 71 | iError = VideoDeviceInit(argv[1], &tVideoDevice); //这边手动传参 72 | if (iError) 73 | { 74 | DBG_PRINTF("VideoDeviceInit for %s error!\n", argv[1]); 75 | return -1; 76 | } 77 | 78 | //2.3.获取摄像头参数信息 79 | int iPixelFormatOfVideo = tVideoDevice.ptOPr->GetFormat(&tVideoDevice); 80 | 81 | 82 | //2.4.注册支持的视频转换工具 83 | VideoConvertInit(); 84 | 85 | //2.5 输入你前面获得是屏幕与摄像头的像素格式,输入进去选择适合的视屏转换工具 86 | ptVideoConvert = GetVideoConvertForFormats(iPixelFormatOfVideo, iPixelFormatOfDisp); 87 | if (NULL == ptVideoConvert) 88 | { 89 | DBG_PRINTF("can not support this format convert\n"); 90 | return -1; 91 | } 92 | 93 | 94 | /*3.启动摄像头设备*/ 95 | iError = tVideoDevice.ptOPr->StartDevice(&tVideoDevice); 96 | if (iError) 97 | { 98 | DBG_PRINTF("StartDevice for %s error!\n", argv[1]); 99 | return -1; 100 | } 101 | //3.1定义三个BUF,来存取信息,先全部设为0 102 | memset(&tVideoBuf, 0, sizeof(tVideoBuf)); 103 | memset(&tConvertBuf, 0, sizeof(tConvertBuf)); 104 | tConvertBuf.iPixelFormat = iPixelFormatOfDisp; 105 | tConvertBuf.tPixelDatas.iBpp = iLcdBpp 106 | 107 | memset(&tZoomBuf, 0, sizeof(tZoomBuf)); 108 | 109 | while(1) 110 | { 111 | /*4. 读入摄像头数据 */ 112 | iError = tVideoDevice.ptOPr->GetFrame(&tVideoDevice, &tVideoBuf); 113 | if (iError) 114 | { 115 | DBG_PRINTF("GetFrame for %s error!\n", argv[1]); 116 | return -1; 117 | } 118 | ptVideoBufCur = &tVideoBuf; 119 | 120 | if (iPixelFormatOfVideo != iPixelFormatOfDisp) 121 | { 122 | //4.1 转换为RGB 123 | iError = ptVideoConvert->Convert(&tVideoBuf, &tConvertBuf); 124 | DBG_PRINTF("Convert %s, ret = %d\n", ptVideoConvert->name, iError); 125 | if (iError) 126 | { 127 | DBG_PRINTF("Convert for %s error!\n", argv[1]); 128 | return -1; 129 | } 130 | ptVideoBufCur = &tConvertBuf; 131 | } 132 | 133 | 134 | 135 | // 4.2 如果图像分辨率大于LCD, 缩放 136 | if (ptVideoBufCur->tPixelDatas.iWidth > iLcdWidth || ptVideoBufCur->tPixelDatas.iHeight > iLcdHeigt) 137 | { 138 | /* 确定缩放后的分辨率 */ 139 | /* 把图片按比例缩放到VideoMem上, 居中显示 140 | * 1. 先算出缩放后的大小 141 | */ 142 | k = (float)ptVideoBufCur->tPixelDatas.iHeight / ptVideoBufCur->tPixelDatas.iWidth; 143 | tZoomBuf.tPixelDatas.iWidth = iLcdWidth; 144 | tZoomBuf.tPixelDatas.iHeight = iLcdWidth * k; 145 | if ( tZoomBuf.tPixelDatas.iHeight > iLcdHeigt) 146 | { 147 | tZoomBuf.tPixelDatas.iWidth = iLcdHeigt / k; 148 | tZoomBuf.tPixelDatas.iHeight = iLcdHeigt; 149 | } 150 | tZoomBuf.tPixelDatas.iBpp = iLcdBpp; 151 | tZoomBuf.tPixelDatas.iLineBytes = tZoomBuf.tPixelDatas.iWidth * tZoomBuf.tPixelDatas.iBpp / 8; 152 | tZoomBuf.tPixelDatas.iTotalBytes = tZoomBuf.tPixelDatas.iLineBytes * tZoomBuf.tPixelDatas.iHeight; 153 | 154 | if (!tZoomBuf.tPixelDatas.aucPixelDatas) 155 | { 156 | tZoomBuf.tPixelDatas.aucPixelDatas = malloc(tZoomBuf.tPixelDatas.iTotalBytes); 157 | } 158 | 159 | PicZoom(&ptVideoBufCur->tPixelDatas, &tZoomBuf.tPixelDatas); 160 | ptVideoBufCur = &tZoomBuf; 161 | } 162 | 163 | // 4.3合并进framebuffer 164 | /* 接着算出居中显示时左上角坐标 */ 165 | iTopLeftX = (iLcdWidth - ptVideoBufCur->tPixelDatas.iWidth) / 2; 166 | iTopLeftY = (iLcdHeigt - ptVideoBufCur->tPixelDatas.iHeight) / 2; 167 | 168 | PicMerge(iTopLeftX, iTopLeftY, &ptVideoBufCur->tPixelDatas, &tFrameBuf.tPixelDatas); 169 | 170 | FlushPixelDatasToDev(&tFrameBuf.tPixelDatas); 171 | 172 | iError = tVideoDevice.ptOPr->PutFrame(&tVideoDevice, &tVideoBuf); 173 | if (iError) 174 | { 175 | DBG_PRINTF("PutFrame for %s error!\n", argv[1]); 176 | return -1; 177 | } 178 | 179 | /* 把framebuffer的数据刷到LCD上, 显示 */ 180 | 181 | 182 | } 183 | 184 | return 0; 185 | } -------------------------------------------------------------------------------- /netprint_client.c: -------------------------------------------------------------------------------- 1 | 2 | #include /* See NOTES */ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /* socket 12 | * connect 13 | * send/recv 14 | */ 15 | 16 | #define SERVER_PORT 5678 17 | 18 | 19 | /* 20 | * ./netprint_client dbglevel=<0-9> 21 | * ./netprint_client stdout=0|1 22 | * ./netprint_client netprint=0|1 23 | * ./netprint_client show // setclient,并且接收打印信息 24 | */ 25 | 26 | int main(int argc, char **argv) 27 | { 28 | int iSocketClient; 29 | struct sockaddr_in tSocketServerAddr; 30 | 31 | int iRet; 32 | unsigned char ucRecvBuf[1000]; 33 | int iSendLen; 34 | int iRecvLen; 35 | int iAddrLen; 36 | 37 | if (argc != 3) 38 | { 39 | printf("Usage:\n"); 40 | printf("%s dbglevel=<0-9>\n", argv[0]); 41 | printf("%s stdout=0|1\n", argv[0]); 42 | printf("%s netprint=0|1\n", argv[0]); 43 | printf("%s show\n", argv[0]); 44 | return -1; 45 | } 46 | 47 | iSocketClient = socket(AF_INET, SOCK_DGRAM, 0); 48 | 49 | tSocketServerAddr.sin_family = AF_INET; 50 | tSocketServerAddr.sin_port = htons(SERVER_PORT); /* host to net, short */ 51 | //tSocketServerAddr.sin_addr.s_addr = INADDR_ANY; 52 | if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr)) 53 | { 54 | printf("invalid server_ip\n"); 55 | return -1; 56 | } 57 | memset(tSocketServerAddr.sin_zero, 0, 8); 58 | 59 | if (strcmp(argv[2], "show") == 0) 60 | { 61 | /* 发送数据 */ 62 | iAddrLen = sizeof(struct sockaddr); 63 | iSendLen = sendto(iSocketClient, "setclient", 9, 0, 64 | (const struct sockaddr *)&tSocketServerAddr, iAddrLen); 65 | 66 | while (1) 67 | { 68 | /* 循环: 从网络读数据, 打印出来 */ 69 | iAddrLen = sizeof(struct sockaddr); 70 | iRecvLen = recvfrom(iSocketClient, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketServerAddr, &iAddrLen); 71 | if (iRecvLen > 0) 72 | { 73 | ucRecvBuf[iRecvLen] = '\0'; 74 | printf("%s\n", ucRecvBuf); 75 | } 76 | } 77 | } 78 | else 79 | { 80 | /* 发送数据 */ 81 | iAddrLen = sizeof(struct sockaddr); 82 | iSendLen = sendto(iSocketClient, argv[2], strlen(argv[2]), 0, 83 | (const struct sockaddr *)&tSocketServerAddr, iAddrLen); 84 | } 85 | 86 | return 0; 87 | } 88 | 89 | 90 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | #嵌入式linux相机项目 -------------------------------------------------------------------------------- /render/Makefile: -------------------------------------------------------------------------------- 1 | obj-y += operation/ 2 | -------------------------------------------------------------------------------- /render/operation/Makefile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1WMD1/linux_camera_project/606fa357c630b88e142284a6a60169286f7987da/render/operation/Makefile -------------------------------------------------------------------------------- /render/operation/merge.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | 6 | // * 函数名称: PicMerge 7 | // * 功能描述: 把小图片合并入大图片里 8 | // * 输入参数: iX,iY - 小图片合并入大图片的某个区域, iX/iY确定这个区域的左上角座标 9 | // * ptSmallPic - 内含小图片的象素数据 10 | // * ptBigPic - 内含大图片的象素数据 11 | 12 | int PicMerge(int iX, int iY, PT_PixelDatas ptSmallPic, PT_PixelDatas ptBigPic) 13 | { 14 | int i; 15 | unsigned char *pucSrc; 16 | unsigned char *pucDst; 17 | 18 | if ((ptSmallPic->iWidth > ptBigPic->iWidth) || 19 | (ptSmallPic->iHeight > ptBigPic->iHeight) || 20 | (ptSmallPic->iBpp != ptBigPic->iBpp)) 21 | { 22 | return -1; 23 | } 24 | 25 | pucSrc = ptSmallPic->aucPixelDatas; 26 | pucDst = ptBigPic->aucPixelDatas + iY * ptBigPic->iLineBytes + iX * ptBigPic->iBpp / 8; 27 | for (i = 0; i < ptSmallPic->iHeight; i++) 28 | { 29 | memcpy(pucDst, pucSrc, ptSmallPic->iLineBytes); 30 | pucSrc += ptSmallPic->iLineBytes; 31 | pucDst += ptBigPic->iLineBytes; 32 | } 33 | return 0; 34 | } 35 | 36 | 37 | 38 | // * 函数名称: PicMergeRegion 39 | // * 功能描述: 把新图片的某部分, 合并入老图片的指定区域 40 | // * 输入参数: iStartXofNewPic, iStartYofNewPic : 从新图片的(iStartXofNewPic, iStartYofNewPic)座标处开始读出数据用于合并 41 | // * iStartXofOldPic, iStartYofOldPic : 合并到老图片的(iStartXofOldPic, iStartYofOldPic)座标去 42 | // * iWidth, iHeight : 合并区域的大小 43 | // * ptNewPic : 新图片 44 | // * ptOldPic : 老图片 45 | 46 | int PicMergeRegion(int iStartXofNewPic, int iStartYofNewPic, int iStartXofOldPic, int iStartYofOldPic, int iWidth, int iHeight, PT_PixelDatas ptNewPic, PT_PixelDatas ptOldPic) 47 | { 48 | int i; 49 | unsigned char *pucSrc; 50 | unsigned char *pucDst; 51 | int iLineBytesCpy = iWidth * ptNewPic->iBpp / 8; 52 | 53 | if ((iStartXofNewPic < 0 || iStartXofNewPic >= ptNewPic->iWidth) || \ 54 | (iStartYofNewPic < 0 || iStartYofNewPic >= ptNewPic->iHeight) || \ 55 | (iStartXofOldPic < 0 || iStartXofOldPic >= ptOldPic->iWidth) || \ 56 | (iStartYofOldPic < 0 || iStartYofOldPic >= ptOldPic->iHeight)) 57 | { 58 | return -1; 59 | } 60 | 61 | pucSrc = ptNewPic->aucPixelDatas + iStartYofNewPic * ptNewPic->iLineBytes + iStartXofNewPic * ptNewPic->iBpp / 8; 62 | pucDst = ptOldPic->aucPixelDatas + iStartYofOldPic * ptOldPic->iLineBytes + iStartXofOldPic * ptOldPic->iBpp / 8; 63 | for (i = 0; i < iHeight; i++) 64 | { 65 | memcpy(pucDst, pucSrc, iLineBytesCpy); 66 | pucSrc += ptNewPic->iLineBytes; 67 | pucDst += ptOldPic->iLineBytes; 68 | } 69 | return 0; 70 | } 71 | 72 | -------------------------------------------------------------------------------- /render/operation/zoom.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | 8 | // * 函数名称: PicZoom 9 | // * 功能描述: 近邻取样插值方法缩放图片 10 | // * 注意该函数会分配内存来存放缩放后的图片,用完后要用free函数释放掉 11 | // * "近邻取样插值"的原理请参考网友"lantianyu520"所著的"图像缩放算法" 12 | // * 输入参数: ptOriginPic - 内含原始图片的象素数据 13 | // * ptBigPic - 内含缩放后的图片的象素数据 14 | 15 | int PicZoom(PT_PixelDatas ptOriginPic, PT_PixelDatas ptZoomPic) 16 | { 17 | unsigned long dwDstWidth = ptZoomPic->iWidth; 18 | unsigned long* pdwSrcXTable; 19 | unsigned long x; 20 | unsigned long y; 21 | unsigned long dwSrcY; 22 | unsigned char *pucDest; 23 | unsigned char *pucSrc; 24 | unsigned long dwPixelBytes = ptOriginPic->iBpp/8; 25 | 26 | DBG_PRINTF("src:\n"); 27 | DBG_PRINTF("%d x %d, %d bpp, data: 0x%x\n", ptOriginPic->iWidth, ptOriginPic->iHeight, ptOriginPic->iBpp, (unsigned int)ptOriginPic->aucPixelDatas); 28 | 29 | DBG_PRINTF("dest:\n"); 30 | DBG_PRINTF("%d x %d, %d bpp, data: 0x%x\n", ptZoomPic->iWidth, ptZoomPic->iHeight, ptZoomPic->iBpp, (unsigned int)ptZoomPic->aucPixelDatas); 31 | 32 | if (ptOriginPic->iBpp != ptZoomPic->iBpp) 33 | { 34 | return -1; 35 | } 36 | 37 | pdwSrcXTable = malloc(sizeof(unsigned long) * dwDstWidth); 38 | if (NULL == pdwSrcXTable) 39 | { 40 | DBG_PRINTF("malloc error!\n"); 41 | return -1; 42 | } 43 | 44 | for (x = 0; x < dwDstWidth; x++)//生成表 pdwSrcXTable 45 | { 46 | pdwSrcXTable[x]=(x*ptOriginPic->iWidth/ptZoomPic->iWidth); 47 | } 48 | 49 | for (y = 0; y < ptZoomPic->iHeight; y++) 50 | { 51 | dwSrcY = (y * ptOriginPic->iHeight / ptZoomPic->iHeight); 52 | 53 | pucDest = ptZoomPic->aucPixelDatas + y*ptZoomPic->iLineBytes; 54 | pucSrc = ptOriginPic->aucPixelDatas + dwSrcY*ptOriginPic->iLineBytes; 55 | 56 | for (x = 0; x 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | 17 | 18 | 19 | /* 构造一个VideoOpr结构体 */ 20 | static T_VideoOpr g_tV4l2VideoOpr = { 21 | .name = "v4l2", 22 | .InitDevice = V4l2InitDevice, 23 | .ExitDevice = V4l2ExitDevice, 24 | .GetFormat = V4l2GetFormat, 25 | .GetFrame = V4l2GetFrameForStreaming, 26 | .PutFrame = V4l2PutFrameForStreaming, 27 | .StartDevice = V4l2StartDevice, 28 | .StopDevice = V4l2StopDevice, 29 | }; 30 | 31 | 32 | /* 注册这个结构体 */ 33 | int V4l2Init(void) 34 | { 35 | return RegisterVideoOpr(&g_tV4l2VideoOpr); 36 | } 37 | 38 | 39 | 40 | static int g_aiSupportedFormats[] = {V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_RGB565}; 41 | 42 | static int V4l2GetFrameForReadWrite(PT_VideoDevice ptVideoDevice, PT_VideoBuf ptVideoBuf); 43 | static int V4l2PutFrameForReadWrite(PT_VideoDevice ptVideoDevice, PT_VideoBuf ptVideoBuf); 44 | static T_VideoOpr g_tV4l2VideoOpr; 45 | 46 | 47 | 48 | static int V4l2GetFrameForReadWrite(PT_VideoDevice ptVideoDevice, PT_VideoBuf ptVideoBuf) 49 | { 50 | int iRet; 51 | 52 | iRet = read(ptVideoDevice->iFd, ptVideoDevice->pucVideBuf[0], ptVideoDevice->iVideoBufMaxLen); 53 | if (iRet <= 0) 54 | { 55 | return -1; 56 | } 57 | 58 | ptVideoBuf->iPixelFormat = ptVideoDevice->iPixelFormat; 59 | ptVideoBuf->tPixelDatas.iWidth = ptVideoDevice->iWidth; 60 | ptVideoBuf->tPixelDatas.iHeight = ptVideoDevice->iHeight; 61 | ptVideoBuf->tPixelDatas.iBpp = (ptVideoDevice->iPixelFormat == V4L2_PIX_FMT_YUYV) ? 16 : \ 62 | (ptVideoDevice->iPixelFormat == V4L2_PIX_FMT_MJPEG) ? 0 : \ 63 | (ptVideoDevice->iPixelFormat == V4L2_PIX_FMT_RGB565)? 16 : \ 64 | 0; 65 | ptVideoBuf->tPixelDatas.iLineBytes = ptVideoDevice->iWidth * ptVideoBuf->tPixelDatas.iBpp / 8; 66 | ptVideoBuf->tPixelDatas.iTotalBytes = iRet; 67 | ptVideoBuf->tPixelDatas.aucPixelDatas = ptVideoDevice->pucVideBuf[0]; 68 | 69 | return 0; 70 | } 71 | 72 | 73 | static int V4l2PutFrameForReadWrite(PT_VideoDevice ptVideoDevice, PT_VideoBuf ptVideoBuf) 74 | { 75 | return 0; 76 | } 77 | 78 | 79 | 80 | 81 | 82 | static int V4l2StartDevice(PT_VideoDevice ptVideoDevice) 83 | { 84 | int iType = V4L2_BUF_TYPE_VIDEO_CAPTURE; 85 | int iError; 86 | 87 | iError = ioctl(ptVideoDevice->iFd, VIDIOC_STREAMON, &iType); 88 | if (iError) 89 | { 90 | DBG_PRINTF("Unable to start capture.\n"); 91 | return -1; 92 | } 93 | return 0; 94 | } 95 | 96 | static int V4l2StopDevice(PT_VideoDevice ptVideoDevice) 97 | { 98 | int iType = V4L2_BUF_TYPE_VIDEO_CAPTURE; 99 | int iError; 100 | 101 | iError = ioctl(ptVideoDevice->iFd, VIDIOC_STREAMOFF, &iType); 102 | if (iError) 103 | { 104 | DBG_PRINTF("Unable to stop capture.\n"); 105 | return -1; 106 | } 107 | return 0; 108 | } 109 | 110 | 111 | static int V4l2PutFrameForStreaming(PT_VideoDevice ptVideoDevice, PT_VideoBuf ptVideoBuf) 112 | { 113 | /* VIDIOC_QBUF */ 114 | struct v4l2_buffer tV4l2Buf; 115 | int iError; 116 | 117 | memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer)); 118 | tV4l2Buf.index = ptVideoDevice->iVideoBufCurIndex; 119 | tV4l2Buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 120 | tV4l2Buf.memory = V4L2_MEMORY_MMAP; 121 | iError = ioctl(ptVideoDevice->iFd, VIDIOC_QBUF, &tV4l2Buf); 122 | if (iError) 123 | { 124 | DBG_PRINTF("Unable to queue buffer.\n"); 125 | return -1; 126 | } 127 | return 0; 128 | } 129 | 130 | 131 | 132 | 133 | static int V4l2GetFrameForStreaming(PT_VideoDevice ptVideoDevice, PT_VideoBuf ptVideoBuf) 134 | { 135 | struct pollfd tFds[1]; 136 | int iRet; 137 | struct v4l2_buffer tV4l2Buf; 138 | 139 | /* poll */ 140 | tFds[0].fd = ptVideoDevice->iFd; 141 | tFds[0].events = POLLIN; 142 | 143 | iRet = poll(tFds, 1, -1); 144 | if (iRet <= 0) 145 | { 146 | DBG_PRINTF("poll error!\n"); 147 | return -1; 148 | } 149 | 150 | /* VIDIOC_DQBUF */ 151 | memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer)); 152 | tV4l2Buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 153 | tV4l2Buf.memory = V4L2_MEMORY_MMAP; 154 | iRet = ioctl(ptVideoDevice->iFd, VIDIOC_DQBUF, &tV4l2Buf); 155 | if (iRet < 0) 156 | { 157 | DBG_PRINTF("Unable to dequeue buffer.\n"); 158 | return -1; 159 | } 160 | ptVideoDevice->iVideoBufCurIndex = tV4l2Buf.index; 161 | 162 | ptVideoBuf->iPixelFormat = ptVideoDevice->iPixelFormat; 163 | ptVideoBuf->tPixelDatas.iWidth = ptVideoDevice->iWidth; 164 | ptVideoBuf->tPixelDatas.iHeight = ptVideoDevice->iHeight; 165 | ptVideoBuf->tPixelDatas.iBpp = (ptVideoDevice->iPixelFormat == V4L2_PIX_FMT_YUYV) ? 16 : \ 166 | (ptVideoDevice->iPixelFormat == V4L2_PIX_FMT_MJPEG) ? 0 : \ 167 | (ptVideoDevice->iPixelFormat == V4L2_PIX_FMT_RGB565) ? 16 : \ 168 | 0; 169 | ptVideoBuf->tPixelDatas.iLineBytes = ptVideoDevice->iWidth * ptVideoBuf->tPixelDatas.iBpp / 8; 170 | ptVideoBuf->tPixelDatas.iTotalBytes = tV4l2Buf.bytesused; 171 | ptVideoBuf->tPixelDatas.aucPixelDatas = ptVideoDevice->pucVideBuf[tV4l2Buf.index]; 172 | return 0; 173 | } 174 | 175 | 176 | 177 | 178 | static int V4l2GetFormat(PT_VideoDevice ptVideoDevice) 179 | { 180 | return ptVideoDevice->iPixelFormat; 181 | } 182 | 183 | 184 | static int V4l2ExitDevice(PT_VideoDevice ptVideoDevice) 185 | { 186 | int i; 187 | for (i = 0; i < ptVideoDevice->iVideoBufCnt; i++) 188 | { 189 | if (ptVideoDevice->pucVideBuf[i]) 190 | { 191 | munmap(ptVideoDevice->pucVideBuf[i], ptVideoDevice->iVideoBufMaxLen); 192 | ptVideoDevice->pucVideBuf[i] = NULL; 193 | } 194 | } 195 | 196 | close(ptVideoDevice->iFd); 197 | return 0; 198 | } 199 | 200 | static int V4l2InitDevice(char *strDevName, PT_VideoDevice ptVideoDevice) 201 | { 202 | int i; 203 | int iFd; 204 | int iError; 205 | struct v4l2_capability tV4l2Cap; 206 | struct v4l2_fmtdesc tFmtDesc; 207 | struct v4l2_format tV4l2Fmt; 208 | struct v4l2_requestbuffers tV4l2ReqBuffs; 209 | struct v4l2_buffer tV4l2Buf; 210 | 211 | int iLcdWidth; 212 | int iLcdHeigt; 213 | int iLcdBpp; 214 | 215 | iFd = open(strDevName, O_RDWR); 216 | if (iFd < 0) 217 | { 218 | DBG_PRINTF("can not open %s\n", strDevName); 219 | return -1; 220 | } 221 | ptVideoDevice->iFd = iFd; 222 | 223 | iError = ioctl(iFd, VIDIOC_QUERYCAP, &tV4l2Cap); 224 | memset(&tV4l2Cap, 0, sizeof(struct v4l2_capability)); 225 | iError = ioctl(iFd, VIDIOC_QUERYCAP, &tV4l2Cap); 226 | if (iError) { 227 | DBG_PRINTF("Error opening device %s: unable to query device.\n", strDevName); 228 | goto err_exit; 229 | } 230 | 231 | if (!(tV4l2Cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) 232 | { 233 | DBG_PRINTF("%s is not a video capture device\n", strDevName); 234 | goto err_exit; 235 | } 236 | 237 | if (tV4l2Cap.capabilities & V4L2_CAP_STREAMING) { 238 | DBG_PRINTF("%s supports streaming i/o\n", strDevName); 239 | } 240 | 241 | if (tV4l2Cap.capabilities & V4L2_CAP_READWRITE) { 242 | DBG_PRINTF("%s supports read i/o\n", strDevName); 243 | } 244 | 245 | memset(&tFmtDesc, 0, sizeof(tFmtDesc)); 246 | tFmtDesc.index = 0; 247 | tFmtDesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 248 | while ((iError = ioctl(iFd, VIDIOC_ENUM_FMT, &tFmtDesc)) == 0) { 249 | if (isSupportThisFormat(tFmtDesc.pixelformat)) 250 | { 251 | ptVideoDevice->iPixelFormat = tFmtDesc.pixelformat; 252 | break; 253 | } 254 | tFmtDesc.index++; 255 | } 256 | 257 | if (!ptVideoDevice->iPixelFormat) 258 | { 259 | DBG_PRINTF("can not support the format of this device\n"); 260 | goto err_exit; 261 | } 262 | 263 | 264 | /* set format in */ 265 | GetDispResolution(&iLcdWidth, &iLcdHeigt, &iLcdBpp); 266 | memset(&tV4l2Fmt, 0, sizeof(struct v4l2_format)); 267 | tV4l2Fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 268 | tV4l2Fmt.fmt.pix.pixelformat = ptVideoDevice->iPixelFormat; 269 | tV4l2Fmt.fmt.pix.width = iLcdWidth; 270 | tV4l2Fmt.fmt.pix.height = iLcdHeigt; 271 | tV4l2Fmt.fmt.pix.field = V4L2_FIELD_ANY; 272 | 273 | /* 如果驱动程序发现无法某些参数(比如分辨率), 274 | * 它会调整这些参数, 并且返回给应用程序 275 | */ 276 | iError = ioctl(iFd, VIDIOC_S_FMT, &tV4l2Fmt); 277 | if (iError) 278 | { 279 | DBG_PRINTF("Unable to set format\n"); 280 | goto err_exit; 281 | } 282 | ptVideoDevice->iWidth = tV4l2Fmt.fmt.pix.width; 283 | ptVideoDevice->iHeight = tV4l2Fmt.fmt.pix.height; 284 | 285 | /* request buffers */ 286 | memset(&tV4l2ReqBuffs, 0, sizeof(struct v4l2_requestbuffers)); 287 | tV4l2ReqBuffs.count = NB_BUFFER; 288 | tV4l2ReqBuffs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 289 | tV4l2ReqBuffs.memory = V4L2_MEMORY_MMAP; 290 | 291 | iError = ioctl(iFd, VIDIOC_REQBUFS, &tV4l2ReqBuffs); 292 | if (iError) 293 | { 294 | DBG_PRINTF("Unable to allocate buffers.\n"); 295 | goto err_exit; 296 | } 297 | 298 | ptVideoDevice->iVideoBufCnt = tV4l2ReqBuffs.count; 299 | if (tV4l2Cap.capabilities & V4L2_CAP_STREAMING) 300 | { 301 | /* map the buffers */ 302 | for (i = 0; i < ptVideoDevice->iVideoBufCnt; i++) 303 | { 304 | memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer)); 305 | tV4l2Buf.index = i; 306 | tV4l2Buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 307 | tV4l2Buf.memory = V4L2_MEMORY_MMAP; 308 | iError = ioctl(iFd, VIDIOC_QUERYBUF, &tV4l2Buf); 309 | if (iError) 310 | { 311 | DBG_PRINTF("Unable to query buffer.\n"); 312 | goto err_exit; 313 | } 314 | 315 | ptVideoDevice->iVideoBufMaxLen = tV4l2Buf.length; 316 | ptVideoDevice->pucVideBuf[i] = mmap(0 /* start anywhere */ , 317 | tV4l2Buf.length, PROT_READ, MAP_SHARED, iFd, 318 | tV4l2Buf.m.offset); 319 | if (ptVideoDevice->pucVideBuf[i] == MAP_FAILED) 320 | { 321 | DBG_PRINTF("Unable to map buffer\n"); 322 | goto err_exit; 323 | } 324 | } 325 | 326 | /* Queue the buffers. */ 327 | for (i = 0; i < ptVideoDevice->iVideoBufCnt; i++) 328 | { 329 | memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer)); 330 | tV4l2Buf.index = i; 331 | tV4l2Buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 332 | tV4l2Buf.memory = V4L2_MEMORY_MMAP; 333 | iError = ioctl(iFd, VIDIOC_QBUF, &tV4l2Buf); 334 | if (iError) 335 | { 336 | DBG_PRINTF("Unable to queue buffer.\n"); 337 | goto err_exit; 338 | } 339 | } 340 | 341 | } 342 | else if (tV4l2Cap.capabilities & V4L2_CAP_READWRITE) 343 | { 344 | g_tV4l2VideoOpr.GetFrame = V4l2GetFrameForReadWrite; 345 | g_tV4l2VideoOpr.PutFrame = V4l2PutFrameForReadWrite; 346 | 347 | /* read(fd, buf, size) */ 348 | ptVideoDevice->iVideoBufCnt = 1; 349 | /* 在这个程序所能支持的格式里, 一个象素最多只需要4字节 */ 350 | ptVideoDevice->iVideoBufMaxLen = ptVideoDevice->iWidth * ptVideoDevice->iHeight * 4; 351 | ptVideoDevice->pucVideBuf[0] = malloc(ptVideoDevice->iVideoBufMaxLen); 352 | } 353 | 354 | ptVideoDevice->ptOPr = &g_tV4l2VideoOpr; 355 | return 0; 356 | 357 | err_exit: 358 | close(iFd); 359 | return -1; 360 | } 361 | 362 | 363 | 364 | 365 | static int isSupportThisFormat(int iPixelFormat) 366 | { 367 | int i; 368 | for (i = 0; i < sizeof(g_aiSupportedFormats)/sizeof(g_aiSupportedFormats[0]); i++) 369 | { 370 | if (g_aiSupportedFormats[i] == iPixelFormat) 371 | return 1; 372 | } 373 | return 0; 374 | } 375 | 376 | 377 | 378 | 379 | /* 参考 luvcview */ 380 | 381 | /* open 382 | * VIDIOC_QUERYCAP 确定它是否视频捕捉设备,支持哪种接口(streaming/read,write) 383 | * VIDIOC_ENUM_FMT 查询支持哪种格式 384 | * VIDIOC_S_FMT 设置摄像头使用哪种格式 385 | * VIDIOC_REQBUFS 申请buffer 386 | 对于 streaming: 387 | * VIDIOC_QUERYBUF 确定每一个buffer的信息 并且 mmap 388 | * VIDIOC_QBUF 放入队列 389 | * VIDIOC_STREAMON 启动设备 390 | * poll 等待有数据 391 | * VIDIOC_DQBUF 从队列中取出 392 | * 处理.... 393 | * VIDIOC_QBUF 放入队列 394 | * .... 395 | 对于read,write: 396 | read 397 | 处理.... 398 | read 399 | * VIDIOC_STREAMOFF 停止设备 400 | * 401 | */ 402 | 403 | 404 | 405 | 406 | 407 | 408 | -------------------------------------------------------------------------------- /video/video_manager.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | static PT_VideoOpr g_ptVideoOprHead = NULL; 10 | 11 | int VideoInit(void) 12 | { 13 | int iError; 14 | 15 | iError = V4l2Init(); 16 | 17 | return iError; 18 | } 19 | 20 | 21 | int VideoDeviceInit(char *strDevName, PT_VideoDevice ptVideoDevice) 22 | { 23 | int iError; 24 | PT_VideoOpr ptTmp; 25 | 26 | while (ptTmp) 27 | { 28 | iError = ptTmp->InitDevice(strDevName, ptVideoDevice); 29 | if (!iError) 30 | { 31 | return 0; 32 | } 33 | ptTmp = ptTmp->ptNext; 34 | } 35 | return -1; 36 | } 37 | 38 | 39 | //注册进链表 40 | int RegisterVideoOpr(PT_VideoOpr ptVideoOpr) 41 | { 42 | PT_VideoOpr ptTmp; 43 | 44 | if (!g_ptVideoOprHead) 45 | { 46 | g_ptVideoOprHead = ptVideoOpr; 47 | ptVideoOpr->ptNext = NULL; 48 | } 49 | else 50 | { 51 | ptTmp = g_ptVideoOprHead; 52 | while (ptTmp->ptNext) 53 | { 54 | ptTmp = ptTmp->ptNext; 55 | } 56 | ptTmp->ptNext = ptVideoOpr; 57 | ptVideoOpr->ptNext = NULL; 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | PT_VideoOpr GetVideoOpr(char *pcName) 64 | { 65 | PT_VideoOpr ptTmp = g_ptVideoOprHead; 66 | 67 | while (ptTmp) 68 | { 69 | if (strcmp(ptTmp->name, pcName) == 0) 70 | { 71 | return ptTmp; 72 | } 73 | ptTmp = ptTmp->ptNext; 74 | } 75 | return NULL; 76 | } 77 | 78 | 79 | void ShowVideoOpr(void) 80 | { 81 | int i = 0; 82 | PT_VideoOpr ptTmp = g_ptVideoOprHead; 83 | 84 | while (ptTmp) 85 | { 86 | printf("%02d %s\n", i++, ptTmp->name); 87 | ptTmp = ptTmp->ptNext; 88 | } 89 | } --------------------------------------------------------------------------------