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 // #ifdef includeFavourites
136 // [EF] Favorite (Scenario 03)
137 boolean favorite = false;
138 startIndex = endIndex + 1;
139 endIndex = iiString.indexOf(DELIMITER, startIndex);
140
141 if (endIndex == -1)
142 endIndex = iiString.length();
143
144 favorite = (iiString.substring(startIndex, endIndex)).equalsIgnoreCase("true");
145 // #endif
146
147 // #ifdef includeCountViews
148 // [EF] Number of Views (Scenario 02)
149 startIndex = endIndex + 1;
150 endIndex = iiString.indexOf(DELIMITER, startIndex);
151
152 if (endIndex == -1)
153 endIndex = iiString.length();
154
155 int numberOfViews = 0;
156 try {
157 numberOfViews = Integer.parseInt(iiString.substring(startIndex, endIndex));
158 } catch (RuntimeException e) {
159 numberOfViews = 0;
160 e.printStackTrace();
161 }
162 // #endif
163
164 // TODO: Add preprocessor statements here
165
166 // Get the phone number if one exists
167 // if ((endIndex + 1) < iiString.length()) {
168 // System.out.println("<* ImageUtil.getImageInfoFromBytes() *> phoneNum : "+endIndex+" < "+iiString.length());
169 // startIndex = endIndex + 1;
170 // endIndex = iiString.indexOf(DELIMITER, startIndex);
171 // if (endIndex == -1)
172 // endIndex = iiString.length();
173 // iiString.substring(startIndex, endIndex);
174 // }
175
176 Integer x = Integer.valueOf(fidString);
177 ImageData ii = new ImageData(x.intValue(), albumLabel, imageLabel);
178
179 // #ifdef includeFavourites
180 ii.setFavorite(favorite);
181 // #endif
182
183 // #ifdef includeCountViews
184 ii.setNumberOfViews(numberOfViews);
185 // #endif
186
187 x = Integer.valueOf(intString);
188 ii.setRecordId(x.intValue());
189 return ii;
190 } catch (Exception e) {
191 throw new InvalidArrayFormatException();
192 }
193 }
194
195 /**
196 *
197 * Convert the ImageInfo (renamed ImageData) object into bytes so we can
198 * store it in RMS Order of the string will look like this: <recordId>*<foreignRecordId>*<labelName>*<imageLabel>
199 * Depending on the optional features, additional fields may be: <phoneNum>
200 * @throws InvalidImageDataException
201 */
202 public byte[] getBytesFromImageInfo(ImageData ii) throws InvalidImageDataException {
203
204 // Take each String and get the bytes from it, separating fields with a
205 // delimiter
206 try {
207 String byteString = new String();
208
209 // Convert the record ID for this record
210 int i = ii.getRecordId();
211 Integer j = new Integer(i);
212 byteString = byteString.concat(j.toString());
213 byteString = byteString.concat(DELIMITER);
214
215 // Convert the 'Foreign' Record ID field for the corresponding Image
216 // record store
217 int i2 = ii.getForeignRecordId();
218 Integer j2 = new Integer(i2);
219 byteString = byteString.concat(j2.toString());
220 byteString = byteString.concat(DELIMITER);
221
222 // Convert the album name field
223 byteString = byteString.concat(ii.getParentAlbumName());
224 byteString = byteString.concat(DELIMITER);
225
226 // Convert the label (name) field
227 byteString = byteString.concat(ii.getImageLabel());
228
229 // #ifdef includeFavourites
230 byteString = byteString.concat(DELIMITER);
231 if (ii.isFavorite()) byteString = byteString.concat("true");
232 else byteString = byteString.concat("false");
233 // #endif
234
235 // #ifdef includeCountViews
236 byteString = byteString.concat(DELIMITER);
237 byteString = byteString.concat(""+ii.getNumberOfViews());
238 // #endif
239
240 // TODO: Add pre-processor statements
241 // Convert the phone number field
242 return byteString.getBytes();
243 } catch (Exception e) {
244 throw new InvalidImageDataException("The provided data are not valid");
245 }
246
247 }
248
249 }
|