//--------一些代码是从MiniGUI中提取的,本来想依靠它来显示一些图片,但是效果实在太糟糕(屏幕是256色的),只好自己想办法去处理图片了,zc0301采集出来图像为jpeg图像,要处理图像首先解压缩,得到各个像素的RGB分量,再进行误差扩散处理得到想要的效果,下边代码是依赖于 jpeg 库的。
#define RWAREA_TYPE_UNKNOWN 0#define RWAREA_TYPE_STDIO 1#define RWAREA_TYPE_MEM 2#define INPUT_BUF_SIZE 4096 #define SIZEOF(object) ((size_t) sizeof(object))#define MGUI_RWread(ctx, ptr, size, n) (ctx)->read(ctx, ptr, size, n)#define MGUI_RWclose(ctx) (ctx)->close(ctx)typedef struct MG_RWops { /** * Seek to \a offset relative to whence, one of stdio's whence values:\n * SEEK_SET, SEEK_CUR, SEEK_END\n * Returns the final offset in the data source. */ int (*seek)(struct MG_RWops *context, int offset, int whence); /** * Read up to \a num objects each of size \a objsize from the data * source to the area pointed at by \a ptr. * Returns the number of objects read, or -1 if the read failed. */ int (*read)(struct MG_RWops *context, void *ptr, int objsize, int num); /** * Write exactly \a num objects each of size \a objsize from the area * pointed at by \a ptr to data source. * Returns \a num, or -1 if the write failed. */ int (*write)(struct MG_RWops *context, const void *ptr, int objsize, int num); /* * Close and free an allocated MG_RWops structure. */ int (*close)(struct MG_RWops *context); /** * Test the end-of-file indicator. */ int (*eof)(struct MG_RWops *context); /** * Indicates the type of data source. * can be one of the following values: * - RWAREA_TYPE_UNKNOWN\n * A unknown (uninitialized) data source type. * - RWAREA_TYPE_STDIO\n * Stdio stream data source. * - RWAREA_TYPE_MEM\n * Memory data source. */ int type; union { struct { int autoclose; FILE *fp; } stdio; struct { unsigned char *base; unsigned char *here; unsigned char *stop; } mem; struct { void *data1; } unknown; } hidden;} MG_RWops;static void term_source (j_decompress_ptr cinfo){ /* no work necessary here */}static int mem_seek(MG_RWops *context, int offset, int whence){ unsigned char *newpos; switch (whence) { case SEEK_SET: newpos = context->hidden.mem.base+offset; break; case SEEK_CUR: newpos = context->hidden.mem.here+offset; break; case SEEK_END: newpos = context->hidden.mem.stop+offset; break; default: printf("Unknown value for 'whence'\n"); return(-1); } if ( newpos < context->hidden.mem.base ) { newpos = context->hidden.mem.base; } if ( newpos > context->hidden.mem.stop ) { newpos = context->hidden.mem.stop; } context->hidden.mem.here = newpos; return(context->hidden.mem.here-context->hidden.mem.base);}static int mem_read(MG_RWops *context, void *ptr, int size, int maxnum){ int num; num = maxnum; if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop ) { num = (context->hidden.mem.stop-context->hidden.mem.here)/size; } memcpy(ptr, context->hidden.mem.here, num*size); context->hidden.mem.here += num*size; return(num);}static int mem_write(MG_RWops *context, const void *ptr, int size, int num){ if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop ) { num = (context->hidden.mem.stop-context->hidden.mem.here)/size; } memcpy(context->hidden.mem.here, ptr, num*size); context->hidden.mem.here += num*size; return(num);}static int mem_close(MG_RWops *context){ if ( context ) { free(context); } return(0);}static int mem_eof(MG_RWops *context){ if (context->hidden.mem.here >= context->hidden.mem.stop) return 1; return 0;}typedef struct { struct jpeg_source_mgr pub; /* public fields */ MG_RWops *infile; /* source stream */ JOCTET * buffer; /* start of buffer */ boolean start_of_file; /* have we gotten any data yet? */} my_source_mgr;typedef my_source_mgr * my_src_ptr;static void init_source (j_decompress_ptr cinfo){ my_src_ptr src = (my_src_ptr) cinfo->src; /* We reset the empty-input-file flag for each image, * but we don't clear the input buffer. * This is correct behavior for reading a series of images from one source. */ src->start_of_file = TRUE;}/* * Fill the input buffer --- called whenever buffer is emptied. */static boolean fill_input_buffer (j_decompress_ptr cinfo){ my_src_ptr src = (my_src_ptr) cinfo->src; size_t nbytes; nbytes = MGUI_RWread ((MG_RWops*) src->infile, src->buffer, 1, INPUT_BUF_SIZE); if (nbytes <= 0) { if (src->start_of_file) /* Treat empty input file as fatal error */ ERREXIT(cinfo, JERR_INPUT_EMPTY); WARNMS(cinfo, JWRN_JPEG_EOF); /* Insert a fake EOI marker */ src->buffer[0] = (JOCTET) 0xFF; src->buffer[1] = (JOCTET) JPEG_EOI; nbytes = 2; } src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer = nbytes; src->start_of_file = FALSE; return TRUE;}/* * Skip data --- used to skip over a potentially large amount of * uninteresting data (such as an APPn marker). */static void skip_input_data (j_decompress_ptr cinfo, long num_bytes){ my_src_ptr src = (my_src_ptr) cinfo->src; /* Just a dumb implementation for now. Could use fseek() except * it doesn't work on pipes. Not clear that being smart is worth * any trouble anyway --- large skips are infrequent. */ if (num_bytes > 0) { while (num_bytes > (long) src->pub.bytes_in_buffer) { num_bytes -= (long) src->pub.bytes_in_buffer; (void) fill_input_buffer(cinfo); /* note we assume that fill_input_buffer will never return FALSE, * so suspension need not be handled. */ } src->pub.next_input_byte += (size_t) num_bytes; src->pub.bytes_in_buffer -= (size_t) num_bytes; }}MG_RWops *MGUI_AllocRW(void){ MG_RWops *area; area = (MG_RWops *)malloc(sizeof *area); if ( area == NULL ) { fprintf (stderr, "Out of memory"); } else area->type = RWAREA_TYPE_UNKNOWN; return(area);}MG_RWops *MGUI_RWFromMem(void *mem, int size){ MG_RWops *rwops; rwops = MGUI_AllocRW(); if ( rwops != NULL ) { rwops->seek = mem_seek; rwops->read = mem_read; rwops->write = mem_write; rwops->close = mem_close; rwops->eof = mem_eof; rwops->hidden.mem.base = (unsigned char *)mem; rwops->hidden.mem.here = rwops->hidden.mem.base; rwops->hidden.mem.stop = rwops->hidden.mem.base+size; rwops->type = RWAREA_TYPE_MEM; } return(rwops);}void my_jpeg_data_src (j_decompress_ptr cinfo, MG_RWops* infile){ my_src_ptr src; /* The source object and input buffer are made permanent so that a series * of JPEG images can be read from the same file by calling jpeg_stdio_src * only before the first one. (If we discarded the buffer at the end of * one image, we'd likely lose the start of the next one.) * This makes it unsafe to use this manager and a different source * manager serially with the same JPEG object. Caveat programmer. */ if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_source_mgr)); src = (my_src_ptr) cinfo->src; src->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * SIZEOF(JOCTET)); } src = (my_src_ptr) cinfo->src; src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->pub.term_source = term_source; src->infile = infile; src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ src->pub.next_input_byte = NULL; /* until buffer loaded */}//-------------------------------------------------------------------------------------------------//-------------------------------------------------------------------------------------------------//-------------------------------------------------------------------------------------------------//-------------------------------------------------------------------------------------------------//-------------------------------------------------------------------------------------------------int kkk; //============================================================================= bool CImg::read_JPEG_file(void *mem,int memsize) // JPEG decompression routine. { struct jpeg_decompress_struct cinfo; // JPEG image parameters struct jpeg_error_mgr jerr; // default JPEG error handler // source file handler unsigned char ** buffer; // points to large array of RGB data int row_stride; // physical row width in output buffer // Set up the normal JPEG error routines cinfo.err = jpeg_std_error(&jerr); // Initialize the JPEG decompression object with a data source (file). jpeg_create_decompress(&cinfo);/*FILE *fp;char jpgbuf[60*1024];fp=fopen("mm.jpg","r");fread(jpgbuf,1,26796,fp);*///printf("memsize=%d \n",memsize);MG_RWops * jpbrwops =MGUI_RWFromMem(mem, memsize);my_jpeg_data_src (&cinfo, jpbrwops); // jpeg_stdio_src(&cinfo, infile); // Read file parameters with jpeg_read_header() jpeg_read_header(&cinfo, TRUE); // Set parameters for decompression, if necessary (not necessary // here - the defaults set by jpeg_read_header() is sufficient. switch (m_mode) { case MODE_RGB: cinfo.out_color_space = JCS_RGB; break; case MODE_GRAYSCALE: cinfo.out_color_space = JCS_GRAYSCALE; break; } // Start decompressor jpeg_start_decompress(&cinfo); // Decompression complete, so now begin extraction of data // row_stride = output pixels per row * number of colours per row row_stride = cinfo.output_width * cinfo.output_components; // Create data buffer buffer = new unsigned char * [cinfo.output_height]; buffer[0] = new unsigned char[cinfo.output_height * row_stride]; for (int k = 0; k < (int)(cinfo.output_height); k++) { buffer[k] = buffer[0] + row_stride*k; } // The JPEG decompress parameters (cinfo) contains a counter, the output // row counter. Keep extracting data until the output row is at the end. int counter = 0; while (cinfo.output_scanline < cinfo.output_height) { counter += jpeg_read_scanlines(&cinfo, &buffer[counter], cinfo.output_height); } // initialize this CImg object //// deallocate(m_mode); m_width = cinfo.output_width; m_height = cinfo.output_height; if(kkk==0){allocate(m_mode);kkk++;} // Convert buffer data to Img struct int i, j; switch (m_mode) { case MODE_RGB: for (j = 0; j < m_height; j++) { for (i = 0; i < m_width*3; i += 3) { image[j][i/3].red = buffer[j][i]; image[j][i/3].green = buffer[j][i+1]; image[j][i/3].blue = buffer[j][i+2]; } } break; case MODE_GRAYSCALE: for (j = 0; j < m_height; j++) { for (i = 0; i < m_width; i++) { gImage[j][i] = buffer[j][i]; } } break; } // Destroy buffer delete [] buffer[0]; delete [] buffer; // Finish decompression and release JPEG compression object jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); MGUI_RWclose(jpbrwops); // Close file in use // fclose(infile); return true; }
//-----------------spcaview 中的解压缩代码,只支持一些格式的jpeg图片,很巧就是不支持我需的那种--
#define ISHIFT 11
#define IFIX(a) ((int)((a) * (1 << ISHIFT) + .5))
#define IMULT(a, b) (((a) * (b)) >> ISHIFT)
#define ITOINT(a) ((a) >> ISHIFT)
#ifndef __P
# define __P(x) x
#endif
/* special markers */
#define M_BADHUFF -1
#define M_EOF 0x80
struct jpeg_decdata {
int dcts[6 * 64 + 16];
int out[64 * 6];
int dquant[3][64];
};
struct in {
unsigned char *p;
unsigned int bits;
int left;
int marker;
int (*func) __P((void *));
void *data;
};
/*********************************/
struct dec_hufftbl;
struct enc_hufftbl;
union hufftblp {
struct dec_hufftbl *dhuff;
struct enc_hufftbl *ehuff;
};
struct scan {
int dc; /* old dc value */
union hufftblp hudc;
union hufftblp huac;
int next; /* when to switch to next scan */
int cid; /* component id */
int hv; /* horiz/vert, copied from comp */
int tq; /* quant tbl, copied from comp */
};
/*********************************/
#define DECBITS 10 /* seems to be the optimum */
struct dec_hufftbl {
int maxcode[17];
int valptr[16];
unsigned char vals[256];
unsigned int llvals[1 << DECBITS];
};
static void decode_mcus __P((struct in *, int *, int, struct scan *, int *));
static int dec_readmarker __P((struct in *));
static void dec_makehuff __P((struct dec_hufftbl *, int *, unsigned char *));
static void setinput __P((struct in *, unsigned char *));
/*********************************/
#undef PREC
#define PREC int
static void idctqtab __P((unsigned char *, PREC *));
static void idct __P((int *, int *, PREC *, PREC, int));
static void scaleidctqtab __P((PREC *, PREC));
/*********************************/
static void initcol __P((PREC[][64]));
static void col221111 __P((int *, unsigned char *, int));
/*********************************/
#define M_SOI 0xd8
#define M_APP0 0xe0
#define M_DQT 0xdb
#define M_SOF0 0xc0
#define M_DHT 0xc4
#define M_DRI 0xdd
#define M_SOS 0xda
#define M_RST0 0xd0
#define M_EOI 0xd9
#define M_COM 0xfe
static unsigned char *datap;
static int getbyte(void)
{
return *datap++;
}
static int getword(void)
{
int c1, c2;
c1 = *datap++;
c2 = *datap++;
return c1 << 8 | c2;
}
struct comp {
int cid;
int hv;
int tq;
};
#define MAXCOMP 4
struct jpginfo {
int nc; /* number of components */
int ns; /* number of scans */
int dri; /* restart interval */
int nm; /* mcus til next marker */
int rm; /* next restart marker */
};
static struct jpginfo info;
static struct comp comps[MAXCOMP];
static struct scan dscans[MAXCOMP];
static unsigned char quant[4][64];
static struct dec_hufftbl dhuff[4];
#define dec_huffdc (dhuff + 0)
#define dec_huffac (dhuff + 2)
static struct in in;
static int readtables(int till)
{
int m, l, i, j, lq, pq, tq;
int tc, th, tt;
for (;;) {
if (getbyte() != 0xff)
return -1;
if ((m = getbyte()) == till)
break;
switch (m) {
case 0xc2:
return 0;
case M_DQT:
lq = getword();
while (lq > 2) {
pq = getbyte();
tq = pq & 15;
if (tq > 3)
return -1;
pq >>= 4;
if (pq != 0)
return -1;
for (i = 0; i < 64; i++)
quant[tq][i] = getbyte();
lq -= 64 + 1;
}
break;
case M_DHT:
l = getword();
while (l > 2) {
int hufflen[16], k;
unsigned char huffvals[256];
tc = getbyte();
th = tc & 15;
tc >>= 4;
tt = tc * 2 + th;
if (tc > 1 || th > 1)
return -1;
for (i = 0; i < 16; i++)
hufflen[i] = getbyte();
l -= 1 + 16;
k = 0;
for (i = 0; i < 16; i++) {
for (j = 0; j < hufflen[i]; j++)
huffvals[k++] = getbyte();
l -= hufflen[i];
}
dec_makehuff(dhuff + tt, hufflen,
huffvals);
}
break;
case M_DRI:
l = getword();
info.dri = getword();
break;
default:
l = getword();
while (l-- > 2)
getbyte();
break;
}
}
return 0;
}
static void dec_initscans(void)
{
int i;
info.nm = info.dri + 1;
info.rm = M_RST0;
for (i = 0; i < info.ns; i++)
dscans[i].dc = 0;
}
static int dec_checkmarker(void)
{
int i;
if (dec_readmarker(&in) != info.rm)
return -1;
info.nm = info.dri;
info.rm = (info.rm + 1) & ~0x08;
for (i = 0; i < info.ns; i++)
dscans[i].dc = 0;
return 0;
}
int jpeg_decode(unsigned char **pic, unsigned char *buf, int *width, int *height )
{
struct jpeg_decdata *decdata;
int i, j, m, tac, tdc;
int intwidth ,intheight;
int mcusx, mcusy, mx, my;
int max[6];
int err = 0;
int enc411 = 1;
decdata = (struct jpeg_decdata*)malloc(sizeof(struct jpeg_decdata));
if (!decdata){
err= -1;
goto error;
}
if (buf == NULL){
err = -1;
goto error;
}
datap = buf;
if (getbyte() != 0xff){
err= ERR_NO_SOI;
goto error;
}
if (getbyte() != M_SOI){
err= ERR_NO_SOI;
goto error;
}
if (readtables(M_SOF0)){
err= ERR_BAD_TABLES;
goto error;
}
getword();
i = getbyte();
if (i != 8){
err = ERR_NOT_8BIT;
goto error;
}
intheight = getword();
intwidth = getword();
//if ((intheight & 15) || (intwidth & 15)){
if ((intheight & 7) || (intwidth & 15)){
err = ERR_BAD_WIDTH_OR_HEIGHT;
goto error;
}
info.nc = getbyte();
if (info.nc > MAXCOMP){
err = ERR_TOO_MANY_COMPPS;
goto error;
}
for (i = 0; i < info.nc; i++) {
int h, v;
comps[i].cid = getbyte();
comps[i].hv = getbyte();
v = comps[i].hv & 15;
h = comps[i].hv >> 4;
comps[i].tq = getbyte();
if (h > 3 || v > 3){
err = ERR_ILLEGAL_HV;
goto error;
}
if (comps[i].tq > 3){
err = ERR_QUANT_TABLE_SELECTOR;
goto error;
}
}
if (readtables(M_SOS)){
err = ERR_BAD_TABLES;
goto error;
}
getword();
info.ns = getbyte();
if (info.ns != 3){
err = ERR_NOT_YCBCR_221111;
goto error;
}
for (i = 0; i < 3; i++) {
dscans[i].cid = getbyte();
tdc = getbyte();
tac = tdc & 15;
tdc >>= 4;
if (tdc > 1 || tac > 1){
err = ERR_QUANT_TABLE_SELECTOR;
goto error;
}
for (j = 0; j < info.nc; j++)
if (comps[j].cid == dscans[i].cid)
break;
if (j == info.nc){
err= ERR_UNKNOWN_CID_IN_SCAN;
goto error;
}
dscans[i].hv = comps[j].hv;
dscans[i].tq = comps[j].tq;
dscans[i].hudc.dhuff = dec_huffdc + tdc;
dscans[i].huac.dhuff = dec_huffac + tac;
}
i = getbyte();
j = getbyte();
m = getbyte();
if (i != 0 || j != 63 || m != 0){
err = ERR_NOT_SEQUENTIAL_DCT;
goto error;
}
if (dscans[0].cid != 1 || dscans[1].cid != 2 || dscans[2].cid != 3){
err = ERR_NOT_YCBCR_221111;
goto error;
}
if (dscans[1].hv != 0x11 || dscans[2].hv != 0x11){
err = ERR_NOT_YCBCR_221111;
goto error;
}
/* if internal width and external are not the same or heigth too
and pic not allocated realloc the good size and mark the change
need 1 macroblock line more ?? */
if (intwidth != *width || intheight != *height || *pic == NULL){
*width = intwidth;
*height = intheight;
*pic = (unsigned char *) realloc((unsigned char*)*pic,(size_t) intwidth*(intheight+8)*3);
}
switch (dscans[0].hv) {
case 0x22:
mcusx = *width >> 4;
mcusy = *height >> 4;
enc411 = 1;
break ;
case 0x21:
mcusx = *width >> 4;
mcusy = *height >> 3;
enc411 = 0;
break;
default:
err = ERR_NOT_YCBCR_221111;
goto error;
break;
}
idctqtab(quant[dscans[0].tq], decdata->dquant[0]);
idctqtab(quant[dscans[1].tq], decdata->dquant[1]);
idctqtab(quant[dscans[2].tq], decdata->dquant[2]);
initcol(decdata->dquant);
setinput(&in, datap);
dec_initscans();
dscans[0].next = 6 - 4;
dscans[1].next = 6 - 4 - 1;
dscans[2].next = 6 - 4 - 1 - 1; /* 411 encoding */
for (my = 0; my < mcusy; my++) {
for (mx = 0; mx < mcusx; mx++) {
if (info.dri && !--info.nm)
if (dec_checkmarker()){
err = ERR_WRONG_MARKER;
goto error;
}
if (enc411){
decode_mcus(&in, decdata->dcts, 6, dscans, max);
idct(decdata->dcts, decdata->out, decdata->dquant[0], IFIX(128.5), max[0]);
idct(decdata->dcts + 64, decdata->out + 64, decdata->dquant[0], IFIX(128.5), max[1]);
idct(decdata->dcts + 128, decdata->out + 128, decdata->dquant[0], IFIX(128.5), max[2]);
idct(decdata->dcts + 192, decdata->out + 192, decdata->dquant[0], IFIX(128.5), max[3]);
idct(decdata->dcts + 256, decdata->out + 256, decdata->dquant[1], IFIX(0.5), max[4]);
idct(decdata->dcts + 320, decdata->out + 320, decdata->dquant[2], IFIX(0.5), max[5]);
col221111(decdata->out, *pic + (my * 16 * mcusx + mx) * 16 * 3, mcusx * 16 * 3);
} else {
decode_mcus(&in, decdata->dcts, 4, dscans, max);
idct(decdata->dcts, decdata->out, decdata->dquant[0], IFIX(128.5), max[0]);
idct(decdata->dcts + 64, decdata->out + 64, decdata->dquant[0], IFIX(128.5), max[1]);
idct(decdata->dcts + 128, decdata->out + 256, decdata->dquant[1], IFIX(0.5), max[4]);
idct(decdata->dcts + 192, decdata->out + 320, decdata->dquant[2], IFIX(0.5), max[5]);
col221111(decdata->out, *pic + (my * 8 * mcusx + mx) * 16 * 3, mcusx * 16 * 3);
}
}
}
m = dec_readmarker(&in);
if (m != M_EOI){
err = ERR_NO_EOI;
goto error;
}
if (decdata)
free(decdata);
return 0;
error:
if (decdata)
free(decdata);
return err;
}