2012-02-27 24 views
10

Tôi đã viết một thuật toán để chuyển đổi hình ảnh RGB thành YUV420. Tôi dành một thời gian dài cố gắng để làm cho nó nhanh hơn nhưng tôi đã không tìm thấy bất kỳ cách nào khác để tăng hiệu quả của nó, vì vậy bây giờ tôi quay sang bạn để bạn có thể cho tôi biết nếu điều này là tốt như tôi nhận được, hoặc nếu có hiệu quả hơn cách để làm điều đó (các thuật toán là trong C++ nhưng C và lắp ráp cũng được lựa chọn)rgb to yuv420 thuật toán hiệu quả

namespace { 
// lookup tables 
int lookup_m_94[] = { 
     0, -94, -188, -282, -376, -470, -564, -658, 
    -752, -846, -940, -1034, -1128, -1222, -1316, -1410, 
    -1504, -1598, -1692, -1786, -1880, -1974, -2068, -2162, 
    -2256, -2350, -2444, -2538, -2632, -2726, -2820, -2914, 
    -3008, -3102, -3196, -3290, -3384, -3478, -3572, -3666, 
    -3760, -3854, -3948, -4042, -4136, -4230, -4324, -4418, 
    -4512, -4606, -4700, -4794, -4888, -4982, -5076, -5170, 
    -5264, -5358, -5452, -5546, -5640, -5734, -5828, -5922, 
    -6016, -6110, -6204, -6298, -6392, -6486, -6580, -6674, 
    -6768, -6862, -6956, -7050, -7144, -7238, -7332, -7426, 
    -7520, -7614, -7708, -7802, -7896, -7990, -8084, -8178, 
    -8272, -8366, -8460, -8554, -8648, -8742, -8836, -8930, 
    -9024, -9118, -9212, -9306, -9400, -9494, -9588, -9682, 
    -9776, -9870, -9964, -10058, -10152, -10246, -10340, -10434, 
    -10528, -10622, -10716, -10810, -10904, -10998, -11092, -11186, 
    -11280, -11374, -11468, -11562, -11656, -11750, -11844, -11938, 
    -12032, -12126, -12220, -12314, -12408, -12502, -12596, -12690, 
    -12784, -12878, -12972, -13066, -13160, -13254, -13348, -13442, 
    -13536, -13630, -13724, -13818, -13912, -14006, -14100, -14194, 
    -14288, -14382, -14476, -14570, -14664, -14758, -14852, -14946, 
    -15040, -15134, -15228, -15322, -15416, -15510, -15604, -15698, 
    -15792, -15886, -15980, -16074, -16168, -16262, -16356, -16450, 
    -16544, -16638, -16732, -16826, -16920, -17014, -17108, -17202, 
    -17296, -17390, -17484, -17578, -17672, -17766, -17860, -17954, 
    -18048, -18142, -18236, -18330, -18424, -18518, -18612, -18706, 
    -18800, -18894, -18988, -19082, -19176, -19270, -19364, -19458, 
    -19552, -19646, -19740, -19834, -19928, -20022, -20116, -20210, 
    -20304, -20398, -20492, -20586, -20680, -20774, -20868, -20962, 
    -21056, -21150, -21244, -21338, -21432, -21526, -21620, -21714, 
    -21808, -21902, -21996, -22090, -22184, -22278, -22372, -22466, 
    -22560, -22654, -22748, -22842, -22936, -23030, -23124, -23218, 
    -23312, -23406, -23500, -23594, -23688, -23782, -23876, -23970 
}; 

int lookup_m_74[] = { 
     0, -74, -148, -222, -296, -370, -444, -518, 
    -592, -666, -740, -814, -888, -962, -1036, -1110, 
    -1184, -1258, -1332, -1406, -1480, -1554, -1628, -1702, 
    -1776, -1850, -1924, -1998, -2072, -2146, -2220, -2294, 
    -2368, -2442, -2516, -2590, -2664, -2738, -2812, -2886, 
    -2960, -3034, -3108, -3182, -3256, -3330, -3404, -3478, 
    -3552, -3626, -3700, -3774, -3848, -3922, -3996, -4070, 
    -4144, -4218, -4292, -4366, -4440, -4514, -4588, -4662, 
    -4736, -4810, -4884, -4958, -5032, -5106, -5180, -5254, 
    -5328, -5402, -5476, -5550, -5624, -5698, -5772, -5846, 
    -5920, -5994, -6068, -6142, -6216, -6290, -6364, -6438, 
    -6512, -6586, -6660, -6734, -6808, -6882, -6956, -7030, 
    -7104, -7178, -7252, -7326, -7400, -7474, -7548, -7622, 
    -7696, -7770, -7844, -7918, -7992, -8066, -8140, -8214, 
    -8288, -8362, -8436, -8510, -8584, -8658, -8732, -8806, 
    -8880, -8954, -9028, -9102, -9176, -9250, -9324, -9398, 
    -9472, -9546, -9620, -9694, -9768, -9842, -9916, -9990, 
    -10064, -10138, -10212, -10286, -10360, -10434, -10508, -10582, 
    -10656, -10730, -10804, -10878, -10952, -11026, -11100, -11174, 
    -11248, -11322, -11396, -11470, -11544, -11618, -11692, -11766, 
    -11840, -11914, -11988, -12062, -12136, -12210, -12284, -12358, 
    -12432, -12506, -12580, -12654, -12728, -12802, -12876, -12950, 
    -13024, -13098, -13172, -13246, -13320, -13394, -13468, -13542, 
    -13616, -13690, -13764, -13838, -13912, -13986, -14060, -14134, 
    -14208, -14282, -14356, -14430, -14504, -14578, -14652, -14726, 
    -14800, -14874, -14948, -15022, -15096, -15170, -15244, -15318, 
    -15392, -15466, -15540, -15614, -15688, -15762, -15836, -15910, 
    -15984, -16058, -16132, -16206, -16280, -16354, -16428, -16502, 
    -16576, -16650, -16724, -16798, -16872, -16946, -17020, -17094, 
    -17168, -17242, -17316, -17390, -17464, -17538, -17612, -17686, 
    -17760, -17834, -17908, -17982, -18056, -18130, -18204, -18278, 
    -18352, -18426, -18500, -18574, -18648, -18722, -18796, -18870 
}; 

int lookup_m_38[] = { 
     0, -38, -76, -114, -152, -190, -228, -266, 
    -304, -342, -380, -418, -456, -494, -532, -570, 
    -608, -646, -684, -722, -760, -798, -836, -874, 
    -912, -950, -988, -1026, -1064, -1102, -1140, -1178, 
    -1216, -1254, -1292, -1330, -1368, -1406, -1444, -1482, 
    -1520, -1558, -1596, -1634, -1672, -1710, -1748, -1786, 
    -1824, -1862, -1900, -1938, -1976, -2014, -2052, -2090, 
    -2128, -2166, -2204, -2242, -2280, -2318, -2356, -2394, 
    -2432, -2470, -2508, -2546, -2584, -2622, -2660, -2698, 
    -2736, -2774, -2812, -2850, -2888, -2926, -2964, -3002, 
    -3040, -3078, -3116, -3154, -3192, -3230, -3268, -3306, 
    -3344, -3382, -3420, -3458, -3496, -3534, -3572, -3610, 
    -3648, -3686, -3724, -3762, -3800, -3838, -3876, -3914, 
    -3952, -3990, -4028, -4066, -4104, -4142, -4180, -4218, 
    -4256, -4294, -4332, -4370, -4408, -4446, -4484, -4522, 
    -4560, -4598, -4636, -4674, -4712, -4750, -4788, -4826, 
    -4864, -4902, -4940, -4978, -5016, -5054, -5092, -5130, 
    -5168, -5206, -5244, -5282, -5320, -5358, -5396, -5434, 
    -5472, -5510, -5548, -5586, -5624, -5662, -5700, -5738, 
    -5776, -5814, -5852, -5890, -5928, -5966, -6004, -6042, 
    -6080, -6118, -6156, -6194, -6232, -6270, -6308, -6346, 
    -6384, -6422, -6460, -6498, -6536, -6574, -6612, -6650, 
    -6688, -6726, -6764, -6802, -6840, -6878, -6916, -6954, 
    -6992, -7030, -7068, -7106, -7144, -7182, -7220, -7258, 
    -7296, -7334, -7372, -7410, -7448, -7486, -7524, -7562, 
    -7600, -7638, -7676, -7714, -7752, -7790, -7828, -7866, 
    -7904, -7942, -7980, -8018, -8056, -8094, -8132, -8170, 
    -8208, -8246, -8284, -8322, -8360, -8398, -8436, -8474, 
    -8512, -8550, -8588, -8626, -8664, -8702, -8740, -8778, 
    -8816, -8854, -8892, -8930, -8968, -9006, -9044, -9082, 
    -9120, -9158, -9196, -9234, -9272, -9310, -9348, -9386, 
    -9424, -9462, -9500, -9538, -9576, -9614, -9652, -9690 
}; 

int lookup_m_18[] = { 
     0, -18, -36, -54, -72, -90, -108, -126, 
    -144, -162, -180, -198, -216, -234, -252, -270, 
    -288, -306, -324, -342, -360, -378, -396, -414, 
    -432, -450, -468, -486, -504, -522, -540, -558, 
    -576, -594, -612, -630, -648, -666, -684, -702, 
    -720, -738, -756, -774, -792, -810, -828, -846, 
    -864, -882, -900, -918, -936, -954, -972, -990, 
    -1008, -1026, -1044, -1062, -1080, -1098, -1116, -1134, 
    -1152, -1170, -1188, -1206, -1224, -1242, -1260, -1278, 
    -1296, -1314, -1332, -1350, -1368, -1386, -1404, -1422, 
    -1440, -1458, -1476, -1494, -1512, -1530, -1548, -1566, 
    -1584, -1602, -1620, -1638, -1656, -1674, -1692, -1710, 
    -1728, -1746, -1764, -1782, -1800, -1818, -1836, -1854, 
    -1872, -1890, -1908, -1926, -1944, -1962, -1980, -1998, 
    -2016, -2034, -2052, -2070, -2088, -2106, -2124, -2142, 
    -2160, -2178, -2196, -2214, -2232, -2250, -2268, -2286, 
    -2304, -2322, -2340, -2358, -2376, -2394, -2412, -2430, 
    -2448, -2466, -2484, -2502, -2520, -2538, -2556, -2574, 
    -2592, -2610, -2628, -2646, -2664, -2682, -2700, -2718, 
    -2736, -2754, -2772, -2790, -2808, -2826, -2844, -2862, 
    -2880, -2898, -2916, -2934, -2952, -2970, -2988, -3006, 
    -3024, -3042, -3060, -3078, -3096, -3114, -3132, -3150, 
    -3168, -3186, -3204, -3222, -3240, -3258, -3276, -3294, 
    -3312, -3330, -3348, -3366, -3384, -3402, -3420, -3438, 
    -3456, -3474, -3492, -3510, -3528, -3546, -3564, -3582, 
    -3600, -3618, -3636, -3654, -3672, -3690, -3708, -3726, 
    -3744, -3762, -3780, -3798, -3816, -3834, -3852, -3870, 
    -3888, -3906, -3924, -3942, -3960, -3978, -3996, -4014, 
    -4032, -4050, -4068, -4086, -4104, -4122, -4140, -4158, 
    -4176, -4194, -4212, -4230, -4248, -4266, -4284, -4302, 
    -4320, -4338, -4356, -4374, -4392, -4410, -4428, -4446, 
    -4464, -4482, -4500, -4518, -4536, -4554, -4572, -4590 
}; 

int lookup25[] = { 
     0,  25,  50,  75, 100, 125, 150, 175, 
    200, 225, 250, 275, 300, 325, 350, 375, 
    400, 425, 450, 475, 500, 525, 550, 575, 
    600, 625, 650, 675, 700, 725, 750, 775, 
    800, 825, 850, 875, 900, 925, 950, 975, 
    1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 
    1200, 1225, 1250, 1275, 1300, 1325, 1350, 1375, 
    1400, 1425, 1450, 1475, 1500, 1525, 1550, 1575, 
    1600, 1625, 1650, 1675, 1700, 1725, 1750, 1775, 
    1800, 1825, 1850, 1875, 1900, 1925, 1950, 1975, 
    2000, 2025, 2050, 2075, 2100, 2125, 2150, 2175, 
    2200, 2225, 2250, 2275, 2300, 2325, 2350, 2375, 
    2400, 2425, 2450, 2475, 2500, 2525, 2550, 2575, 
    2600, 2625, 2650, 2675, 2700, 2725, 2750, 2775, 
    2800, 2825, 2850, 2875, 2900, 2925, 2950, 2975, 
    3000, 3025, 3050, 3075, 3100, 3125, 3150, 3175, 
    3200, 3225, 3250, 3275, 3300, 3325, 3350, 3375, 
    3400, 3425, 3450, 3475, 3500, 3525, 3550, 3575, 
    3600, 3625, 3650, 3675, 3700, 3725, 3750, 3775, 
    3800, 3825, 3850, 3875, 3900, 3925, 3950, 3975, 
    4000, 4025, 4050, 4075, 4100, 4125, 4150, 4175, 
    4200, 4225, 4250, 4275, 4300, 4325, 4350, 4375, 
    4400, 4425, 4450, 4475, 4500, 4525, 4550, 4575, 
    4600, 4625, 4650, 4675, 4700, 4725, 4750, 4775, 
    4800, 4825, 4850, 4875, 4900, 4925, 4950, 4975, 
    5000, 5025, 5050, 5075, 5100, 5125, 5150, 5175, 
    5200, 5225, 5250, 5275, 5300, 5325, 5350, 5375, 
    5400, 5425, 5450, 5475, 5500, 5525, 5550, 5575, 
    5600, 5625, 5650, 5675, 5700, 5725, 5750, 5775, 
    5800, 5825, 5850, 5875, 5900, 5925, 5950, 5975, 
    6000, 6025, 6050, 6075, 6100, 6125, 6150, 6175, 
    6200, 6225, 6250, 6275, 6300, 6325, 6350, 6375 
}; 

int lookup66[] = { 
     0,  66, 132, 198, 264, 330, 396, 462, 
    528, 594, 660, 726, 792, 858, 924, 990, 
    1056, 1122, 1188, 1254, 1320, 1386, 1452, 1518, 
    1584, 1650, 1716, 1782, 1848, 1914, 1980, 2046, 
    2112, 2178, 2244, 2310, 2376, 2442, 2508, 2574, 
    2640, 2706, 2772, 2838, 2904, 2970, 3036, 3102, 
    3168, 3234, 3300, 3366, 3432, 3498, 3564, 3630, 
    3696, 3762, 3828, 3894, 3960, 4026, 4092, 4158, 
    4224, 4290, 4356, 4422, 4488, 4554, 4620, 4686, 
    4752, 4818, 4884, 4950, 5016, 5082, 5148, 5214, 
    5280, 5346, 5412, 5478, 5544, 5610, 5676, 5742, 
    5808, 5874, 5940, 6006, 6072, 6138, 6204, 6270, 
    6336, 6402, 6468, 6534, 6600, 6666, 6732, 6798, 
    6864, 6930, 6996, 7062, 7128, 7194, 7260, 7326, 
    7392, 7458, 7524, 7590, 7656, 7722, 7788, 7854, 
    7920, 7986, 8052, 8118, 8184, 8250, 8316, 8382, 
    8448, 8514, 8580, 8646, 8712, 8778, 8844, 8910, 
    8976, 9042, 9108, 9174, 9240, 9306, 9372, 9438, 
    9504, 9570, 9636, 9702, 9768, 9834, 9900, 9966, 
    10032, 10098, 10164, 10230, 10296, 10362, 10428, 10494, 
    10560, 10626, 10692, 10758, 10824, 10890, 10956, 11022, 
    11088, 11154, 11220, 11286, 11352, 11418, 11484, 11550, 
    11616, 11682, 11748, 11814, 11880, 11946, 12012, 12078, 
    12144, 12210, 12276, 12342, 12408, 12474, 12540, 12606, 
    12672, 12738, 12804, 12870, 12936, 13002, 13068, 13134, 
    13200, 13266, 13332, 13398, 13464, 13530, 13596, 13662, 
    13728, 13794, 13860, 13926, 13992, 14058, 14124, 14190, 
    14256, 14322, 14388, 14454, 14520, 14586, 14652, 14718, 
    14784, 14850, 14916, 14982, 15048, 15114, 15180, 15246, 
    15312, 15378, 15444, 15510, 15576, 15642, 15708, 15774, 
    15840, 15906, 15972, 16038, 16104, 16170, 16236, 16302, 
    16368, 16434, 16500, 16566, 16632, 16698, 16764, 16830 
}; 

int lookup112[] = { 
     0, 112, 224, 336, 448, 560, 672, 784, 
    896, 1008, 1120, 1232, 1344, 1456, 1568, 1680, 
    1792, 1904, 2016, 2128, 2240, 2352, 2464, 2576, 
    2688, 2800, 2912, 3024, 3136, 3248, 3360, 3472, 
    3584, 3696, 3808, 3920, 4032, 4144, 4256, 4368, 
    4480, 4592, 4704, 4816, 4928, 5040, 5152, 5264, 
    5376, 5488, 5600, 5712, 5824, 5936, 6048, 6160, 
    6272, 6384, 6496, 6608, 6720, 6832, 6944, 7056, 
    7168, 7280, 7392, 7504, 7616, 7728, 7840, 7952, 
    8064, 8176, 8288, 8400, 8512, 8624, 8736, 8848, 
    8960, 9072, 9184, 9296, 9408, 9520, 9632, 9744, 
    9856, 9968, 10080, 10192, 10304, 10416, 10528, 10640, 
    10752, 10864, 10976, 11088, 11200, 11312, 11424, 11536, 
    11648, 11760, 11872, 11984, 12096, 12208, 12320, 12432, 
    12544, 12656, 12768, 12880, 12992, 13104, 13216, 13328, 
    13440, 13552, 13664, 13776, 13888, 14000, 14112, 14224, 
    14336, 14448, 14560, 14672, 14784, 14896, 15008, 15120, 
    15232, 15344, 15456, 15568, 15680, 15792, 15904, 16016, 
    16128, 16240, 16352, 16464, 16576, 16688, 16800, 16912, 
    17024, 17136, 17248, 17360, 17472, 17584, 17696, 17808, 
    17920, 18032, 18144, 18256, 18368, 18480, 18592, 18704, 
    18816, 18928, 19040, 19152, 19264, 19376, 19488, 19600, 
    19712, 19824, 19936, 20048, 20160, 20272, 20384, 20496, 
    20608, 20720, 20832, 20944, 21056, 21168, 21280, 21392, 
    21504, 21616, 21728, 21840, 21952, 22064, 22176, 22288, 
    22400, 22512, 22624, 22736, 22848, 22960, 23072, 23184, 
    23296, 23408, 23520, 23632, 23744, 23856, 23968, 24080, 
    24192, 24304, 24416, 24528, 24640, 24752, 24864, 24976, 
    25088, 25200, 25312, 25424, 25536, 25648, 25760, 25872, 
    25984, 26096, 26208, 26320, 26432, 26544, 26656, 26768, 
    26880, 26992, 27104, 27216, 27328, 27440, 27552, 27664, 
    27776, 27888, 28000, 28112, 28224, 28336, 28448, 28560 
}; 

int lookup129[] = { 
     0, 129, 258, 387, 516, 645, 774, 903, 
    1032, 1161, 1290, 1419, 1548, 1677, 1806, 1935, 
    2064, 2193, 2322, 2451, 2580, 2709, 2838, 2967, 
    3096, 3225, 3354, 3483, 3612, 3741, 3870, 3999, 
    4128, 4257, 4386, 4515, 4644, 4773, 4902, 5031, 
    5160, 5289, 5418, 5547, 5676, 5805, 5934, 6063, 
    6192, 6321, 6450, 6579, 6708, 6837, 6966, 7095, 
    7224, 7353, 7482, 7611, 7740, 7869, 7998, 8127, 
    8256, 8385, 8514, 8643, 8772, 8901, 9030, 9159, 
    9288, 9417, 9546, 9675, 9804, 9933, 10062, 10191, 
    10320, 10449, 10578, 10707, 10836, 10965, 11094, 11223, 
    11352, 11481, 11610, 11739, 11868, 11997, 12126, 12255, 
    12384, 12513, 12642, 12771, 12900, 13029, 13158, 13287, 
    13416, 13545, 13674, 13803, 13932, 14061, 14190, 14319, 
    14448, 14577, 14706, 14835, 14964, 15093, 15222, 15351, 
    15480, 15609, 15738, 15867, 15996, 16125, 16254, 16383, 
    16512, 16641, 16770, 16899, 17028, 17157, 17286, 17415, 
    17544, 17673, 17802, 17931, 18060, 18189, 18318, 18447, 
    18576, 18705, 18834, 18963, 19092, 19221, 19350, 19479, 
    19608, 19737, 19866, 19995, 20124, 20253, 20382, 20511, 
    20640, 20769, 20898, 21027, 21156, 21285, 21414, 21543, 
    21672, 21801, 21930, 22059, 22188, 22317, 22446, 22575, 
    22704, 22833, 22962, 23091, 23220, 23349, 23478, 23607, 
    23736, 23865, 23994, 24123, 24252, 24381, 24510, 24639, 
    24768, 24897, 25026, 25155, 25284, 25413, 25542, 25671, 
    25800, 25929, 26058, 26187, 26316, 26445, 26574, 26703, 
    26832, 26961, 27090, 27219, 27348, 27477, 27606, 27735, 
    27864, 27993, 28122, 28251, 28380, 28509, 28638, 28767, 
    28896, 29025, 29154, 29283, 29412, 29541, 29670, 29799, 
    29928, 30057, 30186, 30315, 30444, 30573, 30702, 30831, 
    30960, 31089, 31218, 31347, 31476, 31605, 31734, 31863, 
    31992, 32121, 32250, 32379, 32508, 32637, 32766, 32895 
}; 
} 

void Bitmap2Yuv420p(boost::uint8_t *destination, boost::uint8_t *rgb, 
        const int &width, const int &height) { 
    boost::uint8_t *y; 
    boost::uint8_t *u; 
    boost::uint8_t *v; 

    boost::uint8_t *r; 
    boost::uint8_t *g; 
    boost::uint8_t *b; 

    std::size_t image_size = width * height; 
    std::size_t upos = image_size; 
    std::size_t vpos = upos + upos/4; 
    for (std::size_t i = 0; i < image_size; ++i) { 
    r = rgb + 3 * i; 
    g = rgb + 3 * i + 1; 
    b = rgb + 3 * i + 2; 
    y = destination + i; 
    *y = ((lookup66[*r] + lookup129[*g] + lookup25[*b]) >> 8) + 16; 
    if (!((i/width) % 2) && !(i % 2)) { 
     u = destination + upos++; 
     v = destination + vpos++; 
     *u = ((lookup_m_38[*r] + lookup_m_74[*g] + lookup112[*b]) >> 8) + 128; 
     *v = ((lookup112[*r] + lookup_m_94[*g] + lookup_m_18[*b]) >> 8) + 128; 
    } 
    } 
} 
+0

Vâng, tôi đã lặp qua thuật toán này, từ không có tra cứu các bảng và sử dụng các biến tạm thời cho điều này. – Sambatyon

+2

Tôi cảm thấy nỗi đau của bạn, tôi phải đối phó với chi phí của việc chuyển đổi này ... – UmNyobe

Trả lời

16

Hãy bỏ vòng lặp của bạn và loại bỏ nếu ở vòng trong. Nhưng không chạy trên dữ liệu hình ảnh 3 lần, và nó thậm chí còn nhanh hơn!

void Bitmap2Yuv420p_calc2(uint8_t *destination, uint8_t *rgb, size_t width, size_t height) 
{ 
    size_t image_size = width * height; 
    size_t upos = image_size; 
    size_t vpos = upos + upos/4; 
    size_t i = 0; 

    for(size_t line = 0; line < height; ++line) 
    { 
     if(!(line % 2)) 
     { 
      for(size_t x = 0; x < width; x += 2) 
      { 
       uint8_t r = rgb[3 * i]; 
       uint8_t g = rgb[3 * i + 1]; 
       uint8_t b = rgb[3 * i + 2]; 

       destination[i++] = ((66*r + 129*g + 25*b) >> 8) + 16; 

       destination[upos++] = ((-38*r + -74*g + 112*b) >> 8) + 128; 
       destination[vpos++] = ((112*r + -94*g + -18*b) >> 8) + 128; 

       r = rgb[3 * i]; 
       g = rgb[3 * i + 1]; 
       b = rgb[3 * i + 2]; 

       destination[i++] = ((66*r + 129*g + 25*b) >> 8) + 16; 
      } 
     } 
     else 
     { 
      for(size_t x = 0; x < width; x += 1) 
      { 
       uint8_t r = rgb[3 * i]; 
       uint8_t g = rgb[3 * i + 1]; 
       uint8_t b = rgb[3 * i + 2]; 

       destination[i++] = ((66*r + 129*g + 25*b) >> 8) + 16; 
      } 
     } 
    } 
} 

Trong các thử nghiệm của tôi, đây là nhanh hơn so với câu trả lời chấp nhận của bạn khoảng 25% (VS 2010, tùy thuộc vào việc x86 hoặc x64 được kích hoạt.)

+0

bạn đã kiểm tra kết quả chưa? bởi vì tôi không nghĩ rằng điều này cho: cho (size_t x = 0; x Sambatyon

+0

Tôi không so sánh kết quả, nhưng đích [i ++] được viết hai lần cho mỗi lần lặp lại, vì vậy đó không phải là mối quan tâm từ quan điểm của tôi. i là chỉ mục nguồn và chỉ mục đích cho mặt phẳng y. – Timbo

+0

Bằng cách này nếu bạn quan tâm đến chất lượng hình ảnh đầu ra, bạn nên suy nghĩ xem liệu bạn có thay đổi thuật toán của mình để trung bình giá trị r/g/b của mỗi khối 2x2 pixel trước khi chuyển đổi thành u/v, thay vì chỉ chọn một mẫu r/g/b trong mỗi khối 2x2. Ít nhất đó là cách tôi hiểu mã hóa Y420. – Timbo

2

Bạn có thể sử dụng SSE hoặc mã lắp ráp 3DNow để thúc đẩy hơn nữa việc thực hiện.

Đối với mã C++, tôi nghĩ khó cải thiện dựa trên mã hiện tại của bạn.

+0

xấu đến khả năng lắp ráp của tôi bị giảm để hiểu mã, nhưng tôi không coi bản thân mình là viết tốt. – Sambatyon

1

Điểm duy nhất tôi có thể thấy là bạn đang thực hiện 3 * i ba lần. Bạn có thể lưu trữ kết quả đó trong một biến cục bộ nhưng trình biên dịch cũng có thể đã làm điều đó. Vì vậy ..

r = rgb + 3 * i; 
g = rgb + 3 * i + 1; 
b = rgb + 3 * i + 2; 

... trở thành:

r = rgb + 3 * i; 
g = r + 1; 
b = g + 1; 

..although tôi nghi ngờ nó sẽ có tác động nhiều.

Như đã đề cập, tôi nghĩ rằng lắp ráp là cách duy nhất bạn có khả năng cải thiện những gì bạn đã có ở đó.

+0

Bất kỳ trình biên dịch hợp lý nào cũng sẽ làm điều đó cho bạn.Và những cái tốt sẽ thấy rằng mỗi con trỏ được tăng lên 3 bước mỗi bước, và sẽ chỉ +3 chúng (Hoặc tìm một cách tốt hơn nữa mà tôi không thể nghĩ ra ngay bây giờ!) – Timbo

+0

Điều thú vị là tôi đã thử với hiệu suất phạt ... nhưng tôi chỉ khám phá ra tôi không có tối ưu hóa tất cả các trình biên dịch cho tối đa – Sambatyon

7

Không truy cập con trỏ nhiều hơn một lần, sao chép giá trị vào ngăn xếp và sau đó sử dụng giá trị trên ngăn xếp. (Bí danh)

... 
int v_r = *r; 
int v_g = *g; 
int v_b = *b; 

*y = ((lookup66[v_r] + lookup129[v_g] + lookup25[v_b]) >> 8) + 16; 
... 

Mặt khác, bạn có thể làm điều đó trong SSE mà không cần tra cứu bảng và sẽ làm 8 pixel cùng một lúc.

4

Tôi đoán các bảng tra cứu không cần thiết. Các phép nhân tương ứng phải nhanh hơn truy cập bộ nhớ. Đặc biệt trong vòng lặp bên trong như vậy.

Sau đó, tôi cũng sẽ áp dụng một số thay đổi nhỏ (như những người khác đã có gợi ý) ..:

void Bitmap2Yuv420p(boost::uint8_t *destination, boost::uint8_t *rgb, 
        const int &width, const int &height) { 
    const size_t image_size = width * height; 
    const size_t upos = image_size; 
    const size_t vpos = upos + upos/4; 
    for(size_t i = 0; i < image_size; ++i) { 
    boost::uint8_t r = rgb[3*i ]; 
    boost::uint8_t g = rgb[3*i+1]; 
    boost::uint8_t b = rgb[3*i+2]; 
    destination[i] = ((66*r + 129*g + 25*b) >> 8) + 16; 
    if (!((i/width) % 2) && !(i % 2)) { 
     destination[upos++] = ((-38*r + -74*g + 112*b) >> 8) + 128; 
     destination[vpos++] = ((112*r + -94*g + -18*b) >> 8) + 128; 
    } 
    } 
} 

EDIT

Bạn cũng nên sắp xếp lại mã số, để bạn có thể loại bỏ các if(). Các vòng bên trong nhỏ, đơn giản mà không có nhánh nhanh. Ở đây, bạn nên viết máy bay Y, sau đó là máy bay U và V, như sau:

void Bitmap2Yuv420p(boost::uint8_t *destination, boost::uint8_t *rgb, 
        const int &width, const int &height) { 
    const size_t image_size = width * height; 
    boost::uint8_t *dst_y = destination; 
    boost::uint8_t *dst_u = destination + image_size; 
    boost::uint8_t *dst_v = destination + image_size + image_size/4; 

    // Y plane 
    for(size_t i = 0; i < image_size; ++i) { 
    *dst_y++ = ((66*rgb[3*i] + 129*rgb[3*i+1] + 25*rgb[3*i+2]) >> 8) + 16; 
    } 
#if 1 
    // U plane 
    for(size_t y=0; y<height; y+=2) { 
    for(size_t x=0; x<width; x+=2) { 
     const size_t i = y*width + x; 
     *dst_u++ = ((-38*rgb[3*i] + -74*rgb[3*i+1] + 112*rgb[3*i+2]) >> 8) + 128; 
    } 
    // V plane 
    for(size_t y=0; y<height; y+=2) { 
    for(size_t x=0; x<width; x+=2) { 
     const size_t i = y*width + x; 
     *dst_v++ = ((112*rgb[3*i] + -94*rgb[3*i+1] + -18*rgb[3*i+2]) >> 8) + 128; 
    } 
#else // also try this version: 
    // U+V planes 
    for(size_t y=0; y<height; y+=2) { 
    for(size_t x=0; x<width; x+=2) { 
     const size_t i = y*width + x; 
     *dst_u++ = ((-38*rgb[3*i] + -74*rgb[3*i+1] + 112*rgb[3*i+2]) >> 8) + 128; 
     *dst_v++ = ((112*rgb[3*i] + -94*rgb[3*i+1] + -18*rgb[3*i+2]) >> 8) + 128; 
    } 
#endif 
} 
+0

đó là phiên bản đầu tiên của tôi, và thực sự là nhanh hơn trong chế độ gỡ lỗi, nhưng không phải trong phiên bản phát hành. – Sambatyon

+0

Đồng ý, bằng cách sử dụng bảng tra cứu cho phép nhân là một mất lưới. – zmccord

+0

Nếu bạn đang tìm kiếm các bảng tra cứu nhanh hơn nhân, tôi thực sự không biết phải làm gì. Crank tối ưu hóa và xem nếu đó là sự thật ... – zmccord