Please someone tell me how to overlap two Audio files and generate single audio file from them. I am trying the following code but I am unable to open saved file.
package com.example.audiomix;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// MediaPlayer mediaPlayer=MediaPlayer.create(getApplicationContext(),getAssets()+"")
try {
mixSound();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void mixSound() {
try {
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, 44100, AudioTrack.MODE_STREAM);
// Uri url = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.one);
// System.out.println("MainActivity.mixSound() url1"+url.toString());
// File file = new File(url.toString());
// Uri url2 = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.two);
// System.out.println("MainActivity.mixSound() url1"+url2.toString());
// File file2 = new File(url2.toString());
// InputStream in1=new FileInputStream(file);
// InputStream in2=new FileInputStream(file2);
// int rid = getResources().getIdentifier(getPackageName() + ":raw/one.mp3" , null, null);
// //get the file as a stream
// InputStream in1 = getResources().openRawResource(rid);
//// InputStream in1=new FileInputStream("");
//
// int rid2 = getResources().getIdentifier(getPackageName() + ":raw/two.mp3" , null, null);
// //get the file as a stream
// InputStream in2 = getResources().openRawResource(rid2);
//
//// InputStream in2=new FileInputStream(getResources().openRawResource(R.raw.one).toString());
InputStream in1 = getApplicationContext().getResources().openRawResource(R.raw.media);
InputStream in2 = getApplicationContext().getResources().openRawResource(R.raw.media1);
byte[] music1 = null;
music1= new byte[in1.available()];
music1=convertStreamToByteArray(in1);
in1.close();
byte[] music2 = null;
music2= new byte[in2.available()];
music2=convertStreamToByteArray(in2);
in2.close();
byte[] output = new byte[music2.length];
audioTrack.play();
int j=0;
for(int i=0; i < output.length-1; i++){
float mixed;
if(j<music1.length-1){
float samplef1 = music1[j] / 128.0f; // 2^7=128
float samplef2 = music2[i] / 128.0f;
mixed = samplef1 + samplef2;
j++;
}else{
float samplef2 = music2[i] / 128.0f;
mixed = samplef2;
}
float samplef1 = music1[j] / 128.0f; // 2^7=128
float samplef2 = music2[i] / 128.0f;
mixed = samplef1 + samplef2;
// reduce the volume a bit:
mixed *= 0.8;
// hard clipping
if (mixed > 1.0f) mixed = 1.0f;
if (mixed < -1.0f) mixed = -1.0f;
byte outputSample = (byte)(mixed * 128.0f);
output[i] = outputSample;
} //for loop
audioTrack.write(output, 0, output.length);
//convert array of bytes into file
FileOutputStream fileOuputStream =
new FileOutputStream(Environment.getExternalStorageDirectory()+"/abc.wav");
fileOuputStream.write(output);
fileOuputStream.close();
System.out.println("MainActivity.mixSound()==>Done");
System.out.println("Done");
}catch(Exception e){
// e.printStackTrace();
System.out.println("MainActivity.mixSound()==>"+e);
}
}
public static byte[] convertStreamToByteArray(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buff = new byte[10240];
int i = Integer.MAX_VALUE;
while ((i = is.read(buff, 0, buff.length)) > 0) {
baos.write(buff, 0, i);
}
return baos.toByteArray(); // be sure to close InputStream in calling function
}
}
I have tried to first convert audio file into byte array. Then I am saving it on SD card.
The generated file is saved but when I try to play the saved file it is not playing.
That's because both byte arrays have raw audio bytes and headers, so when you mix them you should get one crappy audio file. But you don't. That means that files you are mixing aren't ones with same properties in other words their formats are different.
Related
I want to resize image came from blob column to maximize it. I make a FUNCTION for this but I get this error message
PLS-00201 - identifier ORDSYS.OrdImage must be declared
CREATE OR REPLACE FUNCTION "resize_img" (resize_img in BLOB)
RETURN BLOB
IS
vImageData BLOB;
vSizedImage BLOB;
BEGIN
DBMS_Lob.createTemporary(vSizedImage, FALSE, DBMS_LOB.CALL);
ORDSYS.OrdImage.processCopy(vImageData, 'maxScale=75 75', vSizedImage);
RETURN vSizedImage;
END;
Ordimage has been removed from 19c (I know you are using 12c) but here is a way to do it without Ordimage. It took me about a week to piece together from multiple sources and alot of reading, googling and trial and error.
Hopefully this will help someone else that needs to resize an image in Oracle 19c.
Oracle Functions:
function BLOB_THUMBNAIL(P_BLOB in Blob, P_MAX_SIZE in Number, P_ATTACH_SID in varchar2 := null) return Blob is
V_DST Blob;
begin
V_DST := resizeBLOB(P_BLOB, P_MAX_SIZE, P_MAX_SIZE);
end BLOB_THUMBNAIL;
function BLOB_THUMBNAIL_OLD(P_BLOB in Blob, P_MAX_SIZE in Number) return Blob is
V_DST Blob;
begin
DBMS_LOB.CREATETEMPORARY(V_DST, true);
DBMS_LOB.OPEN(V_DST, DBMS_LOB.LOB_READWRITE);
ORDSYS.ORDIMAGE.PROCESSCOPY(P_BLOB, 'maxScale=' || P_MAX_SIZE || ' ' || P_MAX_SIZE, V_DST);
DBMS_LOB.CLOSE(V_DST);
return V_DST;
end BLOB_THUMBNAIL_OLD;
Java Class:
SET DEFINE OFF;
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "ResizeImage" as
import java.lang.*;
import java.sql.*;
import java.io.*;
import oracle.sql.*;
import java.awt.image.BufferedImage;
import java.awt.Image;
import java.awt.Color;
import javax.imageio.ImageIO;
import oracle.jdbc.driver.*;
public class ResizeImage extends Object
{
public static java.sql.Blob resizeBLOB(java.sql.Blob img, int newW, int newH)
{
try
{
byte [] newdata = img.getBytes(1L, (int)img.length());
newdata = scale(newdata, newW, newH);
oracle.jdbc.OracleConnection conn = (oracle.jdbc.OracleConnection)new OracleDriver().defaultConnection();
java.sql.Blob retBlob = conn.createBlob();
try
{
java.io.OutputStream outStr = retBlob.setBinaryStream(0);
outStr.write(newdata, 0, newdata.length);
outStr.flush();
outStr.close();
}
catch (IOException ioe)
{
System.out.println("IO Error trying to write the outputstream.");
ioe.printStackTrace();
}
return retBlob;
}
catch (SQLException ex)
{
System.out.println("SQLException Error.");
ex.printStackTrace();
}
return img;
}
public static byte[] scale(byte[] fileData, int width, int height)
{
double newW;
double newH;
ByteArrayInputStream in = new ByteArrayInputStream(fileData);
try
{
BufferedImage img = ImageIO.read(in);
if(height == 0)
height = 100;
if(width == 0)
width = 100;
//Figure new Width and Height with Aspect Ratio
double imgW = img.getWidth();
double imgH = img.getHeight();
if(imgH>imgW)
{
newW = (imgW/imgH)*width;
newH = height;
}
else
{
newH = (imgH/imgW)*height;
newW = width;
}
Image scaledImage = img.getScaledInstance((int)newW, (int)newH, Image.SCALE_SMOOTH);
BufferedImage imageBuff = new BufferedImage((int)newW, (int)newH, BufferedImage.TYPE_INT_RGB);
imageBuff.getGraphics().drawImage(scaledImage, 0, 0, new Color(0,0,0), null);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ImageIO.write(imageBuff, "jpg", buffer);
return buffer.toByteArray();
}
catch (IOException e)
{
//throw new ApplicationException("IOException in scale");
e.printStackTrace();
}
return fileData;
}
}
Oracle Function to call Java:
CREATE OR REPLACE function resizeBLOB( p_img in blob, newW in number, newH in number) return blob
as
language java
name 'ResizeImage.resizeBLOB(java.sql.Blob, int, int) return java.sql.Blob';
/
Great Work Timothy !
I found some problems with ImageIO (see: Java ImageIO IIOException: Unsupported image type?), so I used the Oracle VM internal JPEG decoder instead.
Here is the java: (plsql remaines unchanged):
SET DEFINE OFF;
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "ResizeImage" as
import java.lang.*;
import java.sql.*;
import java.io.*;
import oracle.sql.*;
import java.awt.image.BufferedImage;
import java.awt.Image;
import java.awt.Color;
import javax.imageio.ImageIO;
import oracle.jdbc.driver.*;
import com.sun.image.codec.jpeg.JPEGCodec;
public class ResizeImage extends Object
{
public static java.sql.Blob resizeBLOB(java.sql.Blob img, int newW, int newH)
{
try
{
byte [] newdata = img.getBytes(1L, (int)img.length());
newdata = scale(newdata, newW, newH);
oracle.jdbc.OracleConnection conn = (oracle.jdbc.OracleConnection)new OracleDriver().defaultConnection();
java.sql.Blob retBlob = conn.createBlob();
try
{
java.io.OutputStream outStr = retBlob.setBinaryStream(0);
outStr.write(newdata, 0, newdata.length);
outStr.flush();
outStr.close();
}
catch (IOException ioe)
{
System.out.println("IO Error trying to write the outputstream.");
ioe.printStackTrace();
}
return retBlob;
}
catch (SQLException ex)
{
System.out.println("SQLException Error.");
ex.printStackTrace();
}
return img;
}
public static byte[] scale(byte[] fileData, int width, int height)
{
double newW;
double newH;
ByteArrayInputStream in = new ByteArrayInputStream(fileData);
try
{
// BufferedImage img = ImageIO.read(in);
// weinberger 20220801 ImageIO can not handle all jpeg
BufferedImage img = JPEGCodec.createJPEGDecoder(in).decodeAsBufferedImage();
if(height == 0)
height = 100;
if(width == 0)
width = 100;
//Figure new Width and Height with Aspect Ratio
double imgW = img.getWidth();
double imgH = img.getHeight();
if(imgH>imgW)
{
newW = (imgW/imgH)*width;
newH = height;
}
else
{
newH = (imgH/imgW)*height;
newW = width;
}
Image scaledImage = img.getScaledInstance((int)newW, (int)newH, Image.SCALE_SMOOTH);
BufferedImage imageBuff = new BufferedImage((int)newW, (int)newH, BufferedImage.TYPE_INT_RGB);
imageBuff.getGraphics().drawImage(scaledImage, 0, 0, new Color(0,0,0), null);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ImageIO.write(imageBuff, "jpg", buffer);
return buffer.toByteArray();
}
catch (IOException e)
{
//throw new ApplicationException("IOException in scale");
e.printStackTrace();
}
return fileData;
}
}
I am trying to use a switch statement to pass a LinkedHashMap to the correct class constructor for a school project(I just added the rest of the code).
The code reads takes in a txt file and based off the first word in the text sends the hash map.
I can't seem to get a hit on the case report I am testing.
I have even tried just making everything into an if-else-if structure,
and that still didn't work out,
I've tried using a private enum method to no avail.
I am at a loss here.
I am running Java 8.
I am open to any suggestion on optimizing the code as well.
Thanks.
package linkedlist;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
/**
*
* #author admin
*/
public class TextReaderGUI extends javax.swing.JFrame {
JFileChooser fileChooser = new JFileChooser();
String rawText;
String[] text;
public String listType;
private JButton fileChooserButton;
private JLabel statusLabel;
/**
* Creates new form TextReaderGUI
*/
public TextReaderGUI() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
fileChooserButton = new javax.swing.JButton();
statusLabel = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
fileChooserButton.setText("File Chooser");
fileChooserButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
fileChooserButtonActionPerformed(evt);
}
});
statusLabel.setText("Status: ");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(layout
.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup().addGap(14, 14, 14).addComponent(fileChooserButton))
.addGroup(layout.createSequentialGroup().addGap(36, 36, 36).addComponent(statusLabel)))
.addContainerGap(264, Short.MAX_VALUE)));
layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup().addGap(16, 16, 16).addComponent(fileChooserButton)
.addGap(18, 18, 18).addComponent(statusLabel).addContainerGap(221, Short.MAX_VALUE)));
pack();
}// </editor-fold>
private void fileChooserButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try {
int returnVal = fileChooser.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
rawText = "";
BufferedReader reader = new BufferedReader(new FileReader(file));
StringBuilder stringb = new StringBuilder();
String s;
while ((s = reader.readLine()) != null) {
stringb.append(s);
stringb.append("\n"); // this makes sure that java sees when a new line has started
}
rawText = stringb.toString();
statusLabel.setText("Status: " + file.getName());
}
} catch (IOException e) {
statusLabel.setText("Status" + e);
}
text = rawText.split("\n"); // creating a string array split at each line break
Map<String, String> lines = new LinkedHashMap<>();
for (int i = 0; i < text.length; i++) { // this sets the first word of the line = key
String[] currentLine = text[i].split("\\s+"); // splits the words in the current line to an array
if (i == 0) {
listType = currentLine[0].replaceAll("\n", "").replaceAll("\\s+", ""); // determines listType to pass
}
if (currentLine.length > 1 && i > 0) {
lines.put(currentLine[0] + " " + i, currentLine[1]); // if two words exist on a line
// the first is the key second is the value
} else if (currentLine.length == 1 && i > 0) { // keeps list type out of key values
lines.put(currentLine[0] + " " + i, ""); // " " + i is used to ensure that each command is unique key
}
}
lines.keySet().forEach((name) -> {// Testing to see if document was correctly placed into the HashMap
String key = name;
String value = lines.get(name);
System.out.println(key + " " + value + "\n");
});
System.out.println(listType); // testing to see if list type was correctly stored
switch (listType) {
case "stack":
Stack stack = new Stack((LinkedHashMap) lines);
break;
case "queue":
Queue queue = new Queue((LinkedHashMap) lines);
break;
case "dll":
Dll dll = new Dll((LinkedHashMap) lines);
break;
case "sll":
System.out.println("almost there");
Sll sll = new Sll((LinkedHashMap) lines);
break;
case "cll":
Cll cll = new Cll((LinkedHashMap) lines);
break;
default:
System.out.println("something went wrong here");
break;
}
}
}
This should be a simple question, but I'm struggling with it. Everything in my code is working except for initializing the parameter values for "train_rows" and "cols" read in from the Configuration file.
I set up logging to display the values of "train_rows" and "cols" within the setup() method, and the values were correct. However, when I tried the same thing within the map() method, both values showed 0. What am I doing wrong?
import java.io.File;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.Scanner;
import org.apache.log4j.Logger;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class KNNMapper extends Mapper<LongWritable, Text, IntWritable, IntWritable> {
private static final Logger sLogger = Logger.getLogger(KNNMapper.class);
private int[][] train_vals;
private int[] train_label_vals;
private int train_rows;
private int test_rows;
private int cols;
#Override
public void setup(Context context) throws IOException, InterruptedException {
Configuration conf = context.getConfiguration();
train_rows = conf.getInt("rows", -1);
cols = conf.getInt("columns", -1);
//just changed this
//int[][] train_vals = new int[train_rows][cols];
//int[] train_label_vals = new int[train_rows];
train_vals = new int[train_rows][cols];
train_label_vals = new int[train_rows];
// read train csv, parse, and store into 2d int array
Scanner myScan;
try {
File trainfile = new File("train_sample.csv");
if (!trainfile.exists()) {
throw new IllegalArgumentException("train file didn't load");
}
myScan = new Scanner(trainfile);
//Set the delimiter used in file
myScan.useDelimiter("[,\r\n]+");
//Get all tokens and store them in some data structure
//I am just printing them
for(int row = 0; row < train_rows; row++) {
for(int col = 0; col < cols; col++) {
train_vals[row][col] = Integer.parseInt(myScan.next().toString());
}
}
myScan.close();
} catch (FileNotFoundException e) {
System.out.print("Error: Train file execution did not work.");
}
// read train_labels csv, parse, and store into 2d int array
try {
File trainlabels = new File("train_labels.csv");
if (!trainlabels.exists()) {
throw new IllegalArgumentException("train labels didn't load");
}
myScan = new Scanner(trainlabels);
//Set the delimiter used in file
myScan.useDelimiter("[,\r\n]+");
//Get all tokens and store them in some data structure
//I am just printing them
for(int row = 0; row < train_rows; row++) {
train_label_vals[row] = Integer.parseInt(myScan.next().toString());
if(row < 10) {
System.out.println(train_label_vals[row]);
}
}
myScan.close();
} catch (FileNotFoundException e) {
System.out.print("Error: Train Labels file not found.");
}
}
#Override
public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
// setup() gave us train_vals & train_label_vals.
// Each line in map() represents a test observation. We iterate
// through every train_val row to find nearest L2 match, then
// return a key/value pair of <observation #,
// convert from Text to String
System.out.println("I'm in the map!");
String line = value.toString();
double distance;
double best_distance = Double.POSITIVE_INFINITY;
int col_num;
int best_digit = -1;
IntWritable rowId = null;
int i;
IntWritable rowNum;
String[] pixels;
System.out.println("Number of train rows:" + train_rows);
System.out.println("Number of columns:" + cols);
// comma delimited files, split on commas
// first we find the # of rows
pixels = line.split(",");
rowId = new IntWritable(Integer.parseInt(pixels[0]));
System.out.println("working on row " + rowId);
best_distance = Double.POSITIVE_INFINITY;
for (i = 0; i < train_rows; i++) {
distance = 0.0;
col_num = 0;
for (int j = 1; j < cols; j++) {
distance += (Integer.parseInt(pixels[j]) - train_vals[i][j-1])^2;
}
if (distance < best_distance) {
best_distance = distance;
best_digit = train_label_vals[i];
}
}
System.out.println("And we're out of the loop baby yeah!");
context.write(rowId, new IntWritable(best_digit));
System.out.println("Mapper done!");
}
}
i doubt this , assuming you are scanning the file in hdfs.
you used:
import java.io.File; File trainfile = new File("train_sample.csv");
in hadoop this is how we check for a file in hdfs :
try {
FileSystem fs = FileSystem.get(context.getConfiguration());
if (fs.exists(new Path("/user/username/path/of/file/inhdfs"))) {
System.out.println("File exists");
}
} catch (IOException e) {
e.printStackTrace();
}
I have a solution for copying rich text content from one document to MIME in another document. See http://per.lausten.dk/blog/2012/12/xpages-dynamically-updating-rich-text-content-in-a-ckeditor.html. I use this in an application as a way for the user to insert content templates in a new document and have the content appear on-the-fly in the CKEditor.
The problem is that inline images are not included in the copying - only a reference to temporary storage of the images. This means that the images are only visible for the current user in the current session. So not very useful.
How can I include images?
Update October 4, 2013:
I'm still looking for a solution to this.
I finally got it work. It was much more simple and did not even involve MIME. The trick was to modify the image tags in the working HTML to include the base64 encoded image so that the src tag could use this format (here shown with a gif as example):
src="data:image/gif;base64,<base64 encoded image>"
I already had the code necessary to get the HTML from the rich text field (see my blog post already mentioned in my question). So all I needed was to replace the image src tags with the correct src format including the base64 encoded image.
The following code gets the HTML and goes through each of the included images and modifies the src tag:
String html = this.document.getValue(fieldName).toString();
if (null != html) {
final List<FileRowData> fileRowDataList = document.getEmbeddedImagesList(fieldName);
if (null != fileRowDataList) {
final Matcher matcher = imgRegExp.matcher(html);
while (matcher.find()) {
String src = matcher.group();
final String srcToken = "src=\"";
final int x = src.indexOf(srcToken);
final int y = src.indexOf("\"", x + srcToken.length());
final String srcText = src.substring(x + srcToken.length(), y);
for (FileRowData fileRowData : fileRowDataList) {
final String srcImage = fileRowData.getHref();
final String cidImage = ((AttachmentValueHolder) fileRowData).getCID();
final String typeImage = ((AttachmentValueHolder) fileRowData).getType();
final String persistentName = ((AttachmentValueHolder) fileRowData).getPersistentName();
// Add base 64 image inline (src="data:image/gif;base64,<name>")
if (srcText.endsWith(srcImage)) {
final String newSrc = src.replace(srcText, "data:" + typeImage + ";base64," + getBase64(persistentName));
html = html.replace(src, newSrc);
}
}
}
}
}
Here is the getBase64() method that base64 encodes an image:
private String getBase64(final String fileName) {
String returnText = "";
try {
BASE64Encoder base64Enc = new BASE64Encoder();
ByteArrayOutputStream output = new ByteArrayOutputStream();
base64Enc.encode(this.getEmbeddedImageStream(fileName), output);
returnText = output.toString();
} catch (NotesException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return returnText;
}
Some of the code is from the emailBean by Tony McGuckin.
Can you get a handle to the inline image by the DominoDocument.AttachmentValueHolder, see http://public.dhe.ibm.com/software/dw/lotus/Domino-Designer/JavaDocs/XPagesExtAPI/8.5.2/com/ibm/xsp/model/domino/wrapped/DominoDocument.AttachmentValueHolder.html
I blogged about attachments inside notes documents, see http://www.domino-weblog.nl/weblogs/Domino_Blog.nsf/dx/xpages-tip-get-easily-access-to-your-attachments-in-java.htm
Gruesome hack (you need to sort out authentication and server names)
The SSJS (getting the source from a view)
var unid = curRow.getUniversalID();
var body = getComponent("body1");
var magic = new demo.HTMLMagic();
magic.doMagic(database, unid, body);
The Java
package demo;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import net.htmlparser.jericho.Attribute;
import net.htmlparser.jericho.Attributes;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.OutputDocument;
import net.htmlparser.jericho.Source;
import net.htmlparser.jericho.StartTag;
import lotus.domino.Database;
import lotus.domino.NotesException;
import com.ibm.misc.BASE64Encoder;
import com.ibm.xsp.component.xp.XspInputRichText;
import com.ibm.xsp.http.IMimeMultipart;
import com.ibm.xsp.model.domino.wrapped.DominoRichTextItem;
public class HTMLMagic {
private HttpClient httpClient = null;
private HttpHost httpHost = null;
//TODO: that needs to be resolved smarter
private static final String HOSTNAME = "localhost";
public void doMagic(final Database database, final String unid, final XspInputRichText body) throws NotesException,
ClientProtocolException, IOException {
final String docURL = "http://" + HOSTNAME + "/__" + database.getReplicaID() + ".nsf/0/" + unid + "/Body?OpenField";
final String fixedHTML = this.fixHTML(docURL);
IMimeMultipart result = DominoRichTextItem.convertToMime("-- copied text--<br />" + fixedHTML);
body.setValue(result);
}
private String fixHTML(final String rawHTMLstring) throws ClientProtocolException, IOException {
HttpHost target = this.getHttpHost();
HttpClient client = this.getHttpClient();
HttpGet get = new HttpGet(rawHTMLstring);
HttpResponse response = client.execute(target, get);
InputStream data = response.getEntity().getContent();
Source rawHTML = new Source(data);
OutputDocument outputDocument = new OutputDocument(rawHTML);
StringBuilder sb = new StringBuilder();
String tagName = HTMLElementName.IMG;
String attName = "src";
List<StartTag> links = rawHTML.getAllStartTags(tagName);
for (StartTag onelink : links) {
String href = onelink.getAttributeValue(attName);
if (href != null) {
String replace = this.urltoData(href);
if (replace != null) {
sb.setLength(0);
sb.append("<");
sb.append(tagName);
sb.append(" ");
sb.append(attName);
sb.append("=\"");
sb.append(replace);
sb.append("\"");
Attributes atts = onelink.getAttributes();
if (!atts.isEmpty()) {
for (int i = 0; i < atts.size(); i++) {
Attribute att = atts.get(i);
if (!att.getName().equals(attName)) {
sb.append(" ");
sb.append(att.getName());
sb.append("=\"");
sb.append(att.getValue());
sb.append("\" ");
}
}
}
sb.append(">");
outputDocument.replace(onelink, sb.toString());
}
}
}
return outputDocument.toString();
}
private HttpClient getHttpClient() {
if (this.httpClient == null) {
// general setup
SchemeRegistry supportedSchemes = new SchemeRegistry();
// Register the "http" protocol scheme, it is required
// by the default operator to look up socket factories.
supportedSchemes.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// prepare parameters
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, "UTF-8");
HttpProtocolParams.setUseExpectContinue(params, true);
ClientConnectionManager connMgr = new ThreadSafeClientConnManager(params, supportedSchemes);
this.httpClient = new DefaultHttpClient(connMgr, params);
}
return this.httpClient;
}
private HttpHost getHttpHost() {
if (this.httpHost == null) {
this.httpHost = new HttpHost(HOSTNAME, 80, "http");
}
return this.httpHost;
}
private String urltoData(final String href) throws ClientProtocolException, IOException {
StringBuilder sb = new StringBuilder();
sb.append("data:image/");
sb.append(href.substring(href.lastIndexOf("FieldElemFormat=") + 1));
sb.append(";base64,");
// Here go the Image data
HttpHost target = this.getHttpHost();
HttpClient client = this.getHttpClient();
HttpGet get = new HttpGet(href);
HttpResponse response = client.execute(target, get);
InputStream data = response.getEntity().getContent();
BASE64Encoder encoder = new BASE64Encoder();
OutputStream output = new ByteArrayOutputStream();
encoder.encode(data, output);
sb.append(output.toString());
output.close();
return sb.toString();
}
}
Would be curious if that works for you. The Notes client can't show inline HTML images
I used the code from the following link: Signare's Blog. I have 10 image URLs and would like to retrieve and show them on my screen. When I use the code from the above link, it's taking more than 10 minutes to load all of the images. How do I speed up this loading?
URLBitmapField post_img= new URLBitmapField(image_url);
add(post_img);
where the class URLBitmapField is defined as:
import net.rim.device.api.math.Fixed32;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.EncodedImage;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
public class URLBitmapField extends BitmapField implements URLDataCallback {
EncodedImage result = null;
public static EncodedImage _encoded_img = null;
int _imgWidth = 52;
int _imgHeight = 62;
int _imgMargin = 10;
public URLBitmapField(String url) {
try {
http_image_data_extrator.getWebData(url, this);
}
catch (Exception e) {}
}
public Bitmap getBitmap() {
if (_encoded_img == null) return null;
return _encoded_img.getBitmap();
}
public void callback(final String data) {
if (data.startsWith("Exception")) return;
try {
byte[] dataArray = data.getBytes();
_encoded_img = EncodedImage.createEncodedImage(dataArray, 0, dataArray.length); // with scale
_encoded_img = sizeImage(_encoded_img, _imgWidth, _imgHeight);
setImage(_encoded_img);
UiApplication.getUiApplication().getActiveScreen().invalidate();
}
catch (final Exception e){}
}
public EncodedImage sizeImage(EncodedImage image, int width, int height) {
int currentWidthFixed32 = Fixed32.toFP(image.getWidth());
int currentHeightFixed32 = Fixed32.toFP(image.getHeight());
int requiredWidthFixed32 = Fixed32.toFP(width);
int requiredHeightFixed32 = Fixed32.toFP(height);
int scaleXFixed32 = Fixed32.div(currentWidthFixed32,requiredWidthFixed32);
int scaleYFixed32 = Fixed32.div(currentHeightFixed32,requiredHeightFixed32);
result = image.scaleImage32(scaleXFixed32, scaleYFixed32);
return result;
}
}
public interface URLDataCallback {
public void callback(String data);
}
and the class http_image_data_extrator is defined as:
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import net.rim.device.api.system.RadioInfo;
import net.rim.device.api.system.WLANInfo;
import net.rim.device.api.ui.UiApplication;
public class http_image_data_extrator {
static String url_="";
static StringBuffer rawResponse=null;
public static void getWebData(String url, final URLDataCallback callback) throws IOException {
HttpConnection connection = null;
InputStream inputStream = null;
try {
if ((WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)&& RadioInfo.areWAFsSupported(RadioInfo.WAF_WLAN)) {
url += ";interface=wifi";
}
connection = (HttpConnection) Connector.open(url, Connector.READ, true);
String location=connection.getHeaderField("location");
if(location!=null){
if ((WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)&& RadioInfo.areWAFsSupported(RadioInfo.WAF_WLAN)) {
location += ";interface=wifi";
}
connection = (HttpConnection) Connector.open(location, Connector.READ, true);
}else{
connection = (HttpConnection) Connector.open(url, Connector.READ, true);
}
inputStream = connection.openInputStream();
byte[] responseData = new byte[10000];
int length = 0;
rawResponse = new StringBuffer();
while (-1 != (length = inputStream.read(responseData))) {
rawResponse.append(new String(responseData, 0, length));
}
int responseCode = connection.getResponseCode();
if (responseCode != HttpConnection.HTTP_OK){
throw new IOException("HTTP response code: "+ responseCode);
}
final String result = rawResponse.toString();
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run(){
callback.callback(result);
}
});
}
catch (final Exception ex) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
callback.callback("Exception (" + ex.getClass() + "): " + ex.getMessage());
}
});
}
}
}
Resize on the server
Resizing the images on the server is the best answer. Because downloading big images and scaling them down requires a lot of everything (network, memory, cpu) on the device.
Resize via a proxy
If the image server is not under your control, you could still use your own server as a resizing proxy (send the image url and desired size to your server, it gets the image, resizes, and returns the resized image). Maybe there is a service that does this already.
Cheaper decode option
Some decode options may make decoding (and resizing) cheaper. DECODE_NO_DITHER, DECODE_READONLY, and DECODE_NATIVE all seem worth trying.
http://www.blackberry.com/developers/docs/4.2api/net/rim/device/api/system/EncodedImage.html#DECODE_NO_DITHER
Serial instead of parallel
You mentioned you are loading 10 images. If 10 images takes more than 10x the time 1 image takes, then the system might be "thrashing". Like it might initiate all 10 requests, then wind up working on 10 fullscale images in memory at the same time in callbacks. Could try showing the first image before starting to download the next, which also gives the user something to look at sooner. Similarly, calling invalidate 10 times in parallel (in the callback) might cause a hiccup.