static int saveppm(lua_State *L) { struct ppm ppm; luaL_checktype(L,1,LUA_TSTRING); ppm_type(L, luaL_checkstring(L, 2), &ppm); ppm.width = luaL_checkinteger(L, 3); ppm.height = luaL_checkinteger(L, 4); luaL_checktype(L, 5, LUA_TTABLE); int n = (int)lua_rawlen(L,5); if (n != ppm.width * ppm.height * ppm.step) { return luaL_error(L, "Data number %d invalid , should be %d * %d * %d = %d", n, ppm.width, ppm.height, ppm.step, ppm.width * ppm.height * ppm.step); } if (ppm.type != PPM_ALPHA8 && ppm.type != PPM_ALPHA4) { save_rgb(L, ppm.step, ppm.depth); } if (ppm.type != PPM_RGB8 && ppm.type != PPM_RGB4) { int offset = 3; if (ppm.type == PPM_ALPHA8 || ppm.type == PPM_ALPHA4) { offset = 0; } save_alpha(L, ppm.step, ppm.depth, offset); } return 0; }
/* save_png: * Writes a non-interlaced, no-frills PNG, taking the usual save_xyz * parameters. Returns non-zero on error. */ static int really_save_png(PACKFILE *fp, BITMAP *bmp, AL_CONST RGB *pal) { png_structp png_ptr = NULL; png_infop info_ptr = NULL; int depth; int colour_type; depth = bitmap_color_depth(bmp); if (depth == 8 && !pal) return -1; /* Create and initialize the png_struct with the * desired error handler functions. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (void *)NULL, NULL, NULL); if (!png_ptr) goto Error; /* Allocate/initialize the image information data. */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) goto Error; /* Set error handling. */ if (setjmp(png_ptr->jmpbuf)) { /* If we get here, we had a problem reading the file. */ goto Error; } /* Use packfile routines. */ png_set_write_fn(png_ptr, fp, (png_rw_ptr)write_data, flush_data); /* Set the image information here. Width and height are up to 2^31, * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. */ if (depth == 8) colour_type = PNG_COLOR_TYPE_PALETTE; else if (depth == 32) colour_type = PNG_COLOR_TYPE_RGB_ALPHA; else colour_type = PNG_COLOR_TYPE_RGB; /* Set compression level. */ png_set_compression_level(png_ptr, _png_compression_level); png_set_IHDR(png_ptr, info_ptr, bmp->w, bmp->h, 8, colour_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* Set the palette if there is one. Required for indexed-color images. */ if (colour_type == PNG_COLOR_TYPE_PALETTE) { png_color palette[256]; int i; for (i = 0; i < 256; i++) { palette[i].red = _rgb_scale_6[pal[i].r]; /* 64 -> 256 */ palette[i].green = _rgb_scale_6[pal[i].g]; palette[i].blue = _rgb_scale_6[pal[i].b]; } /* Set palette colors. */ png_set_PLTE(png_ptr, info_ptr, palette, 256); } /* Optionally write comments into the image ... Nah. */ /* Write the file header information. */ png_write_info(png_ptr, info_ptr); /* Once we write out the header, the compression type on the text * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again * at the end. */ /* Save the data. */ switch (depth) { case 8: if (!save_indexed(png_ptr, bmp)) goto Error; break; case 15: case 16: case 24: if (!save_rgb(png_ptr, bmp)) goto Error; break; case 32: if (!save_rgba(png_ptr, bmp)) goto Error; break; default: ASSERT(FALSE); goto Error; } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); return 0; Error: if (png_ptr) { if (info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr); else png_destroy_write_struct(&png_ptr, NULL); } return -1; }