From 6e53c7a59b4aaddf41116e6eb75ea0ddd39bb3e9 Mon Sep 17 00:00:00 2001 From: Jiyoun Park Date: Fri, 9 Sep 2011 15:44:22 +0900 Subject: [PATCH] [*][evas jpeg loader] Implement rotation decoding for image viewer I add rotation decoding code for image viewer app if app use evas_object_image_load_orientation_set, jpeg loader automatically decode according to rotation Change-Id: Ifb0cbd2ce6f757e2d5ed20746e3d681729023d27 --- src/lib/include/evas_common.h | 2 + src/modules/loaders/jpeg/evas_image_load_jpeg.c | 843 +++++++++++++++++------- 2 files changed, 593 insertions(+), 252 deletions(-) diff --git a/src/lib/include/evas_common.h b/src/lib/include/evas_common.h index c222dd3..1570728 100644 --- a/src/lib/include/evas_common.h +++ b/src/lib/include/evas_common.h @@ -486,6 +486,7 @@ struct _RGBA_Image_Loadopts int scale_down_by; // if > 1 then use this double dpi; // if > 0.0 use this unsigned int w, h; // if > 0 use this + unsigned int degree;//if>0 there is some info related with rotation struct { unsigned int x, y, w, h; } region; @@ -513,6 +514,7 @@ struct _Image_Entry_Flags Eina_Bool pending : 1; #endif Eina_Bool animated : 1; + Eina_Bool rotated : 1; }; struct _Image_Entry_Frame diff --git a/src/modules/loaders/jpeg/evas_image_load_jpeg.c b/src/modules/loaders/jpeg/evas_image_load_jpeg.c index 34840cb..d721cb2 100644 --- a/src/modules/loaders/jpeg/evas_image_load_jpeg.c +++ b/src/modules/loaders/jpeg/evas_image_load_jpeg.c @@ -160,6 +160,116 @@ _evas_jpeg_membuf_src(j_decompress_ptr cinfo, return 0; } +/*! Magic number for EXIF header & App1*/ +static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; +static const unsigned char App1[] = {0xff, 0xe1}; +typedef enum { + EXIF_BYTE_ALIGN_II, + EXIF_BYTE_ALIGN_MM +}ExifByteAlign; + +static int +_get_orientation(const char *path) +{ + if (!path) return 0; + + /* open file and get 22type frome file */ + + FILE *f; + int size; + unsigned char buf[4096]; + unsigned char orientation[2]; + ExifByteAlign byte_align; + int num_directory = 0; + int i, j; + int direction; + + f = fopen (path, "rb"); + if (!f) return 0; + + /* 1. read 22byte */ + size = fread (buf, 1, 22, f); + + if (size < 22) + { + fclose(f); + return 0; + } + + /* 2. check 2,3 bypte with APP1(0xFFE1) */ + if (memcmp(buf + 2, App1, sizeof (App1))) + { + fclose(f); + return 0; + } + + /* 3. check 6~11bype with Exif Header (0x45786966 0000) */ + if (memcmp(buf + 6, ExifHeader, sizeof (ExifHeader))) + { + fclose(f); + return 0; + } + + /* 4. get 12&13 byte get info of "II(0x4949)" or "MM(0x4d4d)" */ + /* 5. get [20]&[21] get directory entry # */ + if (!strncmp(buf + 12, "MM", 2)) + { + byte_align = EXIF_BYTE_ALIGN_MM; + num_directory = ((buf[20] << 8) + buf[21]); + orientation[0] = 0x01; + orientation[1] = 0x12; + } + else if (!strncmp(buf + 12, "II", 2)) + { + byte_align = EXIF_BYTE_ALIGN_II; + num_directory = ((buf[21] << 8) + buf[20]); + orientation[0] = 0x12; + orientation[1] = 0x01; + } + else + { + fclose(f); + return 0; + } + + if (fread(buf, 12, num_directory, f) > 4096) + { + fclose(f); + return 0; + } + /* we get all info from file, close file first */ + fclose(f); + j = 0; + + for (i = 0; i < num_directory; i++ ) + { + if (!strncmp(buf + j, orientation, 2)) + { + /*get orientation tag */ + if (byte_align == EXIF_BYTE_ALIGN_MM) + direction = buf[j + 11]; + else direction = buf[j + 8]; + switch (direction) + { + case 3: + case 4: + return 180; + case 6: + case 7: + return 90; + case 5: + case 8: + return 270; + default: + return 0; + } + } + else + j = j + 12; + } + return 0; +} + static Eina_Bool evas_image_load_file_head_jpeg_internal(Image_Entry *ie, void *map, size_t length, @@ -169,19 +279,24 @@ evas_image_load_file_head_jpeg_internal(Image_Entry *ie, struct jpeg_decompress_struct cinfo; struct _JPEG_error_mgr jerr; + /* for rotation decoding */ + int degree = 0; + Eina_Bool change_wh = EINA_FALSE; + unsigned int load_opts_w, load_opts_h; + cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = _JPEGFatalErrorHandler; jerr.pub.emit_message = _JPEGErrorHandler2; jerr.pub.output_message = _JPEGErrorHandler; if (setjmp(jerr.setjmp_buffer)) { - jpeg_destroy_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); _evas_jpeg_membuf_src_term(&cinfo); - if (cinfo.saw_JFIF_marker) - *error = EVAS_LOAD_ERROR_CORRUPT_FILE; - else - *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; - return EINA_FALSE; + if (cinfo.saw_JFIF_marker) + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + else + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + return EINA_FALSE; } jpeg_create_decompress(&cinfo); @@ -200,7 +315,21 @@ evas_image_load_file_head_jpeg_internal(Image_Entry *ie, cinfo.dither_mode = JDITHER_ORDERED; jpeg_start_decompress(&cinfo); -/* head decoding */ + /* head decoding */ + if (ie->load_opts.orientation) + { + degree = _get_orientation(ie->file); + if (degree != 0) + { + ie->load_opts.degree = degree; + ie->flags.rotated = EINA_TRUE; + + if (degree == 90 || degree == 270) + change_wh = EINA_TRUE; + } + + } + /* head decoding */ w = cinfo.output_width; h = cinfo.output_height; if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) || @@ -208,71 +337,86 @@ evas_image_load_file_head_jpeg_internal(Image_Entry *ie, { jpeg_destroy_decompress(&cinfo); _evas_jpeg_membuf_src_term(&cinfo); - if (IMG_TOO_BIG(w, h)) - *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - else - *error = EVAS_LOAD_ERROR_GENERIC; - return EINA_FALSE; + if (IMG_TOO_BIG(w, h)) + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + else + *error = EVAS_LOAD_ERROR_GENERIC; + return EINA_FALSE; } if (ie->load_opts.scale_down_by > 1) { - w /= ie->load_opts.scale_down_by; - h /= ie->load_opts.scale_down_by; + w /= ie->load_opts.scale_down_by; + h /= ie->load_opts.scale_down_by; } else if (ie->load_opts.dpi > 0.0) { - w = (w * ie->load_opts.dpi) / 90.0; - h = (h * ie->load_opts.dpi) / 90.0; + w = (w * ie->load_opts.dpi) / 90.0; + h = (h * ie->load_opts.dpi) / 90.0; } else if ((ie->load_opts.w > 0) && (ie->load_opts.h > 0)) { - unsigned int w2 = w, h2 = h; - if (ie->load_opts.w > 0) - { - w2 = ie->load_opts.w; - h2 = (ie->load_opts.w * h) / w; - if ((ie->load_opts.h > 0) && (h2 > ie->load_opts.h)) - { - unsigned int w3; - h2 = ie->load_opts.h; - w3 = (ie->load_opts.h * w) / h; - if (w3 > w2) - w2 = w3; - } - } - else if (ie->load_opts.h > 0) - { - h2 = ie->load_opts.h; - w2 = (ie->load_opts.h * w) / h; - } - w = w2; - h = h2; + unsigned int w2 = w, h2 = h; + /* user set load_opts' w,h on the assumption + that image already rotated according to it's orientation info */ + if (change_wh) + { + load_opts_w = ie->load_opts.w; + load_opts_h = ie->load_opts.h; + ie->load_opts.w = load_opts_h; + ie->load_opts.h = load_opts_w; + } + + if (ie->load_opts.w > 0) + { + w2 = ie->load_opts.w; + h2 = (ie->load_opts.w * h) / w; + if ((ie->load_opts.h > 0) && (h2 > ie->load_opts.h)) + { + unsigned int w3; + h2 = ie->load_opts.h; + w3 = (ie->load_opts.h * w) / h; + if (w3 > w2) + w2 = w3; + } + } + else if (ie->load_opts.h > 0) + { + h2 = ie->load_opts.h; + w2 = (ie->load_opts.h * w) / h; + } + w = w2; + h = h2; + if (change_wh) + { + ie->load_opts.w = load_opts_w; + ie->load_opts.h = load_opts_h; + } } if (w < 1) w = 1; if (h < 1) h = 1; if ((w != cinfo.output_width) || (h != cinfo.output_height)) { - scalew = cinfo.output_width / w; - scaleh = cinfo.output_height / h; + scalew = cinfo.output_width / w; + scaleh = cinfo.output_height / h; - ie->scale = scalew; - if (scaleh < scalew) ie->scale = scaleh; + ie->scale = scalew; + if (scaleh < scalew) ie->scale = scaleh; - if (ie->scale > 8) ie->scale = 8; - else if (ie->scale < 1) ie->scale = 1; + if (ie->scale > 8) ie->scale = 8; + else if (ie->scale < 1) ie->scale = 1; - if (ie->scale == 3) ie->scale = 2; - else if (ie->scale == 5) ie->scale = 4; - else if (ie->scale == 6) ie->scale = 4; - else if (ie->scale == 7) ie->scale = 4; + if (ie->scale == 3) ie->scale = 2; + else if (ie->scale == 5) ie->scale = 4; + else if (ie->scale == 6) ie->scale = 4; + else if (ie->scale == 7) ie->scale = 4; } if (ie->scale > 1) { - jpeg_destroy_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); _evas_jpeg_membuf_src_term(&cinfo); - jpeg_create_decompress(&cinfo); + jpeg_create_decompress(&cinfo); if (_evas_jpeg_membuf_src(&cinfo, map, length)) { @@ -282,21 +426,53 @@ evas_image_load_file_head_jpeg_internal(Image_Entry *ie, return EINA_FALSE; } - jpeg_read_header(&cinfo, TRUE); - cinfo.do_fancy_upsampling = FALSE; - cinfo.do_block_smoothing = FALSE; - cinfo.scale_num = 1; - cinfo.scale_denom = ie->scale; - jpeg_calc_output_dimensions(&(cinfo)); - jpeg_start_decompress(&cinfo); + jpeg_read_header(&cinfo, TRUE); + cinfo.do_fancy_upsampling = FALSE; + cinfo.do_block_smoothing = FALSE; + cinfo.scale_num = 1; + cinfo.scale_denom = ie->scale; + jpeg_calc_output_dimensions(&(cinfo)); + jpeg_start_decompress(&cinfo); } ie->w = cinfo.output_width; ie->h = cinfo.output_height; - + // be nice and clip region to image. if its totally outside, fail load if ((ie->load_opts.region.w > 0) && (ie->load_opts.region.h > 0)) { + unsigned int load_region_x, load_region_y,load_region_w,load_region_h; + if (ie->flags.rotated) + { + load_region_x = ie->load_opts.region.x; + load_region_y = ie->load_opts.region.y; + load_region_w = ie->load_opts.region.w; + load_region_h = ie->load_opts.region.h; + + switch (degree) + { + case 90: + ie->load_opts.region.x = load_region_y; + ie->load_opts.region.y = h - (load_region_x + load_region_w); + ie->load_opts.region.w = load_region_h; + ie->load_opts.region.h = load_region_w; + break; + case 180: //done + ie->load_opts.region.x = w - (load_region_x+ load_region_w); + ie->load_opts.region.y = h - (load_region_y + load_region_h); + + break; + case 270: //done + ie->load_opts.region.x = w - (load_region_y + load_region_h); + ie->load_opts.region.y = load_region_x; + ie->load_opts.region.w = load_region_h; + ie->load_opts.region.h = load_region_w; + break; + default: + break; + } + + } RECTS_CLIP_TO_RECT(ie->load_opts.region.x, ie->load_opts.region.y, ie->load_opts.region.w, ie->load_opts.region.h, 0, 0, ie->w, ie->h); @@ -304,14 +480,27 @@ evas_image_load_file_head_jpeg_internal(Image_Entry *ie, { jpeg_destroy_decompress(&cinfo); _evas_jpeg_membuf_src_term(&cinfo); - *error = EVAS_LOAD_ERROR_GENERIC; - return EINA_FALSE; + *error = EVAS_LOAD_ERROR_GENERIC; + return EINA_FALSE; } ie->w = ie->load_opts.region.w; ie->h = ie->load_opts.region.h; + if (ie->flags.rotated) + { + ie->load_opts.region.x = load_region_x; + ie->load_opts.region.y = load_region_y; + ie->load_opts.region.w = load_region_w; + ie->load_opts.region.h = load_region_h; + } + } + /* end head decoding */ + if (change_wh) + { + unsigned int tmp; + tmp = ie->w; + ie->w = ie->h; + ie->h = tmp; } -/* end head decoding */ - jpeg_destroy_decompress(&cinfo); _evas_jpeg_membuf_src_term(&cinfo); *error = EVAS_LOAD_ERROR_NONE; @@ -319,15 +508,15 @@ evas_image_load_file_head_jpeg_internal(Image_Entry *ie, } /* -static double -get_time(void) -{ + static double + get_time(void) + { struct timeval timev; - + gettimeofday(&timev, NULL); return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000); -} -*/ + } + */ static Eina_Bool evas_image_load_file_data_jpeg_internal(Image_Entry *ie, @@ -338,20 +527,31 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, struct jpeg_decompress_struct cinfo; struct _JPEG_error_mgr jerr; DATA8 *ptr, *line[16], *data; - DATA32 *ptr2; + DATA32 *ptr2,*ptr_rotate; unsigned int x, y, l, i, scans; int region = 0; + unsigned int tmp, load_region_x, load_region_y, load_region_w, load_region_h;/* for rotation decoding */ + /* rotation setting */ + int degree = 0; + Eina_Bool change_wh = EINA_FALSE; + Eina_Bool line_done = EINA_FALSE; + if (ie->flags.rotated) + { + degree = ie->load_opts.degree; + if (degree == 90 || degree == 270) + change_wh = EINA_TRUE; + } cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = _JPEGFatalErrorHandler; jerr.pub.emit_message = _JPEGErrorHandler2; jerr.pub.output_message = _JPEGErrorHandler; if (setjmp(jerr.setjmp_buffer)) { - jpeg_destroy_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); _evas_jpeg_membuf_src_term(&cinfo); - *error = EVAS_LOAD_ERROR_CORRUPT_FILE; - return EINA_FALSE; + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + return EINA_FALSE; } jpeg_create_decompress(&cinfo); @@ -371,8 +571,8 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, if (ie->scale > 1) { - cinfo.scale_num = 1; - cinfo.scale_denom = ie->scale; + cinfo.scale_num = 1; + cinfo.scale_denom = ie->scale; } /* Colorspace conversion options */ @@ -380,30 +580,69 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, /* GRAYSCLAE => RGB YCbCr => RGB and YCCK => CMYK */ switch (cinfo.jpeg_color_space) { - case JCS_UNKNOWN: - break; - case JCS_GRAYSCALE: - case JCS_RGB: - case JCS_YCbCr: - cinfo.out_color_space = JCS_RGB; - break; - case JCS_CMYK: - case JCS_YCCK: - cinfo.out_color_space = JCS_CMYK; - break; + case JCS_UNKNOWN: + break; + case JCS_GRAYSCALE: + case JCS_RGB: + case JCS_YCbCr: + cinfo.out_color_space = JCS_RGB; + break; + case JCS_CMYK: + case JCS_YCCK: + cinfo.out_color_space = JCS_CMYK; + break; } -/* head decoding */ + /* head decoding */ jpeg_calc_output_dimensions(&(cinfo)); jpeg_start_decompress(&cinfo); w = cinfo.output_width; h = cinfo.output_height; + if (change_wh) + { + tmp = ie->w; + ie->w = ie->h; + ie->h = tmp; + } + if ((ie->load_opts.region.w > 0) && (ie->load_opts.region.h > 0)) { region = 1; #ifdef BUILD_LOADER_JPEG_REGION + + if (ie->flags.rotated) + { + load_region_x = ie->load_opts.region.x; + load_region_y = ie->load_opts.region.y; + load_region_w = ie->load_opts.region.w; + load_region_h = ie->load_opts.region.h; + + switch (degree) + { + case 90: + ie->load_opts.region.x = load_region_y; + ie->load_opts.region.y = h - (load_region_x + load_region_w); + ie->load_opts.region.w = load_region_h; + ie->load_opts.region.h = load_region_w; + break; + case 180: //done + ie->load_opts.region.x = w - (load_region_x+ load_region_w); + ie->load_opts.region.y = h - (load_region_y + load_region_h); + + break; + case 270: //done + ie->load_opts.region.x = w - (load_region_y + load_region_h); + ie->load_opts.region.y = load_region_x; + ie->load_opts.region.w = load_region_h; + ie->load_opts.region.h = load_region_w; + break; + default: + break; + } + + } cinfo.region_x = ie->load_opts.region.x; cinfo.region_y = ie->load_opts.region.y; cinfo.region_w = ie->load_opts.region.w; @@ -412,12 +651,12 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, } if ((!region) && ((w != ie->w) || (h != ie->h))) { - // race condition, the file could have change from when we call header - // this test will not solve the problem with region code. - jpeg_destroy_decompress(&cinfo); + // race condition, the file could have change from when we call header + // this test will not solve the problem with region code. + jpeg_destroy_decompress(&cinfo); _evas_jpeg_membuf_src_term(&cinfo); - *error = EVAS_LOAD_ERROR_GENERIC; - return EINA_FALSE; + *error = EVAS_LOAD_ERROR_GENERIC; + return EINA_FALSE; } if ((region) && ((ie->w != ie->load_opts.region.w) || (ie->h != ie->load_opts.region.h))) @@ -430,31 +669,44 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, ((cinfo.output_components == 3) || (cinfo.output_components == 1))) || ((cinfo.out_color_space == JCS_CMYK) && (cinfo.output_components == 4)))) { - jpeg_destroy_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); _evas_jpeg_membuf_src_term(&cinfo); - *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; - return EINA_FALSE; + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + return EINA_FALSE; } -/* end head decoding */ -/* data decoding */ + /* end head decoding */ + /* data decoding */ if (cinfo.rec_outbuf_height > 16) { - jpeg_destroy_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); _evas_jpeg_membuf_src_term(&cinfo); - *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; - return EINA_FALSE; + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + return EINA_FALSE; } data = alloca(w * 16 * cinfo.output_components); evas_cache_image_surface_alloc(ie, ie->w, ie->h); if (ie->flags.loaded) { - jpeg_destroy_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); _evas_jpeg_membuf_src_term(&cinfo); - *error = EVAS_LOAD_ERROR_NONE; - return EINA_TRUE; + *error = EVAS_LOAD_ERROR_NONE; + if (region && ie->flags.rotated) + { + ie->load_opts.region.x = load_region_x; + ie->load_opts.region.y = load_region_x; + ie->load_opts.region.w = load_region_x; + ie->load_opts.region.h = load_region_x; + } + return EINA_TRUE; } - ptr2 = evas_cache_image_pixels(ie); + if ((ie->flags.rotated) && change_wh) + { + ptr2 = malloc(ie->w * ie->h * sizeof(DATA32)); + ptr_rotate = ptr2; + } + else + ptr2 = evas_cache_image_pixels(ie); if (!ptr2) { *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; @@ -465,14 +717,14 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, if (cinfo.output_components == 4) { // FIXME: handle region - for (i = 0; (int)i < cinfo.rec_outbuf_height; i++) - line[i] = data + (i * w * 4); - for (l = 0; l < h; l += cinfo.rec_outbuf_height) - { - jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); - scans = cinfo.rec_outbuf_height; - if ((h - l) < scans) scans = h - l; - ptr = data; + for (i = 0; (int)i < cinfo.rec_outbuf_height; i++) + line[i] = data + (i * w * 4); + for (l = 0; l < h; l += cinfo.rec_outbuf_height) + { + jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); + scans = cinfo.rec_outbuf_height; + if ((h - l) < scans) scans = h - l; + ptr = data; if (!region) { for (y = 0; y < scans; y++) @@ -485,10 +737,10 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, /* that is C is replaces by 255 - C, etc...*/ /* See the comment below for the computation of RGB values from CMYK ones. */ *ptr2 = - (0xff000000) | - ((ptr[0] * ptr[3] / 255) << 16) | - ((ptr[1] * ptr[3] / 255) << 8) | - ((ptr[2] * ptr[3] / 255)); + (0xff000000) | + ((ptr[0] * ptr[3] / 255) << 16) | + ((ptr[1] * ptr[3] / 255) << 8) | + ((ptr[2] * ptr[3] / 255)); ptr += 4; ptr2++; } @@ -510,28 +762,31 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, /* B = (255 - Y) * (255 - K) / 255 */ /* with C, M, Y and K between 0 and 255. */ *ptr2 = - (0xff000000) | - (((255 - ptr[0]) * (255 - ptr[3]) / 255) << 16) | - (((255 - ptr[1]) * (255 - ptr[3]) / 255) << 8) | - (((255 - ptr[2]) * (255 - ptr[3]) / 255)); + (0xff000000) | + (((255 - ptr[0]) * (255 - ptr[3]) / 255) << 16) | + (((255 - ptr[1]) * (255 - ptr[3]) / 255) << 8) | + (((255 - ptr[2]) * (255 - ptr[3]) / 255)); ptr += 4; ptr2++; } } - } - } + } + } else { // if line # > region last line, break if (l >= (ie->load_opts.region.y + ie->load_opts.region.h)) { - jpeg_destroy_decompress(&cinfo); - _evas_jpeg_membuf_src_term(&cinfo); - *error = EVAS_LOAD_ERROR_NONE; - return EINA_FALSE; + line_done = EINA_TRUE; + /* if rotation flag is set , we have to rotate image */ + goto done; + /*jpeg_destroy_decompress(&cinfo); + _evas_jpeg_membuf_src_term(&cinfo); + *error = EVAS_LOAD_ERROR_NONE; + return EINA_FALSE;*/ } // els if scan block intersects region start or later - else if ((l + scans) > + else if ((l + scans) > (ie->load_opts.region.y)) { for (y = 0; y < scans; y++) @@ -548,10 +803,10 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, /* that is C is replaces by 255 - C, etc...*/ /* See the comment below for the computation of RGB values from CMYK ones. */ *ptr2 = - (0xff000000) | - ((ptr[0] * ptr[3] / 255) << 16) | - ((ptr[1] * ptr[3] / 255) << 8) | - ((ptr[2] * ptr[3] / 255)); + (0xff000000) | + ((ptr[0] * ptr[3] / 255) << 16) | + ((ptr[1] * ptr[3] / 255) << 8) | + ((ptr[2] * ptr[3] / 255)); ptr += 4; ptr2++; } @@ -573,10 +828,10 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, /* B = (255 - Y) * (255 - K) / 255 */ /* with C, M, Y and K between 0 and 255. */ *ptr2 = - (0xff000000) | - (((255 - ptr[0]) * (255 - ptr[3]) / 255) << 16) | - (((255 - ptr[1]) * (255 - ptr[3]) / 255) << 8) | - (((255 - ptr[2]) * (255 - ptr[3]) / 255)); + (0xff000000) | + (((255 - ptr[0]) * (255 - ptr[3]) / 255) << 16) | + (((255 - ptr[1]) * (255 - ptr[3]) / 255) << 8) | + (((255 - ptr[2]) * (255 - ptr[3]) / 255)); ptr += 4; ptr2++; } @@ -588,35 +843,35 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, } } } - } + } } /* We handle then RGB with 3 components */ else if (cinfo.output_components == 3) { -/* - double t; - if (region) - { - // debug for now - printf("R| %p %5ix%5i %s: %5i %5i %5ix%5i - ", - ie, - ie->w, ie->h, - ie->file, - ie->load_opts.region.x, - ie->load_opts.region.y, - ie->load_opts.region.w, - ie->load_opts.region.h); - } + /* + double t; + if (region) + { + // debug for now + printf("R| %p %5ix%5i %s: %5i %5i %5ix%5i - ", + ie, + ie->w, ie->h, + ie->file, + ie->load_opts.region.x, + ie->load_opts.region.y, + ie->load_opts.region.w, + ie->load_opts.region.h); + } t = get_time(); - */ + */ for (i = 0; (int)i < cinfo.rec_outbuf_height; i++) - line[i] = data + (i * w * 3); - for (l = 0; l < h; l += cinfo.rec_outbuf_height) - { - jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); - scans = cinfo.rec_outbuf_height; - if ((h - l) < scans) scans = h - l; - ptr = data; + line[i] = data + (i * w * 3); + for (l = 0; l < h; l += cinfo.rec_outbuf_height) + { + jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); + scans = cinfo.rec_outbuf_height; + if ((h - l) < scans) scans = h - l; + ptr = data; if (!region) { for (y = 0; y < scans; y++) @@ -628,23 +883,19 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, ptr2++; } } - } + } else { // if line # > region last line, break + // but not return immediately for rotation job if (l >= (ie->load_opts.region.y + ie->load_opts.region.h)) { - jpeg_destroy_decompress(&cinfo); - _evas_jpeg_membuf_src_term(&cinfo); -/* - t = get_time() - t; - printf("%3.3f\n", t); - */ - *error = EVAS_LOAD_ERROR_NONE; - return EINA_TRUE; + line_done = EINA_TRUE; + /* if rotation flag is set , we have to rotate image */ + goto done; } // else if scan block intersects region start or later - else if ((l + scans) > + else if ((l + scans) > (ie->load_opts.region.y)) { for (y = 0; y < scans; y++) @@ -666,23 +917,23 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, } } } - } -/* - t = get_time() - t; - printf("%3.3f\n", t); - */ + } + /* + t = get_time() - t; + printf("%3.3f\n", t); + */ } /* We finally handle RGB with 1 component */ else if (cinfo.output_components == 1) { - for (i = 0; (int)i < cinfo.rec_outbuf_height; i++) - line[i] = data + (i * w); - for (l = 0; l < h; l += cinfo.rec_outbuf_height) - { - jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); - scans = cinfo.rec_outbuf_height; - if ((h - l) < scans) scans = h - l; - ptr = data; + for (i = 0; (int)i < cinfo.rec_outbuf_height; i++) + line[i] = data + (i * w); + for (l = 0; l < h; l += cinfo.rec_outbuf_height) + { + jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); + scans = cinfo.rec_outbuf_height; + if ((h - l) < scans) scans = h - l; + ptr = data; if (!region) { for (y = 0; y < scans; y++) @@ -694,19 +945,22 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, ptr2++; } } - } + } else { // if line # > region last line, break if (l >= (ie->load_opts.region.y + ie->load_opts.region.h)) { - jpeg_destroy_decompress(&cinfo); - _evas_jpeg_membuf_src_term(&cinfo); - *error = EVAS_LOAD_ERROR_NONE; - return EINA_TRUE; + line_done = EINA_TRUE; + /* if rotation flag is set , we have to rotate image */ + goto done; + /*jpeg_destroy_decompress(&cinfo); + _evas_jpeg_membuf_src_term(&cinfo); + *error = EVAS_LOAD_ERROR_NONE; + return EINA_TRUE;*/ } // els if scan block intersects region start or later - else if ((l + scans) > + else if ((l + scans) > (ie->load_opts.region.y)) { for (y = 0; y < scans; y++) @@ -728,9 +982,94 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, } } } - } + } } -/* end data decoding */ + /* if rotation operation need, rotate it */ +done: + if (ie->flags.rotated) + { + DATA32 *data1, *data2, *to, *from; + int x, y, w, h, hw; + + if (change_wh) + { + tmp = ie->w; + ie->w = ie->h; + ie->h = tmp; + } + + w = ie->w; + h = ie->h; + hw =w * h; + + data1 = evas_cache_image_pixels(ie); + + if (degree == 180) + { + DATA32 tmp; + + data2 = data1 + (h * w) -1; + for (x = (w * h) / 2; --x >= 0;) + { + tmp = *data1; + *data1 = *data2; + *data2 = tmp; + data1++; + data2--; + } + } + else + { + data2 = ptr_rotate; + + if (degree == 90) + { + to = data1 + w - 1; + hw = -hw - 1; + } + + else if (degree == 270) + { + to = data1 + hw - w; + w = -w; + hw = hw + 1; + } + + from = data2; + for (x = ie->w; --x >= 0;) + { + for (y =ie->h; --y >= 0;) + { + *to = *from; + from++; + to += w; + } + to += hw; + } + if (ptr_rotate) + { + free(ptr_rotate); + ptr_rotate = NULL; + } + + } + if (region ) + { + ie->load_opts.region.x = load_region_x; + ie->load_opts.region.y = load_region_x; + ie->load_opts.region.w = load_region_x; + ie->load_opts.region.h = load_region_x; + } + } + + if (line_done) + { + jpeg_destroy_decompress(&cinfo); + _evas_jpeg_membuf_src_term(&cinfo); + *error = EVAS_LOAD_ERROR_NONE; + return EINA_FALSE; + } + /* end data decoding */ jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); _evas_jpeg_membuf_src_term(&cinfo); @@ -751,8 +1090,8 @@ evas_image_load_file_data_jpeg_alpha_internal(Image_Entry *ie, FILE *f, int *err if (!f) { - *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; - return EINA_FALSE; + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; } cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = _JPEGFatalErrorHandler; @@ -760,9 +1099,9 @@ evas_image_load_file_data_jpeg_alpha_internal(Image_Entry *ie, FILE *f, int *err jerr.pub.output_message = _JPEGErrorHandler; if (setjmp(jerr.setjmp_buffer)) { - jpeg_destroy_decompress(&cinfo); - *error = EVAS_LOAD_ERROR_CORRUPT_FILE; - return EINA_FALSE; + jpeg_destroy_decompress(&cinfo); + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + return EINA_FALSE; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, f); @@ -771,73 +1110,73 @@ evas_image_load_file_data_jpeg_alpha_internal(Image_Entry *ie, FILE *f, int *err cinfo.do_block_smoothing = FALSE; jpeg_start_decompress(&cinfo); -/* head decoding */ + /* head decoding */ ie->w = w = cinfo.output_width; ie->h = h = cinfo.output_height; -/* end head decoding */ -/* data decoding */ + /* end head decoding */ + /* data decoding */ if (cinfo.rec_outbuf_height > 16) { - jpeg_destroy_decompress(&cinfo); - *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; - return EINA_FALSE;; + jpeg_destroy_decompress(&cinfo); + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + return EINA_FALSE;; } data = alloca(w * 16 * 3); if (!ie->flags.loaded) { - jpeg_destroy_decompress(&cinfo); - *error = EVAS_LOAD_ERROR_NONE; - return EINA_TRUE; + jpeg_destroy_decompress(&cinfo); + *error = EVAS_LOAD_ERROR_NONE; + return EINA_TRUE; } ptr2 = evas_cache_image_pixels(ie); prevy = 0; if (cinfo.output_components == 3) { - for (i = 0; i < cinfo.rec_outbuf_height; i++) - line[i] = data + (i * w * 3); - for (l = 0; l < h; l += cinfo.rec_outbuf_height) - { - jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); - scans = cinfo.rec_outbuf_height; - if ((h - l) < scans) scans = h - l; - ptr = data; - for (y = 0; y < scans; y++) - { - for (x = 0; x < w; x++) - { - *ptr2 = - ((*ptr2) & 0x00ffffff) | - (((ptr[0] + ptr[1] + ptr[2]) / 3) << 24); - ptr += 3; - ptr2++; - } - } - } + for (i = 0; i < cinfo.rec_outbuf_height; i++) + line[i] = data + (i * w * 3); + for (l = 0; l < h; l += cinfo.rec_outbuf_height) + { + jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); + scans = cinfo.rec_outbuf_height; + if ((h - l) < scans) scans = h - l; + ptr = data; + for (y = 0; y < scans; y++) + { + for (x = 0; x < w; x++) + { + *ptr2 = + ((*ptr2) & 0x00ffffff) | + (((ptr[0] + ptr[1] + ptr[2]) / 3) << 24); + ptr += 3; + ptr2++; + } + } + } } else if (cinfo.output_components == 1) { - for (i = 0; i < cinfo.rec_outbuf_height; i++) - line[i] = data + (i * w); - for (l = 0; l < h; l += cinfo.rec_outbuf_height) - { - jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); - scans = cinfo.rec_outbuf_height; - if ((h - l) < scans) scans = h - l; - ptr = data; - for (y = 0; y < scans; y++) - { - for (x = 0; x < w; x++) - { - *ptr2 = - ((*ptr2) & 0x00ffffff) | - ((ptr[0]) << 24); - ptr++; - ptr2++; - } - } - } - } -/* end data decoding */ + for (i = 0; i < cinfo.rec_outbuf_height; i++) + line[i] = data + (i * w); + for (l = 0; l < h; l += cinfo.rec_outbuf_height) + { + jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); + scans = cinfo.rec_outbuf_height; + if ((h - l) < scans) scans = h - l; + ptr = data; + for (y = 0; y < scans; y++) + { + for (x = 0; x < w; x++) + { + *ptr2 = + ((*ptr2) & 0x00ffffff) | + ((ptr[0]) << 24); + ptr++; + ptr2++; + } + } + } + } + /* end data decoding */ jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); *error = EVAS_LOAD_ERROR_NONE; @@ -857,13 +1196,13 @@ evas_image_load_file_head_jpeg(Image_Entry *ie, f = eina_file_open(file, EINA_FALSE); if (!f) { - *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; - return EINA_FALSE; + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; } map = eina_file_map_all(f, EINA_FILE_WILLNEED); if (!map) { - *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; goto on_error; } @@ -873,7 +1212,7 @@ evas_image_load_file_head_jpeg(Image_Entry *ie, eina_file_map_free(f, map); - on_error: +on_error: eina_file_close(f); return val; } @@ -890,8 +1229,8 @@ evas_image_load_file_data_jpeg(Image_Entry *ie, f = eina_file_open(file, EINA_FALSE); if (!f) { - *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; - return EINA_FALSE; + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; } map = eina_file_map_all(f, EINA_FILE_WILLNEED); if (!map) @@ -906,7 +1245,7 @@ evas_image_load_file_data_jpeg(Image_Entry *ie, eina_file_map_free(f, map); - on_error: +on_error: eina_file_close(f); return val; } @@ -930,8 +1269,8 @@ static Evas_Module_Api evas_modapi = "jpeg", "none", { - module_open, - module_close + module_open, + module_close } }; -- 2.7.4