/* * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #include #include "mlib_image.h" #include "mlib_ImageCheck.h" typedef union { double d64; struct { float f0; float f1; } f32s; } d64_2_f32; /***************************************************************/ void mlib_v_ImageChannelExtract_U8_2_1(mlib_u8 *sl, mlib_s32 slb, mlib_u8 *dl, mlib_s32 dlb, mlib_s32 width, mlib_s32 height) { mlib_u8 *sp = sl; mlib_u8 *dp = dl; int i, j; for (j = 0; j < height; j++) { mlib_u8 *dend = dl + width; mlib_u32 *sp2; while (((mlib_addr)sp & 7) > 1) { *dp++ = *sp; sp += 2; if (dp >= dend) break; } if ((mlib_addr)sp & 7) { sp2 = (mlib_u32 *)(sp - 1); #pragma pipeloop(0) for (; dp <= (dend-2); dp += 2) { mlib_u32 s0; s0 = *sp2++; dp[0] = s0 >> 16; dp[1] = s0; } if (dp < dend) { dp[0] = sp2[0] >> 16; } } else { sp2 = (mlib_u32 *)sp; #pragma pipeloop(0) for (; dp <= (dend-2); dp += 2) { mlib_u32 s0; s0 = *sp2++; dp[0] = s0 >> 24; dp[1] = s0 >> 8; } if (dp < dend) { dp[0] = sp2[0] >> 24; } } sp = sl += slb; dp = dl += dlb; } } /***************************************************************/ void mlib_v_ImageChannelExtract_U8_3_2(mlib_u8 *sl, mlib_s32 slb, mlib_u8 *dl, mlib_s32 dlb, mlib_s32 width, mlib_s32 height, mlib_s32 count1) { mlib_u8 *sp = sl; mlib_u8 *dp = dl; mlib_u32 *sp2; mlib_u16 *dp2; mlib_u16 *d2end; mlib_u32 s0, s1, s2, s3; int i, j, off, count_off; for (j = 0; j < height; j++) { mlib_u8 *dend = dl + 2*width; if (count1 == 1) { if (dp < dend) *dp++ = sp[0]; sp += 2; } if ((mlib_addr)dp & 1) { #pragma pipeloop(0) for (; dp <= (dend-2); dp += 2) { dp[0] = sp[0]; dp[1] = sp[1]; sp += 3; } if (dp < dend) { dp[0] = sp[0]; } sp = sl += slb; dp = dl += dlb; continue; } dp2 = (mlib_u16*)dp; d2end = (mlib_u16*)((mlib_addr)dend &~ 1); off = (mlib_addr)sp & 3; sp2 = (mlib_u32 *)(sp - off); switch (off) { case 0: #pragma pipeloop(0) for (; dp2 <= (d2end-4); dp2 += 4) { s0 = sp2[0]; s1 = sp2[1]; s2 = sp2[2]; dp2[0] = s0 >> 16; dp2[1] = (s0 << 8) | (s1 >> 24); dp2[2] = s1; dp2[3] = s2 >> 8; sp2 += 3; } break; case 1: #pragma pipeloop(0) for (; dp2 <= (d2end-4); dp2 += 4) { s0 = sp2[0]; s1 = sp2[1]; s2 = sp2[2]; dp2[0] = s0 >> 8; dp2[1] = s1 >> 16; dp2[2] = (s1 << 8) | (s2 >> 24); dp2[3] = s2; sp2 += 3; } break; case 2: #pragma pipeloop(0) s3 = sp2[0]; for (; dp2 <= (d2end-4); dp2 += 4) { s0 = s3; s1 = sp2[1]; s2 = sp2[2]; s3 = sp2[3]; dp2[0] = s0; dp2[1] = s1 >> 8; dp2[2] = s2 >> 16; dp2[3] = (s2 << 8) | (s3 >> 24); sp2 += 3; } break; case 3: #pragma pipeloop(0) s3 = sp2[0]; for (; dp2 <= (d2end-4); dp2 += 4) { s0 = s3; s1 = sp2[1]; s2 = sp2[2]; s3 = sp2[3]; dp2[0] = (s0 << 8) | (s1 >> 24); dp2[1] = s1; dp2[2] = s2 >> 8; dp2[3] = s3 >> 16; sp2 += 3; } } sp = (mlib_u8 *)sp2 + off; dp = (mlib_u8 *)dp2; while (dp < dend) { *dp++ = sp[0]; if (dp < dend) *dp++ = sp[1]; sp += 3; } sp = sl += slb; dp = dl += dlb; } } /***************************************************************/ void mlib_v_ImageChannelExtract_U8_4_2(mlib_u8 *sl, mlib_s32 slb, mlib_u8 *dl, mlib_s32 dlb, mlib_s32 width, mlib_s32 height, mlib_s32 count1) { mlib_u8 *sp = sl; mlib_u8 *dp = dl; mlib_u32 *sp2; mlib_u16 *dp2; mlib_u16 *d2end; mlib_u32 s0, s1, s2, s3; int i, j, off, count_off; for (j = 0; j < height; j++) { mlib_u8 *dend = dl + 2*width; if (count1 == 1) { if (dp < dend) *dp++ = sp[0]; sp += 3; } off = (mlib_addr)sp & 3; if (((mlib_addr)dp & 1) || (off == 3)) { #pragma pipeloop(0) for (; dp <= (dend-2); dp += 2) { dp[0] = sp[0]; dp[1] = sp[1]; sp += 4; } if (dp < dend) { dp[0] = sp[0]; } sp = sl += slb; dp = dl += dlb; continue; } dp2 = (mlib_u16*)dp; d2end = (mlib_u16*)((mlib_addr)dend &~ 1); sp2 = (mlib_u32 *)(sp - off); switch (off) { case 0: #pragma pipeloop(0) for (; dp2 < d2end; dp2++) { s0 = sp2[0]; dp2[0] = s0 >> 16; sp2++; } break; case 1: #pragma pipeloop(0) for (; dp2 < d2end; dp2++) { s0 = sp2[0]; dp2[0] = s0 >> 8; sp2++; } break; case 2: #pragma pipeloop(0) for (; dp2 < d2end; dp2++) { s0 = sp2[0]; dp2[0] = s0; sp2++; } break; } sp = (mlib_u8 *)sp2 + off; dp = (mlib_u8 *)dp2; if (dp < dend) { *dp++ = sp[0]; } sp = sl += slb; dp = dl += dlb; } } /***************************************************************/ void mlib_v_ImageChannelExtract_32_2_1(mlib_f32 *sp, mlib_s32 slb, mlib_f32 *dp, mlib_s32 dlb, mlib_s32 width, mlib_s32 height) { mlib_d64 *sp2; int i, j, off; for (j = 0; j < height; j++) { if (((mlib_addr)sp & 7) == 0) { sp2 = (mlib_d64 *)sp; #pragma pipeloop(0) for (i = 0; i < width; i++) { d64_2_f32 d; d.d64 = sp2[i]; dp[i] = d.f32s.f0; } } else { sp2 = (mlib_d64 *)(sp - 1); #pragma pipeloop(0) for (i = 0; i < width; i++) { d64_2_f32 d; d.d64 = sp2[i]; dp[i] = d.f32s.f1; } } sp += slb; dp += dlb; } } /***************************************************************/ void mlib_v_ImageChannelExtract_32_3_1(mlib_f32 *sl, mlib_s32 slb, mlib_f32 *dl, mlib_s32 dlb, mlib_s32 width, mlib_s32 height) { mlib_f32 *sp = sl; mlib_f32 *dp = dl; mlib_d64 *sp2; d64_2_f32 d0; int i, j, off; for (j = 0; j < height; j++) { mlib_f32 *dend = dl + width; if ((mlib_addr)sp & 7) { dp[0] = sp[0]; sp += 3; dp ++; } sp2 = (mlib_d64 *)sp; #pragma pipeloop(0) for (; dp <= (dend-2); dp += 2) { d64_2_f32 d0, d1; d0.d64 = sp2[0]; d1.d64 = sp2[1]; dp[0] = d0.f32s.f0; dp[1] = d1.f32s.f1; sp2 += 3; } if (dp < dend) { d0.d64 = sp2[0]; dp[0] = d0.f32s.f0; } sp = sl += slb; dp = dl += dlb; } } /***************************************************************/ void mlib_v_ImageChannelExtract_32_3_2(mlib_f32 *sl, mlib_s32 slb, mlib_f32 *dl, mlib_s32 dlb, mlib_s32 width, mlib_s32 height, mlib_s32 count1) { mlib_f32 *sp = sl; mlib_f32 *dp = dl; mlib_d64 *sp2; d64_2_f32 d0; int i, j, off; for (j = 0; j < height; j++) { mlib_f32 *dend = dl + 2*width; if (count1 == 1) { if (dp < dend) *dp++ = sp[0]; sp += 2; } if ((mlib_addr)sp & 7) { if (dp < dend) *dp++ = sp[0]; if (dp < dend) *dp++ = sp[1]; sp += 3; } sp2 = (mlib_d64 *)sp; #pragma pipeloop(0) for (; dp <= (dend-4); dp += 4) { d64_2_f32 d0, d1, d2; d0.d64 = sp2[0]; d1.d64 = sp2[1]; d2.d64 = sp2[2]; dp[0] = d0.f32s.f0; dp[1] = d0.f32s.f1; dp[2] = d1.f32s.f1; dp[3] = d2.f32s.f0; sp2 += 3; } if (dp < dend) { sp = (mlib_f32 *)sp2; *dp++ = sp[0]; if (dp < dend) *dp++ = sp[1]; if (dp < dend) *dp++ = sp[3]; } sp = sl += slb; dp = dl += dlb; } } /***************************************************************/ void mlib_v_ImageChannelExtract_32_4_1(mlib_f32 *sp, mlib_s32 slb, mlib_f32 *dp, mlib_s32 dlb, mlib_s32 width, mlib_s32 height) { mlib_d64 *sp2; int i, j, off; for (j = 0; j < height; j++) { if (((mlib_addr)sp & 7) == 0) { sp2 = (mlib_d64 *)sp; #pragma pipeloop(0) for (i = 0; i < width; i++) { d64_2_f32 d; d.d64 = sp2[2*i]; dp[i] = d.f32s.f0; } } else { sp2 = (mlib_d64 *)(sp - 1); #pragma pipeloop(0) for (i = 0; i < width; i++) { d64_2_f32 d; d.d64 = sp2[2*i]; dp[i] = d.f32s.f1; } } sp += slb; dp += dlb; } } /***************************************************************/ void mlib_v_ImageChannelExtract_32_4_2(mlib_f32 *sl, mlib_s32 slb, mlib_f32 *dl, mlib_s32 dlb, mlib_s32 width, mlib_s32 height, mlib_s32 count1) { mlib_f32 *sp = sl; mlib_f32 *dp = dl; mlib_d64 *sp2; int i, j, off; d64_2_f32 d0, d1; for (j = 0; j < height; j++) { mlib_f32 *dend = dl + 2*width; if (count1 == 1) { dp[0] = sp[0]; sp += 3; dp ++; } if (((mlib_addr)sp & 7) == 0) { sp2 = (mlib_d64 *)sp; #pragma pipeloop(0) for (; dp <= (dend-2); dp += 2) { d64_2_f32 d; d.d64 = sp2[0]; dp[0] = d.f32s.f0; dp[1] = d.f32s.f1; sp2 += 2; } if (dp < dend) { d0.d64 = sp2[0]; dp[0] = d0.f32s.f0; } } else { sp2 = (mlib_d64 *)(sp - 1); #pragma pipeloop(0) for (; dp <= (dend-2); dp += 2) { d64_2_f32 d0, d1; d0.d64 = sp2[0]; d1.d64 = sp2[1]; dp[0] = d0.f32s.f1; dp[1] = d1.f32s.f0; sp2 += 2; } if (dp < dend) { d0.d64 = sp2[0]; dp[0] = d0.f32s.f1; } } sp = sl += slb; dp = dl += dlb; } } /***************************************************************/ void mlib_v_ImageChannelExtract_32_4_3(mlib_f32 *sl, mlib_s32 slb, mlib_f32 *dl, mlib_s32 dlb, mlib_s32 width, mlib_s32 height, mlib_s32 count1) { mlib_f32 *sp = sl; mlib_f32 *dp = dl; mlib_d64 *sp2; int i, j, k; d64_2_f32 d0, d1; for (j = 0; j < height; j++) { mlib_f32 *dend = dl + 3*width; for (k = 0; k < count1; k++) { if (dp < dend) *dp++ = *sp++; } sp++; if (((mlib_addr)sp & 7) == 0) { sp2 = (mlib_d64 *)sp; #pragma pipeloop(0) for (; dp <= (dend-3); dp += 3) { d64_2_f32 d0, d1; d0.d64 = sp2[0]; d1.d64 = sp2[1]; dp[0] = d0.f32s.f0; dp[1] = d0.f32s.f1; dp[2] = d1.f32s.f0; sp2 += 2; } if (dp < dend) { d0.d64 = sp2[0]; *dp++ = d0.f32s.f0; if (dp < dend) *dp++ = d0.f32s.f1; } } else { sp2 = (mlib_d64 *)(sp - 1); #pragma pipeloop(0) for (; dp <= (dend-3); dp += 3) { d64_2_f32 d0, d1; d0.d64 = sp2[0]; d1.d64 = sp2[1]; dp[0] = d0.f32s.f1; dp[1] = d1.f32s.f0; dp[2] = d1.f32s.f1; sp2 += 2; } if (dp < dend) { d0.d64 = sp2[0]; d1.d64 = sp2[1]; *dp++ = d0.f32s.f1; if (dp < dend) *dp++ = d1.f32s.f0; } } sp = sl += slb; dp = dl += dlb; } } /***************************************************************/ /* general channel extraction: slower due to the inner loop */ void mlib_v_ImageChannelExtract_U8(mlib_u8 *src, mlib_s32 slb, mlib_u8 *dst, mlib_s32 dlb, mlib_s32 channels, mlib_s32 channeld, mlib_s32 width, mlib_s32 height, mlib_s32 cmask) { mlib_u8 *sp; /* pointer for pixel in src */ mlib_u8 *sl; /* pointer for line in src */ mlib_u8 *dp; /* pointer for pixel in dst */ mlib_u8 *dl; /* pointer for line in dst */ int i, j, k; /* indices for x, y, channel */ int deltac[5] = { 0, 1, 1, 1, 1 }; int inc0, inc1, inc2, inc3; mlib_u8 s0, s1, s2, s3; deltac[channeld] = 1; for (i = (channels - 1), k = 0; i >= 0; i--) { if ((cmask & (1 << i)) == 0) deltac[k]++; else k++; } deltac[channeld] = channels; for (i = 1; i < channeld; i++) { deltac[channeld] -= deltac[i]; } sp = sl = src + deltac[0]; dp = dl = dst; /* Only THREE CHANNEL CASE could be executed here!!! */ inc0 = deltac[1]; inc1 = deltac[2] + inc0; inc2 = deltac[3] + inc1; for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { #pragma pipeloop(0) s0 = sp[0]; s1 = sp[inc0]; s2 = sp[inc1]; dp[0] = s0; dp[1] = s1; dp[2] = s2; sp += inc2; dp += 3; } sp = sl += slb; dp = dl += dlb; } } /***************************************************************/ /* general channel extraction: slower due to the inner loop */ void mlib_v_ImageChannelExtract_S16(mlib_u16 *src, mlib_s32 slb, mlib_u16 *dst, mlib_s32 dlb, mlib_s32 channels, mlib_s32 channeld, mlib_s32 width, mlib_s32 height, mlib_s32 cmask) { mlib_u16 *sp; /* pointer for pixel in src */ mlib_u16 *sl; /* pointer for line in src */ mlib_u16 *dp; /* pointer for pixel in dst */ mlib_u16 *dl; /* pointer for line in dst */ int i, j, k; /* indices for x, y, channel */ int deltac[5] = { 0, 1, 1, 1, 1 }; int inc0, inc1, inc2, inc3; mlib_u16 s0, s1, s2, s3; slb >>= 1; dlb >>= 1; deltac[channeld] = 1; for (i = (channels - 1), k = 0; i >= 0; i--) { if ((cmask & (1 << i)) == 0) deltac[k]++; else k++; } deltac[channeld] = channels; for (i = 1; i < channeld; i++) { deltac[channeld] -= deltac[i]; } sp = sl = src + deltac[0]; dp = dl = dst; if (channeld == 2) { inc0 = deltac[1]; inc1 = deltac[2] + inc0; for (j = 0; j < height; j++) { #pragma pipeloop(0) for (i = 0; i < width; i++) { s0 = sp[0]; s1 = sp[inc0]; dp[0] = s0; dp[1] = s1; sp += inc1; dp += 2; } sp = sl = sl + slb; dp = dl = dl + dlb; } } else if (channeld == 3) { inc0 = deltac[1]; inc1 = deltac[2] + inc0; inc2 = deltac[3] + inc1; for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { #pragma pipeloop(0) s0 = sp[0]; s1 = sp[inc0]; s2 = sp[inc1]; dp[0] = s0; dp[1] = s1; dp[2] = s2; sp += inc2; dp += 3; } sp = sl = sl + slb; dp = dl = dl + dlb; } }} /***************************************************************/ /* general channel extraction: slower due to the inner loop */ void mlib_v_ImageChannelExtract_D64(mlib_d64 *src, mlib_s32 slb, mlib_d64 *dst, mlib_s32 dlb, mlib_s32 channels, mlib_s32 channeld, mlib_s32 width, mlib_s32 height, mlib_s32 cmask) { mlib_d64 *sp; /* pointer for pixel in src */ mlib_d64 *sl; /* pointer for line in src */ mlib_d64 *dp; /* pointer for pixel in dst */ mlib_d64 *dl; /* pointer for line in dst */ int i, j, k; /* indices for x, y, channel */ int deltac[5] = { 0, 1, 1, 1, 1 }; int inc0, inc1, inc2, inc3; mlib_d64 s0, s1, s2, s3; deltac[channeld] = 1; for (i = (channels - 1), k = 0; i >= 0; i--) { if ((cmask & (1 << i)) == 0) deltac[k]++; else k++; } deltac[channeld] = channels; for (i = 1; i < channeld; i++) { deltac[channeld] -= deltac[i]; } sp = sl = src + deltac[0]; dp = dl = dst; if (channeld == 1) { for (j = 0; j < height; j++) { #pragma pipeloop(0) for (i = 0; i < width; i++) { s0 = sp[0]; dp[i] = s0; sp += channels; } sp = sl = (mlib_d64 *)((mlib_u8 *)sl + slb); dp = dl = (mlib_d64 *)((mlib_u8 *)dl + dlb); } } else if (channeld == 2) { inc0 = deltac[1]; inc1 = deltac[2] + inc0; for (j = 0; j < height; j++) { #pragma pipeloop(0) for (i = 0; i < width; i++) { s0 = sp[0]; s1 = sp[inc0]; dp[0] = s0; dp[1] = s1; sp += inc1; dp += 2; } sp = sl = (mlib_d64 *)((mlib_u8 *)sl + slb); dp = dl = (mlib_d64 *)((mlib_u8 *)dl + dlb); } } else if (channeld == 3) { inc0 = deltac[1]; inc1 = deltac[2] + inc0; inc2 = deltac[3] + inc1; for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { #pragma pipeloop(0) s0 = sp[0]; s1 = sp[inc0]; s2 = sp[inc1]; dp[0] = s0; dp[1] = s1; dp[2] = s2; sp += inc2; dp += 3; } sp = sl = (mlib_d64 *)((mlib_u8 *)sl + slb); dp = dl = (mlib_d64 *)((mlib_u8 *)dl + dlb); } } }