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; }
JNIEXPORT jint JNICALL Java_org_lwjgl_stb_STBImageResize_nstbir_1resize_1uint8_1srgb(JNIEnv *__env, jclass clazz, jlong input_pixelsAddress, jint input_w, jint input_h, jint input_stride_in_bytes, jlong output_pixelsAddress, jint output_w, jint output_h, jint output_stride_in_bytes, jint num_channels, jint alpha_channel, jint flags) { unsigned char const *input_pixels = (unsigned char const *)(intptr_t)input_pixelsAddress; unsigned char *output_pixels = (unsigned char *)(intptr_t)output_pixelsAddress; UNUSED_PARAMS(__env, clazz) return (jint)stbir_resize_uint8_srgb(input_pixels, input_w, input_h, input_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes, num_channels, alpha_channel, flags); }