void Image::save(const char * path) { png_image pngimage_control; memset(&pngimage_control, 0, sizeof(png_image)); pngimage_control.version = PNG_IMAGE_VERSION; pngimage_control.width = _width; pngimage_control.height = _height; pngimage_control.format = PNG_FORMAT_RGBA; //pngimage_control.flags = PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB; int success = png_image_write_to_file(&pngimage_control, //control str path, //file path 0, //convert_to_8bit _buf, //buffer 0, //row_stride NULL);//colormap if (!success) { fprintf(stderr, "Writing png file failed to path: %s.\n", path); } else { fprintf(stderr, "PNG file saved: %s.\n", path); } }
void png_test(){ png_image image; memset(&image, 0, (sizeof image)); image.version = PNG_IMAGE_VERSION; if(png_image_begin_read_from_file(&image, "data/hex.png")){ png_bytep buffer; image.format = PNG_FORMAT_RGBA; buffer = (png_bytep)malloc(PNG_IMAGE_SIZE(image)); if(buffer != NULL && png_image_finish_read(&image, NULL, buffer, 0, NULL)){ if(png_image_write_to_file(&image, "data/hex.jordan.png",0, buffer, 0, NULL)){ printf("Write was successful. F**k freeing memory\n"); char c; int rs = scanf("%c", &c); exit(0); } } else{ if(buffer == NULL){ png_image_free(&image); } else{ free(buffer); } } } printf("You've f****d up\n"); char c; int rs = scanf("%c", &c); }
int gfwx_PngWriteFile(const char* filename, uint8_t* data, uint32_t width, uint32_t height, uint32_t bytesPerPixel) { int status = -1; int png_status; int row_stride; png_image image; memset(&image, 0, sizeof(png_image)); image.version = PNG_IMAGE_VERSION; image.format = (bytesPerPixel == 4) ? PNG_FORMAT_BGRA : PNG_FORMAT_BGR; image.width = width; image.height = height; row_stride = PNG_IMAGE_ROW_STRIDE(image); png_status = png_image_write_to_file(&image, filename, 0, (const void*) data, row_stride, NULL); if (!png_status) goto exit; status = 1; exit: png_image_free(&image); return status; }
void TakeScreenshot() { g_TakeScreenshot = false; mkDir(g_Config.memCardDirectory + "/PSP/SCREENSHOT"); // First, find a free filename. int i = 0; char temp[256]; while (i < 10000){ if(g_Config.bScreenshotsAsPNG) sprintf(temp, "%s/PSP/SCREENSHOT/screen%05d.png", g_Config.memCardDirectory.c_str(), i); else sprintf(temp, "%s/PSP/SCREENSHOT/screen%05d.jpg", g_Config.memCardDirectory.c_str(), i); FileInfo info; if (!getFileInfo(temp, &info)) break; i++; } // Okay, allocate a buffer. u8 *buffer = new u8[3 * pixel_xres * pixel_yres]; // Silly openGL reads upside down, we flip to another buffer for simplicity. u8 *flipbuffer = new u8[3 * pixel_xres * pixel_yres]; glReadPixels(0, 0, pixel_xres, pixel_yres, GL_RGB, GL_UNSIGNED_BYTE, buffer); for (int y = 0; y < pixel_yres; y++) { memcpy(flipbuffer + y * pixel_xres * 3, buffer + (pixel_yres - y - 1) * pixel_xres * 3, pixel_xres * 3); } if (g_Config.bScreenshotsAsPNG) { png_image png; memset(&png, 0, sizeof(png)); png.version = PNG_IMAGE_VERSION; png.format = PNG_FORMAT_RGB; png.width = pixel_xres; png.height = pixel_yres; png_image_write_to_file(&png, temp, 0, flipbuffer, pixel_xres * 3, NULL); png_image_free(&png); } else { jpge::params params; params.m_quality = 90; compress_image_to_jpeg_file(temp, pixel_xres, pixel_yres, 3, flipbuffer, params); } delete [] buffer; delete [] flipbuffer; osm.Show(temp); }
bool PngHandler::TransPngFormat(const string& srcFilePath, const string& desFilePath, PNG_FORMAT pngFormat) { bool result = false; // 初始化变量 png_image image; memset(&image, 0, (sizeof image)); image.version = PNG_IMAGE_VERSION; // 加载源文件 if (png_image_begin_read_from_file(&image, srcFilePath.c_str()) != 0) { // 设置图片格式 switch (pngFormat) { case PF_GRAY_8BIT: image.format = PNG_FORMAT_GRAY; break; case PF_GRAYALPHA_8BIT: image.format = PNG_FORMAT_GA; break; case PF_RGB_16BIT: image.format = PNG_FORMAT_RGB; break; case PF_RGBALPHA_16BIT: image.format = PNG_FORMAT_RGBA; break; } // 创建buffer png_bytep buffer = NULL; size_t bufferSize = PNG_IMAGE_SIZE(image); buffer = new png_byte[bufferSize]; if (buffer != NULL && png_image_finish_read(&image, NULL, buffer, 0, NULL) != 0) { result = (png_image_write_to_file(&image, desFilePath.c_str(), 0, buffer, 0, NULL) != 0); } delete[] buffer; } return result; }
void PNGWriter::write_file(const std::string &file_name, const Image &image) { png_image pngimage; std::memset(&pngimage, 0, sizeof pngimage); pngimage.version = PNG_IMAGE_VERSION; pngimage.width = image.width(); pngimage.height = image.height(); pngimage.format = PNG_FORMAT_BGRA; if (!png_image_write_to_file(&pngimage, file_name.c_str(), 0, image.buffer().data(), static_cast<png_int_32>(image.stride()), nullptr)) throw Exception(file_name, pngimage.message); }
int mergePng(char * fileBack, char * fileFront, char * fileOut) { //fileBackΪ±³¾°Í¼Æ¬£¬É«²Ê¿Õ¼äΪRGB //fileFrontΪǰ¾°Í¼Æ¬£¬É«²Ê¿Õ¼äΪRGBA //fileOutΪµþ¼ÓͼƬ£¬É«²Ê¿Õ¼äΪRGBA int height = 480; int width = 640; png_image image; memset(&image, 0, sizeof image); image.version = PNG_IMAGE_VERSION; image.format = PNG_FORMAT_RGBA; png_image_begin_read_from_file(&image, fileBack); png_bytep bufBack = (png_bytep)malloc(PNG_IMAGE_SIZE(image)); png_image_finish_read(&image, NULL/*background*/, bufBack, 0/*row_stride*/, NULL/*colormap*/); png_image_begin_read_from_file(&image, fileFront); png_bytep bufFront = (png_bytep)malloc(PNG_IMAGE_SIZE(image)); png_image_finish_read(&image, NULL/*background*/, bufFront, 0/*row_stride*/, NULL/*colormap*/); png_bytep bufOut = (png_bytep)malloc(PNG_IMAGE_SIZE(image)); int countRgb = 0; for(int i = 0; i < height; i++) { for(int j = 0; j < width * 4; j += 4) { bufOut[i * width * 4 + j] = bufBack[countRgb++]; bufOut[i * width * 4 + j + 1] = bufBack[countRgb++]; bufOut[i * width * 4 + j + 2] = bufBack[countRgb++]; bufOut[i * width * 4 + j + 3] = 255 - bufFront[i * width * 4 + j + 3]; } } png_image_write_to_file(&image, fileOut, 0/*convert_to_8bit*/, bufOut, 0/*row_stride*/, NULL/*colormap*/); free(bufBack); free(bufFront); free(bufOut); return 0; }
int main(int argc, const char **argv) { if (argc == 3) { png_image image; /* The control structure used by libpng */ /* Initialize the 'png_image' structure. */ memset(&image, 0, (sizeof image)); image.version = PNG_IMAGE_VERSION; /* The first argument is the file to read: */ if (png_image_begin_read_from_file(&image, argv[1])) { png_bytep buffer; /* Set the format in which to read the PNG file; this code chooses a * simple sRGB format with a non-associated alpha channel, adequate to * store most images. */ image.format = PNG_FORMAT_RGBA; /* Now allocate enough memory to hold the image in this format; the * PNG_IMAGE_SIZE macro uses the information about the image (width, * height and format) stored in 'image'. */ buffer = malloc(PNG_IMAGE_SIZE(image)); /* If enough memory was available read the image in the desired format * then write the result out to the new file. 'background' is not * necessary when reading the image because the alpha channel is * preserved; if it were to be removed, for example if we requested * PNG_FORMAT_RGB, then either a solid background color would have to * be supplied or the output buffer would have to be initialized to the * actual background of the image. * * The fourth argument to png_image_finish_read is the 'row_stride' - * this is the number of components allocated for the image in each * row. It has to be at least as big as the value returned by * PNG_IMAGE_ROW_STRIDE, but if you just allocate space for the * default, minimum, size using PNG_IMAGE_SIZE as above you can pass * zero. * * The final argument is a pointer to a buffer for the colormap; * colormaps have exactly the same format as a row of image pixels (so * you choose what format to make the colormap by setting * image.format). A colormap is only returned if * PNG_FORMAT_FLAG_COLORMAP is also set in image.format, so in this * case NULL is passed as the final argument. If you do want to force * all images into an index/color-mapped format then you can use: * * PNG_IMAGE_COLORMAP_SIZE(image) * * to find the maximum size of the colormap in bytes. */ if (buffer != NULL && png_image_finish_read(&image, NULL/*background*/, buffer, 0/*row_stride*/, NULL/*colormap*/)) { /* Now write the image out to the second argument. In the write * call 'convert_to_8bit' allows 16-bit data to be squashed down to * 8 bits; this isn't necessary here because the original read was * to the 8-bit format. */ if (png_image_write_to_file(&image, argv[2], 0/*convert_to_8bit*/, buffer, 0/*row_stride*/, NULL/*colormap*/)) { /* The image has been written successfully. */ exit(0); } } else { /* Calling png_free_image is optional unless the simplified API was * not run to completion. In this case if there wasn't enough * memory for 'buffer' we didn't complete the read, so we must free * the image: */ if (buffer == NULL) png_free_image(&image); else free(buffer); } /* Something went wrong reading or writing the image. libpng stores a * textual message in the 'png_image' structure: */ fprintf(stderr, "pngtopng: error: %s\n", image.message); exit (1); } fprintf(stderr, "pngtopng: usage: pngtopng input-file output-file\n"); exit(1); } /* That's it ;-) Of course you probably want to do more with PNG files than * just converting them all to 32-bit RGBA PNG files; you can do that between * the call to png_image_finish_read and png_image_write_to_file. You can also * ask for the image data to be presented in a number of different formats. You * do this by simply changing the 'format' parameter set before allocating the * buffer. * * The format parameter consists of five flags that define various aspects of * the image, you can simply add these together to get the format or you can use * one of the predefined macros from png.h (as above): * * PNG_FORMAT_FLAG_COLOR: if set the image will have three color components per * pixel (red, green and blue), if not set the image will just have one * luminance (grayscale) component. * * PNG_FORMAT_FLAG_ALPHA: if set each pixel in the image will have an additional * alpha value; a linear value that describes the degree the image pixel * covers (overwrites) the contents of the existing pixel on the display. * * PNG_FORMAT_FLAG_LINEAR: if set the components of each pixel will be returned * as a series of 16-bit linear values, if not set the components will be * returned as a series of 8-bit values encoded according to the 'sRGB' * standard. The 8-bit format is the normal format for images intended for * direct display, because almost all display devices do the inverse of the * sRGB transformation to the data they receive. The 16-bit format is more * common for scientific data and image data that must be further processed; * because it is linear simple math can be done on the component values. * Regardless of the setting of this flag the alpha channel is always linear, * although it will be 8 bits or 16 bits wide as specified by the flag. * * PNG_FORMAT_FLAG_BGR: if set the components of a color pixel will be returned * in the order blue, then green, then red. If not set the pixel components * are in the order red, then green, then blue. * * PNG_FORMAT_FLAG_AFIRST: if set the alpha channel (if present) precedes the * color or grayscale components. If not set the alpha channel follows the * components. * * You do not have to read directly from a file. You can read from memory or, * on systems that support it, from a <stdio.h> FILE*. This is controlled by * the particular png_image_read_from_ function you call at the start. Likewise * on write you can write to a FILE* if your system supports it. Check the * macro PNG_STDIO_SUPPORTED to see if stdio support has been included in your * libpng build. * * If you read 16-bit (PNG_FORMAT_FLAG_LINEAR) data you may need to write it in * the 8-bit format for display. You do this by setting the convert_to_8bit * flag to 'true'. * * Don't repeatedly convert between the 8-bit and 16-bit forms. There is * significant data loss when 16-bit data is converted to the 8-bit encoding and * the current libpng implementation of convertion to 16-bit is also * significantly lossy. The latter will be fixed in the future, but the former * is unavoidable - the 8-bit format just doesn't have enough resolution. */ /* If your program needs more information from the PNG data it reads, or if you * need to do more complex transformations, or minimise transformations, on the * data you read, then you must use one of the several lower level libpng * interfaces. * * All these interfaces require that you do your own error handling - your * program must be able to arrange for control to return to your own code any * time libpng encounters a problem. There are several ways to do this, but the * standard way is to use the ANSI-C (C90) <setjmp.h> interface to establish a * return point within your own code. You must do this if you do not use the * simplified interface (above). * * The first step is to include the header files you need, including the libpng * header file. Include any standard headers and feature test macros your * program requires before including png.h: */ #include <png.h> /* The png_jmpbuf() macro, used in error handling, became available in * libpng version 1.0.6. If you want to be able to run your code with older * versions of libpng, you must define the macro yourself (but only if it * is not already defined by libpng!). */ #ifndef png_jmpbuf # define png_jmpbuf(png_ptr) ((png_ptr)->png_jmpbuf) #endif /* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp() * returns zero if the image is a PNG and nonzero if it isn't a PNG. * * The function check_if_png() shown here, but not used, returns nonzero (true) * if the file can be opened and is a PNG, 0 (false) otherwise. * * If this call is successful, and you are going to keep the file open, * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once * you have created the png_ptr, so that libpng knows your application * has read that many bytes from the start of the file. Make sure you * don't call png_set_sig_bytes() with more than 8 bytes read or give it * an incorrect number of bytes read, or you will either have read too * many bytes (your fault), or you are telling libpng to read the wrong * number of magic bytes (also your fault). * * Many applications already read the first 2 or 4 bytes from the start * of the image to determine the file type, so it would be easiest just * to pass the bytes to png_sig_cmp() or even skip that if you know * you have a PNG file, and call png_set_sig_bytes(). */ #define PNG_BYTES_TO_CHECK 4 int check_if_png(char *file_name, FILE **fp) { char buf[PNG_BYTES_TO_CHECK]; /* Open the prospective PNG file. */ if ((*fp = fopen(file_name, "rb")) == NULL) return 0; /* Read in some of the signature bytes */ if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) return 0; /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. Return nonzero (true) if they match */ return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)); }
int main(int argc, char *argv[]) { png_image image; png_bytep buffer; // Set the seed (as global variable random_integer) if (argc >= 2) random_integer = atoi(argv[1]); else { FILE* f = fopen("/dev/urandom", "r"); fread(&random_integer, sizeof(int), 1, f); printf("Seed: %d\n", random_integer); } // Set the image attributes memset(&image, 0, (sizeof image)); image.version = PNG_IMAGE_VERSION; image.opaque = NULL; image.width = 1024; image.height = 1024; image.format = PNG_FORMAT_GRAY; image.flags = 0; image.colormap_entries = 0; // Allocate the buffer buffer = malloc(PNG_IMAGE_SIZE(image)); // The status messages are used to indicate the progress through the image. // Each thread will spit one const char* statuses = "abcdefghijklmnopqrstuvwxyz"; int status_len = 26; int status_sent = 0; // Each chunk will process chunk_len pixel parts, except the last chunk // which processes the remaining stuff int nchunks = status_len; size_t chunk_len = PNG_IMAGE_SIZE(image) / nchunks; struct fill_image_data *image_datas; image_datas = calloc(nchunks+1, sizeof(struct fill_image_data)); // Allocate space for the thread pointers pthread_t *threads; threads = calloc(nchunks+1, sizeof(pthread_t)); // Display a list of statuses for comparison printf("%s\n", statuses); // i = chunk index, j = index of data to start processing int i, j; j = 0; for (i = 0; i < nchunks; i++) { image_datas[i].image = ℑ image_datas[i].buffer = buffer; image_datas[i].start = j; image_datas[i].end = j + chunk_len; image_datas[i].finish_message = statuses[i]; // Start a worker thread pthread_create(threads+i, NULL, fill_image, image_datas+i); j += chunk_len; #if 1 // This limits number of threads. It can make it faster, can make it slower. if (i % 8 == 0) pthread_join(threads[i], NULL); #endif } // Process the remaining parts image_datas[i].image = ℑ image_datas[i].buffer = buffer; image_datas[i].start = j; image_datas[i].end = PNG_IMAGE_SIZE(image); image_datas[i].finish_message = statuses[i]; pthread_create(threads+i, NULL, fill_image, image_datas+i); // Wait for completion for (i = 0; i < nchunks+1; i++) { pthread_join(threads[i], NULL); } png_image_write_to_file(&image, "out.png", 0, buffer, 0, NULL); free(threads); free(image_datas); free(buffer); printf("\n"); return 0; }