Пример #1
0
/*
 * @brief start processing apng frame
 * @note uses libpng calls, treats apng data as discrete png images
 */
int apng_ani::_processing_start()
{
	static ubyte png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};

	_pngp = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
	_infop = png_create_info_struct(_pngp);
	if (_pngp == nullptr || _infop == nullptr) {
		return 1;
	}

	if (setjmp(png_jmpbuf(_pngp))) {
		png_destroy_read_struct(&_pngp, &_infop, 0);
		return 1;
	}

	png_set_crc_action(_pngp, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
	png_set_progressive_read_fn(_pngp, this, apng::info_callback, apng::row_callback, nullptr);

	png_process_data(_pngp, _infop, png_sig, 8);
	memcpy(&_chunk_IHDR.data[8], &_chunk.data[12], 8); // use frame width & height from fcTL
	png_process_data(_pngp, _infop, &_chunk_IHDR.data[0], _chunk_IHDR.size);

	for (size_t i = 0; i < _info_chunks.size(); ++i) {
		// this processes chunks like tRNS / PLTE / etc
		png_process_data(_pngp, _infop, &_info_chunks.at(i).data[0], _info_chunks.at(i).size);
	}

	return 0;
}
Пример #2
0
bool AutoCleanPng::decodeBounds() {
    if (setjmp(png_jmpbuf(fPng_ptr))) {
        return false;
    }

    png_set_progressive_read_fn(fPng_ptr, this, InfoCallback, nullptr, nullptr);

    // Arbitrary buffer size, though note that it matches (below)
    // SkPngCodec::processData(). FIXME: Can we better suit this to the size of
    // the PNG header?
    constexpr size_t kBufferSize = 4096;
    char buffer[kBufferSize];

    while (true) {
        const size_t bytesRead = fStream->read(buffer, kBufferSize);
        if (!bytesRead) {
            // We have read to the end of the input without decoding bounds.
            break;
        }

        png_process_data(fPng_ptr, fInfo_ptr, (png_bytep) buffer, bytesRead);
        if (fDecodedBounds) {
            break;
        }
    }

    // For safety, clear the pointer to this object.
    png_set_progressive_read_fn(fPng_ptr, nullptr, nullptr, nullptr, nullptr);
    return fDecodedBounds;
}
Пример #3
0
void SkPngCodec::processData() {
    switch (setjmp(png_jmpbuf(fPng_ptr))) {
        case kPngError:
            // There was an error. Stop processing data.
            // FIXME: Do we need to discard png_ptr?
            return;
        case kStopDecoding:
            // We decoded all the lines we want.
            return;
        case kSetJmpOkay:
            // Everything is okay.
            break;
        default:
            // No other values should be passed to longjmp.
            SkASSERT(false);
    }

    // Arbitrary buffer size
    constexpr size_t kBufferSize = 4096;
    char buffer[kBufferSize];

    while (true) {
        const size_t bytesRead = this->stream()->read(buffer, kBufferSize);
        png_process_data(fPng_ptr, fInfo_ptr, (png_bytep) buffer, bytesRead);

        if (!bytesRead) {
            // We have read to the end of the input. Note that we quit *after*
            // calling png_process_data, because decodeBounds may have told
            // libpng to save the remainder of the buffer, in which case
            // png_process_data will process the saved buffer, though the
            // stream has no more to read.
            break;
        }
    }
}
Пример #4
0
s32 cellPngDecExtReadHeader(PHandle handle, PStream stream, PInfo info, PExtInfo extInfo)
{
	cellPngDec.warning("cellPngDecExtReadHeader(handle=*0x%x, stream=*0x%x, info=*0x%x, extInfo=*0x%x)", handle, stream, info, extInfo);
	// Set the reserved value to 0, if passed to the function. (Should this be arg error if they dont pass?)
	if (extInfo)
	{
		extInfo->reserved = 0;
	}

	// lets push what we have so far
	u8* data = static_cast<u8*>(stream->buffer->data.get_ptr()) + stream->buffer->cursor;
	try
	{
		png_process_data(stream->png_ptr, stream->info_ptr, data, stream->buffer->length);
	}
	catch (LibPngCustomException&)
	{
		return CELL_PNGDEC_ERROR_HEADER;
	}

	// lets hope we pushed enough for callback
	pngSetHeader(stream.get_ptr());

	// png doesnt allow empty image, so quick check for 0 verifys if we got the header
	// not sure exactly what should happen if we dont have header, ask for more data with callback?
	if (stream->info.imageWidth == 0)
	{
		fmt::throw_exception("Invalid or not enough data sent to get header");
		return CELL_PNGDEC_ERROR_HEADER;
	}

	// Set the pointer to stream info
	*info = stream->info;
	return CELL_OK;
}
Пример #5
0
void PngReader::feed( size_t length, void const* buffer )
{
    if( setjmp( m_jmpbuf ) )
    {
        throw StrException( m_error );
    }
    png_process_data(
        m_png, m_info, png_bytep( buffer ), length );
}
Пример #6
0
static bool nspng_process_data(struct content *c, const char *data,
			       unsigned int size)
{
	nspng_content *png_c = (nspng_content *)c;
	union content_msg_data msg_data;
	volatile bool ret = true;

	if (png_c->no_process_data) {
		return ret;
	}

	switch (setjmp(png_jmpbuf(png_c->png))) {
	case CBERR_NONE: /* direct return */	
		png_process_data(png_c->png, png_c->info, (uint8_t *)data, size);
		break;

	case CBERR_NOPRE: /* not going to progressive convert */
		png_c->no_process_data = true;
		break;

	default: /* fatal error from library processing png */
		if (png_c->bitmap != NULL) {
			/* A bitmap managed to get created so
			 * operation is past header and possibly some
			 * conversion happened before faliure. 
			 *
			 * In this case keep the partial
			 * conversion. This is usually seen if a png
			 * has been truncated (often jsut lost its
			 * last byte and hence end of image marker)
			 */
			png_c->no_process_data = true;
		} else {
			/* not managed to progress past header, clean
			 * up png conversion and signal the content
			 * error 
			 */
			LOG(("Fatal PNG error during header, error content"));

			png_destroy_read_struct(&png_c->png, &png_c->info, 0);
			png_c->png = NULL;
			png_c->info = NULL;

			msg_data.error = messages_get("PNGError");
			content_broadcast(c, CONTENT_MSG_ERROR, msg_data);

			ret = false;

		}
		break;
	}

	return ret;
}
Пример #7
0
struct fbtk_bitmap *load_bitmap(const char *filename)
{
        BPTR f;
        unsigned char buffer[BUFFER];
        int br;
        int x, y, c;
          
        png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
        info = png_create_info_struct(png);
        
        png_set_progressive_read_fn(png, NULL, info_callback, row_callback, end_callback);
        
        f = Open(filename, MODE_OLDFILE);
        if (!f) {
				Printf("          Unable to open ");
                Printf(filename);
				Printf("\n");
				Close(f);		
                return NULL;
        }
        
        do {
                br = Read(f, buffer, BUFFER);
                if (br > 0) {
                        png_process_data(png, info, buffer, br);
                }
        } while (br > 0);
        
        if (br < 0) {
                Printf("Error reading input: %s\n");
                return NULL;
        }
		
        Close(f);		
		
		struct fbtk_bitmap *bm;

		bm = AllocVec(raw_width*raw_height*4,MEMF_FAST);

		if(bm != NULL)
		{

					bm->width = raw_width;
					bm->height = raw_height;
					bm->pixdata = (uint8_t*) bitmap_data;
					bm->opaque = false;

					return bm;
			
		}
		
        FreeVec (bm);
        return NULL;
}
Пример #8
0
static GstFlowReturn
gst_pngdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
{
  GstPngDec *pngdec = (GstPngDec *) decoder;
  GstFlowReturn ret = GST_FLOW_OK;

  GST_LOG_OBJECT (pngdec, "Got buffer, size=%u",
      (guint) gst_buffer_get_size (frame->input_buffer));

  /* Let libpng come back here on error */
  if (setjmp (png_jmpbuf (pngdec->png))) {
    GST_WARNING_OBJECT (pngdec, "error during decoding");
    ret = GST_FLOW_ERROR;
    goto beach;
  }

  pngdec->current_frame = frame;

  /* Progressive loading of the PNG image */
  if (!gst_buffer_map (frame->input_buffer, &pngdec->current_frame_map,
          GST_MAP_READ)) {
    GST_WARNING_OBJECT (pngdec, "Failed to map input buffer");
    ret = GST_FLOW_ERROR;
    goto beach;
  }

  png_process_data (pngdec->png, pngdec->info,
      pngdec->current_frame_map.data, pngdec->current_frame_map.size);

  if (pngdec->image_ready) {
    if (1) {
      /* Reset ourselves for the next frame */
      gst_pngdec_reset (decoder, TRUE);
      GST_LOG_OBJECT (pngdec, "setting up callbacks for next frame");
      png_set_progressive_read_fn (pngdec->png, pngdec,
          user_info_callback, user_endrow_callback, user_end_callback);
    } else {
      GST_LOG_OBJECT (pngdec, "sending EOS");
      pngdec->ret = GST_FLOW_EOS;
    }
    pngdec->image_ready = FALSE;
  } else {
    /* An error happened and we have to unmap */
    gst_buffer_unmap (pngdec->current_frame->input_buffer,
        &pngdec->current_frame_map);
  }

  ret = pngdec->ret;
beach:

  return ret;
}
Пример #9
0
bool CCodec_PngModule::Input(FXPNG_Context* ctx,
                             const uint8_t* src_buf,
                             uint32_t src_size,
                             CFX_DIBAttribute* pAttribute) {
  if (setjmp(png_jmpbuf(ctx->png_ptr))) {
    if (pAttribute &&
        0 == FXSYS_strcmp(m_szLastError, "Read Header Callback Error")) {
      _png_load_bmp_attribute(ctx->png_ptr, ctx->info_ptr, pAttribute);
    }
    return false;
  }
  png_process_data(ctx->png_ptr, ctx->info_ptr, (uint8_t*)src_buf, src_size);
  return true;
}
Пример #10
0
/* A code fragment that you call as you receive blocks of data */
int inlinepng_process_data(png_bytep buffer, png_uint_32 length) {
  if(Gpng_ptr == 0) {
    png_cleanup();
    return 0;
  };
  
  if (setjmp(png_jmpbuf(Gpng_ptr))) {
    png_destroy_read_struct(&Gpng_ptr, &Ginfo_ptr, (png_infopp)NULL);
    return 1;
  }

  png_process_data(Gpng_ptr, Ginfo_ptr, buffer, length);
  
  return 0;
}
Пример #11
0
/*
 * @brief finish processing apng frame
 * @note uses libpng calls, treats apng data as discrete png images
 */
int apng_ani::_processing_finish()
{
	static ubyte end_sig[12] = {0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130};

	if (_pngp == nullptr || _infop == nullptr) {
		return 1;
	}

	if (setjmp(png_jmpbuf(_pngp))) {
		png_destroy_read_struct(&_pngp, &_infop, 0);
		return 1;
	}

	png_process_data(_pngp, _infop, end_sig, 12);
	png_destroy_read_struct(&_pngp, &_infop, 0);

	return 0;
}
Пример #12
0
    void decode(const Vector<char>& data, bool sizeOnly)
    {
        m_decodingSizeOnly = sizeOnly;

        // We need to do the setjmp here. Otherwise bad things will happen
        if (setjmp(m_png->jmpbuf)) {
            close();
            return;
        }

        // Go ahead and assume we consumed all the data.  If we consume less, the
        // callback will adjust our read offset accordingly.  Do not attempt to adjust the
        // offset after png_process_data returns.
        unsigned offset = m_readOffset;
        unsigned remaining = data.size() - m_readOffset;
        m_readOffset = data.size();
        png_process_data(m_png, m_info, (png_bytep)(data.data()) + offset, remaining);
    }
Пример #13
0
Файл: png.c Проект: Gingar/port
void png_restart(struct cached_image *cimg, unsigned char *data, int length)
{
	png_structp png_ptr;
	png_infop info_ptr;

#ifdef DEBUG
	if (!cimg->decoder)
		internal("decoder NULL in png_restart\n");
#endif /* #ifdef DEBUG */
	png_ptr=((struct png_decoder *)(cimg->decoder))->png_ptr;
	info_ptr=((struct png_decoder *)(cimg->decoder))->info_ptr;
	end_callback_hit=0;
	if (setjmp(png_ptr->jmpbuf)){
		img_end(cimg);
		return;
	}
	png_process_data(png_ptr, info_ptr, data, length);
	if (end_callback_hit) img_end(cimg);
}
Пример #14
0
    bool decode(const SharedBuffer& data, bool sizeOnly)
    {
        m_decodingSizeOnly = sizeOnly;

        // We need to do the setjmp here. Otherwise bad things will happen.
        if (setjmp(JMPBUF(m_png)))
            return m_decoder->setFailed();

        const char* segment;
        while (unsigned segmentLength = data.getSomeData(segment, m_readOffset)) {
            m_readOffset += segmentLength;
            m_currentBufferSize = m_readOffset;
            png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment)), segmentLength);
            if (sizeOnly ? m_decoder->isDecodedSizeAvailable() : m_decoder->frameIsCompleteAtIndex(0))
                return true;
        }

        return false;
    }
Пример #15
0
int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length) {
    png_structp png_ptr = (png_structp) mainprog_ptr->png_ptr;
    png_infop info_ptr = (png_infop) mainprog_ptr->info_ptr;


    /* setjmp() must be called in every function that calls a PNG-reading
     * libpng function */

    if (setjmp(mainprog_ptr->jmpbuf)) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        mainprog_ptr->png_ptr = NULL;
        mainprog_ptr->info_ptr = NULL;
        return 2;
    }


    /* hand off the next chunk of input data to libpng for decoding */

    png_process_data(png_ptr, info_ptr, rawbuf, length);

    return 0;
}
Пример #16
0
    bool decode(const SharedBuffer& data, bool sizeOnly)
    {
        m_decodingSizeOnly = sizeOnly;
        PNGImageDecoder* decoder = static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_png));

        // We need to do the setjmp here. Otherwise bad things will happen.
        if (setjmp(JMPBUF(m_png)))
            return decoder->setFailed();

        const char* segment;
        while (unsigned segmentLength = data.getSomeData(segment, m_readOffset)) {
            m_readOffset += segmentLength;
            m_currentBufferSize = m_readOffset;
            png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment)), segmentLength);
            // We explicitly specify the superclass isSizeAvailable() because we
            // merely want to check if we've managed to set the size, not
            // (recursively) trigger additional decoding if we haven't.
            if (sizeOnly ? decoder->ImageDecoder::isSizeAvailable() : decoder->isComplete())
                return true;
        }
        return false;
    }
Пример #17
0
    virtual int processData(uchar* data, int length)
    {
        if (done)
            return Done;
    
        //This bit takes care of dealing with the libPNG error handling
        if (libPngError)
            return Error;
            
        curLoader = this;                
        if (setjmp(png_jmpbuf(pngReadStruct)))
        {
            curLoader->libPngError = true;
            return Error;
        }

        //OK, now we can actually do work.... Push data to libPNG,
        //it will use callbacks
        //### time limiting?
        png_process_data(pngReadStruct, pngInfoStruct, data, length);
        
        return length;
    }
Пример #18
0
int
process_data(png_structp *png_ptr, png_infop *info_ptr,
   png_bytep buffer, png_uint_32 length)
{
   if (setjmp((*png_ptr)->jmpbuf))
   {
      /* Free the png_ptr and info_ptr memory on error */
      png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
      return ERROR;
   }

   /* this one's new also.  Simply give it chunks of data as
      they arrive from the data stream (in order, of course).
      On Segmented machines, don't give it any more than 64K.
      The library seems to run fine with sizes of 4K, although
      you can give it much less if necessary (I assume you can
      give it chunks of 1 byte, but I haven't tried with less
      than 256 bytes yet).  When this function returns, you may
      want to display any rows that were generated in the row
      callback, if you aren't already displaying them there. */
   png_process_data(*png_ptr, *info_ptr, buffer, length);
   return OK;
}
Пример #19
0
void
nsPNGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
{
  // We use gotos, so we need to declare variables here
  PRUint32 width = 0;
  PRUint32 height = 0;

  NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");

  // If we only want width/height, we don't need to go through libpng
  if (IsSizeDecode()) {

    // Are we done?
    if (mHeaderBytesRead == BYTES_NEEDED_FOR_DIMENSIONS)
      return;

    // Read data into our header buffer
    PRUint32 bytesToRead = NS_MIN(aCount, BYTES_NEEDED_FOR_DIMENSIONS -
                                  mHeaderBytesRead);
    memcpy(mHeaderBuf + mHeaderBytesRead, aBuffer, bytesToRead);
    mHeaderBytesRead += bytesToRead;

    // If we're done now, verify the data and set up the container
    if (mHeaderBytesRead == BYTES_NEEDED_FOR_DIMENSIONS) {

      // Check that the signature bytes are right
      if (memcmp(mHeaderBuf, nsPNGDecoder::pngSignatureBytes, 
                 sizeof(pngSignatureBytes))) {
        PostDataError();
        return;
      }

      // Grab the width and height, accounting for endianness (thanks libpng!)
      width = png_get_uint_32(mHeaderBuf + WIDTH_OFFSET);
      height = png_get_uint_32(mHeaderBuf + HEIGHT_OFFSET);

      // Too big?
      if ((width > MOZ_PNG_MAX_DIMENSION) || (height > MOZ_PNG_MAX_DIMENSION)) {
        PostDataError();
        return;
      }

      // Post our size to the superclass
      PostSize(width, height);
    }
  }

  // Otherwise, we're doing a standard decode
  else {

    // libpng uses setjmp/longjmp for error handling - set the buffer
    if (setjmp(png_jmpbuf(mPNG))) {

      // We might not really know what caused the error, but it makes more
      // sense to blame the data.
      if (!HasError())
        PostDataError();

      png_destroy_read_struct(&mPNG, &mInfo, NULL);
      return;
    }

    // Pass the data off to libpng
    png_process_data(mPNG, mInfo, (unsigned char *)aBuffer, aCount);

  }
}
Пример #20
0
static GstFlowReturn
gst_pngdec_chain (GstPad * pad, GstBuffer * buffer)
{
  GstPngDec *pngdec;
  GstFlowReturn ret = GST_FLOW_OK;

  pngdec = GST_PNGDEC (gst_pad_get_parent (pad));

  GST_LOG_OBJECT (pngdec, "Got buffer, size=%u", GST_BUFFER_SIZE (buffer));

  if (G_UNLIKELY (!pngdec->setup))
    goto not_configured;

  /* Something is going wrong in our callbacks */
  ret = pngdec->ret;
  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
    GST_WARNING_OBJECT (pngdec, "we have a pending return code of %d", ret);
    goto beach;
  }

  /* Let libpng come back here on error */
  if (setjmp (png_jmpbuf (pngdec->png))) {
    GST_WARNING_OBJECT (pngdec, "error during decoding");
    ret = GST_FLOW_ERROR;
    goto beach;
  }

  pngdec->in_timestamp = GST_BUFFER_TIMESTAMP (buffer);
  pngdec->in_duration = GST_BUFFER_DURATION (buffer);

  /* Progressive loading of the PNG image */
  png_process_data (pngdec->png, pngdec->info, GST_BUFFER_DATA (buffer),
      GST_BUFFER_SIZE (buffer));

  if (pngdec->image_ready) {
    if (pngdec->framed) {
      /* Reset ourselves for the next frame */
      gst_pngdec_libpng_clear (pngdec);
      gst_pngdec_libpng_init (pngdec);
      GST_LOG_OBJECT (pngdec, "setting up callbacks for next frame");
      png_set_progressive_read_fn (pngdec->png, pngdec,
          user_info_callback, user_endrow_callback, user_end_callback);
    } else {
      GST_LOG_OBJECT (pngdec, "sending EOS");
      pngdec->ret = gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ());
    }
    pngdec->image_ready = FALSE;
  }

  /* grab new return code */
  ret = pngdec->ret;

  /* And release the buffer */
  gst_buffer_unref (buffer);

beach:
  gst_object_unref (pngdec);

  return ret;

  /* ERRORS */
not_configured:
  {
    GST_LOG_OBJECT (pngdec, "we are not configured yet");
    ret = GST_FLOW_WRONG_STATE;
    goto beach;
  }
}
Пример #21
0
s32 pngDecOpen(ppu_thread& ppu, PHandle handle, PPStream png_stream, PSrc source, POpenInfo open_info, PCbControlStream control_stream = vm::null, POpenParam open_param = vm::null)
{
	// partial decoding only supported with buffer type
	if (source->srcSelect != CELL_PNGDEC_BUFFER && control_stream)
	{
		cellPngDec.error("Attempted partial image decode with file.");
		return CELL_PNGDEC_ERROR_STREAM_FORMAT;
	}

	// Allocate memory for the stream structure
	auto stream = vm::ptr<PngStream>::make(handle->malloc_(ppu, sizeof(PngStream), handle->malloc_arg).addr());

	// Check if the allocation of memory for the stream structure failed
	if (!stream)
	{
		cellPngDec.error("PNG stream creation failed.");
		return CELL_PNGDEC_ERROR_FATAL;
	}

	// Set memory info
	open_info->initSpaceAllocated = sizeof(PngStream);

	// Set the stream source to the source give by the game
	stream->source = *source;

	// Use virtual memory address as a handle
	*png_stream = stream;

	// Allocate memory for the PNG buffer for decoding
	auto buffer = vm::ptr<PngBuffer>::make(handle->malloc_(ppu, sizeof(PngBuffer), handle->malloc_arg).addr());

	// Check for if the buffer structure allocation failed
	if (!buffer)
	{
		fmt::throw_exception("Memory allocation for the PNG buffer structure failed." HERE);
	}

	// We might not be reading from a file stream
	buffer->file = false;

	// Set the buffer pointer in the stream structure, so we can later deallocate it
	stream->buffer = buffer;

	// Open the buffer/file and check the header
	u8 header[8];

	// Need to test it somewhere
	if (stream->source.fileOffset != 0)
	{
		fmt::throw_exception("Non-0 file offset not supported." HERE);
	}

	// Depending on the source type, get the first 8 bytes
	if (source->srcSelect == CELL_PNGDEC_FILE)
	{
		// Open a file stream
		fs::file file_stream(vfs::get(stream->source.fileName.get_ptr()));

		// Check if opening of the PNG file failed
		if (!file_stream)
		{
			cellPngDec.error("Opening of PNG failed. (%s)", stream->source.fileName.get_ptr());
			return CELL_PNGDEC_ERROR_OPEN_FILE;
		}

		// Read the header
		if (file_stream.read(header, 8) != 8)
		{
			cellPngDec.error("PNG header is too small.");
			return CELL_PNGDEC_ERROR_HEADER;
		}

		// Get the file descriptor
		buffer->fd = idm::make<lv2_fs_object, lv2_file>(stream->source.fileName.get_ptr(), std::move(file_stream), 0, 0);

		// Indicate that we need to read from a file stream
		buffer->file = true;
	}
	else
	{
		// We can simply copy the first 8 bytes
		memcpy(header, stream->source.streamPtr.get_ptr(), 8);
	}

	// Check if the header indicates a valid PNG file
	if (png_sig_cmp(header, 0, 8))
	{
		cellPngDec.error("PNG signature is invalid.");
		return CELL_PNGDEC_ERROR_HEADER;
	}

	// Create a libpng structure, also pass our custom error/warning functions
	stream->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, pngDecError, pngDecWarning);

	// Check if the creation of the structure failed
	if (!stream->png_ptr)
	{
		cellPngDec.error("Creation of png_structp failed.");
		return CELL_PNGDEC_ERROR_FATAL;
	}

	// Create a libpng info structure
	stream->info_ptr = png_create_info_struct(stream->png_ptr);

	// Check if the creation of the structure failed
	if (!stream->info_ptr)
	{
		fmt::throw_exception("Creation of png_infop failed." HERE);
	}

	// We must indicate, that we allocated more memory
	open_info->initSpaceAllocated += sizeof(PngBuffer);

	if (source->srcSelect == CELL_PNGDEC_BUFFER)
	{
		buffer->length = stream->source.streamSize;
		buffer->data = stream->source.streamPtr;
		buffer->cursor = 8;
	}

	// Set the custom read function for decoding
	if (control_stream)
	{
		if (open_param && open_param->selectChunk != 0)
			fmt::throw_exception("Partial Decoding with selectChunk not supported yet.");

		stream->cbCtrlStream.cbCtrlStrmArg = control_stream->cbCtrlStrmArg;
		stream->cbCtrlStream.cbCtrlStrmFunc = control_stream->cbCtrlStrmFunc;

		png_set_progressive_read_fn(stream->png_ptr, (void *)stream.get_ptr(), pngDecInfoCallback, pngDecRowCallback, pngDecEndCallback);

		// push header tag to libpng to keep us in sync
		try
		{
			png_process_data(stream->png_ptr, stream->info_ptr, header, 8);
		}
		catch (LibPngCustomException&)
		{
			return CELL_PNGDEC_ERROR_HEADER;
		}
	}
	else
	{
		png_set_read_fn(stream->png_ptr, buffer.get_ptr(), pngDecReadBuffer);

		// We need to tell libpng, that we already read 8 bytes
		png_set_sig_bytes(stream->png_ptr, 8);
	}

	return CELL_OK;
}
Пример #22
0
s32 pngDecodeData(ppu_thread& ppu, PHandle handle, PStream stream, vm::ptr<u8> data, PDataControlParam data_control_param, PDataOutInfo data_out_info, PCbControlDisp cb_control_disp = vm::null, PDispParam disp_param = vm::null)
{
	// Indicate, that the PNG decoding is stopped/failed. This is incase, we return an error code in the middle of decoding
	data_out_info->status = CELL_PNGDEC_DEC_STATUS_STOP;

	const u32 bytes_per_line = data_control_param->outputBytesPerLine;

	// Log this for now
	if (bytes_per_line < stream->out_param.outputWidthByte)
	{
		fmt::throw_exception("Bytes per line less than expected output! Got: %d, expected: %d" HERE, bytes_per_line, stream->out_param.outputWidthByte);
	}

	// partial decoding
	if (cb_control_disp && stream->outputCounts > 0)
	{
		// get data from cb
		auto streamInfo = vm::ptr<CellPngDecStrmInfo>::make(handle->malloc_(ppu, sizeof(CellPngDecStrmInfo), handle->malloc_arg).addr());
		auto streamParam = vm::ptr<CellPngDecStrmParam>::make(handle->malloc_(ppu, sizeof(CellPngDecStrmParam), handle->malloc_arg).addr());
		stream->cbDispInfo = vm::ptr<CellPngDecDispInfo>::make(handle->malloc_(ppu, sizeof(CellPngDecDispInfo), handle->malloc_arg).addr());
		stream->cbDispParam = vm::ptr<CellPngDecDispParam>::make(handle->malloc_(ppu, sizeof(CellPngDecDispParam), handle->malloc_arg).addr());

		auto freeMem = [&]()
		{
			handle->free_(ppu, streamInfo, handle->free_arg);
			handle->free_(ppu, streamParam, handle->free_arg);
			handle->free_(ppu, stream->cbDispInfo, handle->free_arg);
			handle->free_(ppu, stream->cbDispParam, handle->free_arg);
		};

		// set things that won't change between callbacks
		stream->cbDispInfo->outputFrameWidthByte = bytes_per_line;
		stream->cbDispInfo->outputFrameHeight = stream->out_param.outputHeight;
		stream->cbDispInfo->outputWidthByte = stream->out_param.outputWidthByte;
		stream->cbDispInfo->outputBitDepth = stream->out_param.outputBitDepth;
		stream->cbDispInfo->outputComponents = stream->out_param.outputComponents;
		stream->cbDispInfo->outputHeight = stream->outputCounts;
		stream->cbDispInfo->outputStartXByte = 0;
		stream->cbDispInfo->outputStartY = 0;
		stream->cbDispInfo->scanPassCount = 0;
		stream->cbDispInfo->nextOutputStartY = 0;

		stream->ppuContext = &ppu;
		stream->nextRow = stream->cbDispInfo->outputHeight;
		stream->cbCtrlDisp.cbCtrlDispArg = cb_control_disp->cbCtrlDispArg;
		stream->cbCtrlDisp.cbCtrlDispFunc = cb_control_disp->cbCtrlDispFunc;

		stream->cbDispParam->nextOutputImage = disp_param->nextOutputImage;

		streamInfo->decodedStrmSize = stream->buffer->cursor;
		// push the rest of the buffer we have
		if (stream->buffer->length > stream->buffer->cursor)
		{
			u8* data = static_cast<u8*>(stream->buffer->data.get_ptr()) + stream->buffer->cursor;
			try
			{
				png_process_data(stream->png_ptr, stream->info_ptr, data, stream->buffer->length - stream->buffer->cursor);
			}
			catch (LibPngCustomException&)
			{
				freeMem();
				return CELL_PNGDEC_ERROR_FATAL;
			}
			streamInfo->decodedStrmSize = stream->buffer->length;
		}

		// todo: commandPtr
		// then just loop until the end, the callbacks should take care of the rest
		while (stream->endOfFile != true)
		{
			stream->cbCtrlStream.cbCtrlStrmFunc(ppu, streamInfo, streamParam, stream->cbCtrlStream.cbCtrlStrmArg);
			streamInfo->decodedStrmSize += streamParam->strmSize;
			try
			{
				png_process_data(stream->png_ptr, stream->info_ptr, static_cast<u8*>(streamParam->strmPtr.get_ptr()), streamParam->strmSize);
			}
			catch (LibPngCustomException&)
			{
				freeMem();
				return CELL_PNGDEC_ERROR_FATAL;
			}
		}

		freeMem();
	}
	else
	{
		// Check if the image needs to be flipped
		const bool flip = stream->out_param.outputMode == CELL_PNGDEC_BOTTOM_TO_TOP;

		// Decode the image
		// todo: commandptr
		try
		{
			for (int j = 0; j < stream->passes; j++)
			{
				for (int i = 0; i < stream->out_param.outputHeight; ++i)
				{
					const u32 line = flip ? stream->out_param.outputHeight - i - 1 : i;
					png_read_row(stream->png_ptr, &data[line*bytes_per_line], nullptr);
				}
			}
			png_read_end(stream->png_ptr, stream->info_ptr);
		}
		catch (LibPngCustomException&)
		{
			return CELL_PNGDEC_ERROR_FATAL;
		}
	}

	// Get the number of iTXt, tEXt and zTXt chunks
	const s32 text_chunks = png_get_text(stream->png_ptr, stream->info_ptr, nullptr, nullptr);

	// Set the chunk information and the previously obtained number of text chunks
	data_out_info->numText = (u32)text_chunks;
	data_out_info->chunkInformation = pngDecGetChunkInformation(stream.get_ptr(), true);
	png_unknown_chunkp unknowns;
	const int num_unknowns = png_get_unknown_chunks(stream->png_ptr, stream->info_ptr, &unknowns);
	data_out_info->numUnknownChunk = num_unknowns;

	// Indicate that the decoding succeeded
	data_out_info->status = CELL_PNGDEC_DEC_STATUS_FINISH;

	return CELL_OK;
}
Пример #23
0
/*
 * @brief process apng data chunks
 * @note uses libpng calls, treats apng data as discrete png images
 */
void apng_ani::_processing_data(ubyte* data, uint size)
{
	png_process_data(_pngp, _infop, data, size);
}
Пример #24
0
static gboolean
gdk_pixbuf__png_image_load_increment(gpointer context,
                                     const guchar *buf, guint size,
                                     GError **error)
{
        LoadContext* lc = context;

        g_return_val_if_fail(lc != NULL, FALSE);

        /* reset */
        lc->first_row_seen_in_chunk = -1;
        lc->last_row_seen_in_chunk = -1;
        lc->first_pass_seen_in_chunk = -1;
        lc->last_pass_seen_in_chunk = -1;
        lc->max_row_seen_in_chunk = -1;
        lc->error = error;
        
        /* Invokes our callbacks as needed */
	if (setjmp (png_jmpbuf(lc->png_read_ptr))) {
                lc->error = NULL;
		return FALSE;
	} else {
		png_process_data(lc->png_read_ptr, lc->png_info_ptr,
                                 (guchar*) buf, size);
	}

        if (lc->fatal_error_occurred) {
                lc->error = NULL;
                return FALSE;
        } else {
                if (lc->first_row_seen_in_chunk >= 0 && lc->update_func) {
                        /* We saw at least one row */
                        gint pass_diff = lc->last_pass_seen_in_chunk - lc->first_pass_seen_in_chunk;
                        
                        g_assert(pass_diff >= 0);
                        
                        if (pass_diff == 0) {
                                /* start and end row were in the same pass */
                                (lc->update_func)(lc->pixbuf, 0,
                                                  lc->first_row_seen_in_chunk,
                                                  lc->pixbuf->width,
                                                  (lc->last_row_seen_in_chunk -
                                                   lc->first_row_seen_in_chunk) + 1,
						  lc->notify_user_data);
                        } else if (pass_diff == 1) {
                                /* We have from the first row seen to
                                   the end of the image (max row
                                   seen), then from the top of the
                                   image to the last row seen */
                                /* first row to end */
                                (lc->update_func)(lc->pixbuf, 0,
                                                  lc->first_row_seen_in_chunk,
                                                  lc->pixbuf->width,
                                                  (lc->max_row_seen_in_chunk -
                                                   lc->first_row_seen_in_chunk) + 1,
						  lc->notify_user_data);
                                /* top to last row */
                                (lc->update_func)(lc->pixbuf,
                                                  0, 0, 
                                                  lc->pixbuf->width,
                                                  lc->last_row_seen_in_chunk + 1,
						  lc->notify_user_data);
                        } else {
                                /* We made at least one entire pass, so update the
                                   whole image */
                                (lc->update_func)(lc->pixbuf,
                                                  0, 0, 
                                                  lc->pixbuf->width,
                                                  lc->max_row_seen_in_chunk + 1,
						  lc->notify_user_data);
                        }
                }

                lc->error = NULL;
                
                return TRUE;
        }
}
Пример #25
0
void
nsPNGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
{
  MOZ_ASSERT(!HasError(), "Shouldn't call WriteInternal after error!");

  // If we only want width/height, we don't need to go through libpng
  if (IsSizeDecode()) {

    // Are we done?
    if (mHeaderBytesRead == BYTES_NEEDED_FOR_DIMENSIONS) {
      return;
    }

    // Scan the header for the width and height bytes
    uint32_t pos = 0;
    const uint8_t* bptr = (uint8_t*)aBuffer;

    while (pos < aCount && mHeaderBytesRead < BYTES_NEEDED_FOR_DIMENSIONS) {
      // Verify the signature bytes
      if (mHeaderBytesRead < sizeof(pngSignatureBytes)) {
        if (bptr[pos] != nsPNGDecoder::pngSignatureBytes[mHeaderBytesRead]) {
          PostDataError();
          return;
        }
      }

      // Get width and height bytes into the buffer
      if ((mHeaderBytesRead >= WIDTH_OFFSET) &&
          (mHeaderBytesRead < BYTES_NEEDED_FOR_DIMENSIONS)) {
        mSizeBytes[mHeaderBytesRead - WIDTH_OFFSET] = bptr[pos];
      }
      pos ++;
      mHeaderBytesRead ++;
    }

    // If we're done now, verify the data and set up the container
    if (mHeaderBytesRead == BYTES_NEEDED_FOR_DIMENSIONS) {

      // Grab the width and height, accounting for endianness (thanks libpng!)
      uint32_t width = png_get_uint_32(mSizeBytes);
      uint32_t height = png_get_uint_32(mSizeBytes + 4);

      // Too big?
      if ((width > MOZ_PNG_MAX_DIMENSION) || (height > MOZ_PNG_MAX_DIMENSION)) {
        PostDataError();
        return;
      }

      // Post our size to the superclass
      PostSize(width, height);
    }

  // Otherwise, we're doing a standard decode
  } else {

    // libpng uses setjmp/longjmp for error handling - set the buffer
    if (setjmp(png_jmpbuf(mPNG))) {

      // We might not really know what caused the error, but it makes more
      // sense to blame the data.
      if (!HasError()) {
        PostDataError();
      }

      png_destroy_read_struct(&mPNG, &mInfo, nullptr);
      return;
    }

    // Pass the data off to libpng
    png_process_data(mPNG, mInfo, (unsigned char*)aBuffer, aCount);

  }
}