Compress Images Size in Phimpme Android application

In the Phimpme Android application, users can perform various operations on images such as editing an image, sharing an image, moving the image to another folder, printing a pdf version of the image and many more. However, another important functionality that has been implemented is the option to compress an image. Two modes of compress operation have been implemented namely compress by size and compress by dimensions. So in this blog post, I will be discussing how we achieved the functionality to compress any image by size. Step 1 First, we need to add an option in the bottom bar menu(in the SingleMediaActivity) to compress the image being viewed. The option to compress an image has been added by implementing the following lines of code in the  menu_bottom_view_pager.xml file. <item       android:id="@+id/action_compress"       android:orderInCategory="2"       app:showAsAction="always"       android:icon="@drawable/compressicn"       android:title="Compress"/> Step 2 Now on selecting the compress option, the user would be prompted to choose the compress mode i.e compress by size or compress by dimension. Once the user has opted for the size mode a dialog with a seekbar to set the compress percentage is to be displayed. Code snippets used to implement the dialog along with seekbar is displayed below. <RelativeLayout   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:layout_marginTop="8dp">   <SeekBar       android:id="@+id/seekBar"       android:layout_width="match_parent"       android:layout_height="wrap_content"       android:layout_weight="0.65"       android:max="90"       android:progressBackgroundTint="@color/colorPrimary"       android:thumb="@drawable/ic_location_on_black_24dp" />   <TextView       android:id="@+id/textview2"       android:layout_width="wrap_content"       android:layout_height="wrap_content"       android:layout_alignParentEnd="true"       android:layout_below="@+id/seekBar"       android:layout_marginBottom="5dp"       android:layout_marginEnd="16dp"       android:text="95%"       android:textAppearance="@style/TextAppearance.AppCompat.Body1"       android:textSize="16sp" /> </RelativeLayout> A screenshot displaying the dialog to set the compress percentage is provided below Step 3 Here to obtain the compress functionality we have used an open-sourced custom image compression library Compressor. After the user has set the compress percentage, the Compressor class of the library is instantiated by passing-in the context as the parameter and some of its functions are invoked simultaneously. The functions invoked are setQuality(), setCompressFormat(), setDestinationDirectoryPath(), compressToFile(). setQuality(int) - to set the percentage compressed. setCompressFormat(Bitmap.CompressFormat) - to determine the format of the output compressed image. setDestinationDirectoryPath(File) - to specify the path to which the compressed image is to be saved. compressToFile(File) - to perform the compress operation, passing-in the file object of the corresponding image to be compressed. The compressToFile() function performs the final compress operation and saves the compressed image to the specified path. Code snippets to implement the above-mentioned operations are given below private void compressSize() {   LayoutInflater inflater = getLayoutInflater();   View dialogLayout = inflater.inflate(R.layout.dialog_compresssize, null);   TextView title = (TextView) dialogLayout.findViewById(R.id.compress_title);   title.setBackgroundColor(getPrimaryColor());   SeekBar percentsize = (SeekBar) dialogLayout.findViewById(R.id.seekBar);   percentsize.getThumb().setColorFilter(getAccentColor(), PorterDuff.Mode.SRC_IN);   percentsize.setProgress(0);   final TextView percent=(TextView)dialogLayout.findViewById(R.id.textview2);   percentsize.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {       @Override       public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {           //options of compress by size from 5% to 9;           int progress1=95-progress;           progress1=progress1-progress1%5;           percent.setText(progress1+"%");           percentagecompress=progress1;}       @Override       public void onStartTrackingTouch(SeekBar seekBar) {           //do nothing       }       @Override       public void onStopTrackingTouch(SeekBar seekBar) {           //do nothing       }   });} new Compressor(getApplicationContext()) .setQuality(percentagecompress) .setCompressFormat(Bitmap.CompressFormat.JPEG) .setDestinationDirectoryPath(FileUtilsCompress.createFolders().getPath()) .compressToFile(new File(saveFilePath)); This is how we have implemented the functionality to compress an image by size in the Phimpme Android application. To get the full source code, please refer to the Phimpme Android Github repository. Resources Android Developer documentation -https://developer.android.com/reference/java/io/File Compressor Library - https://github.com/zetbaitsu/Compressor Seekbar Tutorial - https://abhiandroid.com/ui/seekbar

Continue ReadingCompress Images Size in Phimpme Android application

Implementing the discrete Seekbar for Wave Generator

The Wave Generator instrument in PSLab Android app allows us to produce waveforms having different values of properties like frequency, duty, phase etc. The range of these properties allowed by PSLab Device are : Table showing the range of properties that can be set for waves by PSLab device Wave Property Range Min Max Step Size Frequency 10 Hz 5000 Hz 1 Hz Phase 0° 360° 1° Duty 10% 100% 10% We can set these values using the up/down arrow buttons provided by the wave generator but the problem is that the range of values is very high and least counts are small so it is convenient to set the values using only the up and down arrow buttons. Therefore we need something that could allow us to directly set any value of our choice while keeping the UI interactive. The solution to this problem - “Discrete Seekbar”. It contains a slider having points at equal intervals and whose length represents the range of the values and a head that slides over the slider and is used to select a specific value from a range of values. I have included the discrete Seekbar in Wave Generator by using a third-party library if you want to add Seekbar directly you can do that by directly using the default Seekbar widget provided by Android SDK and setting the following attribute in as shown below. android:theme = “@style/Widget.AppCompat.SeekBar.Discrete” Refer to this post[2] for implementing Seekbar directly without an external library. The reason I chose this library is that:- It offers various implementation of different types of Seekbar like discrete and continuous. Implementation of Seekbar is simpler and it offers various customizations like thumb color, track color, tick text etc.   In following steps I will implement the discrete Seekbar: Step 1 Adding the dependency For this project, I will be using an external library “IndicatorSeekbarLibrary” by Warkiz[1], for adding the dependency we need to include the following code in our build.gradle file. dependencies{ implementation 'com.github.warkiz.widget:indicatorseekbar:2.0.9' } Step 2 Including the Seekbar in layout For this step, we need to add the Seekbar widget using <com.warkiz.widget.IndicatorSeekBar> XML tag in our wave generator layout file to include the Seekbar in our layout as shown in the code below: <com.warkiz.widget.IndicatorSeekBar android:layout_width="match_parent" android:layout_height="wrap_content" app:isb_max="5000" app:isb_min="0" app:isb_ticks_count="5" app:isb_thumb_color="@color/color_green" app:isb_thumb_size="20dp" app:isb_track_background_color="@color/color_gray" app:isb_track_background_size="2dp" app:isb_track_progress_color="@color/color_blue" app:isb_track_progress_size="4dp" /> Some important attributes used above: app:isb_max : defines the max value that can be achieved by the Seekbar. app:isb_min :  defines the min value that can be achieved by the Seekbar app:isb_ticks_count: no. of ticks(interval) that has to be shown on the slider We can see different components of Seekbar like track, indicator, thumb, tick of SeekBar in the following diagram[2]. Step 3 Attaching the listener to the Seekbar in Java file In this step we need to attach the listener to the Seekbar to record changes in the Seekbar made by the user, for this we will create a new listener with the help of onSeekBarChangeListener interface and attach it with the Seekbar as shown in following code…

Continue ReadingImplementing the discrete Seekbar for Wave Generator

Custom SeekBar in PSLab Android

By default Seekbar in Android only return integer values greater than zero. But there can be some situation where we need the SeekBar to return a float and negative values. To implement trigger functionality in the Oscilloscope activity of PSLab Android app, we require a SeekBar that sets a voltage level that should trigger the capture sequence. Since this voltage value ranges between -16.5 V to 16.5 V, default Seekbar don't serve the purpose. The solution is to create a custom SeekBar that returns float values. Let’s understand how to implement it. Create a FloatSeekBar class which extends AppCompatSeekBar. Create a constructor for the class with Context, AttributeSet and defStyle as parameters. AttributeSet is the set of properties specified in an XML resource file whereas defStyle is default style to apply to this view. public class FloatSeekBar extends android.support.v7.widget.AppCompatSeekBar { private double max = 0.0; private double min = 0.0; public FloatSeekBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); applyAttrs(attrs); }   Then define setters method which set the max and min values of the SeekBar. This method basically sets the range of the SeekBar. public void setters(double a, double b) { min = a; max = b; }   getValue is a method that manipulates current progress of the SeekBar and returns the value. Here the equation used to determine the value is (max - min) * (getProgress() / getMax()) + min. public double getValue() { DecimalFormat df = new DecimalFormat("#.##"); Double value = (max - min) * ((float) getProgress() / (float) getMax()) + min; value = Double.valueOf(df.format(value)); return value; }   setValue method takes the double value, and accordingly set the progress of the SeekBar. public void setValue(double value) { setProgress((int) ((value - min) / (max - min) * getMax())); } This creates a custom SeekBar, it can be used just like a normal SeekBar. Now, set the range of custom SeekBar between -16.5 and 16.5. seekBarTrigger = (FloatSeekBar) v.findViewById(R.id.seekBar_trigger); seekBarTrigger.setters(-16.5, 16.5);   In order to get value of the custom SeekBar call getValue method. seekBarTrigger.getValue(); In order to follow the entire code for custom SeekBar implementation in PSLab refer FloatSeekBar.java, Attr.xml and TimebaseTrigger.java. A glimpse of custom SeekBar in PSLab Android. Resources Android.com reference for AttributeSet Android.com reference for Custom Attributes Niusounds: Custom SeekBar for Android  

Continue ReadingCustom SeekBar in PSLab Android