#include "gl_local.h" #include typedef struct png_s { // TPng = class(TGraphic) char *tmpBuf; int tmpi; long FBgColor; // DL Background color Added 30/05/2000 int FTransparent; // DL Is this Image Transparent Added 30/05/2000 long FRowBytes; //DL Added 30/05/2000 double FGamma; //DL Added 07/06/2000 double FScreenGamma; //DL Added 07/06/2000 char *FRowPtrs; // DL Changed for consistancy 30/05/2000 char* Data; //property Data: pByte read fData; char* Title; char* Author; char* Description; int BitDepth; int BytesPerPixel; int ColorType; unsigned long Height; unsigned long Width; int Interlace; int Compression; int Filter; double LastModified; int Transparent; } png_t; png_t *my_png=0; unsigned char* pngbytes; /* ============================================================= PNG STUFF ============================================================= */ void InitializeDemData() { long* cvaluep; //ub long y; // Initialize Data and RowPtrs if(my_png->Data) { free(my_png->Data); my_png->Data = 0; } if(my_png->FRowPtrs) { free(my_png->FRowPtrs); my_png->FRowPtrs = 0; } my_png->Data = malloc(my_png->Height * my_png->FRowBytes ); // DL Added 30/5/2000 my_png->FRowPtrs = malloc(sizeof(void*) * my_png->Height); if((my_png->Data)&&(my_png->FRowPtrs)) { cvaluep = (long*)my_png->FRowPtrs; for(y=0;yHeight;y++) { cvaluep[y] = (long)my_png->Data + ( y * (long)my_png->FRowBytes ); //DL Added 08/07/2000 } } } void mypng_struct_create() { if(my_png) return; my_png = malloc(sizeof(png_t)); my_png->Data = 0; my_png->FRowPtrs = 0; my_png->Height = 0; my_png->Width = 0; my_png->ColorType = PNG_COLOR_TYPE_RGB; my_png->Interlace = PNG_INTERLACE_NONE; my_png->Compression = PNG_COMPRESSION_TYPE_DEFAULT; my_png->Filter = PNG_FILTER_TYPE_DEFAULT; } void mypng_struct_destroy(qboolean keepData) { if(!my_png) return; if(my_png->Data && !keepData) free(my_png->Data); if(my_png->FRowPtrs) free(my_png->FRowPtrs); free(my_png); my_png = 0; } /* ============================================================= fReadData ============================================================= */ void PNGAPI fReadData(png_structp png,png_bytep data,png_size_t length) { // called by pnglib int i; for(i=0;itmpBuf[my_png->tmpi++]; // give pnglib a some more bytes } /* ============================================================= GL_ScreenShot_PNG - psychospaz ============================================================= */ void GL_ScreenShot_PNG (void) { byte *rgbdata; FILE *file; char picname[80], checkname[MAX_OSPATH]; int i, j, k; png_structp png_ptr; png_infop info_ptr; //not working yet... ri.Con_Printf (PRINT_ALL, "PNG Screenshot...(^iDisabled^i)\n"); return; // Create the scrnshots directory if it doesn't exist Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot", ri.FS_Gamedir()); Sys_Mkdir (checkname); for (i=0 ; i<=999 ; i++) { Com_sprintf (picname, sizeof(picname), "quake2max%i%i%i.png", (int)(i/100)%10, (int)(i/10)%10, i%10); Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", ri.FS_Gamedir(), picname); file = fopen (checkname, "rb"); if (!file) break; // file doesn't exist fclose (file); } if (i==1000) { ri.Con_Printf (PRINT_ALL, "GL_ScreenShot_PNG: Couldn't create a file\n"); return; } // Allocate room for a copy of the framebuffer rgbdata = malloc(vid.width * vid.height * 3); if(!rgbdata) return; // Read the framebuffer into our storage qglReadPixels(0, 0, vid.width, vid.height, GL_RGB, GL_UNSIGNED_BYTE, rgbdata); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0,0,0); if (!png_ptr) { free(rgbdata); ri.Con_Printf (PRINT_ALL, "GL_ScreenShot_PNG: Couldn't create image (NO PNG_PTR)\n"); return; } // Allocate/initialize the image information data. REQUIRED info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, 0); free(rgbdata); ri.Con_Printf (PRINT_ALL, "GL_ScreenShot_PNG: Couldn't create image (NO INFO_PTR)\n"); return; } if (setjmp(png_ptr->jmpbuf)) { png_destroy_write_struct(&png_ptr, &info_ptr); free(rgbdata); ri.Con_Printf (PRINT_ALL, "GL_ScreenShot_PNG: Couldn't create image (BAD INFO)\n"); return; } // Open the file for Binary Output file = fopen(checkname, "wb"); if(!file) { ri.Con_Printf (PRINT_ALL, "GL_ScreenShot_PNG: Couldn't create a file\n"); return; } png_init_io(png_ptr, file); png_set_IHDR(png_ptr, info_ptr, vid.width, vid.height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); for (k = 0; k < vid.height; k++) { void *pointer = rgbdata + k*vid.width*3; png_write_row(png_ptr, pointer); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); // Close File fclose(file); // Free Temp Framebuffer free(rgbdata); // Done! ri.Con_Printf (PRINT_ALL, "Wrote %s\n", picname); } /* ============================================================= LoadPNG ============================================================= */ void LoadPNG (char *filename, byte **pic, int *width, int *height) { png_structp png; png_infop pnginfo; byte ioBuffer[8192]; int len; byte *raw; *pic=0; len = ri.FS_LoadFile (filename, (void **)&raw); if (!raw) { ri.Con_Printf (PRINT_DEVELOPER, "Bad png file %s\n", filename); return; } if( png_sig_cmp(raw,0,4)) return; png = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0); if(!png) return; pnginfo = png_create_info_struct( png ); if(!pnginfo) { png_destroy_read_struct(&png,&pnginfo,0); return; } png_set_sig_bytes(png,0/*sizeof( sig )*/); mypng_struct_create(); // creates the my_png struct my_png->tmpBuf = raw; //buf = whole file content my_png->tmpi=0; png_set_read_fn(png,ioBuffer,fReadData ); png_read_info( png, pnginfo ); png_get_IHDR(png, pnginfo, &my_png->Width, &my_png->Height,&my_png->BitDepth, &my_png->ColorType, &my_png->Interlace, &my_png->Compression, &my_png->Filter ); // ...removed bgColor code here... if (my_png->ColorType == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); if (my_png->ColorType == PNG_COLOR_TYPE_GRAY && my_png->BitDepth < 8) png_set_gray_1_2_4_to_8(png); // Add alpha channel if present if(png_get_valid( png, pnginfo, PNG_INFO_tRNS )) png_set_tRNS_to_alpha(png); // hax: expand 24bit to 32bit if (my_png->BitDepth == 8 && my_png->ColorType == PNG_COLOR_TYPE_RGB) png_set_filler(png,255, PNG_FILLER_AFTER); if (( my_png->ColorType == PNG_COLOR_TYPE_GRAY) || (my_png->ColorType == PNG_COLOR_TYPE_GRAY_ALPHA )) png_set_gray_to_rgb( png ); if (my_png->BitDepth < 8) png_set_expand (png); // update the info structure png_read_update_info( png, pnginfo ); my_png->FRowBytes = png_get_rowbytes( png, pnginfo ); my_png->BytesPerPixel = png_get_channels( png, pnginfo ); // DL Added 30/08/2000 InitializeDemData(); if((my_png->Data)&&(my_png->FRowPtrs)) png_read_image(png, (png_bytepp)my_png->FRowPtrs); png_read_end(png, pnginfo); // read last information chunks png_destroy_read_struct(&png, &pnginfo, 0); //only load 32 bit by now... if (my_png->BitDepth == 8) { *pic= my_png->Data; *width = my_png->Width; *height = my_png->Height; } else { ri.Con_Printf (PRINT_DEVELOPER, "Bad png color depth: %s\n", filename); *pic = NULL; free(my_png->Data); } mypng_struct_destroy(true); ri.FS_FreeFile ((void *)raw); } //_____________________________________________________________________________