Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of the Scale2x project.
  3.  *
  4.  * Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /*
  22.  * This file contains a C and MMX implementation of the Scale2x effect.
  23.  *
  24.  * You can find an high level description of the effect at :
  25.  *
  26.  * http://scale2x.sourceforge.net/
  27.  *
  28.  * Alternatively at the previous license terms, you are allowed to use this
  29.  * code in your program with these conditions:
  30.  * - the program is not used in commercial activities.
  31.  * - the whole source code of the program is released with the binary.
  32.  * - derivative works of the program are allowed.
  33.  */
  34.  
  35. #if HAVE_CONFIG_H
  36. #include <config.h>
  37. #endif
  38.  
  39. #include "scale3x.h"
  40.  
  41. #include <assert.h>
  42.  
  43. /***************************************************************************/
  44. /* Scale3x C implementation */
  45.  
  46. /**
  47.  * Define the macro USE_SCALE_RANDOMWRITE to enable
  48.  * an optimized version which writes memory in random order.
  49.  * This version is a little faster if you write in system memory.
  50.  * But it's a lot slower if you write in video memory.
  51.  * So, enable it only if you are sure to never write directly in video memory.
  52.  */
  53. /* #define USE_SCALE_RANDOMWRITE */
  54.  
  55. #ifdef USE_SCALE_RANDOMWRITE
  56.  
  57. static inline void scale3x_8_def_whole(scale3x_uint8* restrict dst0, scale3x_uint8* restrict dst1, scale3x_uint8* restrict dst2, const scale3x_uint8* restrict src0, const scale3x_uint8* restrict src1, const scale3x_uint8* restrict src2, unsigned count)
  58. {
  59.         assert(count >= 2);
  60.  
  61.         /* first pixel */
  62.         if (src0[0] != src2[0] && src1[0] != src1[1]) {
  63.                 dst0[0] = src1[0];
  64.                 dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
  65.                 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  66.                 dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  67.                 dst1[1] = src1[0];
  68.                 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  69.                 dst2[0] = src1[0];
  70.                 dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0];
  71.                 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
  72.         } else {
  73.                 dst0[0] = src1[0];
  74.                 dst0[1] = src1[0];
  75.                 dst0[2] = src1[0];
  76.                 dst1[0] = src1[0];
  77.                 dst1[1] = src1[0];
  78.                 dst1[2] = src1[0];
  79.                 dst2[0] = src1[0];
  80.                 dst2[1] = src1[0];
  81.                 dst2[2] = src1[0];
  82.         }
  83.         ++src0;
  84.         ++src1;
  85.         ++src2;
  86.         dst0 += 3;
  87.         dst1 += 3;
  88.         dst2 += 3;
  89.  
  90.         /* central pixels */
  91.         count -= 2;
  92.         while (count) {
  93.                 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
  94.                         dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  95.                         dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  96.                         dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  97.                         dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  98.                         dst1[1] = src1[0];
  99.                         dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  100.                         dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
  101.                         dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
  102.                         dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
  103.                 } else {
  104.                         dst0[0] = src1[0];
  105.                         dst0[1] = src1[0];
  106.                         dst0[2] = src1[0];
  107.                         dst1[0] = src1[0];
  108.                         dst1[1] = src1[0];
  109.                         dst1[2] = src1[0];
  110.                         dst2[0] = src1[0];
  111.                         dst2[1] = src1[0];
  112.                         dst2[2] = src1[0];
  113.                 }
  114.  
  115.                 ++src0;
  116.                 ++src1;
  117.                 ++src2;
  118.                 dst0 += 3;
  119.                 dst1 += 3;
  120.                 dst2 += 3;
  121.                 --count;
  122.         }
  123.  
  124.         /* last pixel */
  125.         if (src0[0] != src2[0] && src1[-1] != src1[0]) {
  126.                 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  127.                 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  128.                 dst0[2] = src1[0];
  129.                 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  130.                 dst1[1] = src1[0];
  131.                 dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  132.                 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
  133.                 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
  134.                 dst2[2] = src1[0];
  135.         } else {
  136.                 dst0[0] = src1[0];
  137.                 dst0[1] = src1[0];
  138.                 dst0[2] = src1[0];
  139.                 dst1[0] = src1[0];
  140.                 dst1[1] = src1[0];
  141.                 dst1[2] = src1[0];
  142.                 dst2[0] = src1[0];
  143.                 dst2[1] = src1[0];
  144.                 dst2[2] = src1[0];
  145.         }
  146. }
  147.  
  148. #else /* USE_SCALE_RANDOMWRITE */
  149.  
  150. static inline void scale3x_8_def_border(scale3x_uint8* restrict dst, const scale3x_uint8* restrict src0, const scale3x_uint8* restrict src1, const scale3x_uint8* restrict src2, unsigned count)
  151. {
  152.         assert(count >= 2);
  153.  
  154.         /* first pixel */
  155.         if (src0[0] != src2[0] && src1[0] != src1[1]) {
  156.                 dst[0] = src1[0];
  157.                 dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
  158.                 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  159.         } else {
  160.                 dst[0] = src1[0];
  161.                 dst[1] = src1[0];
  162.                 dst[2] = src1[0];
  163.         }
  164.         ++src0;
  165.         ++src1;
  166.         ++src2;
  167.         dst += 3;
  168.  
  169.         /* central pixels */
  170.         count -= 2;
  171.         while (count) {
  172.                 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
  173.                         dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  174.                         dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  175.                         dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  176.                 } else {
  177.                         dst[0] = src1[0];
  178.                         dst[1] = src1[0];
  179.                         dst[2] = src1[0];
  180.                 }
  181.  
  182.                 ++src0;
  183.                 ++src1;
  184.                 ++src2;
  185.                 dst += 3;
  186.                 --count;
  187.         }
  188.  
  189.         /* last pixel */
  190.         if (src0[0] != src2[0] && src1[-1] != src1[0]) {
  191.                 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  192.                 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  193.                 dst[2] = src1[0];
  194.         } else {
  195.                 dst[0] = src1[0];
  196.                 dst[1] = src1[0];
  197.                 dst[2] = src1[0];
  198.         }
  199. }
  200.  
  201. static inline void scale3x_8_def_center(scale3x_uint8* restrict dst, const scale3x_uint8* restrict src0, const scale3x_uint8* restrict src1, const scale3x_uint8* restrict src2, unsigned count)
  202. {
  203.         assert(count >= 2);
  204.  
  205.         /* first pixel */
  206.         if (src0[0] != src2[0] && src1[0] != src1[1]) {
  207.                 dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  208.                 dst[1] = src1[0];
  209.                 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  210.         } else {
  211.                 dst[0] = src1[0];
  212.                 dst[1] = src1[0];
  213.                 dst[2] = src1[0];
  214.         }
  215.         ++src0;
  216.         ++src1;
  217.         ++src2;
  218.         dst += 3;
  219.  
  220.         /* central pixels */
  221.         count -= 2;
  222.         while (count) {
  223.                 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
  224.                         dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  225.                         dst[1] = src1[0];
  226.                         dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  227.                 } else {
  228.                         dst[0] = src1[0];
  229.                         dst[1] = src1[0];
  230.                         dst[2] = src1[0];
  231.                 }
  232.  
  233.                 ++src0;
  234.                 ++src1;
  235.                 ++src2;
  236.                 dst += 3;
  237.                 --count;
  238.         }
  239.  
  240.         /* last pixel */
  241.         if (src0[0] != src2[0] && src1[-1] != src1[0]) {
  242.                 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  243.                 dst[1] = src1[0];
  244.                 dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  245.         } else {
  246.                 dst[0] = src1[0];
  247.                 dst[1] = src1[0];
  248.                 dst[2] = src1[0];
  249.         }
  250. }
  251.  
  252. #endif /* USE_SCALE_RANDOMWRITE */
  253.  
  254. #ifdef USE_SCALE_RANDOMWRITE
  255.  
  256. static inline void scale3x_16_def_whole(scale3x_uint16* restrict dst0, scale3x_uint16* restrict dst1, scale3x_uint16* restrict dst2, const scale3x_uint16* restrict src0, const scale3x_uint16* restrict src1, const scale3x_uint16* restrict src2, unsigned count)
  257. {
  258.         assert(count >= 2);
  259.  
  260.         /* first pixel */
  261.         if (src0[0] != src2[0] && src1[0] != src1[1]) {
  262.                 dst0[0] = src1[0];
  263.                 dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
  264.                 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  265.                 dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  266.                 dst1[1] = src1[0];
  267.                 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  268.                 dst2[0] = src1[0];
  269.                 dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0];
  270.                 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
  271.         } else {
  272.                 dst0[0] = src1[0];
  273.                 dst0[1] = src1[0];
  274.                 dst0[2] = src1[0];
  275.                 dst1[0] = src1[0];
  276.                 dst1[1] = src1[0];
  277.                 dst1[2] = src1[0];
  278.                 dst2[0] = src1[0];
  279.                 dst2[1] = src1[0];
  280.                 dst2[2] = src1[0];
  281.         }
  282.         ++src0;
  283.         ++src1;
  284.         ++src2;
  285.         dst0 += 3;
  286.         dst1 += 3;
  287.         dst2 += 3;
  288.  
  289.         /* central pixels */
  290.         count -= 2;
  291.         while (count) {
  292.                 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
  293.                         dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  294.                         dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  295.                         dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  296.                         dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  297.                         dst1[1] = src1[0];
  298.                         dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  299.                         dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
  300.                         dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
  301.                         dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
  302.                 } else {
  303.                         dst0[0] = src1[0];
  304.                         dst0[1] = src1[0];
  305.                         dst0[2] = src1[0];
  306.                         dst1[0] = src1[0];
  307.                         dst1[1] = src1[0];
  308.                         dst1[2] = src1[0];
  309.                         dst2[0] = src1[0];
  310.                         dst2[1] = src1[0];
  311.                         dst2[2] = src1[0];
  312.                 }
  313.  
  314.                 ++src0;
  315.                 ++src1;
  316.                 ++src2;
  317.                 dst0 += 3;
  318.                 dst1 += 3;
  319.                 dst2 += 3;
  320.                 --count;
  321.         }
  322.  
  323.         /* last pixel */
  324.         if (src0[0] != src2[0] && src1[-1] != src1[0]) {
  325.                 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  326.                 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  327.                 dst0[2] = src1[0];
  328.                 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  329.                 dst1[1] = src1[0];
  330.                 dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  331.                 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
  332.                 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
  333.                 dst2[2] = src1[0];
  334.         } else {
  335.                 dst0[0] = src1[0];
  336.                 dst0[1] = src1[0];
  337.                 dst0[2] = src1[0];
  338.                 dst1[0] = src1[0];
  339.                 dst1[1] = src1[0];
  340.                 dst1[2] = src1[0];
  341.                 dst2[0] = src1[0];
  342.                 dst2[1] = src1[0];
  343.                 dst2[2] = src1[0];
  344.         }
  345. }
  346.  
  347. #else /* USE_SCALE_RANDOMWRITE */
  348.  
  349. static inline void scale3x_16_def_border(scale3x_uint16* restrict dst, const scale3x_uint16* restrict src0, const scale3x_uint16* restrict src1, const scale3x_uint16* restrict src2, unsigned count)
  350. {
  351.         assert(count >= 2);
  352.  
  353.         /* first pixel */
  354.         if (src0[0] != src2[0] && src1[0] != src1[1]) {
  355.                 dst[0] = src1[0];
  356.                 dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
  357.                 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  358.         } else {
  359.                 dst[0] = src1[0];
  360.                 dst[1] = src1[0];
  361.                 dst[2] = src1[0];
  362.         }
  363.         ++src0;
  364.         ++src1;
  365.         ++src2;
  366.         dst += 3;
  367.  
  368.         /* central pixels */
  369.         count -= 2;
  370.         while (count) {
  371.                 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
  372.                         dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  373.                         dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  374.                         dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  375.                 } else {
  376.                         dst[0] = src1[0];
  377.                         dst[1] = src1[0];
  378.                         dst[2] = src1[0];
  379.                 }
  380.  
  381.                 ++src0;
  382.                 ++src1;
  383.                 ++src2;
  384.                 dst += 3;
  385.                 --count;
  386.         }
  387.  
  388.         /* last pixel */
  389.         if (src0[0] != src2[0] && src1[-1] != src1[0]) {
  390.                 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  391.                 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  392.                 dst[2] = src1[0];
  393.         } else {
  394.                 dst[0] = src1[0];
  395.                 dst[1] = src1[0];
  396.                 dst[2] = src1[0];
  397.         }
  398. }
  399.  
  400. static inline void scale3x_16_def_center(scale3x_uint16* restrict dst, const scale3x_uint16* restrict src0, const scale3x_uint16* restrict src1, const scale3x_uint16* restrict src2, unsigned count)
  401. {
  402.         assert(count >= 2);
  403.  
  404.         /* first pixel */
  405.         if (src0[0] != src2[0] && src1[0] != src1[1]) {
  406.                 dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  407.                 dst[1] = src1[0];
  408.                 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  409.         } else {
  410.                 dst[0] = src1[0];
  411.                 dst[1] = src1[0];
  412.                 dst[2] = src1[0];
  413.         }
  414.         ++src0;
  415.         ++src1;
  416.         ++src2;
  417.         dst += 3;
  418.  
  419.         /* central pixels */
  420.         count -= 2;
  421.         while (count) {
  422.                 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
  423.                         dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  424.                         dst[1] = src1[0];
  425.                         dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  426.                 } else {
  427.                         dst[0] = src1[0];
  428.                         dst[1] = src1[0];
  429.                         dst[2] = src1[0];
  430.                 }
  431.  
  432.                 ++src0;
  433.                 ++src1;
  434.                 ++src2;
  435.                 dst += 3;
  436.                 --count;
  437.         }
  438.  
  439.         /* last pixel */
  440.         if (src0[0] != src2[0] && src1[-1] != src1[0]) {
  441.                 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  442.                 dst[1] = src1[0];
  443.                 dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  444.         } else {
  445.                 dst[0] = src1[0];
  446.                 dst[1] = src1[0];
  447.                 dst[2] = src1[0];
  448.         }
  449. }
  450.  
  451. #endif /* USE_SCALE_RANDOMWRITE */
  452.  
  453. #ifdef USE_SCALE_RANDOMWRITE
  454.  
  455. static inline void scale3x_32_def_whole(scale3x_uint32* restrict dst0, scale3x_uint32* restrict dst1, scale3x_uint32* restrict dst2, const scale3x_uint32* restrict src0, const scale3x_uint32* restrict src1, const scale3x_uint32* restrict src2, unsigned count)
  456. {
  457.         assert(count >= 2);
  458.  
  459.         /* first pixel */
  460.         if (src0[0] != src2[0] && src1[0] != src1[1]) {
  461.                 dst0[0] = src1[0];
  462.                 dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
  463.                 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  464.                 dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  465.                 dst1[1] = src1[0];
  466.                 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  467.                 dst2[0] = src1[0];
  468.                 dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0];
  469.                 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
  470.         } else {
  471.                 dst0[0] = src1[0];
  472.                 dst0[1] = src1[0];
  473.                 dst0[2] = src1[0];
  474.                 dst1[0] = src1[0];
  475.                 dst1[1] = src1[0];
  476.                 dst1[2] = src1[0];
  477.                 dst2[0] = src1[0];
  478.                 dst2[1] = src1[0];
  479.                 dst2[2] = src1[0];
  480.         }
  481.         ++src0;
  482.         ++src1;
  483.         ++src2;
  484.         dst0 += 3;
  485.         dst1 += 3;
  486.         dst2 += 3;
  487.  
  488.         /* central pixels */
  489.         count -= 2;
  490.         while (count) {
  491.                 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
  492.                         dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  493.                         dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  494.                         dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  495.                         dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  496.                         dst1[1] = src1[0];
  497.                         dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  498.                         dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
  499.                         dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
  500.                         dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
  501.                 } else {
  502.                         dst0[0] = src1[0];
  503.                         dst0[1] = src1[0];
  504.                         dst0[2] = src1[0];
  505.                         dst1[0] = src1[0];
  506.                         dst1[1] = src1[0];
  507.                         dst1[2] = src1[0];
  508.                         dst2[0] = src1[0];
  509.                         dst2[1] = src1[0];
  510.                         dst2[2] = src1[0];
  511.                 }
  512.  
  513.                 ++src0;
  514.                 ++src1;
  515.                 ++src2;
  516.                 dst0 += 3;
  517.                 dst1 += 3;
  518.                 dst2 += 3;
  519.                 --count;
  520.         }
  521.  
  522.         /* last pixel */
  523.         if (src0[0] != src2[0] && src1[-1] != src1[0]) {
  524.                 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  525.                 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  526.                 dst0[2] = src1[0];
  527.                 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  528.                 dst1[1] = src1[0];
  529.                 dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  530.                 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
  531.                 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
  532.                 dst2[2] = src1[0];
  533.         } else {
  534.                 dst0[0] = src1[0];
  535.                 dst0[1] = src1[0];
  536.                 dst0[2] = src1[0];
  537.                 dst1[0] = src1[0];
  538.                 dst1[1] = src1[0];
  539.                 dst1[2] = src1[0];
  540.                 dst2[0] = src1[0];
  541.                 dst2[1] = src1[0];
  542.                 dst2[2] = src1[0];
  543.         }
  544. }
  545.  
  546. #else /* USE_SCALE_RANDOMWRITE */
  547.  
  548. static inline void scale3x_32_def_border(scale3x_uint32* restrict dst, const scale3x_uint32* restrict src0, const scale3x_uint32* restrict src1, const scale3x_uint32* restrict src2, unsigned count)
  549. {
  550.         assert(count >= 2);
  551.  
  552.         /* first pixel */
  553.         if (src0[0] != src2[0] && src1[0] != src1[1]) {
  554.                 dst[0] = src1[0];
  555.                 dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
  556.                 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  557.         } else {
  558.                 dst[0] = src1[0];
  559.                 dst[1] = src1[0];
  560.                 dst[2] = src1[0];
  561.         }
  562.         ++src0;
  563.         ++src1;
  564.         ++src2;
  565.         dst += 3;
  566.  
  567.         /* central pixels */
  568.         count -= 2;
  569.         while (count) {
  570.                 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
  571.                         dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  572.                         dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  573.                         dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
  574.                 } else {
  575.                         dst[0] = src1[0];
  576.                         dst[1] = src1[0];
  577.                         dst[2] = src1[0];
  578.                 }
  579.  
  580.                 ++src0;
  581.                 ++src1;
  582.                 ++src2;
  583.                 dst += 3;
  584.                 --count;
  585.         }
  586.  
  587.         /* last pixel */
  588.         if (src0[0] != src2[0] && src1[-1] != src1[0]) {
  589.                 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
  590.                 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
  591.                 dst[2] = src1[0];
  592.         } else {
  593.                 dst[0] = src1[0];
  594.                 dst[1] = src1[0];
  595.                 dst[2] = src1[0];
  596.         }
  597. }
  598.  
  599. static inline void scale3x_32_def_center(scale3x_uint32* restrict dst, const scale3x_uint32* restrict src0, const scale3x_uint32* restrict src1, const scale3x_uint32* restrict src2, unsigned count)
  600. {
  601.         assert(count >= 2);
  602.  
  603.         /* first pixel */
  604.         if (src0[0] != src2[0] && src1[0] != src1[1]) {
  605.                 dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  606.                 dst[1] = src1[0];
  607.                 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  608.         } else {
  609.                 dst[0] = src1[0];
  610.                 dst[1] = src1[0];
  611.                 dst[2] = src1[0];
  612.         }
  613.         ++src0;
  614.         ++src1;
  615.         ++src2;
  616.         dst += 3;
  617.  
  618.         /* central pixels */
  619.         count -= 2;
  620.         while (count) {
  621.                 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
  622.                         dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  623.                         dst[1] = src1[0];
  624.                         dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
  625.                 } else {
  626.                         dst[0] = src1[0];
  627.                         dst[1] = src1[0];
  628.                         dst[2] = src1[0];
  629.                 }
  630.  
  631.                 ++src0;
  632.                 ++src1;
  633.                 ++src2;
  634.                 dst += 3;
  635.                 --count;
  636.         }
  637.  
  638.         /* last pixel */
  639.         if (src0[0] != src2[0] && src1[-1] != src1[0]) {
  640.                 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
  641.                 dst[1] = src1[0];
  642.                 dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
  643.         } else {
  644.                 dst[0] = src1[0];
  645.                 dst[1] = src1[0];
  646.                 dst[2] = src1[0];
  647.         }
  648. }
  649.  
  650. #endif /* USE_SCALE_RANDOMWRITE */
  651.  
  652. /**
  653.  * Scale by a factor of 3 a row of pixels of 8 bits.
  654.  * The function is implemented in C.
  655.  * The pixels over the left and right borders are assumed of the same color of
  656.  * the pixels on the border.
  657.  * \param src0 Pointer at the first pixel of the previous row.
  658.  * \param src1 Pointer at the first pixel of the current row.
  659.  * \param src2 Pointer at the first pixel of the next row.
  660.  * \param count Length in pixels of the src0, src1 and src2 rows.
  661.  * It must be at least 2.
  662.  * \param dst0 First destination row, triple length in pixels.
  663.  * \param dst1 Second destination row, triple length in pixels.
  664.  * \param dst2 Third destination row, triple length in pixels.
  665.  */
  666. void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count)
  667. {
  668. #ifdef USE_SCALE_RANDOMWRITE
  669.         scale3x_8_def_whole(dst0, dst1, dst2, src0, src1, src2, count);
  670. #else
  671.         scale3x_8_def_border(dst0, src0, src1, src2, count);
  672.         scale3x_8_def_center(dst1, src0, src1, src2, count);
  673.         scale3x_8_def_border(dst2, src2, src1, src0, count);
  674. #endif
  675. }
  676.  
  677. /**
  678.  * Scale by a factor of 3 a row of pixels of 16 bits.
  679.  * This function operates like scale3x_8_def() but for 16 bits pixels.
  680.  * \param src0 Pointer at the first pixel of the previous row.
  681.  * \param src1 Pointer at the first pixel of the current row.
  682.  * \param src2 Pointer at the first pixel of the next row.
  683.  * \param count Length in pixels of the src0, src1 and src2 rows.
  684.  * It must be at least 2.
  685.  * \param dst0 First destination row, triple length in pixels.
  686.  * \param dst1 Second destination row, triple length in pixels.
  687.  * \param dst2 Third destination row, triple length in pixels.
  688.  */
  689. void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count)
  690. {
  691. #ifdef USE_SCALE_RANDOMWRITE
  692.         scale3x_16_def_whole(dst0, dst1, dst2, src0, src1, src2, count);
  693. #else
  694.         scale3x_16_def_border(dst0, src0, src1, src2, count);
  695.         scale3x_16_def_center(dst1, src0, src1, src2, count);
  696.         scale3x_16_def_border(dst2, src2, src1, src0, count);
  697. #endif
  698. }
  699.  
  700. /**
  701.  * Scale by a factor of 3 a row of pixels of 32 bits.
  702.  * This function operates like scale3x_8_def() but for 32 bits pixels.
  703.  * \param src0 Pointer at the first pixel of the previous row.
  704.  * \param src1 Pointer at the first pixel of the current row.
  705.  * \param src2 Pointer at the first pixel of the next row.
  706.  * \param count Length in pixels of the src0, src1 and src2 rows.
  707.  * It must be at least 2.
  708.  * \param dst0 First destination row, triple length in pixels.
  709.  * \param dst1 Second destination row, triple length in pixels.
  710.  * \param dst2 Third destination row, triple length in pixels.
  711.  */
  712. void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count)
  713. {
  714. #ifdef USE_SCALE_RANDOMWRITE
  715.         scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src2, count);
  716. #else
  717.         scale3x_32_def_border(dst0, src0, src1, src2, count);
  718.         scale3x_32_def_center(dst1, src0, src1, src2, count);
  719.         scale3x_32_def_border(dst2, src2, src1, src0, count);
  720. #endif
  721. }
  722.  
  723.