void Gosu::saveImageFile(const Gosu::Bitmap& bitmap, Gosu::Writer writer, const std::wstring& formatHint) { int ok; if (isExtension(formatHint.c_str(), L"bmp")) { ok = stbi_write_bmp_to_func(stbiWriteToWriter, &writer, bitmap.width(), bitmap.height(), 4, bitmap.data()); } else if (isExtension(formatHint.c_str(), L"tga")) { stbi_write_tga_with_rle = 0; ok = stbi_write_tga_to_func(stbiWriteToWriter, &writer, bitmap.width(), bitmap.height(), 4, bitmap.data()); } else { ok = stbi_write_png_to_func(stbiWriteToWriter, &writer, bitmap.width(), bitmap.height(), 4, bitmap.data(), 0); } if (ok == 0) throw std::runtime_error("Could not save image data to memory (format hint = '" + Gosu::wstringToUTF8(formatHint) + "'"); }
JNIEXPORT jint JNICALL Java_org_lwjgl_stb_STBImageWrite_nstbi_1write_1bmp_1to_1func(JNIEnv *__env, jclass clazz, jlong funcAddress, jlong contextAddress, jint w, jint h, jint comp, jlong dataAddress) { stbi_write_func *func = (stbi_write_func *)(intptr_t)funcAddress; void *context = (void *)(intptr_t)contextAddress; const void *data = (const void *)(intptr_t)dataAddress; UNUSED_PARAMS(__env, clazz) return (jint)stbi_write_bmp_to_func(func, context, w, h, comp, data); }
int main(int argc, char **argv) { int w,h; //test_ycbcr(); #if 0 // test hdr asserts for (h=0; h < 100; h += 2) for (w=0; w < 200; ++w) hdr_data[h][w][0] = (float) rand(), hdr_data[h][w][1] = (float) rand(), hdr_data[h][w][2] = (float) rand(); stbi_write_hdr("output/test.hdr", 200,200,3,hdr_data[0][0]); #endif if (argc > 1) { int i, n; for (i=1; i < argc; ++i) { int res; int w2,h2,n2; unsigned char *data; printf("%s\n", argv[i]); res = stbi_info(argv[1], &w2, &h2, &n2); data = stbi_load(argv[i], &w, &h, &n, 4); if (data) free(data); else printf("Failed &n\n"); data = stbi_load(argv[i], &w, &h, 0, 1); if (data) free(data); else printf("Failed 1\n"); data = stbi_load(argv[i], &w, &h, 0, 2); if (data) free(data); else printf("Failed 2\n"); data = stbi_load(argv[i], &w, &h, 0, 3); if (data) free(data); else printf("Failed 3\n"); data = stbi_load(argv[i], &w, &h, &n, 4); assert(data); assert(w == w2 && h == h2 && n == n2); assert(res); if (data) { char fname[512]; stb_splitpath(fname, argv[i], STB_FILE); stbi_write_png(stb_sprintf("output/%s.png", fname), w, h, 4, data, w*4); stbi_write_bmp(stb_sprintf("output/%s.bmp", fname), w, h, 4, data); stbi_write_tga(stb_sprintf("output/%s.tga", fname), w, h, 4, data); stbi_write_png_to_func(dummy_write,0, w, h, 4, data, w*4); stbi_write_bmp_to_func(dummy_write,0, w, h, 4, data); stbi_write_tga_to_func(dummy_write,0, w, h, 4, data); free(data); } else printf("FAILED 4\n"); } } else { int i, nope=0; #ifdef PNGSUITE_PRIMARY char **files = stb_readdir_files("pngsuite/primary"); #else char **files = stb_readdir_files("images"); #endif for (i=0; i < stb_arr_len(files); ++i) { int n; char **failed = NULL; unsigned char *data; printf("."); //printf("%s\n", files[i]); data = stbi_load(files[i], &w, &h, &n, 0); if (data) free(data); else stb_arr_push(failed, "&n"); data = stbi_load(files[i], &w, &h, 0, 1); if (data) free(data); else stb_arr_push(failed, "1"); data = stbi_load(files[i], &w, &h, 0, 2); if (data) free(data); else stb_arr_push(failed, "2"); data = stbi_load(files[i], &w, &h, 0, 3); if (data) free(data); else stb_arr_push(failed, "3"); data = stbi_load(files[i], &w, &h, 0, 4); if (data) ; else stb_arr_push(failed, "4"); if (data) { char fname[512]; #ifdef PNGSUITE_PRIMARY int w2,h2; unsigned char *data2; stb_splitpath(fname, files[i], STB_FILE_EXT); data2 = stbi_load(stb_sprintf("pngsuite/primary_check/%s", fname), &w2, &h2, 0, 4); if (!data2) printf("FAILED: couldn't load 'pngsuite/primary_check/%s\n", fname); else { if (w != w2 || h != w2 || 0 != memcmp(data, data2, w*h*4)) { int x,y,c; if (w == w2 && h == h2) for (y=0; y < h; ++y) for (x=0; x < w; ++x) for (c=0; c < 4; ++c) assert(data[y*w*4+x*4+c] == data2[y*w*4+x*4+c]); printf("FAILED: %s loaded but didn't match PRIMARY_check 32-bit version\n", files[i]); } free(data2); } #else stb_splitpath(fname, files[i], STB_FILE); stbi_write_png(stb_sprintf("output/%s.png", fname), w, h, 4, data, w*4); #endif free(data); } if (failed) { int j; printf("FAILED: "); for (j=0; j < stb_arr_len(failed); ++j) printf("%s ", failed[j]); printf(" -- %s\n", files[i]); } } printf("Tested %d files.\n", i); } return 0; }
rdctype::array<byte> CaptureFile::GetThumbnail(FileType type, uint32_t maxsize) { rdctype::array<byte> buf; Serialiser ser(Filename(), Serialiser::READING, false); if(ser.HasError()) return buf; ser.Rewind(); int chunkType = ser.PushContext(NULL, NULL, 1, false); if(chunkType != THUMBNAIL_DATA) return buf; bool HasThumbnail = false; ser.Serialise(NULL, HasThumbnail); if(!HasThumbnail) return buf; byte *jpgbuf = NULL; size_t thumblen = 0; uint32_t thumbwidth = 0, thumbheight = 0; { ser.Serialise("ThumbWidth", thumbwidth); ser.Serialise("ThumbHeight", thumbheight); ser.SerialiseBuffer("ThumbnailPixels", jpgbuf, thumblen); } if(jpgbuf == NULL) return buf; // if the desired output is jpg and either there's no max size or it's already satisfied, // return the data directly if(type == FileType::JPG && (maxsize == 0 || (maxsize > thumbwidth && maxsize > thumbheight))) { create_array_init(buf, thumblen, jpgbuf); } else { // otherwise we need to decode, resample maybe, and re-encode int w = (int)thumbwidth; int h = (int)thumbheight; int comp = 3; byte *thumbpixels = jpgd::decompress_jpeg_image_from_memory(jpgbuf, (int)thumblen, &w, &h, &comp, 3); if(maxsize != 0) { uint32_t clampedWidth = RDCMIN(maxsize, thumbwidth); uint32_t clampedHeight = RDCMIN(maxsize, thumbheight); if(clampedWidth != thumbwidth || clampedHeight != thumbheight) { // preserve aspect ratio, take the smallest scale factor and multiply both float scaleX = float(clampedWidth) / float(thumbwidth); float scaleY = float(clampedHeight) / float(thumbheight); if(scaleX < scaleY) clampedHeight = uint32_t(scaleX * thumbheight); else if(scaleY < scaleX) clampedWidth = uint32_t(scaleY * thumbwidth); byte *resizedpixels = (byte *)malloc(3 * clampedWidth * clampedHeight); stbir_resize_uint8_srgb(thumbpixels, thumbwidth, thumbheight, 0, resizedpixels, clampedWidth, clampedHeight, 0, 3, -1, 0); free(thumbpixels); thumbpixels = resizedpixels; thumbwidth = clampedWidth; thumbheight = clampedHeight; } } std::vector<byte> encodedBytes; switch(type) { case FileType::JPG: { int len = thumbwidth * thumbheight * 3; encodedBytes.resize(len); jpge::params p; p.m_quality = 90; jpge::compress_image_to_jpeg_file_in_memory(&encodedBytes[0], len, (int)thumbwidth, (int)thumbheight, 3, thumbpixels, p); encodedBytes.resize(len); break; } case FileType::PNG: { stbi_write_png_to_func(&writeToByteVector, &encodedBytes, (int)thumbwidth, (int)thumbheight, 3, thumbpixels, 0); break; } case FileType::TGA: { stbi_write_tga_to_func(&writeToByteVector, &encodedBytes, (int)thumbwidth, (int)thumbheight, 3, thumbpixels); break; } case FileType::BMP: { stbi_write_bmp_to_func(&writeToByteVector, &encodedBytes, (int)thumbwidth, (int)thumbheight, 3, thumbpixels); break; } default: { RDCERR("Unsupported file type %d in thumbnail fetch", type); free(thumbpixels); delete[] jpgbuf; return buf; } } buf = encodedBytes; free(thumbpixels); } delete[] jpgbuf; return buf; }