How to fix rotated image from iOS camera in Codename One? - codenameone

I have written a code to open gallery and choose image file in CodenameOne. On iOS it also allows to capture image. When I capture a photo on iOS, the photo is rotated by 90°. When I pick photo from gallery it is not rotated. How to fix that 90° rotation? Here is my code for opening gallery:
Display.getInstance().openGallery((evt) -> {
if (evt != null && evt.getSource() != null) {
String filePath = (String) evt.getSource();
Image img = null;
try {
img = Image.createImage(filePath);
} catch (IOException e) {
}
if (img != null) {
img = img.scaledLargerRatio(IMAGE_WIDTH_FOR_UPLOAD, IMAGE_HEIGHT_FOR_UPLOAD);
ImageHelper.saveToFileSystem("image" + ".jpg", img, null, null);
base64Img = (String) ImageHelper.loadBase64FromFileSystem("image" + ".jpg");
browser.execute("document.getElementById(\"" + QR_PHOTO_UPLOAD_IMG_ID + "\").setAttribute('src', '" + BASE64_PREFIX + base64Img + "');"
+ " document.getElementById(\"" + QR_PHOTO_UPLOAD_INPUT_ID + "\").setAttribute('base64', '" + BASE64_PREFIX + base64Img + "');"
+ "");
}
}
photoGalleryOpened = false;
}, Display.GALLERY_IMAGE);
Here is code for Image saving to file system:
public static boolean saveToFileSystem(String path, Image capturedImage, String format, Float quality) {
if (format == null) {
format = ImageIO.FORMAT_JPEG;
}
if (quality == null) {
quality = 1f;
}
OutputStream os = null;
try {
String pathToBeStored = path.startsWith(APPHOMEPATH)? path : (APPHOMEPATH + path);
os = FileSystemStorage.getInstance().openOutputStream(pathToBeStored);
ImageIO.getImageIO().save(capturedImage, os, format, quality);
os.close();
} catch (Exception e) {
Log.e(e);
try {
if (os != null) {
os.close();
}
} catch (IOException ex) {
Log.e(ex);
}
return false;
} finally {
try {
if (os != null) {
os.close();
}
} catch (IOException ex) {
Log.p(ex.getMessage());
}
}
return true;
}
Here is code for getting base64 string from image file:
public static Object loadBase64FromFileSystem(String path) {
String ret = "";
try {
Image image = loadFromFileSystem(path);
if (image == null) {
throw new IOException("File not found (" + APPHOMEPATH + path + ")");
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.getImageIO().save(image, baos, ImageIO.FORMAT_JPEG, 1);
byte[] bytes = baos.toByteArray();
ret = Base64.encodeNoNewline(bytes);
} catch (Exception ex) {
Log.e(ex);
}
return ret;
}
public static Image loadFromFileSystem(String path) {
try {
File f = new File(APPHOMEPATH + path);
if(f.exists()){
Log.p("Image exists: " + f.exists());
Image img = Image.createImage(f.getPath());
return img;
}else{
Log.p("Image doesn't exist");
return null;
}
} catch (Exception ex) {
Log.e(ex);
}
Log.p("Image doesn't exist");
return null;
}

Mobile OS's often take a photo with one orientation and then just mark it as rotated in a tag e.g. photos are always landscape but when you take a portrait mode photo it's marked as rotated by 90 degrees.
This works fine as most apps read the tags and implicitly rotate that photo after loading. Some apps don't and the native image reading code doesn't do that on mobile OSs. We need to explicitly parse the tags and do the rotation. We do that for capture logic but we don't do that generically for image loading.
The problem is that rotating the image is very expensive and doing it for every image load would be expensive (but might be what we have to do in this case). Right now the only workaround I can think about is manually parsing the image tags which would be a bit painful.

Related

View files in j2ee web application using fancybox and google doc viewer

I have a java servlet that serves files from s3. These files can be either image, pdf or doc/docx. I have to implement a feature in my web application to display these files in google doc viewer.
In my case, I am not able to send content so that google doc viewer reads it and displays the file. (when shouldDownload == Binary.YES).
This the code I have that downloads the file from s3 and set it in my bean class -
ApplicantzFileModel document = (ApplicantzFileModel) MongoSelectRogueModel
.selectOneById(ApplicantzFileModel.class, id);
Binary shouldDownload = Binary.valueOf(download);
if (document != null) {
if (shouldDownload == Binary.YES) {
docBean.fileStream = document.downloadFileStream();
docBean.fileName = document.getFileName();
docBean.isFileDownloadResponse = true;
} else {
File file = document.downloadFile();
if (file != null) {
String content = null;
content = FileHandler.read(file);
if (content != null) {
docBean.fileContent = content;
docBean.fileName = document.getFileName();
}
}
}
docBean.actionSuccess = true;
docBean.isFileContentResponse = true;
}
This is the code in my doGet/doPost to serve the response -
if (bean.isFileDownloadResponse) {
OutputStream responseOutputStream;
try {
response.setContentType("application/octet-stream");
response.addHeader("Content-disposition", "inline; filename=" + bean.fileName);
responseOutputStream = response.getOutputStream();
byte[] buf = new byte[4096];
int len = -1;
while ((len = bean.fileStream.read(buf)) != -1) {
responseOutputStream.write(buf, 0, len);
}
responseOutputStream.flush();
responseOutputStream.close();
bean.fileStream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
} else {
response.setContentType("application/msword");
response.addHeader("Content-disposition", "inline; filename=" + bean.fileName);
responseStr = bean.fileContent;
PrintWriter writer = null;
try {
writer = response.getWriter();
} catch (IOException e) {
e.printStackTrace();
}
if (writer != null) {
writer.println(responseStr);
writer.flush();
writer.close();
}
}
And this is the html code in my frontend to open google doc viewer in fancybox -
"<a data-fancybox="" data-type="iframe" data-src="http://docs.google.com/viewer?url=http%3A%2F%2Fsomeserver.com%2Fapplication%2Fdocument%3Faction%3Dget%26id%3Dsomeid%26download%3DYES&embedded=true" href="javascript:void(0);" data-doc-id="someid">My Link</a>"
Or more specifically, google doc viewer url that opens up -
var innerurl = encodeURIComponent('http://someserver.com/application/document?action=get&id='+this.docId+'&download=YES');
this.docUrl = 'http://docs.google.com/viewer?url='+innerurl+'&embedded=true';
I am not able to open the word or pdf document in my fancybox. Can someone please suggest what to do to serve files via Java.

Can't get URI for selecting any file from download folder in MI-Oreo(MI-A2) device in android

I need help in fetching file path of contents that we pick from downloads folder or any other folder through Intent.
I am attaching a fileUtil class that I have been using and it works well till Nougat version. But with oreo and that too in some specific devices, we receive a null path in return. So if anyone has faced such an error and found a solution to this, then please share here.
if(resultCode ==RESULT_OK)
{
final Uri uri = data.getData();
// Get the File path from the Uri
String path = FileUtils.getPath(this, uri);
// Alternatively, use FileUtils.getFile(Context, Uri)
if (path != null && FileUtils.isLocal(path)) {
//File file = new File(path);
this.file = new File(path);
profile_imagepath = path;
filename = file.getName();
txtselectedfile.setText(filename);
}
}
You can try to use ACTION_PICK for api level above 26 to get this issue fixed, instead of using ACTION_GET_CONTENT.
Try and hope this helps you.
1) Open file intent.
Intent intent = new Intent()
.setType("*/*")
.setAction(Intent.ACTION_GET_CONTENT);
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setFlags(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(Intent.createChooser(intent, "Select a file"), REQUEST_CODE);
2)get download document path using below method.
if (isDownloadsDocument(uri)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final String id;
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(uri, new String[]{MediaStore.MediaColumns.DISPLAY_NAME}, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
String fileName = cursor.getString(0);
String path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName;
if (!TextUtils.isEmpty(path)) {
return path;
}
}
} finally {
if (cursor != null)
cursor.close();
}
id = DocumentsContract.getDocumentId(uri);
if (!TextUtils.isEmpty(id)) {
if (id.startsWith("raw:")) {
return id.replaceFirst("raw:", "");
}
String[] contentUriPrefixesToTry = new String[]{
"content://downloads/public_downloads",
"content://downloads/my_downloads"
};
for (String contentUriPrefix : contentUriPrefixesToTry) {
try {
final Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
/* final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));*/
return getDataColumn(context, contentUri, null, null);
} catch (NumberFormatException e) {
//In Android 8 and Android P the id is not a number
return uri.getPath().replaceFirst("^/document/raw:", "").replaceFirst("^raw:", "");
}
}
}
} else {
final String id = DocumentsContract.getDocumentId(uri);
final boolean isOreo = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
if (id.startsWith("raw:")) {
return id.replaceFirst("raw:", "");
}
try {
contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
} catch (NumberFormatException e) {
e.printStackTrace();
}
if (contentUri != null) {
return getDataColumn(context, contentUri, null, null);
}
}
}

Multipart image upload issue in Codename One

I am using this code to upload an image. It works on emulator but always fail on Android device (OS 6.0)
My code is
`private void uploadImage3(final String imagePath, String id){
final Hashtable htArg = new Hashtable();
htArg.put("pk1value", id);
htArg.put("pk2value", "");
htArg.put("pk3value", "");
htArg.put("datatype", "6");
htArg.put("module", "");
htArg.put("action", "");
try {
htArg.put("thefile", FileSystemStorage.getInstance().openInputStream(imagePath));
} catch (IOException ex) {
Log.p("imgRequest.Error = " + ex.toString());
}
htArg.put("submit", "Submit");
final String boundary = "-----------------------------0123456789012";
MultipartRequest request = new MultipartRequest(){
#Override
protected void buildRequestBody(OutputStream os) throws IOException {
Writer writer = null;
writer = new OutputStreamWriter(os, "UTF-8");
String CRLF = "\r\n";
boolean canFlushStream = true;
Enumeration e = htArg.keys();
while(e.hasMoreElements()) {
if (shouldStop()) {
break;
}
String key = (String)e.nextElement();
Object value = htArg.get(key);
writer.write("--");
writer.write(boundary);
writer.write(CRLF);
if(value instanceof String) {
writer.write("Content-Disposition: form-data; name=\""+key+"\"");
writer.write(CRLF);
writer.write(CRLF);
writer.write(CRLF);
if(canFlushStream){
writer.flush();
}
writer.write(Util.encodeBody((String)value));
if(canFlushStream){
writer.flush();
}
}else {
writer.write("Content-Disposition: form-data; name=\"" + key + "\"; filename=\"" + key +"\"");
writer.write(CRLF);
writer.write("Content-Type: ");
writer.write("image/jpeg");
writer.write(CRLF);
writer.write("Content-Transfer-Encoding: binary");
writer.write(CRLF);
writer.write(CRLF);
if(canFlushStream){
writer.flush();
}
InputStream i;
if (value instanceof InputStream) {
i = (InputStream)value;
byte[] buffer = new byte[8192];
int s = i.read(buffer);
while(s > -1) {
os.write(buffer, 0, s);
if(canFlushStream){
writer.flush();
}
s = i.read(buffer);
}
// (when passed by stream, leave for caller to clean up).
if (!(value instanceof InputStream)) {
Util.cleanup(i);
}
} else {
os.write((byte[])value);
}
value = null;
if(canFlushStream){
writer.flush();
}
}
writer.write(CRLF);
if(canFlushStream){
writer.flush();
}
}
writer.write("--" + boundary + "--");
writer.write(CRLF);
if(canFlushStream){
writer.flush();
}
writer.close();
}
#Override
protected void readResponse(InputStream input) {
try {
Result result = Result.fromContent(input, Result.XML);
Log.p("imgRequest response: " + result.toString());
} catch (Exception ex) {
Log.p("imgRequest.Error = " + ex.toString());
ex.printStackTrace();
}
}
#Override
protected void handleErrorResponseCode(int code, String message) {
Log.p("handleErrorResponseCode = "+code + ":" + message);
}
#Override
protected void handleException(Exception err) {
Log.p("handleException = "+err.toString());
err.printStackTrace();
}
};
String theURL = Application.getCurrentConnection().get("URL").toString() + "/W1Servlet";
request.setUrl(theURL+"/uploadfiledebug");
request.setBoundary(boundary);
request.setPost(true);
try {
//need to keep this code as it will calculate file size internally
// and also have to add thefile separately in myArgHashTable
request.addData("thefile", imagePath, "image/jpeg");
request.setFilename("thefile", "img.jpeg");
} catch (Exception ex) {
}
InfiniteProgress prog = new InfiniteProgress();
Dialog dlg = prog.showInifiniteBlocking();
request.setDisposeOnCompletion(dlg);
NetworkManager.getInstance().addToQueueAndWait(request);
}`
The traced error on real device is,
`java.net.ProtocolException: exceeded content-length limit of 11076 bytes
at com.android.okhttp.internal.http.RetryableSink.write(RetryableSink.java:58)
at com.android.okhttp.okio.RealBufferedSink.close(RealBufferedSink.java:234)
at com.android.okhttp.okio.RealBufferedSink$1.close(RealBufferedSink.java:209)
at com.codename1.impl.CodenameOneImplementation.cleanup(CodenameOneImplementation.java:4385)
at com.codename1.impl.android.AndroidImplementation.cleanup(AndroidImplementation.java:4579)
at com.codename1.io.Util.cleanup(Util.java:149)
at com.codename1.io.BufferedOutputStream.close(BufferedOutputStream.java:287)
at com.codename1.impl.CodenameOneImplementation.cleanup(CodenameOneImplementation.java:4385)
at com.codename1.impl.android.AndroidImplementation.cleanup(AndroidImplementation.java:4579)
at com.codename1.io.ConnectionRequest.performOperation(ConnectionRequest.java:804)
at com.codename1.io.NetworkManager$NetworkThread.run(NetworkManager.java:282)
at com.codename1.impl.CodenameOneThread$1.run(CodenameOneThread.java:60)
at java.lang.Thread.run(Thread.java:818)`
I am not sure what I am missing.
Please someone can help me.
Thanks
Updated Code
`private void uploadImage4(final String imagePath, String id){
MultipartRequest request = new MultipartRequest(){
#Override
protected void readResponse(InputStream input) throws IOException {
try {
Result result = Result.fromContent(input, Result.XML);
if(isDebugOn){
Application.writeInDebugFile(debugFileName,
"result.toString(): "+ result.toString());
}
Log.p("imgRequest response: " + result.toString());
} catch (Exception ex) {
Log.p("imgRequest.Error = " + ex.toString());
ex.printStackTrace();
if(isDebugOn){
Application.writeInDebugFile(debugFileName,
"readResponse.Exception: "+ex.toString());
}
}
}
};
String theURL = Application.getCurrentConnection().get("URL").toString() + "/W1Servlet";
request.setUrl(theURL+"/uploadfiledebug");
request.addArgument("entityname", "RCV_HEADERS");
request.addArgument("category", "37");
request.addArgument("description", "Uploaded by More4Apps Mobile App");
request.addArgument("pk1value", id);//this is used as a primary key
request.addArgument("pk2value", "");
request.addArgument("pk3value", "");
request.addArgument("datatype", "6");
request.addArgument("module", "");
request.addArgument("action", "");
request.addArgument("submit", "Submit");
try {
//add the data image
request.addData("thefile", imagePath, "image/jpeg");
request.setFilename("thefile", "img.jpeg");
} catch (IOException ex) {
Log.p("Error:"+ ex.toString());
}
request.setPriority(ConnectionRequest.PRIORITY_CRITICAL);
NetworkManager.getInstance().addToQueue(request);
}`
And new error is:
`<ERROR_MESSAGE>IO Error:com.more4apps.mobile.ActionUploadFileoracle.ord.im.OrdHttpUploadException: IMW-00106: the end-of-headers delimiter (CR-LF) was not present
IMW-00112: additional error information: Content-Type: text/plain; charset=UTF-8IMW-00106: the end-of-headers delimiter (CR-LF) was not present
IMW-00112: additional error information: Content-Type: text/plain; charset=UTF-8
oracle.ord.im.OrdMultipartParser.doParse(OrdMultipartParser.java:312)
oracle.ord.im.OrdMultipartParser.parseFormData(OrdMultipartParser.java:150)
oracle.ord.im.OrdHttpUploadFormData.parseFormData(OrdHttpUploadFormData.java:532)
com.more4apps.mobile.ActionUploadFile.performAction(ActionUploadFile.java:39)
com.more4apps.mobile.W1Servlet.processAction(W1Servlet.java:449)
com.more4apps.mobile.W1Servlet.doPost(W1Servlet.java:248)
javax.servlet.http.HttpServlet.service(HttpServlet.java:763)
javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
com.evermind.server.http.ResourceFilterChain.doFilter(ResourceFilterChain.java:64)
oracle.apps.jtf.base.session.ReleaseResFilter.doFilter(ReleaseResFilter.java:26)
com.evermind.server.http.EvermindFilterChain.doFilter(EvermindFilterChain.java:15)
oracle.apps.fnd.security.AppsServletFilter.doFilter(AppsServletFilter.java:318)
com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:642)
com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:391)
com.evermind.server.http.HttpRequestHandler.doProcessRequest(HttpRequestHandler.java:908)
com.evermind.server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:458)
com.evermind.server.http.AJPRequestHandler.run(AJPRequestHandler.java:313)
com.evermind.server.http.AJPRequestHandler.run(AJPRequestHandler.java:199)
oracle.oc4j.network.ServerSocketReadHandler$SafeRunnable.run(ServerSocketReadHandler.java:260)
com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:303)
java.lang.Thread.run(Thread.java:682)</ERROR_MESSAGE>`
If you override buildRequestBody in a multipart request you effectively disable its functionality...
All of that code is incorrect and shouldn't be there. Multipart will work for large files by default.

Check if txt file has text ,if so don't write the same text again?

So right now I'm making a mod in Minecraft where it takes everyones username from a server and adds it to a txt file, it works but the the problem is I don't want to duplicate the names when I use the command again. Nothing has worked so far. How would I check if the txt already contains the username, don't add it again? Thank you. Again, I need it to before writing another name to the list, check the txt file if it already contains the name, if so don't add it.
[code]
for (int i = 0; i < minecraft.thePlayer.sendQueue.playerInfoList.size(); i++) {
List playerList = minecraft.thePlayer.sendQueue.playerInfoList;
GuiPlayerInfo playerInfo = (GuiPlayerInfo) playerList.get(i);
String playerName = StringUtils.stripControlCodes(playerInfo.name);
try {
fileWriter = new FileWriter(GameDirectory() + "\\scraped.txt", true);
bufferedReader = new BufferedReader(new FileReader(GameDirectory() + "\\scraped.txt"));
lineNumberReader = new LineNumberReader(new FileReader(GameDirectory() + "\\scraped.txt"));
} catch (IOException e) {
e.printStackTrace();
}
printWriter = new PrintWriter(fileWriter);
try {
fileWriter.write(playerName + "\r\n");
lineNumberReader.skip(Long.MAX_VALUE);
} catch (IOException e) {
e.printStackTrace();
}
printWriter.flush();
}
addMessage("Scraped " + lineNumberReader.getLineNumber() + " usernames!");
}
[/code]
I've tried this too but with this it doesn't even write anymore.
[code]
List playerList = minecraft.thePlayer.sendQueue.playerInfoList;
for (int i = 0; i < minecraft.thePlayer.sendQueue.playerInfoList.size(); i++) {
GuiPlayerInfo playerInfo = (GuiPlayerInfo) playerList.get(i);
String playerName = StringUtils.stripControlCodes(playerInfo.name);
String lines;
try {
if ((lines = bufferedReader.readLine()) != null) {
if (!lines.contains(playerName)) {
bufferedWriter.write(playerName);
bufferedWriter.newLine();
bufferedWriter.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
int linenumber = 0;
try {
while (lineNumberReader.readLine() != null) {
linenumber++;
}
} catch (IOException e) {
e.printStackTrace();
}
[/code]

loading image to jsp (struts2) from database

I have problem with loading image from database to jsp view. It looks like action are execute but stop in middle.
I log when execute() method start and when its end. In log file i can see start this method but there are no end.
I have action:
public class ShowImageAction extends BaseAction {
private static final long serialVersionUID = 1L;
private static final Log LOG = LogFactory.getLog(ShowImageAction.class);
private int id;
public String execute() {
LOG.info("Enter execute()");
MessageBean messageBean = (MessageBean) sessionParameters
.get(SessionParameters.BANNER_EDIT);
IFiles filesEJB = EJBLocator.getFiles();
if (messageBean != null) {
id = messageBean.getBannerId();
}
FileBean file = filesEJB.file(id);
LOG.info("Id = " + id);
if (file != null) {
byte[] bytes = null;
try {
LOG.info("File: name = " + file.getName() + ". type = "
+ file.getType());
if (file.getImage() != null) {
bytes = FileUtils.readFileToByteArray(file.getImage());
HttpServletResponse response = ServletActionContext
.getResponse();
response.setContentType(file.getType());
OutputStream out = response.getOutputStream();
out.write(bytes);
out.close();
} else {
LOG.info("execute(): Nie udało się pobrać pliku z bazy danych!");
}
} catch (IOException e) {
LOG.error(e);
}
} else {
LOG.info("execute(): Nie udało się pobrać pliku z bazy danych!");
}
LOG.info("Exit execute()");
return NONE;
}
jsp:
<div class="OneFilteringRow">
Podgląd<br />
<img src="/ebok-bm/ShowImageAction" alt="Podgląd banera" />
</div>
struts.xml
<action name="ShowImageAction"
class="pl.bm.action.content.ShowImageAction">
</action>
Problem was in:
FileBean file = filesEJB.file(id);
I get bytes from database and try to save it to tmpFile. Now I get bytes and writes them to a temporary file and immediately transmit it to the action and everything is ok.
Now I have:
FileBean file = filesEJB.file(id);
LOG.info("Id = " + id);
if (file != null) {
byte[] bytes = null;
try {
LOG.info("File: name = " + file.getName() + ". type = "
+ file.getType());
if (file.getImage() != null) {
**bytes = file.getImage();**
HttpServletResponse response = ServletActionContext
.getResponse();
response.setContentType(file.getType());
OutputStream out = response.getOutputStream();
out.write(bytes);
out.close();
} else {
LOG.info("execute(): Nie udało się pobrać pliku z bazy danych!");
}
} catch (IOException e) {
LOG.error(e);
}
}
Switch to your own result implements Result class and write output here.Other in struts.xmlaction result type specified own with approx mate parameters.
refer:generate own image as action result

Resources