打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
内存中读取jpeg图片并解压缩
//--------一些代码是从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;   
}
 
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
jpeg库使用及源码分析
快速压缩jpeg
如何使用jpeglib库压缩yuv422?
使用libpng,libjpeg从文件读取和从内存读取2中方式的实现
mem.h函数库
OpenCL快速入门教程 | Imagination中文技术社区
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服