✔️ Hide a secret message in an image

Overview

Image Steganography

Steganography is the process of hiding a secret message within a larger one in such a way that someone cannot know the presence or contents of the hidden message. Although related, Steganography is not to be confused with Encryption, which is the process of making a message unintelligible—Steganography attempts to hide the existence of communication. The main advantage of steganography algorithm is because of its simple security mechanism. Because the steganographic message is integrated invisibly and covered inside other harmless sources, it is very difficult to detect the message without knowing the existence and the appropriate encoding scheme .

Proposed Algorithm

The algorithm is more dedicated towards the algorithm proposed by Rosziati Ibrahim and Teoh Suk Kuan in their Research Paper published on February 25, 2011.

Encoding Algorithm

  • Firstly, the secret message that is extracted is compressed as the contents in the compressed string will significantly hard to detect and read, furthermore it reduces the size of string.
  • Secondly, the compressed string is encrypted with the secret key.
  • Finally, encoding the encrypted message in the image. It uses LSB steganographic embedding to encode data into an image. Once the message is encoded the process stops.

LSB(Least Significant Bit) Embedding

The LSB is the lowest significant bit in the byte value of the image pixel. The LSB based image steganography embeds the secret in the least significant bits of pixel values of the cover image (CVR). The concept of LSB Embedding is simple. It exploits the fact that the level of precision in many image formats is far greater than that perceivable by average human vision. Therefore, an altered image with slight variations in its colors will be indistinguishable from the original by a human being, just by looking at it. In conventional LSB technique, which requires eight bytes of pixels to store 1byte of secret data but in proposed LSB technique, just four bytes of pixels are sufficient to hold one message byte. Rest of the bits in the pixels remains the same. Following shows the bit level interpretation of the algorithm :

Decoding Algorithm

  • Firstly, decode the message from the encrypted image using LSB decoding.

  • Secondly, decrypt the compressed message from the decoded message using the secret key.

  • Finally, decompress the message to get the original compressed message.

Consider the following encoding, it is totally undetectable by human eyes.

Usage

Add it in your root build.gradle at the end of repositories:

allprojects {
	repositories {
		...
		maven { url 'https://jitpack.io' }
	}
}

Now add the following dependency in your app's build.gradle

dependencies {
      implementation 'com.github.aagarwal1012:Image-Steganography-Library-Android:v1.0'
}

How to encode message into an image ?

Note : Your Activity class should implements TextEncodingCallback interface and also contains its override methods.

public class MainActivity extends AppCompatActivity implements TextEncodingCallback 
  • Firstly, instantiate the ImageSteganography object and pass the values Message , Secret Key and Image Bitmap to the constructor.

    ImageSteganography imageSteganography = new ImageSteganography(message, 
                                            secret_key, 
                                            original_image);
  • Secondly, instantiate the TextEncoding object and pass the values Activity and TextEncodingCallback object to the constructor.

    TextEncoding textEncoding = new TextEncoding(MainActivity.this,
                                MainActivity.this);
  • Finally, execute our encoding task.

    textEncoding.execute(imageSteganography);

Note : By default a ProgressDialog will appear in the process of text encoding.

Override Methods

  • OnStartTextEncoding() : In this method you can whatever by the start of text encoding process.

    @Override
        public void onStartTextEncoding() {
            //Whatever you want to do at the start of text encoding
        }
  • onCompleteTextEncoding() : After the completion of text encoding, this method is called and gives result.

    @Override
        public void onCompleteTextEncoding(ImageSteganography result) {
    
            //After the completion of text encoding.
            
            //result object is instantiated 
            this.result = result;
    
            if (result != null && result.isEncoded()){
                
                //encrypted image bitmap is extracted from result object
                encoded_image = result.getEncrypted_image();
                
                //set text and image to the UI component.
                textView.setText("Encoded");
                imageView.setImageBitmap(encoded_image);
        }

How to decode message from an image ?

Note : Your Activity class should implements TextDecodingCallback interface and also contains its override methods.

public class MainActivity extends AppCompatActivity implements TextDecodingCallback 
  • Firstly, instantiate the ImageSteganography object and pass the values Secret Key and Image Bitmap to the constructor.

    ImageSteganography imageSteganography = new ImageSteganography(secret_key,
                                            original_image);
  • Secondly, instantiate the TextDecoding object and pass the values Activity and TextDecodingCallback object to the constructor.

    TextDecoding textDecoding = new TextDecoding(MainActivity.this, 
                                MainActivity.this);
  • Finally, execute our decoding task.

    textDecoding.execute(imageSteganography);

    Note : By default a ProgressDialog will appear in the process of text decoding.

Override Methods

  • OnStartTextDecoding() : In this method you can whatever by the start of text decoding process.

    @Override
        public void onStartTextDecoding() {
            //Whatever you want to do at the start of text encoding
        }
  • onCompleteTextDecoding() : After the completion of text decoding, this method is called and gives result.

    @Override
        public void onCompleteTextEncoding(ImageSteganography result) {
    
            //After the completion of text encoding.
            
            //result object is instantiated 
            this.result = result;
    
            if (result != null){
                
                /* If result.isDecoded() is false, it means no Message was found in 					the image. */
                if (!result.isDecoded())
                    textView.setText("No message found");
                
                else{
                    /* If result.isSecretKeyWrong() is true, it means that secret key provided 				is wrong. */ 
                    if (!result.isSecretKeyWrong()){
                        //set the message to the UI component.
                        textView.setText("Decoded");
                        message.setText("" + result.getMessage());
                    }
                    else {
                        textView.setText("Wrong secret key");
                    }
                }
            }
            else {
                //If result is null it means that bitmap is null
                textView.setText("Select Image First");
            }
        }

Documentation

ImageSteganography Class

Java attribute Java set methods Description Default Value
Message setMessage(...) , getMessage() Set the value of message, Get the value of message. Null
Secret_Key setSecret_key(...) Set the value of secret key. Null
Image setImage(...) Set the value of image. Null
Encoded_Image getEncoded_image() Get the value of encoded image after text encoding. Null
Encoded isEncoded() Check that the encoding is over or not false
Decoded isDecoded() Check that the decoding is over or not. false
SecretKeyWrong isSecretKeyWrong() Check that the secret key provided was right or wrong but after decoding was done. true

Class Domain Diagram

Example App

There are two options Encode and Decode. In the encode section you can hide a secret message into an image without making any noticeable changes. In the decode section you can extract the message from the encoded image by inserting the correct key.

Note - After pressing the Save button, both the original and encoded images are saved at the location Android/data/com.ayush.steganography/files/Documents/<UUID>/

Encode Decode

Want to contribute !

This is the well documented library. I have documented each and every method that I have used, so have a good read to the code and suggest some changes and new feature to be added in the library.
Feel free to open an issue.

Donate

If you found this project helpful or you learned something from the source code and want to thank me, consider buying me a cup of

Contributors

Thanks goes to these wonderful people (emoji key):

Ryan Hayes
Ryan Hayes

🚧 🤔 🐛

This project follows the all-contributors specification. Contributions of any kind welcome!

License

Image Steganography is licensed under MIT license.

MIT License

Copyright (c) 2018 Ayush Agarwal

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Comments
  • Whatsapp and telegram delete the message.

    Whatsapp and telegram delete the message.

    The problem is found when you share the encoded image is shared with both app. When I downloaded the same image again, I found that both applications deleted the message

    regards

    opened by CROCDC 7
  • Gradle implementation does not resolve

    Gradle implementation does not resolve

    Describe the bug I have tried to follow your instructions to add your library to my project, When I add "implementation 'com.github.aagarwal1012:Image-Steganography-Library-Android:v1.0'" into the build.gradle I get the following error.

    ERROR: Failed to resolve: com.github.aagarwal1012:Image-Steganography-Library-Android:v1.0

    My build environment. Android Studio 3.6 Canary 5 Build #AI-191.7479.19.36.5721125, built on July 11, 2019 JRE: 1.8.0_202-release-1483-b49-5587405 amd64 JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o Linux 5.0.0-25-generic

    opened by kjbaker-uk 5
  • Decoding Error [ Incorrect Secret Key error ]

    Decoding Error [ Incorrect Secret Key error ]

    Describe the bug I am using this key - "123456789A" during encoding & decoding. Encoding is successful (despite result.getSecretKey() returning null) . But during Decoding , I receive error that Secret Key is wrong ( result.issecretkeywrong returned true). All others seems fine. Below are the screenshots of code fragments & error log. Thanks for ur assistance & the great library! Regards from Malaysia.

    encoding decoding error

    question 
    opened by rkram007 4
  • Save Fix + Threading

    Save Fix + Threading

    I couldn't save no matter what I tried, I believe this was permission related, I added a check Permissions function to check, Also changed save to be done off the UI thread, Right now not under the same conditional, I was unsure if we wanted to save the original picture again

    Great Work!

    opened by rhayes2 3
  • Base64 char support

    Base64 char support

    I had issues with the compress function,

    I noticed that the middle payload needed to base64 encoded to accept other types of chars

    I hope this helps, I can get it to decode these extra chars

    opened by rhayes2 2
  • Unable to save the encoded message

    Unable to save the encoded message

    Hi, I got an error when I built this app on my smartphone. I was not able to save the encoded image, and after I click "ENCODED" button and "SAVE IMAGE" button. I got two same error messages:

    2020-12-08 23:38:06.105 21616-21616/com.ayush.steganography E/DecorView: mWindow.mActivityCurrentConfig is null 2020-12-08 23:38:06.469 21616-21616/com.ayush.steganography E/ViewRootImpl: sendUserActionEvent() mView returned.

    Also, folder Android/data/com.ayush.steganography/files/Documents// was not showing.

    Any ideas about these two problems?

    Thanks

    opened by niusenc 1
  • The project uses Gradle 4.1 which is incompatible with Java 11 or newer

    The project uses Gradle 4.1 which is incompatible with Java 11 or newer

    Describe the bug Unable to start the daemon process.

    The project uses Gradle 4.1 which is incompatible with Java 11 or newer.

    To Reproduce Steps to reproduce the behavior: Open project with latest android studio

    Expected behavior all are ok

    Additional context Possible solution:

    • Upgrade Gradle wrapper to 4.8 version and re-import the project

    After that I see:

    FAILURE: Build failed with an exception.
    
    * What went wrong:
    A problem occurred configuring project ':app'.
    > Failed to notify project evaluation listener.
       > Could not initialize class com.android.sdklib.repository.AndroidSdkHandler
    
    * Try:
    Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    
    * Exception is:
    org.gradle.api.ProjectConfigurationException: A problem occurred configuring project ':app'.
    	at org.gradle.configuration.project.LifecycleProjectEvaluator.addConfigurationFailure(LifecycleProjectEvaluator.java:109)
    	at org.gradle.configuration.project.LifecycleProjectEvaluator.onAfterEvaluateFailure(LifecycleProjectEvaluator.java:105)
    	at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:87)
    	at org.gradle.configuration.project.LifecycleProjectEvaluator.doConfigure(LifecycleProjectEvaluator.java:72)
    	at org.gradle.configuration.project.LifecycleProjectEvaluator.access$100(LifecycleProjectEvaluator.java:37)
    	at org.gradle.configuration.project.LifecycleProjectEvaluator$ConfigureProject.run(LifecycleProjectEvaluator.java:125)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:317)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:309)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:185)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:97)
    	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
    	at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:52)
    	at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:677)
    	at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:138)
    	at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:35)
    	at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:62)
    	at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:41)
    	at org.gradle.initialization.DefaultGradleLauncher$ConfigureBuild.run(DefaultGradleLauncher.java:262)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:317)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:309)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:185)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:97)
    	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
    	at org.gradle.initialization.DefaultGradleLauncher.configureBuild(DefaultGradleLauncher.java:175)
    	at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:132)
    	at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:115)
    	at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:77)
    	at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:74)
    	at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:152)
    	at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:38)
    	at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:96)
    	at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:74)
    	at org.gradle.tooling.internal.provider.runner.ClientProvidedPhasedActionRunner.run(ClientProvidedPhasedActionRunner.java:61)
    	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    	at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
    	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.run(RunAsBuildOperationBuildActionRunner.java:47)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:317)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:309)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:185)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:97)
    	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
    	at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:43)
    	at org.gradle.tooling.internal.provider.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:51)
    	at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:50)
    	at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:46)
    	at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:65)
    	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:46)
    	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:32)
    	at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:39)
    	at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:25)
    	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:80)
    	at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:53)
    	at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:62)
    	at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:34)
    	at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:36)
    	at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:25)
    	at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
    	at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
    	at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:59)
    	at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:31)
    	at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:59)
    	at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:44)
    	at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:46)
    	at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:30)
    	at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
    	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
    	at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
    	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
    	at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
    	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
    	at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
    	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
    	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
    	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
    	at org.gradle.util.Swapper.swap(Swapper.java:38)
    	at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
    	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
    	at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
    	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
    	at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:62)
    	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
    	at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:82)
    	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
    	at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
    	at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:295)
    	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
    	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
    	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
    Caused by: org.gradle.internal.event.ListenerNotificationException: Failed to notify project evaluation listener.
    	at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:86)
    	at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:324)
    	at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:234)
    	at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:140)
    	at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:37)
    	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    	at com.sun.proxy.$Proxy37.afterEvaluate(Unknown Source)
    	at org.gradle.configuration.project.LifecycleProjectEvaluator$1.execute(LifecycleProjectEvaluator.java:83)
    	at org.gradle.configuration.project.LifecycleProjectEvaluator$1.execute(LifecycleProjectEvaluator.java:80)
    	at org.gradle.api.internal.project.DefaultProject.stepEvaluationListener(DefaultProject.java:1393)
    	at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:80)
    	... 89 more
    Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.android.sdklib.repository.AndroidSdkHandler
    	at com.android.builder.sdk.DefaultSdkLoader.init(DefaultSdkLoader.java:383)
    	at com.android.builder.sdk.DefaultSdkLoader.getSdkInfo(DefaultSdkLoader.java:366)
    	at com.android.build.gradle.internal.SdkHandler.initTarget(SdkHandler.java:168)
    	at com.android.build.gradle.BasePlugin.ensureTargetSetup(BasePlugin.java:718)
    	at com.android.build.gradle.BasePlugin.createAndroidTasks(BasePlugin.java:600)
    	at com.android.build.gradle.BasePlugin.lambda$null$3(BasePlugin.java:555)
    	at com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:81)
    	at com.android.build.gradle.BasePlugin.lambda$createTasks$4(BasePlugin.java:551)
    	at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:91)
    	at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:80)
    	at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:42)
    	at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:230)
    	at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:149)
    	at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:58)
    	... 99 more
    
    
    * Get more help at https://help.gradle.org
    
    BUILD FAILED in 4s
    
    opened by dumprop 0
  • Unable to connect to this library

    Unable to connect to this library

    I have added implementation 'com.github.aagarwal1012:Image-Steganography-Library-Android:v1.0' but, when I implements TextEncodingCallback I am getting error. Like I am unable to connect to steganography-library

    opened by b-Istiak-s 0
  • [ImgBot] Optimize images

    [ImgBot] Optimize images

    Beep boop. Your images are optimized!

    Your image file size has been reduced!

    Details

    | File | Before | After | Percent reduction | |:--|:--|:--|:--| | /images/original_encoded.png | 412.87kb | 397.59kb | 3.70% | | /images/lsb1.png | 25.29kb | 24.52kb | 3.04% | | /images/encode.gif | 1,843.02kb | 1,813.07kb | 1.63% | | /images/decode.gif | 1,335.72kb | 1,322.31kb | 1.00% | | | | | | | Total : | 3,616.90kb | 3,557.49kb | 1.64% |


    Black Lives Matter | 💰 donate | 🎓 learn | ✍🏾 sign

    📝 docs | :octocat: repo | 🙋🏾 issues | 🏅 swag | 🏪 marketplace

    opened by imgbot[bot] 0
  • Android/data/com.ayush.steganography/files/Documents/<UUID>/ location in not showing.

    Android/data/com.ayush.steganography/files/Documents// location in not showing.

    Describe the bug A clear and concise description of what the bug is.

    To Reproduce Steps to reproduce the behavior:

    1. Go to '...'
    2. Click on '....'
    3. Scroll down to '....'
    4. See error

    Expected behavior A clear and concise description of what you expected to happen.

    Screenshots If applicable, add screenshots to help explain your problem.

    Smartphone (please complete the following information):

    • Device: [e.g. iPhone6]
    • OS: [e.g. iOS8.1]
    • Browser [e.g. stock browser, safari]
    • Version [e.g. 22]

    Additional context Add any other context about the problem here.

    opened by kartikeya199819 0
  • Secret key of length >16 doesn't work

    Secret key of length >16 doesn't work

    Describe the bug If the user passes secret key of length >16 to ImageSteganography constructor the convertKeyTo128bit method won't convert it properly. Instead of: result = result.substring(0, 16); it has: result = result.substring(0, 15);

    And the encryption step fails then.

    Possible solution without the pull request It is easy to fix in the library, but if it won't be fixed here is an easy workaround:

    1. Create class ImageSteganographyV2 which extends ImageSteganography
    2. Copy the whole code(since ImageSteganography doesn't open access to fields)
    3. Fix the bug by changing 15 to 16 in "result = result.substring(0, 15);"
    4. Create ImageSteganography instances using new class. For example:

    ImageSteganography imageSteganography = new ImageSteganographyV2(message, secretKey, originalImage);

    Everything else can stay the same

    opened by vtsyvina 0
Releases(v1.1)
Owner
Ayush Agarwal
Research Intern @adobe | GSoC'20 Mentor @jenkinsci | GSoC'19 @typetools | CSE Senior @IITR | Flutter Developer @mdg-iitr
Ayush Agarwal
This is an Image slider with swipes, Here we used Volley to Image load URL's from JSON! Here we make it very easy way to load images from Internet and We customized the description font style(OpenSans).

ImageSliderWithSwipes This is an Image slider with swipes, Here we used Volley to load URL's from JSON! Here we make it very easy way to load images f

Prabhakar Thota 44 May 31, 2021
Add curve at bottom of image views and relative layouts.

Crescento Android library that adds a curve at the below of image views and relative layouts. CrescentoImageView and CrescentoContainer are the image

Shivam Satija 1.3k Nov 18, 2022
some android image filters

android-image-filter some android image filters in some filter, I use NDK to implement to make it more efficient Setup Install Android NDK and properl

RagnarokStack 643 Dec 27, 2022
An android image compression library.

Compressor Compressor is a lightweight and powerful android image compression library. Compressor will allow you to compress large photos into smaller

Zetra 6.7k Dec 31, 2022
Android widget for cropping and rotating an image.

Cropper The Cropper is an image cropping tool. It provides a way to set an image in XML and programmatically, and displays a resizable crop window on

Edmodo 2.9k Nov 14, 2022
A simple image cropping library for Android.

SimpleCropView The SimpleCropView is an image cropping library for Android. It simplifies your code for cropping image and provides an easily customiz

Issei Aoki 2.5k Dec 28, 2022
Customizable Android full screen image viewer for Fresco library supporting "pinch to zoom" and "swipe to dismiss" gestures. Made by Stfalcon

This project is no longer supported. If you're able to switch from Fresco to any other library that works with the Android's ImageView, please migrate

Stfalcon LLC 1.8k Dec 19, 2022
Add curve at bottom of image views and relative layouts.

Crescento Android library that adds a curve at the below of image views and relative layouts. CrescentoImageView and CrescentoContainer are the image

Shivam Satija 1.3k Mar 24, 2021
Dali is an image blur library for Android. It contains several modules for static blurring, live blurring and animations.

Dali Dali is an image blur library for Android. It is easy to use, fast and extensible. Dali contains several modules for either static blurring, live

Patrick Favre-Bulle 1k Dec 1, 2022
A small customizable library useful to handle an gallery image pick action built-in your app. :sunrise_over_mountains::stars:

Louvre A small customizable image picker. Useful to handle an gallery image pick action built-in your app. *Images from Google Image Search Installati

André Mion 640 Nov 19, 2022
An image resizing library for Android

Resizer Inspired by zetbaitsu's Compressor, Resizer is a lightweight and easy-to-use Android library for image scaling. It allows you to resize an ima

Kakit Ho 426 Dec 22, 2022
Auto Scrolling Image Pager with Pager Indicator and Text

AutoImageFlipper Auto Scrolling Image Pager with Pager Indicator and Text Note: It works only on Apps which are using AndroidX dependencies, if you're

Shahbaz Hussain 105 Nov 10, 2022
Simple android image popup Library

Android Image Popup Show image as a popup on a click event or any event. Simply set the image as drawable and thats it!!!. And also you can set width,

Chathura Lakmal 64 Nov 15, 2022
Library to save image locally and shows options to open and share !

Image Save and Share Library to save image locally and shows options to open and share ! Download Demo APK from HERE Kindly use the following links to

Prabhakar Thota 27 Apr 18, 2022
Image loading library for Android

Image Loader Image loader library for Android. Deprecated. See Glide. Features Image transformations Automatic memory and storage caching Ability to l

Yuriy Budiyev 19 May 28, 2022
RoundedImageView-Library 0.9 0.0 Java To set single or multiple corners on Image Views.

RoundedImageView-Library Rounded ImageView Android Library, to set single or multiple corners on imageview. Screenshot Usage Step 1. Add the JitPack r

Dushyant Mainwal 15 Sep 2, 2020
A library for image manipulation with power of renderScript which is faster than other ordinary solutions.

Pixl is a library for image manipulation with power of renderScript which is faster than other ordinary solutions, currently it includes three basic scripts, brightness, contrast, saturation.

Jibran Iqbal 20 Jan 23, 2022
Phimp.me Android Phimp.me is an Android image editor app

Phimp.me Android Phimp.me is an Android image editor app that aims to replace proprietary photographing and image apps on smart phones. It offers feat

FOSSASIA 2.6k Jan 6, 2023
Image Cropping Library for Android, optimised for Camera / Gallery.

Image Cropping Library for Android, optimised for Camera / Gallery.

CanHub 812 Dec 30, 2022