1 package ubc.midp.mobilephoto.core.util;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5
6 import lancs.midp.mobilephoto.lib.exceptions.ImagePathNotValidException;
7 import lancs.midp.mobilephoto.lib.exceptions.InvalidArrayFormatException;
8 import lancs.midp.mobilephoto.lib.exceptions.InvalidImageDataException;
9 import lancs.midp.mobilephoto.lib.exceptions.InvalidImageFormatException;
10
11 import ubc.midp.mobilephoto.core.ui.datamodel.ImageData;
12
13 /**
14 * @author trevor This is a utility class. It performs conversions between Image
15 * objects and byte arrays, and Image metadata objects and byte arrays.
16 * Byte arrays are the main format for storing data in RMS, and for
17 * sending data over the wire.
18 */
19 public class ImageUtil {
20
21 // Delimiter used in record store data to separate fields in a string.
22 private static final String DELIMITER = "*";
23
24 /**
25 * Constructor
26 */
27 public ImageUtil() {
28 super();
29 }
30
31 /**
32 * This method reads an Image from an Input Stream and converts it from a
33 * standard image file format into a byte array, so that it can be
34 * transported over wireless protocols such as SMS
35 *
36 * @throws ImagePathNotValidException
37 * @throws InvalidImageFormatException
38 */
39 public byte[] readImageAsByteArray(String imageFile)
40 throws ImagePathNotValidException, InvalidImageFormatException {
41
42 byte bArray[] = new byte[1000];
43
44 // Read an Image into a byte array
45 // Required to transfer images over SMS
46 InputStream is = null;
47 try {
48 is = (InputStream) this.getClass().getResourceAsStream(imageFile);
49 } catch (Exception e) {
50 throw new ImagePathNotValidException(
51 "Path not valid for this image:"+imageFile);
52 }
53
54 int i, len = 0;
55 byte bArray2[];
56 byte b[] = new byte[1];
57 try {
58 while (is.read(b) != -1) {
59
60 if (len + 1 >= bArray.length) {
61
62 bArray2 = new byte[bArray.length];
63
64 // Transfer all data from old array to temp array
65 for (i = 0; i < len; i++)
66 bArray2[i] = bArray[i];
67
68 bArray = new byte[bArray2.length + 500];
69
70 // Re-Copy contents back into new bigger array
71 for (i = 0; i < len; i++)
72 bArray[i] = bArray2[i];
73 }
74
75 // Set the size to be exact
76 bArray[len] = b[0];
77 len++;
78 }
79
80 is.close();
81 } catch (IOException e1) {
82 throw new InvalidImageFormatException(
83 "The file "+imageFile+" does not have PNG format");
84 } catch(NullPointerException e2){
85 throw new ImagePathNotValidException(
86 "Path not valid for this image:"+imageFile);
87 }
88
89 return bArray;
90 }
91
92 /**
93 *
94 * Convert the byte array from a retrieved RecordStore record into the
95 * ImageInfo ((renamed ImageData) object Order of the string will look like
96 * this: <recordId>*<foreignRecordId>*<labelName>*<imageLabel> Depending
97 * on the optional features, additional fields may be: <phoneNum>
98 *
99 * @throws InvalidArrayFormatException
100 */
101 public ImageData getImageInfoFromBytes(byte[] bytes)
102 throws InvalidArrayFormatException {
103
104 try {
105 String iiString = new String(bytes);
106
107 // Track our position in the String using delimiters
108 // Ie. Get chars from beginning of String to first Delim
109 int startIndex = 0;
110 int endIndex = iiString.indexOf(DELIMITER);
111
112 // Get recordID int value as String - everything before first
113 // delimeter
114 String intString = iiString.substring(startIndex, endIndex);
115
116 // Get 'foreign' record ID corresponding to the image table
117 startIndex = endIndex + 1;
118 endIndex = iiString.indexOf(DELIMITER, startIndex);
119 String fidString = iiString.substring(startIndex, endIndex);
120
121 // Get Album name (recordstore) - next delimeter
122 startIndex = endIndex + 1;
123 endIndex = iiString.indexOf(DELIMITER, startIndex);
124 String albumLabel = iiString.substring(startIndex, endIndex);
125
126 startIndex = endIndex + 1;
127 endIndex = iiString.indexOf(DELIMITER, startIndex);
128
129 if (endIndex == -1)
130 endIndex = iiString.length();
131
132 String imageLabel = "";
133 imageLabel = iiString.substring(startIndex, endIndex);
134
135 boolean favorite = false;
136 startIndex = endIndex + 1;
137 endIndex = iiString.indexOf(DELIMITER, startIndex);
138
139 if (endIndex == -1)
140 endIndex = iiString.length();
141
142 favorite = (iiString.substring(startIndex, endIndex)).equalsIgnoreCase("true");
143
144 startIndex = endIndex + 1;
145 endIndex = iiString.indexOf(DELIMITER, startIndex);
146
147 if (endIndex == -1)
148 endIndex = iiString.length();
149
150 int numberOfViews = 0;
151 try {
152 numberOfViews = Integer.parseInt(iiString.substring(startIndex, endIndex));
153 } catch (RuntimeException e) {
154 numberOfViews = 0;
155 e.printStackTrace();
156 }
157
158 // TODO: Add preprocessor statements here
159
160 // Get the phone number if one exists
161 // if ((endIndex + 1) < iiString.length()) {
162 // System.out.println("<* ImageUtil.getImageInfoFromBytes() *> phoneNum : "+endIndex+" < "+iiString.length());
163 // startIndex = endIndex + 1;
164 // endIndex = iiString.indexOf(DELIMITER, startIndex);
165 // if (endIndex == -1)
166 // endIndex = iiString.length();
167 // iiString.substring(startIndex, endIndex);
168 // }
169
170 Integer x = Integer.valueOf(fidString);
171 ImageData ii = new ImageData(x.intValue(), albumLabel, imageLabel);
172
173 ii.setFavorite(favorite);
174
175 ii.setNumberOfViews(numberOfViews);
176
177 x = Integer.valueOf(intString);
178 ii.setRecordId(x.intValue());
179 return ii;
180 } catch (Exception e) {
181 throw new InvalidArrayFormatException();
182 }
183 }
184
185 /**
186 *
187 * Convert the ImageInfo (renamed ImageData) object into bytes so we can
188 * store it in RMS Order of the string will look like this: <recordId>*<foreignRecordId>*<labelName>*<imageLabel>
189 * Depending on the optional features, additional fields may be: <phoneNum>
190 * @throws InvalidImageDataException
191 */
192 public byte[] getBytesFromImageInfo(ImageData ii) throws InvalidImageDataException {
193
194 // Take each String and get the bytes from it, separating fields with a
195 // delimiter
196 try {
197 String byteString = new String();
198
199 // Convert the record ID for this record
200 int i = ii.getRecordId();
201 Integer j = new Integer(i);
202 byteString = byteString.concat(j.toString());
203 byteString = byteString.concat(DELIMITER);
204
205 // Convert the 'Foreign' Record ID field for the corresponding Image
206 // record store
207 int i2 = ii.getForeignRecordId();
208 Integer j2 = new Integer(i2);
209 byteString = byteString.concat(j2.toString());
210 byteString = byteString.concat(DELIMITER);
211
212 // Convert the album name field
213 byteString = byteString.concat(ii.getParentAlbumName());
214 byteString = byteString.concat(DELIMITER);
215
216 // Convert the label (name) field
217 byteString = byteString.concat(ii.getImageLabel());
218
219 byteString = byteString.concat(DELIMITER);
220 if (ii.isFavorite()) byteString = byteString.concat("true");
221 else byteString = byteString.concat("false");
222
223 byteString = byteString.concat(DELIMITER);
224 byteString = byteString.concat(""+ii.getNumberOfViews());
225
226 // TODO: Add pre-processor statements
227 // Convert the phone number field
228 return byteString.getBytes();
229 } catch (Exception e) {
230 throw new InvalidImageDataException("The provided data are not valid");
231 }
232
233 }
234
235 }
|