static void _png_read(png_structp png_ptr, png_bytep data, png_size_t length) { struct _bb* p = static_cast<struct _bb*>(png_get_io_ptr(png_ptr)); const UT_Byte* pBytes = p->pBB->getPointer(0); // make sure that we don't read outside of pBytes if (p->iCurPos >= p->pBB->getLength() - length) { UT_WARNINGMSG(("PNG: Reading past buffer bounds. cur = %u, buflen = %u, length = %lu\n", p->iCurPos, p->pBB->getLength(), length)); length = p->pBB->getLength() - p->iCurPos; if (length == 0) { UT_WARNINGMSG(("PNG: Truncating to ZERO length.\n")); png_error(png_ptr, "Premature end of buffer"); return; } else { UT_WARNINGMSG(("PNG: Truncating to %lu.\n", length)); } } memcpy(data, pBytes + p->iCurPos, length); p->iCurPos += length; }
static void caerLibPNGWriteBuffer(png_structp png_ptr, png_bytep data, png_size_t length) { struct mem_encode *p = (struct mem_encode *) png_get_io_ptr(png_ptr); size_t nsize = p->size + length; // Allocate or grow buffer as needed. if (p->buffer) { p->buffer = realloc(p->buffer, nsize); } else { p->buffer = malloc(nsize); } if (p->buffer == NULL) { png_error(png_ptr, "Write Buffer Error"); return; } // Copy the new bytes to the end of the buffer. memcpy(p->buffer + p->size, data, length); p->size += length; }
void PngReader::PngRabi::MemoryCallback(png_structp png_ptr, png_bytep outBytes, png_size_t byteCountToRead) { MemoryBuffer* from = reinterpret_cast<MemoryBuffer*>(png_get_io_ptr(png_ptr)); if (!from->ok_) { return; } if (from->pos_ + byteCountToRead > from->size_) { from->ok_ = false; return; } memcpy(outBytes, from->buffer_ + from->pos_, byteCountToRead); from->pos_ += byteCountToRead; }
static void user_end_callback (png_structp png_ptr, png_infop info) { GstPngDec *pngdec = NULL; pngdec = GST_PNGDEC (png_get_io_ptr (png_ptr)); GST_LOG_OBJECT (pngdec, "and we are done reading this image"); if (!pngdec->current_frame->output_buffer) return; gst_buffer_unmap (pngdec->current_frame->input_buffer, &pngdec->current_frame_map); pngdec->ret = gst_video_decoder_finish_frame (GST_VIDEO_DECODER (pngdec), pngdec->current_frame); pngdec->image_ready = TRUE; }
static void read_data(png_structp png_ptr, png_bytep data, png_size_t length) { png_size_t check; FILE *fp; if (png_ptr == NULL ) return; fp = (FILE *) png_get_io_ptr(png_ptr); if ( fp == NULL ) return; /* fread() returns 0 on error, so it is OK to store this in a png_size_t * instead of an int, which is what fread() actually returns. */ check = fread(data, 1, length, fp); if (check != length) G_fatal_error(_("Unable to read PNG")); }
static void user_info_callback (png_structp png_ptr, png_infop info) { GstPngDec *pngdec = NULL; GstFlowReturn ret = GST_FLOW_OK; size_t buffer_size; GstBuffer *buffer = NULL; pngdec = GST_PNGDEC (png_get_io_ptr (png_ptr)); GST_LOG ("info ready"); /* Generate the caps and configure */ ret = gst_pngdec_caps_create_and_set (pngdec); if (ret != GST_FLOW_OK) { goto beach; } /* Allocate output buffer */ pngdec->rowbytes = png_get_rowbytes (pngdec->png, pngdec->info); if (pngdec->rowbytes > (G_MAXUINT32 - 3) || pngdec->height > G_MAXUINT32 / pngdec->rowbytes) { ret = GST_FLOW_ERROR; goto beach; } pngdec->rowbytes = GST_ROUND_UP_4 (pngdec->rowbytes); buffer_size = pngdec->height * pngdec->rowbytes; ret = gst_pad_alloc_buffer_and_set_caps (pngdec->srcpad, GST_BUFFER_OFFSET_NONE, buffer_size, GST_PAD_CAPS (pngdec->srcpad), &buffer); if (ret != GST_FLOW_OK) { goto beach; } pngdec->buffer_out = buffer; beach: pngdec->ret = ret; }
/* * Chunk handler */ static void opng_handle_chunk(png_structp png_ptr, png_bytep chunk_type) { if (opng_is_image_chunk(chunk_type)) return; struct opng_codec_context * context = (struct opng_codec_context *)png_get_io_ptr(png_ptr); struct opng_encoding_stats * stats = context->stats; /* Bypass the chunks that are intended to be stripped. */ if (opng_transform_query_strip_chunk(context->transformer, chunk_type)) { char debug_chunk_name[5]; memcpy(debug_chunk_name, chunk_type, 4); debug_chunk_name[4] = (char)0; if (opng_is_apng_chunk(chunk_type)) { /*printf("Snipping: %s\n", debug_chunk_name);*/ stats->flags |= OPNG_HAS_SNIPPED_IMAGES; } else { /*printf("Stripping: %s\n", debug_chunk_name);*/ stats->flags |= OPNG_HAS_STRIPPED_METADATA; } opng_set_keep_unknown_chunk(png_ptr, PNG_HANDLE_CHUNK_NEVER, chunk_type); return; } /* Let libpng handle bKGD, hIST and sBIT. */ if (memcmp(chunk_type, opng_sig_bKGD, 4) == 0 || memcmp(chunk_type, opng_sig_hIST, 4) == 0 || memcmp(chunk_type, opng_sig_sBIT, 4) == 0) return; /* Everything else is handled as unknown by libpng. */ if (memcmp(chunk_type, opng_sig_dSIG, 4) == 0) stats->flags |= OPNG_HAS_DIGITAL_SIGNATURE; else if (memcmp(chunk_type, opng_sig_fdAT, 4) == 0) stats->flags |= OPNG_HAS_MULTIPLE_IMAGES; opng_set_keep_unknown_chunk(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, chunk_type); }
void png_data_write_func(png_structp png_ptr, png_bytep buf, png_size_t size) { my_png_buffer *png_buff = (my_png_buffer *)png_get_io_ptr(png_ptr); unsigned long new_data_len; unsigned char *tmp; if (png_buff->data_offset + size > png_buff->data_len) { new_data_len = 2 * png_buff->data_len; if (png_buff->data_offset + size > new_data_len) { new_data_len = png_buff->data_offset + size; } tmp = realloc(png_buff->data, new_data_len); if (tmp == NULL) { fprintf(stderr, "png_data_write_func: can't realloc: new_data_len(%lu), data_len(%lu)\n", new_data_len, png_buff->data_len); png_error(png_ptr,"png_data_write_func failed"); } png_buff->data = tmp; png_buff->data_len = new_data_len; } memcpy(png_buff->data + png_buff->data_offset, buf, size); png_buff->data_offset += size; }
void loadPNGEx_user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { loadPNGExData *lPEd = (loadPNGExData *)png_get_io_ptr(png_ptr); // check requested length if ((int)length > lPEd->bufLength - lPEd->bufPos) { cprintf("loadPNGEx_user_read_data(): too much data requested by libpng, padding with 0\n"); memset(data + lPEd->bufLength - lPEd->bufPos, 0, length - (lPEd->bufLength - lPEd->bufPos)); length = lPEd->bufLength - lPEd->bufPos; } // copy data memcpy(data, lPEd->buf + lPEd->bufPos, length); // update structure lPEd->bufPos += (int)length; //return length; return; }
void tarpng_read_data(png_structp read_ptr, png_bytep data, png_size_t length) { /* Get the animation archive. */ struct archive *animarc; animarc = (struct archive *)png_get_io_ptr(read_ptr); /* printf("%d bytes requested\n", length); */ int res; res = archive_read_data(animarc, data, length); /* If the result is zero then no more data. If the result is FATAL, WARN, * or RETRY there was a problem. If the value is > 1 then it wrote that * many bytes. */ if (res == 0) { printf("EOF\n"); } else if (res == ARCHIVE_FATAL || res == ARCHIVE_WARN || res == ARCHIVE_RETRY) { png_error(read_ptr, "Read Error!\n"); printf("Read error!\n"); /* set error and end */ } else if ( res > 1) { /* printf("Read %d bytes.\n",res); */ } }
void PngEncoder::png_chunk_producer(png_structp png_ptr, png_bytep data, png_size_t length) { PngEncoder *p = (PngEncoder *)png_get_io_ptr(png_ptr); if (!p->png) { p->png = (char *)malloc(sizeof(p->png)*41); // from tests pngs are at least 41 bytes if (!p->png) throw "malloc failed in node-png (PngEncoder::png_chunk_producer)"; p->mem_len = 41; } if (p->png_len + length > p->mem_len) { char *new_png = (char *)realloc(p->png, sizeof(char)*p->png_len + length); if (!new_png) throw "realloc failed in node-png (PngEncoder::png_chunk_producer)."; p->png = new_png; p->mem_len += length; } memcpy(p->png + p->png_len, data, length); p->png_len += length; }
static VALUE write_png2(VALUE *args) { struct io_write *data; png_structp png_ptr = (png_structp)args[0]; png_infop info_ptr = (png_infop)args[1]; VALUE scanline, image_in = args[2]; size_t i; write_configure(image_in, png_ptr, info_ptr); png_write_info(png_ptr, info_ptr); for (i = 0; i < png_get_image_height(png_ptr, info_ptr); i++) { scanline = rb_funcall(image_in, id_gets, 0); write_scanline(scanline, png_ptr, info_ptr); } png_write_end(png_ptr, info_ptr); data = (struct io_write *)png_get_io_ptr(png_ptr); return INT2FIX(data->total); }
static void user_endrow_callback (png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass) { GstPngDec *pngdec = NULL; pngdec = GST_PNGDEC (png_get_io_ptr (png_ptr)); /* FIXME: implement interlaced pictures */ /* If buffer_out doesn't exist, it means buffer_alloc failed, which * will already have set the return code */ if (GST_IS_BUFFER (pngdec->buffer_out)) { size_t offset = row_num * pngdec->rowbytes; GST_LOG ("got row %u, copying in buffer %p at offset %" G_GSIZE_FORMAT, (guint) row_num, pngdec->buffer_out, offset); memcpy (GST_BUFFER_DATA (pngdec->buffer_out) + offset, new_row, pngdec->rowbytes); pngdec->ret = GST_FLOW_OK; } }
static void CALLBACK_CALL_TYPE iod_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) { QPngHandlerPrivate *d = (QPngHandlerPrivate *)png_get_io_ptr(png_ptr); QIODevice *in = d->q->device(); if (d->state == QPngHandlerPrivate::ReadingEnd && !in->isSequential() && (in->size() - in->pos()) < 4 && length == 4) { // Workaround for certain malformed PNGs that lack the final crc bytes uchar endcrc[4] = { 0xae, 0x42, 0x60, 0x82 }; qMemCopy(data, endcrc, 4); in->seek(in->size()); return; } while (length) { int nr = in->read((char*)data, length); if (nr <= 0) { png_error(png_ptr, "Read Error"); return; } length -= nr; } }
/* libpng calls this (at read_png_data's request) * to copy data from the in-RAM PNG into our bitmap */ void read_cb (png_structp png_ptr, png_bytep outBytes, png_size_t byteCountToRead) { struct bufdata * bd = png_get_io_ptr(png_ptr); //pthread_mutex_lock(&lock_read_cb); if (bd == NULL) abort_("[read_png_file/read_cb] invalid memory passed to png reader"); if (bd->pos + byteCountToRead >= bd->len) { #ifdef _DEBUG_1_ printf("\nError (read_cb): bd->pos: %d, byteCountToRead: %d, bd->len: %d\n", bd->pos, byteCountToRead, bd->len); fflush(stdout); #endif abort_("[read_png_file/read_cb] attempting to read beyond end of buffer"); } #ifdef _DEBUG_1_ //printf("\read_cb: bd->pos: %d, byteCountToRead: %d, bd->len: %d\n", bd->pos, byteCountToRead, bd->len); //fflush(stdout); #endif memcpy(outBytes, bd->buf+bd->pos, byteCountToRead); bd->pos += byteCountToRead; //pthread_mutex_unlock(&lock_read_cb); }
static void pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { png_size_t check; png_byte *n_data; png_FILE_p io_ptr; /* Check if data really is near. If so, use usual code. */ n_data = (png_byte *)CVT_PTR_NOCHECK(data); io_ptr = (png_FILE_p)CVT_PTR(png_get_io_ptr(png_ptr)); if ((png_bytep)n_data == data) { check = fread(n_data, 1, length, io_ptr); } else { png_byte buf[NEAR_BUF_SIZE]; png_size_t read, remaining, err; check = 0; remaining = length; do { read = MIN(NEAR_BUF_SIZE, remaining); err = fread(buf, 1, 1, io_ptr); png_memcpy(data, buf, read); /* Copy far buffer to near buffer */ if (err != read) break; else check += err; data += read; remaining -= read; } while (remaining != 0); } if (check != length) png_error(png_ptr, "read Error"); }
void read_data_fn(png_structp png_ptr, png_bytep data, png_size_t length) { VALUE io, str; size_t read_len; if (png_ptr == NULL) return; io = (VALUE)png_get_io_ptr(png_ptr); str = rb_funcall(io, id_read, 1, INT2FIX(length)); if (NIL_P(str)) rb_raise(rb_eRuntimeError, "Read Error. Reader returned nil."); StringValue(str); read_len = RSTRING_LEN(str); if (read_len != length) rb_raise(rb_eRuntimeError, "Read Error. Read %d instead of %d bytes.", (int)read_len, (int)length); memcpy(data, RSTRING_PTR(str), length); }
// Custom read function for libpng, so we could decode images from a buffer void pngDecReadBuffer(png_structp png_ptr, png_bytep out, png_size_t length) { // Get the IO pointer png_voidp io_ptr = png_get_io_ptr(png_ptr); // Check if obtaining of the IO pointer failed if (!io_ptr) { cellPngDec.error("Failed to obtain the io_ptr failed."); return; } // Cast the IO pointer to our custom structure PngBuffer& buffer = *(PngBuffer*)io_ptr; // Read froma file or a buffer if (buffer.file) { // Get the file auto file = idm::get<lv2_file_t>(buffer.fd); // Read the data file->file.read(out, length); } else { // Get the current data pointer, including the current cursor position void* data = static_cast<u8*>(buffer.data.get_ptr()) + buffer.cursor; // Copy the length of the current data pointer to the output memcpy(out, data, length); // Increment the cursor for the next time buffer.cursor += length; } }
static void user_write_data (png_structp png_ptr, png_bytep data, png_uint_32 length) { GstPngEnc *pngenc; GstMapInfo map; pngenc = (GstPngEnc *) png_get_io_ptr (png_ptr); gst_buffer_map (pngenc->buffer_out, &map, GST_MAP_WRITE); if (pngenc->written + length >= map.size) { gst_buffer_unmap (pngenc->buffer_out, &map); GST_ERROR_OBJECT (pngenc, "output buffer bigger than the input buffer!?"); png_error (png_ptr, "output buffer bigger than the input buffer!?"); /* never reached */ return; } GST_DEBUG_OBJECT (pngenc, "writing %u bytes", (guint) length); memcpy (map.data + pngenc->written, data, length); gst_buffer_unmap (pngenc->buffer_out, &map); pngenc->written += length; }
void PNGReadCallback(png_structp PNGPtr, png_bytep outBytes, png_size_t byteCountToRead) { PNGVectorStream *stream = reinterpret_cast<PNGVectorStream*>(png_get_io_ptr(PNGPtr)); if (stream == nullptr) { // TODO: Error handling. outBytes = nullptr; return; } if (stream->offset + byteCountToRead > stream->vec->size()) { // TODO: Error handling. stream->offset = stream->vec->size(); outBytes = nullptr; return; } memcpy(outBytes, &(*stream->vec)[stream->offset], byteCountToRead); // outBytes = &(*stream->vec)[stream->offset]; stream->offset += byteCountToRead; }
void GameWindow::captureToFile(const std::string& path, GameRenderer* renderer) { Logger log; std::ofstream file(path); if (!file.is_open()) { log.error("Game", "Could not open screenshot file!"); return; } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); png_infop info_ptr = png_create_info_struct(png_ptr); png_set_write_fn(png_ptr, &file, { [](png_structp png_ptr, png_bytep data, png_size_t length) { reinterpret_cast<std::ofstream*>(png_get_io_ptr(png_ptr))-> write(reinterpret_cast<char*>(data), length); } }, { [](png_structp) { } } ); auto size = getSize(); png_set_IHDR(png_ptr, info_ptr, size.x, size.y, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); unsigned char* buffer = renderer->getRenderer()->readPixels(size); for (int y = size.y-1; y >= 0; y--) png_write_row(png_ptr, &buffer[y * size.x * 3]); png_write_end(png_ptr, nullptr); png_destroy_write_struct(&png_ptr, &info_ptr); delete[] buffer; }
int begin(char* base_file_name, unsigned char *png_buf, long long png_length) { MY_PNG_READ_OFFSET = 0; PNG_LENGTH = png_length; ENTIRE_PNG_BUF = png_buf; if (png_sig_cmp(ENTIRE_PNG_BUF, 0, 8) != 0) { error(-1, "png_sig_cmp", E_INVALID); return -1; } DEBUG_PRINT(("Initial png size is %lld bytes\n", PNG_LENGTH)); my_png_meta *pm = calloc(1, sizeof(my_png_meta)); my_init_libpng(pm); //If libpng errors, we end up here if (setjmp(png_jmpbuf(pm->read_ptr))) { DEBUG_PRINT(("libpng called setjmp!\n")); my_deinit_libpng(pm); free(ENTIRE_PNG_BUF); error(-1, "libpng", "libpng encountered an error\n"); return -1; } //Normally a file, but instead make it our buffer void *read_io_ptr = png_get_io_ptr(pm->read_ptr); png_set_read_fn(pm->read_ptr, read_io_ptr, my_png_read_fn); //Transform all PNG image types to RGB int transforms = PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_EXPAND; png_read_png(pm->read_ptr, pm->info_ptr, transforms, NULL); //Now that it was read and transformed, its size will differ PNG_LENGTH = 0; //Lets collect our metadata struct ihdr_infos_s ihdr_infos; ihdr_infos.bit_depth = png_get_bit_depth(pm->read_ptr, pm->info_ptr); ihdr_infos.color_type = png_get_color_type(pm->read_ptr, pm->info_ptr); ihdr_infos.filter_method = png_get_filter_type(pm->read_ptr, pm->info_ptr); ihdr_infos.compression_type = png_get_compression_type(pm->read_ptr, pm->info_ptr); ihdr_infos.interlace_type = png_get_interlace_type(pm->read_ptr, pm->info_ptr); ihdr_infos.height = png_get_image_height(pm->read_ptr, pm->info_ptr); ihdr_infos.width = png_get_image_width(pm->read_ptr, pm->info_ptr); if (ihdr_infos.color_type != 2) { DEBUG_PRINT((E_INVALID)); free(ENTIRE_PNG_BUF); my_deinit_libpng(pm); DEBUG_PRINT(("Looks like libpng could not correctly convert to RGB\n")); return -1; } //Just in case we want to enable alpha, etc switch(ihdr_infos.color_type) { case 0: //greyscale case 3: //indexed ihdr_infos.bytes_per_pixel = 1; break; case 4: ihdr_infos.bytes_per_pixel = 2; break; //greyscale w/ alpha case 2: ihdr_infos.bytes_per_pixel = 3; break; //Truecolour (RGB) case 6: ihdr_infos.bytes_per_pixel = 4; break; //Truecolour w/ alpha default: error_fatal(1, "ihdr_infos", "Unknown image type"); //should never happen } ihdr_infos.scanline_len = (ihdr_infos.bytes_per_pixel * ihdr_infos.width) + 1; DEBUG_PRINT(("HEIGHT: %u\n", ihdr_infos.height)); DEBUG_PRINT(("WIDTH: %u\n", ihdr_infos.width)); DEBUG_PRINT(("BIT_DEPTH: %u\n", ihdr_infos.bit_depth)); // Don't compress, since we are merely copying it to memory, // we will be decompressing it again anyway png_set_compression_level(pm->write_ptr, Z_NO_COMPRESSION); void *write_io_ptr = png_get_io_ptr(pm->write_ptr); png_set_write_fn(pm->write_ptr, write_io_ptr, my_png_write_fn, my_png_dummy_flush); //Make sure we use all filters png_set_filter(pm->write_ptr, 0, PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | PNG_FILTER_UP | PNG_FILTER_VALUE_UP | PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH); //Set our comment struct png_text_struct comment_struct; comment_struct.compression = -1; comment_struct.key = " Glitched by pnglitch.xyz "; comment_struct.text = NULL; comment_struct.text_length = 0; png_set_text(pm->write_ptr, pm->info_ptr, &comment_struct, 1); //Buffer is Written using callback my_png_write_fn to buffer //ENTIRE_PNG_BUF. PNG_LENGTH will be updated automatically by it png_write_png(pm->write_ptr, pm->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); my_deinit_libpng(pm); DEBUG_PRINT(("libpng output buf is %lld bytes\n", PNG_LENGTH)); //Now that libpng has converted the image //and we have it in a buffer, we process it by hand with zlib struct z_stream_s inflate_stream; my_init_zlib(&inflate_stream); inflateInit(&inflate_stream); //Pointer to keep track of where we are unsigned char *pngp = ENTIRE_PNG_BUF; //Skip PNG Signature pngp += 8; //Get Header unsigned char ihdr_bytes_buf[4+4+13+4]; // size + label + content + crc buf_read(ihdr_bytes_buf, &pngp, 4+4+13+4); //When we run into non-idat chunks, we will want to preserve them. //The spec says there's no chunk that needs to go after IDAT, //so we can simply concatenate all of these chunks into a buffer //then write them all at once after the IHDR //ancillary chunks, eg comments unsigned char *ancil_chunks_buf = calloc(1,1); long long ancil_chunks_len = 0; unsigned char *unzip_idats_buf = calloc(1, 1); long unzip_buf_len = 1; long unzip_buf_offset = 0; long long zipped_idats_len = 0; //Length of all idats as we read them unsigned long accum_png_len = 8 + (4+4+13+4); int chunk_count = 0; printf("Uncompressing image data...\n"); while (1) { unsigned char chunk_label[4]; unsigned char chunk_len_buf[4]; buf_read(chunk_len_buf, &pngp, 4); //first 4 bytes are the length of data section long chunk_len = four_bytes_to_int(chunk_len_buf); accum_png_len += chunk_len + 4 + 4 + 4; // plus len, crc, label DEBUG_PRINT(("at %lu --> %lld\n", accum_png_len, PNG_LENGTH)); //leave at end of buffer if (accum_png_len >= PNG_LENGTH) break; //read the chunk label (name of this header) buf_read(chunk_label, &pngp, 4); DEBUG_PRINT(("Reading chunk %d with label '%c%c%c%c', size %ld\n", chunk_count, chunk_label[0], chunk_label[1], chunk_label[2], chunk_label[3], chunk_len)); chunk_count += 1; if (memcmp(chunk_label, "IDAT", 4) == 0) { zipped_idats_len += chunk_len; //read the chunk's data section unsigned char *raw_chunk_buf = calloc(chunk_len, 1); buf_read(raw_chunk_buf, &pngp, chunk_len); //Tell inflate to uncompress it inflate_stream.next_in = raw_chunk_buf; inflate_stream.avail_in = chunk_len; //Now uncompress it (resizes buffer automatically) unsigned char *check_uncompress = uncompress_buffer(&inflate_stream, unzip_idats_buf, &unzip_buf_len, &unzip_buf_offset); //Stop if error if (check_uncompress == NULL) { DEBUG_PRINT((E_GLITCH)); free(ancil_chunks_buf); free(raw_chunk_buf); free(unzip_idats_buf); free(ENTIRE_PNG_BUF); return -1; } //Moving on unzip_idats_buf = check_uncompress; free(raw_chunk_buf); pngp += 4; // skip CRC } else { //This is not an idat ancil_chunks_buf = realloc(ancil_chunks_buf, ancil_chunks_len + 4 + 4 + chunk_len + 4); //make room for new data //append length and label bytes append_bytes(ancil_chunks_buf, chunk_len_buf, &ancil_chunks_len, 4); append_bytes(ancil_chunks_buf, chunk_label, &ancil_chunks_len, 4); //append chunk data unsigned char *raw_chunk_buf = calloc(chunk_len, 1); buf_read(raw_chunk_buf, &pngp, chunk_len); append_bytes(ancil_chunks_buf, raw_chunk_buf, &ancil_chunks_len, chunk_len ); //append chunk crc unsigned char chunk_crc_buf[4]; buf_read(chunk_crc_buf, &pngp, 4); append_bytes(ancil_chunks_buf, chunk_crc_buf, &ancil_chunks_len, 4); free(raw_chunk_buf); DEBUG_PRINT(("ancillary chunks length: %lld\n", ancil_chunks_len)); } } //buf contains all idats uncompressed, concatenated unsigned long unzipped_idats_len = inflate_stream.total_out; unzip_idats_buf = realloc(unzip_idats_buf, unzipped_idats_len); //we already have ancillary chunks and idats, don't need the original free(ENTIRE_PNG_BUF); inflateEnd(&inflate_stream); printf("Uncompressed %lld bytes to %ld bytes\n", zipped_idats_len, unzipped_idats_len); printf("Glitching image data...\n"); for (int g=0;g<NUM_OUTPUT_FILES;g++) { //do glitches switch(g) { case 5: glitch_random(unzip_idats_buf, unzipped_idats_len, ihdr_infos.scanline_len, 0.0005); break; case 6: glitch_random_filter(unzip_idats_buf, unzipped_idats_len, ihdr_infos.scanline_len); break; default: glitch_filter(unzip_idats_buf, unzipped_idats_len, ihdr_infos.scanline_len, g); } //recompress so we can write them to file long long glitched_idats_len = 0; unsigned char *glitched_idats = zip_idats(unzip_idats_buf, unzipped_idats_len, &glitched_idats_len); if (glitched_idats == NULL) { DEBUG_PRINT((E_GLITCH)); free (unzip_idats_buf); free (ancil_chunks_buf); return -1; } char path[MAX_PATH_LENGTH]; bzero(path, MAX_PATH_LENGTH); snprintf(path, MAX_PATH_LENGTH, "%s%s%s-%d.png", OUTPUT_DIRECTORY, DIR_SEP, base_file_name, g); DEBUG_PRINT(("Output file name is %s\n", path)); FILE *outfp = fopen(path, "wb"); write_glitched_image(glitched_idats, glitched_idats_len, ihdr_bytes_buf, ancil_chunks_buf, ancil_chunks_len, outfp); printf("%s\n", path); fflush(stdout); fclose(outfp); free(glitched_idats); } free(ancil_chunks_buf); free(unzip_idats_buf); return 0; }
/* read_data: * Custom read function to use Allegro packfile routines, * rather than C streams (so we can read from datafiles!) */ static void read_data(png_structp png_ptr, png_bytep data, png_uint_32 length) { PACKFILE *f = (PACKFILE *)png_get_io_ptr(png_ptr); if ((png_uint_32)pack_fread(data, length, f) != length) png_error(png_ptr, "read error (loadpng calling pack_fread)"); }
// write libpng output to PNG file static void io_write(png_struct* png_ptr, u8* data, png_size_t length) { DynArray* da = (DynArray*)png_get_io_ptr(png_ptr); if(da_append(da, data, length) != 0) png_error(png_ptr, "io_write failed"); }
static void write( png_structp png_ptr, png_bytep data, png_size_t length) { QAnimationWriterMNG* that = (QAnimationWriterMNG*)png_get_io_ptr(png_ptr); /*uint nw =*/ that->dev->writeBlock((const char*)data,length); }
// Note: Calls req.Respond(). Other data can be added afterward. static bool StreamBufferToDataURI(DebuggerRequest &req, const GPUDebugBuffer &buf, bool includeAlpha, int stackWidth) { #ifdef USING_QT_UI req.Fail("Not supported on Qt yet, pull requests accepted"); return false; #else u8 *flipbuffer = nullptr; u32 w = (u32)-1; u32 h = (u32)-1; const u8 *buffer = ConvertBufferToScreenshot(buf, includeAlpha, flipbuffer, w, h); if (!buffer) { req.Fail("Internal error converting buffer for PNG encode"); return false; } if (stackWidth > 0) { u32 totalPixels = w * h; w = stackWidth; while ((totalPixels % w) != 0) --w; h = totalPixels / w; } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!png_ptr) { req.Fail("Internal error setting up PNG encoder (png_ptr)"); return false; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, nullptr); req.Fail("Internal error setting up PNG encoder (info_ptr)"); return false; } // Speed. Wireless N should give 35 KB/ms. For most devices, zlib/filters will cost more. png_set_compression_strategy(png_ptr, Z_RLE); png_set_compression_level(png_ptr, 1); png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE); auto &json = req.Respond(); json.writeInt("width", w); json.writeInt("height", h); // Start a value... json.writeRaw("uri", ""); req.Flush(); // Now we'll write it directly to the stream. req.ws->AddFragment(false, "\"data:image/png;base64,"); struct Context { DebuggerRequest *req; uint8_t buf[3]; size_t bufSize; }; Context ctx = { &req, {}, 0 }; auto write = [](png_structp png_ptr, png_bytep data, png_size_t length) { auto ctx = (Context *)png_get_io_ptr(png_ptr); auto &req = *ctx->req; // If we buffered some bytes, fill to 3 bytes for a clean base64 encode. // This way we don't have padding. while (length > 0 && ctx->bufSize > 0 && ctx->bufSize != 3) { ctx->buf[ctx->bufSize++] = data[0]; data++; length--; } if (ctx->bufSize == 3) { req.ws->AddFragment(false, Base64Encode(ctx->buf, ctx->bufSize)); ctx->bufSize = 0; } assert(ctx->bufSize == 0 || length == 0); // Save bytes that would result in padding for next time. size_t toBuffer = length % 3; for (size_t i = 0; i < toBuffer; ++i) { ctx->buf[i] = data[length - toBuffer + i]; ctx->bufSize++; } if (length > toBuffer) { req.ws->AddFragment(false, Base64Encode(data, length - toBuffer)); } }; auto flush = [](png_structp png_ptr) { // Nothing, just here to prevent stdio flush. }; png_bytep *row_pointers = new png_bytep[h]; u32 stride = includeAlpha ? w * 4 : w * 3; for (u32 i = 0; i < h; ++i) { row_pointers[i] = (u8 *)buffer + stride * i; } png_set_write_fn(png_ptr, &ctx, write, flush); int colorType = includeAlpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, w, h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr); png_destroy_write_struct(&png_ptr, &info_ptr); delete [] row_pointers; delete [] flipbuffer; if (ctx.bufSize > 0) { req.ws->AddFragment(false, Base64Encode(ctx.buf, ctx.bufSize)); ctx.bufSize = 0; } // End the string. req.ws->AddFragment(false, "\""); return true; #endif }
extern "C" void fakeread(png_structp png_ptr, png_bytep data, png_size_t length) { uint8_t **t_data_ptr = (uint8_t**)png_get_io_ptr(png_ptr); memcpy(data, *t_data_ptr, length); *t_data_ptr += length; }
static void PngReadData(png_structp png_ptr, png_bytep data, png_size_t length) { uint8_t** d = (uint8_t**) png_get_io_ptr(png_ptr); memcpy(data, *d, length); (*d) += length; }
void flush_data (png_structp png_ptr) { T * out = static_cast<T*>(png_get_io_ptr(png_ptr)); out->flush(); }
void write_data (png_structp png_ptr, png_bytep data, png_size_t length) { T * out = static_cast<T*>(png_get_io_ptr(png_ptr)); out->write(reinterpret_cast<char*>(data), length); }