Mbed OS version of IoT.js implementation running on GR-PEACH
Embed:
(wiki syntax)
Show/hide line numbers
iotjs_module_jpeg.c
00001 /* Copyright 2017-present Renesas Electronics Corporation and other contributors 00002 * 00003 * Licensed under the Apache License, Version 2.0 (the "License"); 00004 * you may not use this file except in compliance with the License. 00005 * You may obtain a copy of the License at 00006 * 00007 * http://www.apache.org/licenses/LICENSE-2.0 00008 * 00009 * Unless required by applicable law or agreed to in writing, software 00010 * distributed under the License is distributed on an "AS IS" BASIS 00011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 * See the License for the specific language governing permissions and 00013 * limitations under the License. 00014 */ 00015 00016 #include "iotjs_def.h" 00017 00018 #if defined(USE_POSIX_BRIDGE) 00019 #include "peripheral_io.h" 00020 #include "iotjs_module_aligned_buffer.h" 00021 #include "iotjs_module_jpeg.h" 00022 #include <malloc.h> 00023 00024 IOTJS_DEFINE_NATIVE_HANDLE_INFO_THIS_MODULE(jpeg); 00025 00026 struct iotjs_jpeg_platform_data_s { 00027 int dummy; 00028 }; 00029 00030 jerry_value_t iotjs_jpeg_set_platform_config(iotjs_jpeg_t* jpeg, 00031 const jerry_value_t jconfig) { 00032 return jerry_create_undefined(); 00033 } 00034 00035 void iotjs_jpeg_create_platform_data(iotjs_jpeg_t* jpeg) { 00036 jpeg->platform_data = IOTJS_ALLOC(iotjs_jpeg_platform_data_t); 00037 } 00038 00039 void iotjs_jpeg_destroy_platform_data( 00040 iotjs_jpeg_platform_data_t* platform_data) { 00041 IOTJS_RELEASE(platform_data); 00042 } 00043 00044 IOTJS_DEFINE_PERIPH_CREATE_FUNCTION(jpeg); 00045 00046 static uint32_t get_pixel_bytes(jpeg_pixel_format_t format) { 00047 switch(format) { 00048 case JPEG_PIXELFORMAT_YCBCR422: 00049 case JPEG_PIXELFORMAT_RGB565: 00050 return 2; 00051 case JPEG_PIXELFORMAT_ARGB8888: 00052 return 4; 00053 default: 00054 return 0; 00055 } 00056 } 00057 00058 bool iotjs_jpeg_encode(iotjs_jpeg_t* jpeg) { 00059 uint32_t width = (jpeg->encode_data.width + 31)&~31; 00060 uint32_t height = (jpeg->encode_data.height + 15)&~15; 00061 uint32_t encode_len = width * height * get_pixel_bytes(jpeg->encode_data.pixel_format); 00062 jpeg->encode_data.dst.buf = memalign(32, encode_len); 00063 if(jpeg->encode_data.dst.buf == NULL) { 00064 return false; 00065 } 00066 jpeg->encode_data.src.len = encode_len; 00067 jpeg->encode_data.dst.len = encode_len; 00068 00069 int ret = jpeg_encode(jpeg->encode_data); 00070 if(ret < 0) { 00071 IOTJS_RELEASE(jpeg->encode_data.dst.buf); 00072 return false; 00073 } 00074 00075 jpeg->encode_data.dst.len = ret; 00076 00077 return true; 00078 } 00079 00080 bool iotjs_jpeg_decode(iotjs_jpeg_t* jpeg) { 00081 uint32_t width = (jpeg->decode_data.width + 31)&~31; 00082 uint32_t height = (jpeg->decode_data.height + 15)&~15; 00083 uint32_t decode_len = width * height * get_pixel_bytes(jpeg->decode_data.pixel_format); 00084 jpeg->decode_data.dst.buf = memalign(32, decode_len); 00085 if(jpeg->decode_data.dst.buf == NULL) { 00086 return false; 00087 } 00088 memset(jpeg->decode_data.dst.buf, 0, decode_len); 00089 jpeg->decode_data.dst.len = decode_len; 00090 00091 bool ret = jpeg_decode(jpeg->decode_data); 00092 if(!ret) { 00093 IOTJS_RELEASE(jpeg->decode_data.dst.buf); 00094 return false; 00095 } 00096 00097 return true; 00098 } 00099 00100 static void iotjs_jpeg_destroy(iotjs_jpeg_t* jpeg) { 00101 iotjs_jpeg_destroy_platform_data(jpeg->platform_data); 00102 IOTJS_RELEASE(jpeg); 00103 } 00104 00105 static void jpeg_worker(uv_work_t* work_req) { 00106 iotjs_periph_reqwrap_t* req_wrap = 00107 (iotjs_periph_reqwrap_t*)(iotjs_reqwrap_from_request( 00108 (uv_req_t*)work_req)); 00109 iotjs_jpeg_t* jpeg = (iotjs_jpeg_t*)req_wrap->data; 00110 00111 switch (req_wrap->op) { 00112 case kJpegOpEncode: 00113 req_wrap->result = iotjs_jpeg_encode(jpeg); 00114 break; 00115 case kJpegOpDecode: 00116 req_wrap->result = iotjs_jpeg_decode(jpeg); 00117 break; 00118 default: 00119 IOTJS_ASSERT(!"Invalid Operation"); 00120 } 00121 } 00122 00123 static jerry_value_t jpeg_set_configuration(iotjs_jpeg_t* jpeg, 00124 jerry_value_t jconfig) { 00125 return jerry_create_undefined(); 00126 } 00127 00128 00129 static jerry_value_t jpeg_get_encode_param(iotjs_jpeg_t* jpeg, 00130 const jerry_value_t jargv[], 00131 const jerry_length_t jargc) { 00132 if(jargc < 1) { 00133 return JS_CREATE_ERROR(TYPE, "Invalid Arguments"); 00134 } 00135 00136 jerry_value_t jimage = JS_GET_ARG(0, object); 00137 jerry_value_t jwidth = iotjs_jval_get_property(jimage, "width"); 00138 if (jerry_value_is_number(jwidth)) { 00139 jpeg->encode_data.width = iotjs_jval_as_number(jwidth); 00140 } else { 00141 jerry_release_value(jwidth); 00142 return JS_CREATE_ERROR( 00143 TYPE, "Invalid image.width"); 00144 } 00145 jerry_release_value(jwidth); 00146 00147 jerry_value_t jheight = iotjs_jval_get_property(jimage, "height"); 00148 if (jerry_value_is_number(jheight)) { 00149 jpeg->encode_data.height = iotjs_jval_as_number(jheight); 00150 } else { 00151 jerry_release_value(jheight); 00152 return JS_CREATE_ERROR( 00153 TYPE, "Invalid image.height"); 00154 } 00155 jerry_release_value(jheight); 00156 00157 jerry_value_t jformat = iotjs_jval_get_property(jimage, "format"); 00158 if (jerry_value_is_number(jformat)) { 00159 jpeg->encode_data.pixel_format = iotjs_jval_as_number(jformat); 00160 } else { 00161 jpeg->encode_data.pixel_format = JPEG_PIXELFORMAT_MAX; 00162 } 00163 jerry_release_value(jformat); 00164 if(jpeg->encode_data.pixel_format != JPEG_PIXELFORMAT_YCBCR422) { 00165 return JS_CREATE_ERROR(TYPE, "Invalid image.format"); 00166 } 00167 00168 jerry_value_t jbitmap = iotjs_jval_get_property(jimage, "bitmap"); 00169 iotjs_aligned_buffer_wrap_t* buffer_wrap = iotjs_aligned_buffer_wrap_from_jbuffer(jbitmap); 00170 jpeg->encode_data.src.buf = (uint8_t*)iotjs_aligned_buffer_wrap_native_buffer_ptr(buffer_wrap); 00171 jerry_release_value(jbitmap); 00172 if(((buffer_wrap->alignment % 32) != 0) || (((int)jpeg->encode_data.src.buf % 32) != 0)) { 00173 return JS_CREATE_ERROR(TYPE, "Invalid image.bitmap alignment"); 00174 } 00175 00176 return jerry_create_undefined(); 00177 } 00178 00179 00180 static jerry_value_t jpeg_get_decode_param(iotjs_jpeg_t* jpeg, 00181 const jerry_value_t jargv[], 00182 const jerry_length_t jargc) { 00183 if(jargc < 2) { 00184 return JS_CREATE_ERROR(TYPE, "Invalid Arguments"); 00185 } 00186 00187 const jerry_value_t jjpeg_data = JS_GET_ARG(0, object); 00188 iotjs_aligned_buffer_wrap_t* buffer_wrap = iotjs_aligned_buffer_wrap_from_jbuffer(jjpeg_data); 00189 jpeg->decode_data.src.buf = iotjs_aligned_buffer_wrap_native_buffer_ptr(buffer_wrap); 00190 jpeg->decode_data.src.len = buffer_wrap->length; 00191 if(((buffer_wrap->alignment % 32) != 0) || (((int)jpeg->decode_data.src.buf % 32) != 0)) { 00192 return JS_CREATE_ERROR(TYPE, "Invalid jpegData alignment"); 00193 } 00194 00195 const jerry_value_t jconfig = JS_GET_ARG(1, object); 00196 00197 jerry_value_t jwidth = iotjs_jval_get_property(jconfig, "width"); 00198 if (jerry_value_is_number(jwidth)) { 00199 jpeg->decode_data.width = iotjs_jval_as_number(jwidth); 00200 } else { 00201 jerry_release_value(jwidth); 00202 return JS_CREATE_ERROR( 00203 TYPE, "Invalid options.width"); 00204 } 00205 jerry_release_value(jwidth); 00206 00207 jerry_value_t jheight = iotjs_jval_get_property(jconfig, "height"); 00208 if (jerry_value_is_number(jheight)) { 00209 jpeg->decode_data.height = iotjs_jval_as_number(jheight); 00210 } else { 00211 jerry_release_value(jheight); 00212 return JS_CREATE_ERROR( 00213 TYPE, "Invalid options.height"); 00214 } 00215 jerry_release_value(jheight); 00216 00217 jerry_value_t jformat = iotjs_jval_get_property(jconfig, "format"); 00218 if (jerry_value_is_number(jformat)) { 00219 jpeg->decode_data.pixel_format = iotjs_jval_as_number(jformat); 00220 } else { 00221 jpeg->decode_data.pixel_format = JPEG_PIXELFORMAT_MAX; 00222 } 00223 jerry_release_value(jformat); 00224 if(jpeg->decode_data.pixel_format >= JPEG_PIXELFORMAT_MAX) { 00225 return JS_CREATE_ERROR(TYPE, "Invalid options.format"); 00226 } 00227 00228 if(jpeg->decode_data.pixel_format == JPEG_PIXELFORMAT_ARGB8888) { 00229 jerry_value_t jalpha = iotjs_jval_get_property(jconfig, "alpha"); 00230 if (jerry_value_is_undefined(jalpha)) { 00231 jpeg->decode_data.alpha = 0xFF; 00232 } else { 00233 if (jerry_value_is_number(jalpha)) { 00234 jpeg->decode_data.alpha = iotjs_jval_as_number(jalpha); 00235 } else { 00236 jerry_release_value(jalpha); 00237 return JS_CREATE_ERROR(TYPE, "Invalid options.alpha"); 00238 } 00239 } 00240 jerry_release_value(jalpha); 00241 } else { 00242 jpeg->decode_data.alpha = 0; 00243 } 00244 00245 return jerry_create_undefined(); 00246 } 00247 00248 JS_FUNCTION(JpegCons) { 00249 DJS_CHECK_THIS(); 00250 00251 // Create Jpeg object 00252 jerry_value_t jjpeg = JS_GET_THIS(); 00253 iotjs_jpeg_t* jpeg = jpeg_create(jjpeg); 00254 00255 jerry_value_t jconfig = JS_GET_ARG(0, object); 00256 00257 // set configuration 00258 jerry_value_t res = iotjs_jpeg_set_platform_config(jpeg, jconfig); 00259 if (jerry_value_is_error(res)) { 00260 return res; 00261 } 00262 00263 res = jpeg_set_configuration(jpeg, jconfig); 00264 if (jerry_value_is_error(res)) { 00265 return res; 00266 } 00267 00268 return jerry_create_undefined(); 00269 } 00270 00271 00272 JS_FUNCTION(Encode) { 00273 JS_DECLARE_THIS_PTR(jpeg, jpeg); 00274 DJS_CHECK_ARGS(1, object); 00275 00276 jerry_value_t jerr = jpeg_get_encode_param(jpeg, jargv, jargc); 00277 if(jerry_value_is_error(jerr)) { 00278 return jerr; 00279 } 00280 iotjs_ext_periph_call_async(jpeg, JS_GET_ARG_IF_EXIST(1, function), kJpegOpEncode, 00281 jpeg_worker); 00282 return jerry_create_undefined(); 00283 } 00284 00285 00286 JS_FUNCTION(EncodeSync) { 00287 JS_DECLARE_THIS_PTR(jpeg, jpeg); 00288 DJS_CHECK_ARGS(1, object); 00289 00290 jerry_value_t jerr = jpeg_get_encode_param(jpeg, jargv, jargc); 00291 if(jerry_value_is_error(jerr)) { 00292 return jerr; 00293 } 00294 00295 if(!iotjs_jpeg_encode(jpeg)) { 00296 return JS_CREATE_ERROR(COMMON, "Encode error, cannot encode Jpeg"); 00297 } 00298 00299 jerry_value_t jbuf = iotjs_aligned_buffer_wrap_create_buffer((size_t)jpeg->encode_data.dst.len, 32); 00300 if (jerry_value_is_error(jbuf)) { 00301 IOTJS_RELEASE(jpeg->encode_data.dst.buf); 00302 return jbuf; 00303 } 00304 00305 iotjs_aligned_buffer_wrap_t* buf_wrap = iotjs_aligned_buffer_wrap_from_jbuffer(jbuf); 00306 iotjs_aligned_buffer_wrap_copy(buf_wrap, jpeg->encode_data.dst.buf, jpeg->encode_data.dst.len); 00307 IOTJS_RELEASE(jpeg->encode_data.dst.buf); 00308 00309 return jbuf; 00310 } 00311 00312 00313 JS_FUNCTION(Decode) { 00314 JS_DECLARE_THIS_PTR(jpeg, jpeg); 00315 DJS_CHECK_ARGS(2, object, object); 00316 00317 jerry_value_t res = jpeg_get_decode_param(jpeg, jargv, jargc); 00318 if (jerry_value_is_error(res)) { 00319 return res; 00320 } 00321 00322 iotjs_ext_periph_call_async(jpeg, JS_GET_ARG_IF_EXIST(2, function), kJpegOpDecode, 00323 jpeg_worker); 00324 return jerry_create_undefined(); 00325 } 00326 00327 00328 JS_FUNCTION(DecodeSync) { 00329 JS_DECLARE_THIS_PTR(jpeg, jpeg); 00330 DJS_CHECK_ARGS(2, object, object); 00331 00332 jerry_value_t res = jpeg_get_decode_param(jpeg, jargv, jargc); 00333 if (jerry_value_is_error(res)) { 00334 return res; 00335 } 00336 00337 if(!iotjs_jpeg_decode(jpeg)) { 00338 return JS_CREATE_ERROR(COMMON, "Decode error, cannot decode Jpeg"); 00339 } 00340 00341 jerry_value_t jbuf = iotjs_aligned_buffer_wrap_create_buffer((size_t)jpeg->decode_data.dst.len, 32); 00342 if (jerry_value_is_error(jbuf)) { 00343 IOTJS_RELEASE(jpeg->decode_data.dst.buf); 00344 return jbuf; 00345 } 00346 00347 iotjs_aligned_buffer_wrap_t* buf_wrap = iotjs_aligned_buffer_wrap_from_jbuffer(jbuf); 00348 iotjs_aligned_buffer_wrap_copy(buf_wrap, jpeg->decode_data.dst.buf, jpeg->decode_data.dst.len); 00349 IOTJS_RELEASE(jpeg->decode_data.dst.buf); 00350 00351 return jbuf; 00352 } 00353 00354 #endif // #if defined(USE_POSIX_BRIDGE) 00355 00356 00357 jerry_value_t InitJpeg() { 00358 00359 #if defined(USE_POSIX_BRIDGE) 00360 jerry_value_t jjpeg_cons = jerry_create_external_function(JpegCons); 00361 00362 jerry_value_t prototype = jerry_create_object(); 00363 iotjs_jval_set_method(prototype, "encode", Encode); 00364 iotjs_jval_set_method(prototype, "encodeSync", EncodeSync); 00365 iotjs_jval_set_method(prototype, "decode", Decode); 00366 iotjs_jval_set_method(prototype, "decodeSync", DecodeSync); 00367 00368 // JPEG Pixel Format 00369 jerry_value_t jformat = jerry_create_object(); 00370 iotjs_jval_set_property_number(jformat, "YCBCR422", JPEG_PIXELFORMAT_YCBCR422); 00371 iotjs_jval_set_property_number(jformat, "ARGB8888", JPEG_PIXELFORMAT_ARGB8888); 00372 iotjs_jval_set_property_number(jformat, "RGB565", JPEG_PIXELFORMAT_RGB565); 00373 iotjs_jval_set_property_number(jformat, "MAX", JPEG_PIXELFORMAT_MAX); 00374 iotjs_jval_set_property_jval(prototype, "PIXELFORMAT", jformat); 00375 jerry_release_value(jformat); 00376 00377 iotjs_jval_set_property_jval(jjpeg_cons, IOTJS_MAGIC_STRING_PROTOTYPE, 00378 prototype); 00379 jerry_release_value(prototype); 00380 00381 #else // #if defined(USE_POSIX_BRIDGE) 00382 jerry_value_t jjpeg_cons = jerry_create_object(); 00383 #endif // #if defined(USE_POSIX_BRIDGE) 00384 00385 return jjpeg_cons; 00386 }
Generated on Wed Jul 13 2022 20:23:11 by 1.7.2