由于我们基于网络的应用程序爱上了webp图像格式,我发现自己需要一个可以解码它的方法或lib,
我已经编写了这段代码,但它只是错过了原生解码器(我更喜欢它是一个jar lib):
public BufferedImage decodeWebP(byte[] encoded, int w, int h) {
int[] width = new int[]{w};
int[] height = new int[]{h};
byte[] decoded = decodeRGBAnative(encoded); //here is the missing part ,
if (decoded.length == 0) return null;
int[] pixels = new int[decoded.length / 4];
ByteBuffer.wrap(decoded).asIntBuffer().get(pixels);
BufferedImage bufferedImage = new BufferedImage(width[0], height[0], BufferedImage.TYPE_INT_RGB);
// bufferedImage.setRGB(x, y, your_value);
int BLOCK_SIZE = 3;
for(int r=0; r< height[0]; r++) {
for (int c = 0; c < width[0]; c++) {
int index = r * width[0] * BLOCK_SIZE + c * BLOCK_SIZE;
int red = pixels[index] & 0xFF;
int green = pixels[index + 1] & 0xFF;
int blue = pixels[index + 2] & 0xFF;
int rgb = (red << 16) | (green << 8) | blue;
bufferedImage.setRGB(c, r, rgb);
}
}
return bufferedImage;
}
答案 0 :(得分:1)
答案 1 :(得分:1)
原始答案的 bitbucket 链接不再可用,但可以找到来自原始存储库的 fork,例如:https://github.com/sejda-pdf/webp-imageio
我尝试使用上述 github 中的 webp-imageio 实现,但在生产中使用它 2 天后,我遇到了来自本机库的分段错误,导致整个服务器崩溃。
我在这里使用了 google 提供的编译工具:https://developers.google.com/speed/webp/download 并做了一个小的包装类来调用二进制文件。
就我而言,我需要从其他图像格式转换为 webp,所以我需要“cwebp”二进制文件。我写的包装器是:
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.concurrent.TimeUnit;
public class ImageWebpLibraryWrapper {
private static final String CWEBP_BIN_PATH = "somepath/libwebp-1.1.0-linux-x86-64/bin/cwebp";
public static boolean isWebPAvailable() {
if ( CWEBP_BIN_PATH == null ) {
return false;
}
return new File( CWEBP_BIN_PATH ).exists();
}
public static boolean convertToWebP( File imageFile, File targetFile, int quality ) {
Process process;
try {
process = new ProcessBuilder( CWEBP_BIN_PATH, "-q", "" + quality, imageFile.getAbsolutePath(), "-o",
targetFile.getAbsolutePath() ).start();
process.waitFor( 10, TimeUnit.SECONDS );
if ( process.exitValue() == 0 ) {
// Success
printProcessOutput( process.getInputStream(), System.out );
return true;
} else {
printProcessOutput( process.getErrorStream(), System.err );
return false;
}
} catch ( Exception e ) {
e.printStackTrace();
return false;
}
}
private static void printProcessOutput( InputStream inputStream, PrintStream output ) throws IOException {
try ( InputStreamReader isr = new InputStreamReader( inputStream );
BufferedReader bufferedReader = new BufferedReader( isr ) ) {
String line;
while ( ( line = bufferedReader.readLine() ) != null ) {
output.println( line );
}
}
}
围绕 ImageIO 的实现更好,但我不能让生产服务器崩溃的分段错误。
示例用法:
public static void main( String args[] ) {
if ( !isWebPAvailable() ) {
System.err.println( "cwebp binary not found!" );
return;
}
File file = new File( "/home/xxx/Downloads/image_11.jpg" );
File outputFile = new File( "/home/xxx/Downloads/image_11-test.webp" );
int quality = 80;
if ( convertToWebP( file, outputFile, quality ) ) {
System.out.println( "SUCCESS" );
} else {
System.err.println( "FAIL" );
}
}
答案 2 :(得分:1)
请使用 OpenCV。我使用 maven 和 org.openpnp:opencv:4.5.1-2。对存储在 Mat 中的图像进行编码只需要:
public static byte [] encodeWebp(Mat image, int quality) {
MatOfInt parameters = new MatOfInt(Imgcodecs.IMWRITE_WEBP_QUALITY, quality);
MatOfByte output = new MatOfByte();
if(Imgcodecs.imencode(".webp", image, output, parameters))
return output.toArray();
else
throw new IllegalStateException("Failed to encode the image as webp with quality " + quality);
}
我将其转换为字节 [] 数组,因为我主要将它存储在 S3 和 DB 中,而很少存储在文件系统中。
答案 3 :(得分:0)
在 kotlin 中使用 OpenPnP OpenCV:
fun encodeToWebP(image: ByteArray): ByteArray {
val matImage = Imgcodecs.imdecode(MatOfByte(*image), Imgcodecs.IMREAD_UNCHANGED)
val parameters = MatOfInt(Imgcodecs.IMWRITE_WEBP_QUALITY, 100)
val output = MatOfByte()
if (Imgcodecs.imencode(".webp", matImage, output, parameters)) {
return output.toArray()
} else {
throw IllegalStateException("Failed to encode the image as webp")
}
}