Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/LibWebP/src/dec/dec.idec.c  view on Meta::CPAN

    return IDecError(idec, dec->status_);
  }

  // Finish setting up the decoding parameters. Will call io->setup().
  if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) {
    return IDecError(idec, dec->status_);
  }

  // Note: past this point, teardown() must always be called
  // in case of error.
  idec->state_ = STATE_VP8_DATA;
  // Allocate memory and prepare everything.
  if (!VP8InitFrame(dec, io)) {
    return IDecError(idec, dec->status_);
  }
  return VP8_STATUS_OK;
}

// Remaining partitions
static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
  VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
  VP8Io* const io = &idec->io_;

  assert(dec->ready_);
  for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) {
    if (idec->last_mb_y_ != dec->mb_y_) {
      if (!VP8ParseIntraModeRow(&dec->br_, dec)) {
        // note: normally, error shouldn't occur since we already have the whole
        // partition0 available here in DecodeRemaining(). Reaching EOF while
        // reading intra modes really means a BITSTREAM_ERROR.
        return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
      }
      idec->last_mb_y_ = dec->mb_y_;
    }
    for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) {
      VP8BitReader* const token_br =
          &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)];
      MBContext context;
      SaveContext(dec, token_br, &context);
      if (!VP8DecodeMB(dec, token_br)) {
        // We shouldn't fail when MAX_MB data was available
        if (dec->num_parts_ == 1 && MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
          return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
        }
        RestoreContext(&context, dec, token_br);
        return VP8_STATUS_SUSPENDED;
      }
      // Release buffer only if there is only one partition
      if (dec->num_parts_ == 1) {
        idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_;
        assert(idec->mem_.start_ <= idec->mem_.end_);
      }
    }
    VP8InitScanline(dec);   // Prepare for next scanline

    // Reconstruct, filter and emit the row.
    if (!VP8ProcessRow(dec, io)) {
      return IDecError(idec, VP8_STATUS_USER_ABORT);
    }
  }
  // Synchronize the thread and check for errors.
  if (!VP8ExitCritical(dec, io)) {
    return IDecError(idec, VP8_STATUS_USER_ABORT);
  }
  dec->ready_ = 0;
  return FinishDecoding(idec);
}

static VP8StatusCode ErrorStatusLossless(WebPIDecoder* const idec,
                                         VP8StatusCode status) {
  if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) {
    return VP8_STATUS_SUSPENDED;
  }
  return IDecError(idec, status);
}

static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) {
  VP8Io* const io = &idec->io_;
  VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
  const WebPDecParams* const params = &idec->params_;
  WebPDecBuffer* const output = params->output;
  size_t curr_size = MemDataSize(&idec->mem_);
  assert(idec->is_lossless_);

  // Wait until there's enough data for decoding header.
  if (curr_size < (idec->chunk_size_ >> 3)) {
    dec->status_ = VP8_STATUS_SUSPENDED;
    return ErrorStatusLossless(idec, dec->status_);
  }

  if (!VP8LDecodeHeader(dec, io)) {
    if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR &&
        curr_size < idec->chunk_size_) {
      dec->status_ = VP8_STATUS_SUSPENDED;
    }
    return ErrorStatusLossless(idec, dec->status_);
  }
  // Allocate/verify output buffer now.
  dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options,
                                       output);
  if (dec->status_ != VP8_STATUS_OK) {
    return IDecError(idec, dec->status_);
  }

  idec->state_ = STATE_VP8L_DATA;
  return VP8_STATUS_OK;
}

static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) {
  VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
  const size_t curr_size = MemDataSize(&idec->mem_);
  assert(idec->is_lossless_);

  // Switch to incremental decoding if we don't have all the bytes available.
  dec->incremental_ = (curr_size < idec->chunk_size_);

  if (!VP8LDecodeImage(dec)) {
    return ErrorStatusLossless(idec, dec->status_);
  }
  assert(dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED);
  return (dec->status_ == VP8_STATUS_SUSPENDED) ? dec->status_

src/Source/LibWebP/src/dec/dec.idec.c  view on Meta::CPAN

  }
  if (idec->state_ == STATE_VP8L_DATA) {
    status = DecodeVP8LData(idec);
  }
  return status;
}

//------------------------------------------------------------------------------
// Public functions

WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) {
  WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec));
  if (idec == NULL) {
    return NULL;
  }

  idec->state_ = STATE_WEBP_HEADER;
  idec->chunk_size_ = 0;

  idec->last_mb_y_ = -1;

  InitMemBuffer(&idec->mem_);
  WebPInitDecBuffer(&idec->output_);
  VP8InitIo(&idec->io_);

  WebPResetDecParams(&idec->params_);
  idec->params_.output = (output_buffer != NULL) ? output_buffer
                                                 : &idec->output_;
  WebPInitCustomIo(&idec->params_, &idec->io_);  // Plug the I/O functions.

  return idec;
}

WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size,
                          WebPDecoderConfig* config) {
  WebPIDecoder* idec;

  // Parse the bitstream's features, if requested:
  if (data != NULL && data_size > 0 && config != NULL) {
    if (WebPGetFeatures(data, data_size, &config->input) != VP8_STATUS_OK) {
      return NULL;
    }
  }
  // Create an instance of the incremental decoder
  idec = WebPINewDecoder(config ? &config->output : NULL);
  if (idec == NULL) {
    return NULL;
  }
  // Finish initialization
  if (config != NULL) {
    idec->params_.options = &config->options;
  }
  return idec;
}

void WebPIDelete(WebPIDecoder* idec) {
  if (idec == NULL) return;
  if (idec->dec_ != NULL) {
    if (!idec->is_lossless_) {
      if (idec->state_ == STATE_VP8_DATA) {
        // Synchronize the thread, clean-up and check for errors.
        VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
      }
      VP8Delete((VP8Decoder*)idec->dec_);
    } else {
      VP8LDelete((VP8LDecoder*)idec->dec_);
    }
  }
  ClearMemBuffer(&idec->mem_);
  WebPFreeDecBuffer(&idec->output_);
  WebPSafeFree(idec);
}

//------------------------------------------------------------------------------
// Wrapper toward WebPINewDecoder

WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer,
                          size_t output_buffer_size, int output_stride) {
  const int is_external_memory = (output_buffer != NULL);
  WebPIDecoder* idec;

  if (mode >= MODE_YUV) return NULL;
  if (!is_external_memory) {    // Overwrite parameters to sane values.
    output_buffer_size = 0;
    output_stride = 0;
  } else {  // A buffer was passed. Validate the other params.
    if (output_stride == 0 || output_buffer_size == 0) {
      return NULL;   // invalid parameter.
    }
  }
  idec = WebPINewDecoder(NULL);
  if (idec == NULL) return NULL;
  idec->output_.colorspace = mode;
  idec->output_.is_external_memory = is_external_memory;
  idec->output_.u.RGBA.rgba = output_buffer;
  idec->output_.u.RGBA.stride = output_stride;
  idec->output_.u.RGBA.size = output_buffer_size;
  return idec;
}

WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride,
                           uint8_t* u, size_t u_size, int u_stride,
                           uint8_t* v, size_t v_size, int v_stride,
                           uint8_t* a, size_t a_size, int a_stride) {
  const int is_external_memory = (luma != NULL);
  WebPIDecoder* idec;
  WEBP_CSP_MODE colorspace;

  if (!is_external_memory) {    // Overwrite parameters to sane values.
    luma_size = u_size = v_size = a_size = 0;
    luma_stride = u_stride = v_stride = a_stride = 0;
    u = v = a = NULL;
    colorspace = MODE_YUVA;
  } else {  // A luma buffer was passed. Validate the other parameters.
    if (u == NULL || v == NULL) return NULL;
    if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL;
    if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL;
    if (a != NULL) {
      if (a_size == 0 || a_stride == 0) return NULL;
    }
    colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA;



( run in 2.577 seconds using v1.01-cache-2.11-cpan-5a3173703d6 )