我正在尝试使用从摄像机获得的jpeg制作gif动画.但是这个过程是漫长的.我使用了两个不同的库. First用本机C代码编写,其次是Java的one.
我尽可能地压缩帧,但是即使这样也不能减少生成时间.
原生库大约需要80-100秒,而Java大约需要40-60秒(我不知道Java的速度是2倍,但是日志显示了这个结果),显示了5秒的视频,帧率为16 fps(每gif 80帧).
我根据this更改了C语言算法,因为我遇到了同样的问题(尝试通过更改一段代码和更改整个learning()函数来尝试这两个版本).
在这里您可以看到一段日志:
这是本机实现中的最后三个框架:
D/TimeUtils: Adding frame executed in 949msD/TimeUtils: Adding frame executed in 976msD/TimeUtils: Adding frame executed in 1028msD/TimeUtils: Creating gif with native library executed in 82553ms
这是Java版本的最后三帧:
D/TimeUtils: Adding frame executed in 541msD/TimeUtils: Adding frame executed in 513msD/TimeUtils: Adding frame executed in 521msD/TimeUtils: Creating gif with nbadal's library executed in 44811ms
也许其他有用的日志:
D/CameraActivity: Duration of the captured vIDeo is 5000msV/CameraActivity: Dimensions are 288w x 288hD/CameraActivity: Final bitmaps count: 80
TimeUtils.java包含静态方法以检查方法执行的时间.
NativeGifConverter.java(仅转换函数):
@OverrIDe public voID createGiffile(String path, List<String> bitmapPaths) { Bitmap bitmap = BitmapUtils.retrIEve(bitmapPaths.get(0)); if (init(path, bitmap.getWIDth(), bitmap.getHeight(), mNumcolors, mQuality, mFrameDelay) != 0) { Timber.e("Gifflen init Failed"); return; } bitmap.recycle(); for (String bitmapPath : bitmapPaths) { bitmap = howLong("RetrIEving bitmap", () -> BitmapUtils.retrIEve(bitmapPath)); final int wIDth = bitmap.getWIDth(); final int height = bitmap.getHeight(); final int[] pixels = new int[wIDth * height]; final Bitmap finalBitmap = bitmap; // for counting time howLongVoID("RetrIEving pixels", () -> finalBitmap.getPixels(pixels, 0, wIDth, 0, 0, wIDth, height)); howLongVoID("Adding frame", () -> addFrame(pixels)); bitmap.recycle(); } bitmap = null; close(); }
NbadalgifConverter.java(仅转换函数):
@OverrIDe public voID createGiffile(String path, List<String> bitmapsnames) { final ByteArrayOutputStream bos = new ByteArrayOutputStream(); final AnimatedGifEncoder encoder = new AnimatedGifEncoder(); encoder.setDelay(mDelay); encoder.setQuality(mQuality); encoder.start(bos); for (String bitmapname : bitmapsnames) { final Bitmap bitmap = howLong("RetrIEving bitmap", () -> BitmapUtils.retrIEve(bitmapname)); howLongVoID("Adding frame", () -> encoder.addFrame(bitmap)); } encoder.finish(); fileUtils.store(bos.toByteArray(), path.substring(0, path.lastIndexOf('.')) + ".gif"); }
我愿意向您展示另一个相关的代码段.我将不胜感激任何帮助.
[更新]
检索位图的日志:
D/TimeUtils: RetrIEving bitmap executed in 3msD/TimeUtils: RetrIEving bitmap executed in 3msD/TimeUtils: RetrIEving bitmap executed in 4ms
解决方法:
首先,我必须感谢@Spektre的答案:Effective gif/image color quantization?
我和我的同事刚刚将其从C语言转换为Java语言.在短于4倍的时间内显示出良好的结果.我将尝试对其进行改进,但这已经比AnimatedGifEncoder.java(我之前使用过)更好的结果
这是代码:
public static final int MAX_color_COUNT = 65536;/** * @param pixels rgb 888 * @param palette int[256] * @return indices of colors in palette */private int[][][] createPalette(int[] pixels, int[] palette) { final int[] histogram = new int[MAX_color_COUNT]; // pixel count histogram final int[] indices = new int[MAX_color_COUNT]; // here index is color value for (int i = 0; i < MAX_color_COUNT; i++) { indices[i] = i; } // creating histogram for (int color : pixels) { // 0001 1111 0111 1110 0000 1111 1000 0000 0000 color = ((color >> 3) & 0x1F) | ((color >> 5) & 0x7E0) | ((color >> 8) & 0xF800); if (histogram[color] < Integer.MAX_VALUE) { // picture must be really big histogram[color]++; } } // removing zeros int j = 0; for (int i = 0; i < MAX_color_COUNT; i++) { histogram[j] = histogram[i]; indices[j] = indices[i]; if (histogram[j] != 0) { j++; } } final int histograms = j; // bubble sort for (int i = 1; i != 0; ) { i = 0; for (int x = 0, y = 1; y < histograms; x++, y++) { if (histogram[x] < histogram[y]) { i = histogram[x]; histogram[x] = histogram[y]; histogram[y] = i; i = indices[x]; indices[x] = indices[y]; indices[y] = i; i = 1; } } } final int[][][] colorMap = new int[32][64][32]; int colortableIndex = 0, x = 0; for (; x < histograms; x++) { // main colors final int color = indices[x]; // 1f (16) = 0001 1111 (2) // 3f (16) = 0011 1111 (2) // (1111 1)(111 111)(1 1111) final int b = color & 0x1f; final int g = (color >> 5) & 0x3f; final int r = (color >> 11) & 0x1f; // skip if similar color already in palette[] int a = 0, i = 0; for (; i < colortableIndex; i++) { final byte tempB = (byte) ((palette[i] >> 3) & 0x1f); final byte tempG = (byte) ((palette[i] >> 10) & 0x3f); final byte tempR = (byte) ((palette[i] >> 19) & 0x1f); // if difference between two colors is pretty small // taxicab distance int difference = tempB - b; if (difference < 0) { difference = -difference; } a = difference; difference = tempG - g; if (difference < 0) { difference = -difference; } a += difference; difference = tempR - r; if (difference < 0) { difference = -difference; } a += difference; if (a <= 2) { // smaller than 16/8 a = 1; break; } a = 0; } if (a != 0) { colorMap[r][g][b] = i; // map to existing color } else { colorMap[r][g][b] = colortableIndex; // map to new index // 1111 1000 1111 1100 1111 1000 palette[colortableIndex] = b << 3 | (g << 10) | (r << 19); // fill this index with new color colortableIndex++; if (colortableIndex >= 256/*palette.length*/) { x++; break; } } } // colortableIndex = new color table size for (; x < histograms; x++) { // minor colors final int color = indices[x]; final int b = color & 0x1f; final int g = (color >> 5) & 0x3f; final int r = (color >> 11) & 0x1f; // find closest color int mindistance = -1; int colorIndex = 0; for (int a, i = 0; i < colortableIndex; i++) { final byte tempB = (byte) ((palette[i] >> 3) & 0x1f); final byte tempG = (byte) ((palette[i] >> 10) & 0x3f); final byte tempR = (byte) ((palette[i] >> 19) & 0x1f); int difference = tempB - b; if (difference < 0) { difference = -difference; } a = difference; difference = tempG - g; if (difference < 0) { difference = -difference; } a += difference; difference = tempR - r; if (difference < 0) { difference = -difference; } a += difference; if ((mindistance < 0) || (mindistance > a)) { mindistance = a; colorIndex = i; } } colorMap[r][g][b] = colorIndex; } return colorMap;}private byte[] map(int[] pixels, int[][][] colorMap) { final int pixelsLength = pixels.length; final byte[] mapped = new byte[pixelsLength]; for (int i = 0; i < pixelsLength; i++) { final int color = ((pixels[i] >> 3) & 0x1F) | ((pixels[i] >> 5) & 0x7E0) | ((pixels[i] >> 8) & 0xF800); final int b = color & 0x1f; final int g = (color >> 5) & 0x3f; final int r = (color >> 11) & 0x1f; mapped[i] = (byte) colorMap[r][g][b]; } return mapped;}
总结 以上是内存溢出为你收集整理的java-将jpegs转换为gifs太长全部内容,希望文章能够帮你解决java-将jpegs转换为gifs太长所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)