1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <jni.h>
18 #include <android/log.h>
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <math.h>
23 
24 #include <RenderScript.h>
25 
26 #define  LOG_TAG    "rscpptest"
27 #define  LOGV(...)  __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__)
28 
29 using namespace android::RSC;
30 
31 /*returns an addr aligned to the byte boundary specified by align*/
32 #define align_addr(addr,align) (void *)(((size_t)(addr) + ((align) - 1)) & (size_t) - (align))
33 #define ADDRESS_STORAGE_SIZE sizeof(size_t)
34 
aligned_alloc(size_t align,size_t size)35 void * aligned_alloc(size_t align, size_t size) {
36     void * addr, * x = NULL;
37     addr = malloc(size + align - 1 + ADDRESS_STORAGE_SIZE);
38     if (addr) {
39         x = align_addr((unsigned char *) addr + ADDRESS_STORAGE_SIZE, (int) align);
40         /* save the actual malloc address */
41         ((size_t *) x)[-1] = (size_t) addr;
42     }
43     return x;
44 }
45 
aligned_free(void * memblk)46 void aligned_free(void * memblk) {
47     if (memblk) {
48         void * addr = (void *) (((size_t *) memblk)[-1]);
49         free(addr);
50     }
51 }
52 
makeElement(const sp<RS> & rs,RsDataType dt,int vecSize)53 sp<const Element> makeElement(const sp<RS> &rs, RsDataType dt, int vecSize) {
54     if (vecSize > 1) {
55         return Element::createVector(rs, dt, vecSize);
56     } else {
57         if (dt == RS_TYPE_UNSIGNED_8) {
58             return Element::U8(rs);
59         } else {
60             return Element::F32(rs);
61         }
62     }
63 }
64 
Java_android_cts_rscpp_RSInitTest_initTest(JNIEnv * env,jclass obj,jstring pathObj)65 extern "C" JNIEXPORT jboolean JNICALL Java_android_cts_rscpp_RSInitTest_initTest(JNIEnv * env,
66                                                                                  jclass obj,
67                                                                                  jstring pathObj)
68 {
69     const char * path = env->GetStringUTFChars(pathObj, NULL);
70     bool r = true;
71     for (int i = 0; i < 1000; i++) {
72         sp<RS> rs = new RS();
73         r &= rs->init(path);
74         LOGV("Native iteration %i, returned %i", i, (int)r);
75     }
76     env->ReleaseStringUTFChars(pathObj, path);
77     return r;
78 }
79 
Java_android_cts_rscpp_RSBlurTest_blurTest(JNIEnv * env,jclass obj,jstring pathObj,jint X,jint Y,jbyteArray inputByteArray,jbyteArray outputByteArray,jboolean singleChannel)80 extern "C" JNIEXPORT jboolean JNICALL Java_android_cts_rscpp_RSBlurTest_blurTest(JNIEnv * env,
81                                                                                  jclass obj,
82                                                                                  jstring pathObj,
83                                                                                  jint X,
84                                                                                  jint Y,
85                                                                                  jbyteArray inputByteArray,
86                                                                                  jbyteArray outputByteArray,
87                                                                                  jboolean singleChannel)
88 {
89     const char * path = env->GetStringUTFChars(pathObj, NULL);
90     jbyte * input = (jbyte *) env->GetPrimitiveArrayCritical(inputByteArray, 0);
91     jbyte * output = (jbyte *) env->GetPrimitiveArrayCritical(outputByteArray, 0);
92 
93     sp<RS> rs = new RS();
94     rs->init(path);
95 
96     sp<const Element> e;
97     if (singleChannel) {
98         e = Element::A_8(rs);
99     } else {
100         e = Element::RGBA_8888(rs);
101     }
102 
103     sp<Allocation> inputAlloc = Allocation::createSized2D(rs, e, X, Y);
104     sp<Allocation> outputAlloc = Allocation::createSized2D(rs, e, X, Y);
105     sp<ScriptIntrinsicBlur> blur = ScriptIntrinsicBlur::create(rs, e);
106 
107     inputAlloc->copy2DRangeFrom(0, 0, X, Y, input);
108 
109     blur->setRadius(15);
110     blur->setInput(inputAlloc);
111     blur->forEach(outputAlloc);
112     outputAlloc->copy2DRangeTo(0, 0, X, Y, output);
113 
114     env->ReleasePrimitiveArrayCritical(inputByteArray, input, 0);
115     env->ReleasePrimitiveArrayCritical(outputByteArray, output, 0);
116     env->ReleaseStringUTFChars(pathObj, path);
117     return (rs->getError() == RS_SUCCESS);
118 
119 }
120 
121 extern "C" JNIEXPORT jboolean JNICALL
Java_android_cts_rscpp_RSConvolveTest_convolveTest(JNIEnv * env,jclass obj,jstring pathObj,jint X,jint Y,jbyteArray inputByteArray,jbyteArray outputByteArray,jfloatArray coeffArray,jboolean is3x3)122 Java_android_cts_rscpp_RSConvolveTest_convolveTest(JNIEnv * env, jclass obj, jstring pathObj,
123                                                    jint X, jint Y, jbyteArray inputByteArray,
124                                                    jbyteArray outputByteArray,
125                                                    jfloatArray coeffArray,
126                                                    jboolean is3x3)
127 {
128     const char * path = env->GetStringUTFChars(pathObj, NULL);
129     jfloat * coeffs = env->GetFloatArrayElements(coeffArray, NULL);
130     jbyte * input = (jbyte *) env->GetPrimitiveArrayCritical(inputByteArray, 0);
131     jbyte * output = (jbyte *) env->GetPrimitiveArrayCritical(outputByteArray, 0);
132 
133 
134     sp<RS> rs = new RS();
135     rs->init(path);
136 
137     sp<const Element> e = Element::A_8(rs);
138 
139     sp<Allocation> inputAlloc = Allocation::createSized2D(rs, e, X, Y);
140     sp<Allocation> outputAlloc = Allocation::createSized2D(rs, e, X, Y);
141 
142     inputAlloc->copy2DRangeFrom(0, 0, X, Y, input);
143 
144 
145     if (is3x3) {
146         sp<ScriptIntrinsicConvolve3x3> convolve = ScriptIntrinsicConvolve3x3::create(rs, e);
147         convolve->setInput(inputAlloc);
148         convolve->setCoefficients(coeffs);
149         convolve->forEach(outputAlloc);
150     } else {
151         sp<ScriptIntrinsicConvolve5x5> convolve = ScriptIntrinsicConvolve5x5::create(rs, e);
152         convolve->setInput(inputAlloc);
153         convolve->setCoefficients(coeffs);
154         convolve->forEach(outputAlloc);
155     }
156 
157     outputAlloc->copy2DRangeTo(0, 0, X, Y, output);
158 
159     env->ReleasePrimitiveArrayCritical(inputByteArray, input, 0);
160     env->ReleasePrimitiveArrayCritical(outputByteArray, output, 0);
161     env->ReleaseFloatArrayElements(coeffArray, coeffs, JNI_ABORT);
162     env->ReleaseStringUTFChars(pathObj, path);
163     return (rs->getError() == RS_SUCCESS);
164 
165 }
166 
Java_android_cts_rscpp_RSLUTTest_lutTest(JNIEnv * env,jclass obj,jstring pathObj,jint X,jint Y,jbyteArray inputByteArray,jbyteArray outputByteArray)167 extern "C" JNIEXPORT jboolean JNICALL Java_android_cts_rscpp_RSLUTTest_lutTest(JNIEnv * env,
168                                                                                jclass obj,
169                                                                                jstring pathObj,
170                                                                                jint X,
171                                                                                jint Y,
172                                                                                jbyteArray inputByteArray,
173                                                                                jbyteArray outputByteArray)
174 {
175     const char * path = env->GetStringUTFChars(pathObj, NULL);
176     jbyte * input = (jbyte *) env->GetPrimitiveArrayCritical(inputByteArray, 0);
177     jbyte * output = (jbyte *) env->GetPrimitiveArrayCritical(outputByteArray, 0);
178 
179     sp<RS> rs = new RS();
180     rs->init(path);
181 
182     sp<const Element> e = Element::RGBA_8888(rs);
183 
184     sp<Allocation> inputAlloc = Allocation::createSized2D(rs, e, X, Y);
185     sp<Allocation> outputAlloc = Allocation::createSized2D(rs, e, X, Y);
186     sp<ScriptIntrinsicLUT> lut = ScriptIntrinsicLUT::create(rs, e);
187 
188     inputAlloc->copy2DRangeFrom(0, 0, X, Y, input);
189     unsigned char lutValues[256];
190     for (int i = 0; i < 256; i++) {
191         lutValues[i] = 255-i;
192     }
193     lut->setRed(0, 256, lutValues);
194     lut->setGreen(0, 256, lutValues);
195     lut->setBlue(0, 256, lutValues);
196 
197     lut->forEach(inputAlloc,outputAlloc);
198     outputAlloc->copy2DRangeTo(0, 0, X, Y, output);
199 
200     env->ReleasePrimitiveArrayCritical(inputByteArray, input, 0);
201     env->ReleasePrimitiveArrayCritical(outputByteArray, output, 0);
202     env->ReleaseStringUTFChars(pathObj, path);
203     return (rs->getError() == RS_SUCCESS);
204 
205 }
206 
Java_android_cts_rscpp_RS3DLUTTest_lutTest(JNIEnv * env,jclass obj,jstring pathObj,jint X,jint Y,jint lutSize,jbyteArray inputByteArray,jbyteArray inputByteArray2,jbyteArray outputByteArray)207 extern "C" JNIEXPORT jboolean JNICALL Java_android_cts_rscpp_RS3DLUTTest_lutTest(JNIEnv * env,
208                                                                                  jclass obj,
209                                                                                  jstring pathObj,
210                                                                                  jint X,
211                                                                                  jint Y,
212                                                                                  jint lutSize,
213                                                                                  jbyteArray inputByteArray,
214                                                                                  jbyteArray inputByteArray2,
215                                                                                  jbyteArray outputByteArray)
216 {
217     const char * path = env->GetStringUTFChars(pathObj, NULL);
218     jbyte * input = (jbyte *) env->GetPrimitiveArrayCritical(inputByteArray, 0);
219     jbyte * input2 = (jbyte *) env->GetPrimitiveArrayCritical(inputByteArray2, 0);
220     jbyte * output = (jbyte *) env->GetPrimitiveArrayCritical(outputByteArray, 0);
221 
222     sp<RS> rs = new RS();
223     rs->init(path);
224 
225     sp<const Element> e = Element::RGBA_8888(rs);
226 
227     Type::Builder builder(rs, e);
228 
229     builder.setX(lutSize);
230     builder.setY(lutSize);
231     builder.setZ(lutSize);
232 
233     sp<Allocation> inputAlloc = Allocation::createSized2D(rs, e, X, Y);
234     sp<Allocation> colorCube = Allocation::createTyped(rs, builder.create());
235     sp<Allocation> outputAlloc = Allocation::createSized2D(rs, e, X, Y);
236     sp<ScriptIntrinsic3DLUT> lut = ScriptIntrinsic3DLUT::create(rs, e);
237 
238     inputAlloc->copy2DRangeFrom(0, 0, X, Y, input);
239     colorCube->copy3DRangeFrom(0, 0, 0, lutSize, lutSize, lutSize, input2);
240 
241     lut->setLUT(colorCube);
242     lut->forEach(inputAlloc,outputAlloc);
243 
244     outputAlloc->copy2DRangeTo(0, 0, X, Y, output);
245 
246     env->ReleasePrimitiveArrayCritical(inputByteArray, input, 0);
247     env->ReleasePrimitiveArrayCritical(inputByteArray2, input2, 0);
248     env->ReleasePrimitiveArrayCritical(outputByteArray, output, 0);
249     env->ReleaseStringUTFChars(pathObj, path);
250     return (rs->getError() == RS_SUCCESS);
251 
252 }
253 
254 extern "C" JNIEXPORT jboolean JNICALL
Java_android_cts_rscpp_RSColorMatrixTest_colorMatrixTest(JNIEnv * env,jclass obj,jstring pathObj,jint X,jint Y,jbyteArray inputByteArray,jbyteArray outputByteArray,jfloatArray coeffArray,jint optionFlag)255 Java_android_cts_rscpp_RSColorMatrixTest_colorMatrixTest(JNIEnv * env, jclass obj, jstring pathObj,
256                                                          jint X, jint Y, jbyteArray inputByteArray,
257                                                          jbyteArray outputByteArray,
258                                                          jfloatArray coeffArray,
259                                                          jint optionFlag)
260 {
261     const char * path = env->GetStringUTFChars(pathObj, NULL);
262     jfloat * coeffs = env->GetFloatArrayElements(coeffArray, NULL);
263     jbyte * input = (jbyte *) env->GetPrimitiveArrayCritical(inputByteArray, 0);
264     jbyte * output = (jbyte *) env->GetPrimitiveArrayCritical(outputByteArray, 0);
265 
266     sp<RS> rs = new RS();
267     rs->init(path);
268 
269     sp<const Element> e = Element::RGBA_8888(rs);
270 
271     sp<Allocation> inputAlloc = Allocation::createSized2D(rs, e, X, Y);
272     sp<Allocation> outputAlloc = Allocation::createSized2D(rs, e, X, Y);
273 
274     inputAlloc->copy2DRangeFrom(0, 0, X, Y, input);
275 
276     sp<ScriptIntrinsicColorMatrix> cm = ScriptIntrinsicColorMatrix::create(rs);
277     if (optionFlag == 0) {
278         cm->setColorMatrix3(coeffs);
279     } else if (optionFlag == 1) {
280         cm->setGreyscale();
281     } else if (optionFlag == 2) {
282         cm->setColorMatrix4(coeffs);
283     } else if (optionFlag == 3) {
284         cm->setYUVtoRGB();
285     } else if (optionFlag == 4) {
286         cm->setRGBtoYUV();
287     } else if (optionFlag == 5) {
288         cm->setColorMatrix4(coeffs);
289         float add[4] = {5.3f, 2.1f, 0.3f, 4.4f};
290         cm->setAdd(add);
291     }
292     cm->forEach(inputAlloc, outputAlloc);
293 
294     outputAlloc->copy2DRangeTo(0, 0, X, Y, output);
295 
296     env->ReleasePrimitiveArrayCritical(inputByteArray, input, 0);
297     env->ReleasePrimitiveArrayCritical(outputByteArray, output, 0);
298     env->ReleaseFloatArrayElements(coeffArray, coeffs, JNI_ABORT);
299     env->ReleaseStringUTFChars(pathObj, path);
300     return (rs->getError() == RS_SUCCESS);
301 
302 }
303 
304 extern "C" JNIEXPORT jboolean JNICALL
Java_android_cts_rscpp_RSBlendTest_blendTest(JNIEnv * env,jclass obj,jstring pathObj,jint X,jint Y,jbyteArray inputByteArray,jbyteArray outputByteArray,jint optionFlag)305 Java_android_cts_rscpp_RSBlendTest_blendTest(JNIEnv * env, jclass obj, jstring pathObj,
306                                              jint X, jint Y, jbyteArray inputByteArray,
307                                              jbyteArray outputByteArray,
308                                              jint optionFlag)
309 {
310     const char * path = env->GetStringUTFChars(pathObj, NULL);
311     jbyte * input = (jbyte *) env->GetPrimitiveArrayCritical(inputByteArray, 0);
312     jbyte * output = (jbyte *) env->GetPrimitiveArrayCritical(outputByteArray, 0);
313 
314     sp<RS> rs = new RS();
315     rs->init(path);
316 
317     sp<const Element> e = Element::RGBA_8888(rs);
318 
319     sp<Allocation> inputAlloc = Allocation::createSized2D(rs, e, X, Y);
320     sp<Allocation> outputAlloc = Allocation::createSized2D(rs, e, X, Y);
321 
322     inputAlloc->copy2DRangeFrom(0, 0, X, Y, input);
323     outputAlloc->copy2DRangeFrom(0, 0, X, Y, output);
324 
325     sp<ScriptIntrinsicBlend> blend = ScriptIntrinsicBlend::create(rs, e);
326     switch(optionFlag) {
327     case 0:
328         blend->forEachAdd(inputAlloc, outputAlloc);
329         break;
330     case 1:
331         blend->forEachClear(inputAlloc, outputAlloc);
332         break;
333     case 2:
334         blend->forEachDst(inputAlloc, outputAlloc);
335         break;
336     case 3:
337         blend->forEachDstAtop(inputAlloc, outputAlloc);
338         break;
339     case 4:
340         blend->forEachDstIn(inputAlloc, outputAlloc);
341         break;
342     case 5:
343         blend->forEachDstOut(inputAlloc, outputAlloc);
344         break;
345     case 6:
346         blend->forEachDstOver(inputAlloc, outputAlloc);
347         break;
348     case 7:
349         blend->forEachMultiply(inputAlloc, outputAlloc);
350         break;
351     case 8:
352         blend->forEachSrc(inputAlloc, outputAlloc);
353         break;
354     case 9:
355         blend->forEachSrcAtop(inputAlloc, outputAlloc);
356         break;
357     case 10:
358         blend->forEachSrcIn(inputAlloc, outputAlloc);
359         break;
360     case 11:
361         blend->forEachSrcOut(inputAlloc, outputAlloc);
362         break;
363     case 12:
364         blend->forEachSrcOver(inputAlloc, outputAlloc);
365         break;
366     case 13:
367         blend->forEachSubtract(inputAlloc, outputAlloc);
368         break;
369     case 14:
370         blend->forEachXor(inputAlloc, outputAlloc);
371         break;
372     default:
373         break;
374     }
375 
376     outputAlloc->copy2DRangeTo(0, 0, X, Y, output);
377 
378     env->ReleasePrimitiveArrayCritical(inputByteArray, input, 0);
379     env->ReleasePrimitiveArrayCritical(outputByteArray, output, 0);
380     env->ReleaseStringUTFChars(pathObj, path);
381     return (rs->getError() == RS_SUCCESS);
382 
383 }
384 
Java_android_cts_rscpp_RSResizeTest_resizeTest(JNIEnv * env,jclass obj,jstring pathObj,jint X,jint Y,jfloat scaleX,jfloat scaleY,jboolean useByte,jint vecSize,jbyteArray inputByteArray,jbyteArray outputByteArray,jfloatArray inputFloatArray,jfloatArray outputFloatArray)385 extern "C" JNIEXPORT jboolean JNICALL Java_android_cts_rscpp_RSResizeTest_resizeTest(JNIEnv * env,
386                                                                                      jclass obj,
387                                                                                      jstring pathObj,
388                                                                                      jint X,
389                                                                                      jint Y,
390                                                                                      jfloat scaleX,
391                                                                                      jfloat scaleY,
392                                                                                      jboolean useByte,
393                                                                                      jint vecSize,
394                                                                                      jbyteArray inputByteArray,
395                                                                                      jbyteArray outputByteArray,
396                                                                                      jfloatArray inputFloatArray,
397                                                                                      jfloatArray outputFloatArray
398                                                                                      )
399 {
400     const char * path = env->GetStringUTFChars(pathObj, NULL);
401 
402     sp<RS> rs = new RS();
403     rs->init(path);
404 
405     RsDataType dt = RS_TYPE_UNSIGNED_8;
406     if (!useByte) {
407         dt = RS_TYPE_FLOAT_32;
408     }
409     sp<const Element> e = makeElement(rs, dt, vecSize);
410     sp<Allocation> inputAlloc = Allocation::createSized2D(rs, e, X, Y);
411 
412     int outX = (int) (X * scaleX);
413     int outY = (int) (Y * scaleY);
414     sp<Allocation> outputAlloc = Allocation::createSized2D(rs, e, outX, outY);
415     sp<ScriptIntrinsicResize> resize = ScriptIntrinsicResize::create(rs);
416 
417     if (useByte) {
418         jbyte * input = (jbyte *) env->GetPrimitiveArrayCritical(inputByteArray, 0);
419         inputAlloc->copy2DRangeFrom(0, 0, X, Y, input);
420         env->ReleasePrimitiveArrayCritical(inputByteArray, input, 0);
421     } else {
422         jfloat * input = (jfloat *) env->GetPrimitiveArrayCritical(inputFloatArray, 0);
423         inputAlloc->copy2DRangeFrom(0, 0, X, Y, input);
424         env->ReleasePrimitiveArrayCritical(inputFloatArray, input, 0);
425     }
426 
427     resize->setInput(inputAlloc);
428     resize->forEach_bicubic(outputAlloc);
429 
430     if (useByte) {
431         jbyte * output = (jbyte *) env->GetPrimitiveArrayCritical(outputByteArray, 0);
432         outputAlloc->copy2DRangeTo(0, 0, outX, outY, output);
433         env->ReleasePrimitiveArrayCritical(outputByteArray, output, 0);
434     } else {
435         jfloat * output = (jfloat *) env->GetPrimitiveArrayCritical(outputFloatArray, 0);
436         outputAlloc->copy2DRangeTo(0, 0, outX, outY, output);
437         env->ReleasePrimitiveArrayCritical(outputFloatArray, output, 0);
438     }
439 
440     env->ReleaseStringUTFChars(pathObj, path);
441     return (rs->getError() == RS_SUCCESS);
442 
443 }
444 
Java_android_cts_rscpp_RSYuvTest_yuvTest(JNIEnv * env,jclass obj,jstring pathObj,jint X,jint Y,jbyteArray inputByteArray,jbyteArray outputByteArray,jint yuvFormat)445 extern "C" JNIEXPORT jboolean JNICALL Java_android_cts_rscpp_RSYuvTest_yuvTest(JNIEnv * env,
446                                                                                jclass obj,
447                                                                                jstring pathObj,
448                                                                                jint X,
449                                                                                jint Y,
450                                                                                jbyteArray inputByteArray,
451                                                                                jbyteArray outputByteArray,
452                                                                                jint yuvFormat
453                                                                                )
454 {
455     const char * path = env->GetStringUTFChars(pathObj, NULL);
456     jbyte * input = (jbyte *) env->GetPrimitiveArrayCritical(inputByteArray, 0);
457     jbyte * output = (jbyte *) env->GetPrimitiveArrayCritical(outputByteArray, 0);
458 
459     sp<RS> mRS = new RS();
460     mRS->init(path);
461 
462     RsYuvFormat mYuvFormat = (RsYuvFormat)yuvFormat;
463     sp<ScriptIntrinsicYuvToRGB> syuv = ScriptIntrinsicYuvToRGB::create(mRS, Element::U8_4(mRS));;
464     sp<Allocation> inputAlloc = nullptr;
465 
466     if (mYuvFormat != RS_YUV_NONE) {
467         //syuv = ScriptIntrinsicYuvToRGB::create(mRS, Element::YUV(mRS));
468         Type::Builder tb(mRS, Element::YUV(mRS));
469         tb.setX(X);
470         tb.setY(Y);
471         tb.setYuvFormat(mYuvFormat);
472         inputAlloc = Allocation::createTyped(mRS, tb.create());
473         inputAlloc->copy2DRangeFrom(0, 0, X, Y, input);
474     } else {
475         //syuv = ScriptIntrinsicYuvToRGB::create(mRS, Element::U8(mRS));
476         size_t arrLen = X * Y + ((X + 1) / 2) * ((Y + 1) / 2) * 2;
477         inputAlloc = Allocation::createSized(mRS, Element::U8(mRS), arrLen);
478         inputAlloc->copy1DRangeFrom(0, arrLen, input);
479     }
480 
481     sp<const Type> tout = Type::create(mRS, Element::RGBA_8888(mRS), X, Y, 0);
482     sp<Allocation> outputAlloc = Allocation::createTyped(mRS, tout);
483 
484     syuv->setInput(inputAlloc);
485     syuv->forEach(outputAlloc);
486 
487     outputAlloc->copy2DRangeTo(0, 0, X, Y, output);
488 
489     env->ReleasePrimitiveArrayCritical(inputByteArray, input, 0);
490     env->ReleasePrimitiveArrayCritical(outputByteArray, output, 0);
491     env->ReleaseStringUTFChars(pathObj, path);
492     return (mRS->getError() == RS_SUCCESS);
493 
494 }
495