How do you scale images to 60% in Wordpress 3.9? - image-scaling

In previous versions of Wordpress images could be automatically scaled to 60% with one click. Now in Wordpress 3.9 the only automatic scaling is Thumbnail, Medium, and Full Size. I could chose Custom Size or drag it to the approximate size I want, but Custom Size requires me to compute 60% myself and dragging it is inexact.
All of my images are different heights and widths. They are images of a written font so the font size needs to be the same for every image, even though the height and width are different. In the past I just made all of my images display at 60%. Is there a way to do that in Wordpress 3.9?

Since I couldn't find a better long term method, I just wrote some Java code to do the job. This way I can just cut and paste from the HTML view.
import java.util.Scanner;
public class ImageResizer {
public static void main(String[] args) {
Scanner userInput = new Scanner(System.in);
String inputString;
String outputString;
System.out.print("Default resize is 60%\n");
System.out.print("Type \"exit\" to quit: \n\n");
do {
// input something like:
// width="208" height="425"
System.out.print("Enter html: ");
inputString = userInput.nextLine();
outputString = resize(inputString);
System.out.print(outputString + "\n");
} while (!inputString.equals("exit"));
}
public static String resize(String myString) {
final int RESIZE_PERCENT = 60;
// parse input string
String delims = "[ ]+"; // spaces
String[] tokens = myString.split(delims);
for (int i = 0; i < tokens.length; i++) {
if (tokens[i].startsWith("width") || tokens[i].startsWith("height")) {
// extract the height/width number
String subDelims = "[\"]"; // quote mark
String[] subTokens = tokens[i].split(subDelims);
int number = Integer.parseInt(subTokens[1]);
number = number * RESIZE_PERCENT / 100;
// rebuild string
tokens[i] = subTokens[0] + "\"" + number + "\"";
}
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < tokens.length; i++) {
sb.append(tokens[i]);
if ((i + 1) < tokens.length) {
sb.append(" ");
}
}
return sb.toString();
}
}

Related

How is a JPEG file formated?

I'm trying to write Bytes into a JPEG file, but I don't know the file's format and so the Bytes aren't in the right place of the image after writing into the file.
Does somebody know?
There are several markers that must appear in a JPEG file stream. I believe you can easily find the detailed description of the tags listed below on Internet.
SOI(0xFFD8) Start of Image
APP0(0xFFE0) Application
[APPn(0xFFEn)] (alternative)
DQT(0xFFDB) Define Quantization Table
SOF0(0xFFC0) Start of Frame
DHT(0xFFC4) Difine Huffman Table
SOS(0xFFDA) Start of Scan
DRI(0xFFDD) Define Restart Interval,(alternative)
...Image Stream
EOI(0xFFD9) End of Image
Those markers are followed by lengths in BIG ENDIAN format. You can decode Image Stream that exactly follows DRI using the huffman trees you decoded by DQT. For easier illustration, here are some functions I have written on my own in Java that decodes a header of JPEG, but without doubt there are many better JPEG Java projects on Github that you can refer to.
public int[][] cutX(byte[] x){
int s = x.length;int k = 1;int i = 2;int j;
d2[0][0]=Tool.unsignDecoder(x[1]);d2[1][0]=0;d2[2][0]=1;
while(d2[0][k-1]!=218){
d2[1][k]=i;
d2[0][k]=Tool.unsignDecoder(x[i+1]);
i=i+2+Tool.unsignDecoder(x[i+2])*256+Tool.unsignDecoder(x[i+3]);
d2[2][k]=i-1;
k=k+1;
}
for (j=s-1;j<i;j--){
if((Tool.unsignDecoder(x[j-1])==255)&&(Tool.unsignDecoder(x[j])==217)) break;
}
d2[0][k]=217;d2[1][k]=i;d2[2][k]=j+1;
return d2;
}
public void cutdata(byte[] x,int[][] d){
int a =Tool.indexOf_1(d[0],218);
int b =Tool.indexOf_1(d[0],217);
head = Arrays.copyOfRange(x, 0, d[2][a]+1);
byte[] im = Arrays.copyOfRange(x, d[1][b], d[2][b]-1);//-2:delete the last EOI message.
im1 = new byte[im.length];
int j=0;int i=0;//dynamically record the length of the revised sequence
while(i<im.length){
im1[j]=im[i];
j++;
if((i!=im.length-1)&&(Tool.unsignDecoder(im[i])==255)&&(Tool.unsignDecoder(im[i+1]))==0){
i++;//move rightward i
}
i++;
}
im1=Arrays.copyOfRange(im1, 0, j);//delete zeros in the end of the sequence
}
public void sof(byte[] x,int[][] d){
int z = Tool.indexOf_1(d[0],192);
int i = d[1][z];
int[] temp = new int[19];
for(int j=0;j<19;j++){
temp[j]=Tool.unsignDecoder(x[j+i]);
}
int ph=i+5;int pw=i+7;
size[0] = Tool.unsignDecoder(x[ph])*256+Tool.unsignDecoder(x[ph+1]);
size[1] = Tool.unsignDecoder(x[pw])*256+Tool.unsignDecoder(x[pw+1]);
i += 11;//skip some unused letters
for(int j=0;j<3;j++){
int k = Tool.unsignDecoder(x[i]);
Q[j][0] = (k & 0xF0)/16;
Q[j][1] = k & 0x0F;
i += 3;
}
}
public void hfm(byte[] x,int[][] d){
//the DHT marker may appear several times in a JPEG, or several huffman trees can be found in a single DHT.
ArrayList res =Tool.indexOf(d[0],196);int thisLength;int pointer;int pointerOrigin;
int a;int huffLength = 0;
for(int z=0;z<res.size();z++){
a=(int) res.get(z);
pointer = d[1][a];pointerOrigin = d[1][a]+2;//please follow the straight-forward moving of this pointer
thisLength = Tool.unsignDecoder(x[pointer+2])*256+Tool.unsignDecoder(x[pointer+3]);
int[] temp = new int[thisLength+4];
for(int i=0;i<thisLength;i++){
temp[i]=Tool.unsignDecoder(x[pointer+i]);
}
pointer += 4;
while(huffLength<thisLength){
int mode = Tool.unsignDecoder(x[pointer]);pointer += 1;
int[] huff_num = new int[16];int total=0;
for(int i=0;i<16;i++){//码字总个数
huff_num[i] = x[pointer+i];total+=huff_num[i];
}
pointer +=16;int codePointer=0;int code=0;
int[][] huffmanTree = new int[3][total];
for(int i=0;i<16;i++){
if(i!=0){
code *= 2;
}
for(int j=0;j<huff_num[i];j++){
huffmanTree[0][codePointer]=i+1;
huffmanTree[1][codePointer]=code;
huffmanTree[2][codePointer]=Tool.unsignDecoder(x[pointer+codePointer]);
code++;codePointer++;
}
}
huffLength += pointer + codePointer - pointerOrigin;pointer += codePointer;
pointerOrigin = pointer;
switch(mode){
case(0):d0 = huffmanTree;break;
case(1):d1 = huffmanTree;break;
case(16):a0 = huffmanTree;break;
case(17):a1 = huffmanTree;break;
}
}
}
}
public void dri(byte[] x,int[][] d){
int z = Tool.indexOf_1(d[0],221);
if(z!=-1){
int pointer = d[1][z];
int len = Tool.unsignDecoder(x[pointer+2])*256+Tool.unsignDecoder(x[pointer+3]);
int[] temp = new int[len+2];
for(int i=0;i<len;i++){
temp[i]=Tool.unsignDecoder(x[pointer+i]);
}
DRI = Tool.unsignDecoder(x[d[1][z]+4])*256+Tool.unsignDecoder(x[d[1][z]+5]);}
}
public void sos(byte[] x,int[][] d){
int z = Tool.indexOf_1(d[0],218);int a = d[1][z];
int len = Tool.unsignDecoder(x[a+2])*256+Tool.unsignDecoder(x[a+3]);
int[] temp = new int[len+2];
for(int j=0;j<len+2;j++){
temp[j]=Tool.unsignDecoder(x[j+a]);
}
int pointer = d[1][z]+6;
for(int j=0;j<3;j++){
treeSelect[j] = Tool.unsignDecoder(x[pointer]);
pointer += 2;
}
}

Reversing the letters in words in a String

I have coded the following solution, and it works, except for when there is punctuation. I was wondering if there are O(1) space complexity and O(length of string) time complexity solutions, without using reverse() method, or anything similar that makes this task too easy. Any answer that can also handle punctuation correctly would be great.
Example:
Given string: "I love chocolate"
Return string should be: "I evol etalocohc"
For clarity, when I say handle punctuation correctly, I mean punctuation should not move around.
// reverse the letters of every word in a sentence (string), and return the result
public static String reverse(String x)
{
String[] str = x.split(" ");
StringBuilder rev = new StringBuilder("");
for (int i = 0; i < str.length; i++)
{
for (int s = str[i].length()-1; s >= 0; s--)
{
rev.append(str[i].charAt(s));
}
rev.append(" ");
}
return rev.toString();
}
Here is my output for some tests of mine:
public static void main(String[] args)
{
System.out.println(reverse("I love chocolate"));//this passes
System.out.println(reverse("Geeks for Geeks"));//this passes
System.out.println(reverse("You, are awesome"));//not handling puncutation mark correctly, gives me ",uoY era emosewa", instead of "uoY, era emosewa"
System.out.println(reverse("Geeks! for Geeks."));//not handling puncutation marks correctly, gives me "!skeeG rof .skeeG", instead of "skeeG! rof skeeG."
}
This would probably work with the punctuation:
public static String reverse(String x)
{
String[] str = x.split("\\W"); //Split on non-word characters.
StringBuilder rev = new StringBuilder("");
int currentPosition = 0;
for (int i = 0; i < str.length; i++)
{
for (int s = str[i].length()-1; s >= 0; s--)
{
rev.append(str[i].charAt(s));
currentPosition++;
}
while (currentPosition < x.length() && Character.toString(x.charAt(currentPosition)).matches("\\W"))
rev.append(x.charAt(currentPosition++)); //Add the actual character there.
}
return rev.toString();
}
Haven't coded in Java in a while now so I know it's probably not best practices here.
Complexity is O(n) (space and time).
If you start off with a string builder you might be able to lower space complexity by using in-place character swaps instead of appending, but you'd need to preemptively find where all the non-word characters are.
Here is an implementation which uses in-place reversing of words requiring only O(1) storage. In addition, the reversing algorithm itself is O(N) with the length of the string.
The basic algorithm is to walk down the string until hitting a space. Then, the swap() method is called to reverse that particular word in place. It only needs at any moment one extra character.
This approach may not be as performant as the accepted answer due to its heavy use of StringBuilder manipulations. But this might something to consider in an environment like an Android application where space is very precious.
public static void swap(StringBuilder input, int start, int end) {
for (int i=0; i <= (end - start) / 2; ++i) {
char ch = input.charAt(start + i);
input.setCharAt(start + i, input.charAt(end - i));
input.setCharAt(end - i, ch);
}
}
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("I love chocolate");
int start = 0;
int end = 0;
while (true) {
while (end <= sb.length() - 1 && sb.charAt(end) != ' ') {
++end;
}
swap(sb, start, end - 1);
start = end + 1;
end = start;
if (end > sb.length() - 1) {
break;
}
}
System.out.println(sb);
}
Demo here:
Rextester
A compact solution is
public static String reverse(String x) {
Matcher m = Pattern.compile("\\w+").matcher(x);
if(!m.find()) return x;
StringBuffer target = new StringBuffer(x.length());
do m.appendReplacement(target, new StringBuilder(m.group()).reverse().toString());
while(m.find());
return m.appendTail(target).toString();
}
The appendReplacement loop + appendTail on a Matcher is the manual equivalent of String.replaceAll(regex), intended to support exactly such cases where the replacement is more complex than a simple string with placeholders, like reversing the found words.
Unfortunately, we have to use the outdated StringBuffer here, as the API is older than StringBuilder. Java 9 is going to change that.
A potentially more efficient alternative is
public static String reverse(String x) {
Matcher m = Pattern.compile("\\w+").matcher(x);
if(!m.find()) return x;
StringBuilder target = new StringBuilder(x.length());
int last=0;
do {
int s = m.start(), e = m.end();
target.append(x, last, s).append(new StringBuilder(e-s).append(x, s, e).reverse());
last = e;
}
while(m.find());
return target.append(x, last, x.length()).toString();
}
This uses StringBuilder throughout the operation and usese the feature to append partial character sequences, not creating intermediate strings for the match and replacement. It also elides the search for placeholders in the replacement, which appendReplacement does internally.
I just have made changes on your code, not additional methods or loops, just some variables and if conditions.
/* Soner - The methods reverse a string with preserving punctiations */
public static String reverse(String x) {
String[] str = x.split(" ");
boolean flag = false;
int lastCharPosition;
StringBuilder rev = new StringBuilder("");
for (int i = 0; i < str.length; i++) {
flag = false;
lastCharPosition = str[i].length()-1;
if (str[i].charAt(lastCharPosition) == '.' || str[i].charAt(lastCharPosition) == '!'
|| str[i].charAt(lastCharPosition) == ',') { // you can add new punctiations
flag = true;
lastCharPosition = str[i].length()-2;
}
for (int s = lastCharPosition; s >= 0; s--) {
rev.append(str[i].charAt(s));
}
if (flag) rev.append(str[i].charAt(lastCharPosition + 1));
rev.append(" ");
}
return rev.toString();
}

Index out of range exception while reading pixel data

Related post: Stride of the BitmapData is different than the original
dimension.
I have taken the source code from here and modified it.
The code is generating a variety of exceptions in different occasions.
.
Error in BitmapLocker.cs
At the following line in Lock(),
// Copy data from IntegerPointer to _imageData
Marshal.Copy(IntegerPointer, _imageData, 0, _imageData.Length);
The following exception is being generated:
An unhandled exception of type 'System.AccessViolationException'
occurred in mscorlib.dll
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
For the following driver code,
double[,] mask = new double[,]
{
{ .11, .11, .11, },
{ .11, .11, .11, },
{ .11, .11, .11, },
};
Bitmap bitmap = ImageDataConverter.ToBitmap(mask);
BitmapLocker locker = new BitmapLocker(bitmap);
locker.Lock();
for (int i = 0; i < bitmap.Width; i++)
{
for (int j = 0; j < bitmap.Height; j++)
{
Color c = locker.GetPixel(i, j);
locker.SetPixel(i, j, c);
}
}
locker.Unlock();
At the following line in GetPixel(),
if (i > dataLength)
{
throw new IndexOutOfRangeException();
}
An unhandled exception of type 'System.IndexOutOfRangeException'
occurred in Simple.ImageProcessing.Framework.dll
Additional information: Index was outside the bounds of the array.
.
At the following line in SetPixel(),
if (ColorDepth == 8)
{
_imageData[i] = color.B;
}
An unhandled exception of type 'System.Exception' occurred in
Simple.ImageProcessing.Framework.dll
Additional information: (0, 0), 262144, Index was outside the bounds
of the array., i=262144
.
Error in Driver program
At the line,
Color c = bmp.GetPixel(i, j);
An unhandled exception of type 'System.InvalidOperationException'
occurred in System.Drawing.dll
Additional information: Bitmap region is already locked.
Source Code:
public class BitmapLocker : IDisposable
{
//private properties
Bitmap _bitmap = null;
bool _isLocked = false;
BitmapData _bitmapData = null;
private byte[] _imageData = null;
//public properties
public IntPtr IntegerPointer { get; private set; }
public int Width { get { return _bitmap.Width; } }
public int Height { get { return _bitmap.Height; } }
public int Stride { get { return _bitmapData.Stride; } }
public int ColorDepth { get { return Bitmap.GetPixelFormatSize(_bitmap.PixelFormat); } }
public int Channels { get { return ColorDepth / 8; } }
public int PaddingOffset { get { return _bitmapData.Stride - (_bitmap.Width * Channels); } }
public PixelFormat ImagePixelFormat { get { return _bitmap.PixelFormat; } }
public bool IsGrayscale { get { return Grayscale.IsGrayscale(_bitmap); } }
//Constructor
public BitmapLocker(Bitmap source)
{
IntegerPointer = IntPtr.Zero;
this._bitmap = source;
}
/// Lock bitmap
public void Lock()
{
if (_isLocked == false)
{
try
{
// Lock bitmap (so that no movement of data by .NET framework) and return bitmap data
_bitmapData = _bitmap.LockBits(
new Rectangle(0, 0, _bitmap.Width, _bitmap.Height),
ImageLockMode.ReadWrite,
_bitmap.PixelFormat);
// Create byte array to copy pixel values
int noOfBitsNeededForStorage = _bitmapData.Stride * _bitmapData.Height;
int noOfBytesNeededForStorage = noOfBitsNeededForStorage / 8;
_imageData = new byte[noOfBytesNeededForStorage * ColorDepth];//# of bytes needed for storage
IntegerPointer = _bitmapData.Scan0;
// Copy data from IntegerPointer to _imageData
Marshal.Copy(IntegerPointer, _imageData, 0, _imageData.Length);
_isLocked = true;
}
catch (Exception)
{
throw;
}
}
else
{
throw new Exception("Bitmap is already locked.");
}
}
/// Unlock bitmap
public void Unlock()
{
if (_isLocked == true)
{
try
{
// Copy data from _imageData to IntegerPointer
Marshal.Copy(_imageData, 0, IntegerPointer, _imageData.Length);
// Unlock bitmap data
_bitmap.UnlockBits(_bitmapData);
_isLocked = false;
}
catch (Exception)
{
throw;
}
}
else
{
throw new Exception("Bitmap is not locked.");
}
}
public Color GetPixel(int x, int y)
{
Color clr = Color.Empty;
// Get color components count
int channels = ColorDepth / 8;
// Get start index of the specified pixel
int i = (Height - y - 1) * Stride + x * channels;
int dataLength = _imageData.Length - channels;
if (i > dataLength)
{
throw new IndexOutOfRangeException();
}
if (ColorDepth == 32) // For 32 bpp get Red, Green, Blue and Alpha
{
byte b = _imageData[i];
byte g = _imageData[i + 1];
byte r = _imageData[i + 2];
byte a = _imageData[i + 3]; // a
clr = Color.FromArgb(a, r, g, b);
}
if (ColorDepth == 24) // For 24 bpp get Red, Green and Blue
{
byte b = _imageData[i];
byte g = _imageData[i + 1];
byte r = _imageData[i + 2];
clr = Color.FromArgb(r, g, b);
}
if (ColorDepth == 8)
// For 8 bpp get color value (Red, Green and Blue values are the same)
{
byte c = _imageData[i];
clr = Color.FromArgb(c, c, c);
}
return clr;
}
public void SetPixel(int x, int y, Color color)
{
// Get color components count
int cCount = ColorDepth / 8;
// Get start index of the specified pixel
int i = ((Height - y -1) * Stride + x * cCount);
try
{
if (ColorDepth == 32) // For 32 bpp set Red, Green, Blue and Alpha
{
_imageData[i] = color.B;
_imageData[i + 1] = color.G;
_imageData[i + 2] = color.R;
_imageData[i + 3] = color.A;
}
if (ColorDepth == 24) // For 24 bpp set Red, Green and Blue
{
_imageData[i] = color.B;
_imageData[i + 1] = color.G;
_imageData[i + 2] = color.R;
}
if (ColorDepth == 8)
// For 8 bpp set color value (Red, Green and Blue values are the same)
{
_imageData[i] = color.B;
}
}
catch(Exception ex)
{
throw new Exception("("+x+", "+y+"), "+_imageData.Length+", "+ ex.Message+", i=" + i);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// free managed resources
_bitmap = null;
_bitmapData = null;_imageData = null;IntegerPointer = IntPtr.Zero;
}
// free native resources if there are any.
//private properties
//public properties
}
}
.
ImageDataConverter.cs
public static Bitmap ToBitmap(double[,] input)
{
int width = input.GetLength(0);
int height = input.GetLength(1);
Bitmap output = Grayscale.CreateGrayscaleImage(width, height);
BitmapData data = output.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly,
output.PixelFormat);
int pixelSize = System.Drawing.Image.GetPixelFormatSize(PixelFormat.Format8bppIndexed) / 8;
int offset = data.Stride - width * pixelSize;
double Min = 0.0;
double Max = 255.0;
unsafe
{
byte* address = (byte*)data.Scan0.ToPointer();
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
double v = 255 * (input[x, y] - Min) / (Max - Min);
byte value = unchecked((byte)v);
for (int c = 0; c < pixelSize; c++, address++)
{
*address = value;
}
}
address += offset;
}
}
output.UnlockBits(data);
return output;
}
Here is the picture I used for the test,
int noOfBitsNeededForStorage = _bitmapData.Stride * _bitmapData.Height;
That is the most essential bug in the code. Stride * Height are the number of bytes needed for storage. So it doesn't make the _imageData array large enough and IndexOutOfRangeException is the expected outcome.
int pixelSize = System.Drawing.Image.GetPixelFormatSize(PixelFormat.Format8bppIndexed) / 8;
Lots of possible mishaps from this statement. It hard-codes the pixel format to 8bpp but that is not the actual pixel format that the LockBits() call used. Which was output.PixelFormat. Notably fatal on the sample image, although it is not clear how it is used in the code, 8bpp is a very awkward pixel format since it requires a palette. The PNG codec will create a 32bpp image in memory, even though the original file uses 8bpp. You must use output.PixelFormat here to get a match with the locked data and adjust the pixel writing code accordingly. Not clear why it is being used at all, the SetPixel() method provided by the library code should already be good enough.
int dataLength = _imageData.Length - channels;
Unclear what that statement tries to do, subtracting the number of channels is not a sensible operation. It will generate a spurious IndexOutOfRangeException. There is no obvious reason to help, the CLR already provides array index checking on the _imageData array. So just delete that code.
Additional information: Bitmap region is already locked.
Exception handling in the code is not confident, a possible reason for this exception. In general it must be noted that the underlying bitmap is completely inaccessible, other than through _imageData, after the Lock() method was called and Unlock() wasn't called yet. Best way to do this is with try/finally with the Unlock() call in the finally block so you can always be sure that the bitmap doesn't remain locked by accident.
byte c = _imageData[i];
This is not correct, except in the corner case of an 8bpp image that has a palette that was explicitly created to handle grayscale images. The default palette for an 8bpp image does not qualify that requirement nor is it something you can blindly rely on when loading images from a file. Indexed pixel formats where a dreadful hack that was necessary in the early 1990s because video adapters where not yet powerful enough. It no longer makes any sense at all today. Note that SetPixel() also doesn't handle a 16-bit pixel formats. And that the PNG codec will never create an 8bpp memory image and cannot encode an 8bpp file. Best advice is to eliminate 8bpp support completely to arrive at more reliable code.
In fact, the point of directly accessing pixel data is to make image manipulation fast. There is only one pixel format that consistently produces fast code, it is Format32bppArgb. The pixels can now be accessed with an int* instead of a byte*, moving pixels ~4 times faster. And no special tweaks are necessary to deal with stride or special-case the code for methods like SetPixel(). So pass that format into LockBits(), the codec will do the work necessary if the actual image format is not 32bpp as well.
I should note that Format32bppPArgb is the fast pixel format for displaying images on the screen since it is compatible with the pixel format used by all modern video adapters. But that isn't the point of this code and dealing with the pre-multiplied alpha is awkward.

Why is if-else for String faster than switch-case for enum?

As Java 6 does not have switch-case for String, I often change an if-else block to switch-case using enum as in the code below. However, when I tried to check the performance of the two alternatives, I found that switch-case to be slower than the if-else alternative, contrary to what I had expected. Here are some of the results that I got for the code below
Iterations If-Else Switch-Case
1 11810 1609181
10 8214 1059115
100 24141 1152494
1000 183975 1580605
10000 4452698 8710648
100000 7069243 19457585
package conditionals;
import java.util.Random;
public class StringConditionalCheck {
private static int ifElseCounter = 0;
private static int switchCaseCounter = 0;
private static final String first = "First";
private static final String second = "Second";
private static final String third = "Third";
private static final String fourth = "Fourth";
enum StringOptions {
First, Second, Third, Fourth
}
public static void main(String[] args) {
final int iterations = Integer.parseInt(args[0]);
String[] userInputs = generateUserInputs(iterations);
// Using if-else
long ifelseStartTime = System.nanoTime();
for(int i=0; i<iterations; i++){
useIfElse(userInputs[i]);
}
long ifelseEndTime = System.nanoTime();
long ifElseDuration = ifelseEndTime - ifelseStartTime;
long switchcaseStartTime = System.nanoTime();
for(int i=0; i<iterations; i++){
useSwitchCase(userInputs[i]);
}
long switchcaseEndTime = System.nanoTime();
//just to verify that both options had the same result.
long switchcaseDuration = switchcaseEndTime - switchcaseStartTime;
System.out.println(iterations + " " + ifElseDuration + " " + switchcaseDuration + " " + ifElseCounter + " " + switchCaseCounter);
}
private static String[] generateUserInputs(int numberOfInputs) {
String[] generatedInputs = new String[numberOfInputs];
String[] inputsToChooseFrom = new String[]{first, second, third, fourth};
Random r = new Random();
for (int i = 0; i < numberOfInputs; i++) {
int choice = r.nextInt(4);
generatedInputs[i] = inputsToChooseFrom[choice];
}
return generatedInputs;
}
public static void useSwitchCase(String input) {
StringOptions option = StringOptions.valueOf(input);
switch(option){
case First:
switchCaseCounter += 1;
break;
case Second:
switchCaseCounter += 2;
break;
case Third:
switchCaseCounter += 3;
break;
case Fourth:
switchCaseCounter += 4;
break;
}
}
public static void useIfElse(String input) {
if(input.equals("First")){
ifElseCounter += 1;
}else if(input.equals("Second")){
ifElseCounter += 2;
}else if(input.equals("Third")){
ifElseCounter += 3;
}else if(input.equals("Fourth")){
ifElseCounter += 4;
}
}
}
What is the cause for this difference? I was expecting that if-else would be slower as there will be more comparisons on average.
Because 99% of your time is being spent in StringOptions option = StringOptions.valueOf(input);, not in the switch
Based on the source code, the StringOptions.valueOf call does several complicated things, including building a HashMap every call, whereas String.equals simply loops through the string once.
Compare the source code for Enum.valueOf (which calls Enum.getConstantDirectory) to String.equals.

Array of Images

I'm working on a blackberry project and for that I need to create grid layout. I'm working on "Blackberry java sdk".
I'm using this code
public class GridScreen extends UiApplication {
// main method
public static void main(String[] args) {
GridScreen theApp = new GridScreen();
UiApplication.getUiApplication().pushScreen(new GFMScreen());
theApp.enterEventDispatcher();
}
}
// VFM
class GFMScreen extends MainScreen {
public GFMScreen() {
// this doesnt do anything for VCENTER!!
//super(Field.USE_ALL_HEIGHT);
// create a grid field manager, with 2 cols and 0 style param for super class
// style of Manager.FIELD_VCENTER | Field.USE_ALL_HEIGHT doesnt do a thing!
int columns = 2;
final GridFieldManager gfm = new GridFieldManager(columns, 0);
// add some items to the screen
int size = 6;
BitmapField[] fRay = new BitmapField[size];
for (int i = 0; i < size; i++) {
// create an bitmap field that's centered H + V (inside grid space)
fRay[i] = new BitmapField(loadBitmap("images/" + (i + 1) + ".png"),
Field.FIELD_HCENTER | Field.FIELD_VCENTER | Field.FOCUSABLE);
gfm.add(fRay[i]);
}
// set padding on top/bottom
{
// add gfm to screen - this does not center the gfm on the screen... is top aligned no matter what!
add(gfm);
int gfmHeight = 48 * (size / columns);
int borderHeight = (Display.getHeight() - gfmHeight) / 2;
gfm.setBorder(BorderFactory.createSimpleBorder(
new XYEdges(borderHeight, 0, borderHeight, 0),
Border.STYLE_TRANSPARENT));
System.out.println("border=" + borderHeight);
System.out.println("display=" + Display.getHeight());
System.out.println("gfm=" + gfmHeight);
}
}
/** #param res eg "images/icon.png" */
public static Bitmap loadBitmap(String res) {
EncodedImage img = EncodedImage.getEncodedImageResource(res);
return img.getBitmap();
}
}// end class
What is wrong in this code?
Is there any best approch to create grid layout in BlackBerry.
In above code error is "Display.getHeight() is not define".
Hope this code helps:
Bitmap[] images = new Bitmap[6];
for ((int i = 0; i < 6; i++) {
string filename = "images/" + String.valueOf(i + 1) + ".png";
images[i] = Bitmap.getBitmapResource(filename);
}
}

Resources