diff --git a/src/modules/evas/savers/tgv/evas_image_save_tgv.c b/src/modules/evas/savers/tgv/evas_image_save_tgv.c index 5ccbed4022..c344df0e7a 100644 --- a/src/modules/evas/savers/tgv/evas_image_save_tgv.c +++ b/src/modules/evas/savers/tgv/evas_image_save_tgv.c @@ -28,6 +28,7 @@ evas_image_save_file_tgv(RGBA_Image *im, unsigned int x, y; unsigned int compress_length; unsigned int block_count; + unsigned int real_x, real_y; if (!im || !im->image.data || !file) return 0; @@ -86,63 +87,104 @@ evas_image_save_file_tgv(RGBA_Image *im, } // Write block - for (y = 0; y < im->cache_entry.h; y += block) - for (x = 0; x < im->cache_entry.w; x += block) - { - unsigned int i, j; - int wlen; - char *offset = buffer; + for (y = 0; y < im->cache_entry.h + 2; y += block) + { + real_y = y > 0 ? y - 1 : 0; - for (i = 0; i < block; i += 4) - for (j = 0; j < block; j += 4) - { - unsigned char todo[64] = { 0 }; - int k, kmax, lmax; + for (x = 0; x < im->cache_entry.w + 2; x += block) + { + unsigned int i, j; + unsigned char duplicate_w[2], duplicate_h[2]; + int wlen; + char *offset = buffer; - kmax = y + i + 4 < im->cache_entry.h ? - 4 : im->cache_entry.h - y - i - 1; - lmax = x + j + 4 < im->cache_entry.w ? - 4 : im->cache_entry.w - x - j - 1; + real_x = x > 0 ? x - 1 : 0; - if (lmax > 0) - { - for (k = 0; k < kmax; k++) - memcpy(&todo[k * 16], - &data[(y + i + k) * im->cache_entry.w + x + j], - 4 * lmax); - } + for (i = 0; i < block; i += 4) + { + unsigned char block_h; + int kmax; - rg_etc1_pack_block(offset, (unsigned int*) todo, ¶m); - offset += 8; - } + duplicate_h[0] = !!((real_y + i) == 0); + duplicate_h[1] = !!((real_y + i + (4 - duplicate_h[0])) >= im->cache_entry.h); + block_h = 4 - duplicate_h[0] - duplicate_h[1]; - if (compress) - { - wlen = LZ4_compress(buffer, comp, block_count * 8); - } - else - { - comp = buffer; - wlen = block_count * 8; - } + kmax = real_y + i + block_h < im->cache_entry.h ? + block_h : im->cache_entry.h - real_y - i - 1; - if (wlen > 0) - { - unsigned int blen = wlen; + for (j = 0; j < block; j += 4) + { + unsigned char todo[64] = { 0 }; + unsigned char block_w; + int block_length; + int k, lmax; - while (blen) - { - unsigned char plen; + duplicate_w[0] = !!((real_x + j) == 0); + duplicate_w[1] = !!(((real_x + j + (4 - duplicate_w[0]))) >= im->cache_entry.w); + block_w = 4 - duplicate_w[0] - duplicate_w[1]; - plen = blen & 0x7F; - blen = blen >> 7; + lmax = real_x + j + block_w < im->cache_entry.w ? + block_w : im->cache_entry.w - real_x - j - 1; + block_length = real_x + j + 4 < im->cache_entry.w ? + 4 : im->cache_entry.w - real_x - j - 1; - if (blen) plen = 0x80 | plen; - fwrite(&plen, 1, 1, f); - } - fwrite(comp, wlen, 1, f); - } - } + if (lmax > 0) + { + for (k = duplicate_h[0]; k < kmax; k++) + memcpy(&todo[k * 16 + duplicate_w[0] * 4], + &data[(real_y + i + k) * im->cache_entry.w + real_x + j], + 4 * lmax); + } + + if (duplicate_h[0] && block_length > 0) // Duplicate first line + memcpy(&todo[0], &data[(real_y + i) * im->cache_entry.w + real_x + j], block_length); + if (duplicate_h[1] && block_length > 0 && kmax > 0) // Duplicate last line + memcpy(&todo[kmax * 16], &data[(real_y + i + kmax) * im->cache_entry.w + real_x + j], block_length); + if (duplicate_w[0]) // Duplicate first row + { + for (k = 0; k < kmax; k++) + memcpy(&todo[k * 16], &data[(real_y + i + k) * im->cache_entry.w + real_x + j], 4); // Copy a pixel at a time + } + if (duplicate_w[1] && lmax >= 0) // Duplicate last row + { + for (k = 0; k < kmax; k++) + memcpy(&todo[k * 16 + (duplicate_w[0] + lmax) * 4], + &data[(real_y + i + k) * im->cache_entry.w + real_x + j + lmax], 4); // Copy a pixel at a time + } + + rg_etc1_pack_block(offset, (unsigned int*) todo, ¶m); + offset += 8; + } + } + + if (compress) + { + wlen = LZ4_compress(buffer, comp, block_count * 8); + } + else + { + comp = buffer; + wlen = block_count * 8; + } + + if (wlen > 0) + { + unsigned int blen = wlen; + + while (blen) + { + unsigned char plen; + + plen = blen & 0x7F; + blen = blen >> 7; + + if (blen) plen = 0x80 | plen; + fwrite(&plen, 1, 1, f); + } + fwrite(comp, wlen, 1, f); + } + } + } fclose(f); return 1;