@Nullable @Override public Resource<byte[]> transcode(@NonNull Resource<GifDrawable> toTranscode, @NonNull Options options) { GifDrawable gifData = toTranscode.get(); ByteBuffer byteBuffer = gifData.getBuffer(); return new BytesResource(ByteBufferUtil.toBytes(byteBuffer)); } }
@Override public boolean encode(@NonNull Resource<GifDrawable> data, @NonNull File file, @NonNull Options options) { GifDrawable drawable = data.get(); boolean success = false; try { ByteBufferUtil.toFile(drawable.getBuffer(), file); success = true; } catch (IOException e) { if (Log.isLoggable(TAG, Log.WARN)) { Log.w(TAG, "Failed to encode GIF drawable data", e); } } return success; } }
private boolean encodeTransformedToFile(GifDrawable drawable, File file) { long startTime = LogTime.getLogTime(); OutputStream os = null; boolean success = false; try { os = new BufferedOutputStream(new FileOutputStream(file)); success = encodeTransformedToStream(drawable, os); os.close(); } catch (IOException e) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Failed to encode GIF", e); } } finally { if (os != null) { try { os.close(); } catch (IOException e) { // Ignored. } } } if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Re-encoded GIF with " + drawable.getFrameCount() + " frames and " + drawable.getBuffer().limit() + " bytes in " + LogTime.getElapsedMillis(startTime) + " ms"); } return success; }
@Override public boolean encode(@NonNull Resource<GifDrawable> resource, @NonNull File file, @NonNull Options options) { GifDrawable drawable = resource.get(); Transformation<Bitmap> transformation = drawable.getFrameTransformation(); boolean isTransformed = !(transformation instanceof UnitTransformation); if (isTransformed && options.get(ENCODE_TRANSFORMATION)) { return encodeTransformedToFile(drawable, file); } else { return writeDataDirect(drawable.getBuffer(), file); } }
@Test public void testSetsDataOnParserBeforeParsingHeader() { ByteBuffer data = ByteBuffer.allocate(1); when(gifDrawable.getBuffer()).thenReturn(data); GifHeader header = mock(GifHeader.class); when(parser.parseHeader()).thenReturn(header); encoder.encode(resource, file, options); InOrder order = inOrder(parser, decoder); order.verify(parser).setData(eq(data)); order.verify(parser).parseHeader(); order.verify(decoder).setData(header, data); }
@Test public void testWritesBytesDirectlyToDiskIfTransformationIsUnitTransformation() { when(gifDrawable.getFrameTransformation()).thenReturn(UnitTransformation.<Bitmap>get()); String expected = "expected"; when(gifDrawable.getBuffer()).thenReturn(ByteBuffer.wrap(expected.getBytes())); encoder.encode(resource, file, options); assertThat(getEncodedData()).isEqualTo(expected); verify(gifEncoder, never()).start(any(OutputStream.class)); verify(parser, never()).setData(any(byte[].class)); verify(parser, never()).parseHeader(); }
@Test public void testReturnsBytesOfGivenGifDrawable() { for (String fakeData : new String[] { "test", "1235asfklaw3", "@$@#" }) { ByteBuffer expected = ByteBuffer.wrap(fakeData.getBytes(Charset.defaultCharset())); when(gifDrawable.getBuffer()).thenReturn(expected); Resource<byte[]> transcoded = transcoder.transcode(resource, new Options()); assertArrayEquals(expected.array(), transcoded.get()); } } }
@Test public void testEncode_WithEncodeTransformationFalse_whenOsThrows_returnsFalse() throws IOException { options.set(ReEncodingGifResourceEncoder.ENCODE_TRANSFORMATION, false); byte[] data = "testString".getBytes("UTF-8"); when(gifDrawable.getBuffer()).thenReturn(ByteBuffer.wrap(data)); assertThat(file.mkdirs()).isTrue(); assertFalse(encoder.encode(resource, file, options)); }
@Test public void testEncode_withEncodeTransformationFalse_writesSourceDataToStream() throws IOException { options.set(ReEncodingGifResourceEncoder.ENCODE_TRANSFORMATION, false); String expected = "testString"; byte[] data = expected.getBytes("UTF-8"); when(gifDrawable.getBuffer()).thenReturn(ByteBuffer.wrap(data)); assertTrue(encoder.encode(resource, file, options)); assertThat(getEncodedData()).isEqualTo(expected); }
@SuppressWarnings("unchecked") @Before public void setUp() { MockitoAnnotations.initMocks(this); Application context = RuntimeEnvironment.application; ReEncodingGifResourceEncoder.Factory factory = mock(ReEncodingGifResourceEncoder.Factory.class); when(decoder.getNextFrame()).thenReturn(Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)); when(factory.buildDecoder(any(GifDecoder.BitmapProvider.class))).thenReturn(decoder); when(factory.buildParser()).thenReturn(parser); when(factory.buildEncoder()).thenReturn(gifEncoder); when(factory.buildFrameResource(any(Bitmap.class), any(BitmapPool.class))) .thenReturn(frameResource); // TODO Util.anyResource once Util is moved to testutil module (remove unchecked above!) when(frameTransformation.transform(anyContext(), any(Resource.class), anyInt(), anyInt())) .thenReturn(frameResource); when(gifDrawable.getFrameTransformation()).thenReturn(frameTransformation); when(gifDrawable.getBuffer()).thenReturn(ByteBuffer.allocate(0)); when(resource.get()).thenReturn(gifDrawable); encoder = new ReEncodingGifResourceEncoder(context, mock(BitmapPool.class), factory); options = new Options(); options.set(ReEncodingGifResourceEncoder.ENCODE_TRANSFORMATION, true); file = new File(context.getCacheDir(), "test"); }
private boolean encodeTransformedToStream(GifDrawable drawable, OutputStream os) { Transformation<Bitmap> transformation = drawable.getFrameTransformation(); GifDecoder decoder = decodeHeaders(drawable.getBuffer()); AnimatedGifEncoder encoder = factory.buildEncoder(); if (!encoder.start(os)) { return false; } for (int i = 0; i < decoder.getFrameCount(); i++) { Bitmap currentFrame = decoder.getNextFrame(); Resource<Bitmap> transformedResource = getTransformedFrame(currentFrame, transformation, drawable); try { if (!encoder.addFrame(transformedResource.get())) { return false; } int currentFrameIndex = decoder.getCurrentFrameIndex(); int delay = decoder.getDelay(currentFrameIndex); encoder.setDelay(delay); decoder.advance(); } finally { transformedResource.recycle(); } } return encoder.finish(); }