summaryrefslogtreecommitdiffstats
path: root/apps/recorder/resize.h
blob: 4ea4eaa9a06dff9e72c58fc74495e1abef913c3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2008 by Akio Idehara
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/
#ifndef _RESIZE_H_
#define _RESIZE_H_
#include "config.h"
#include "lcd.h"
#include "inttypes.h"

/****************************************************************
 * resize_on_load()
 *
 * resize bitmap on load with scaling
 *
 * If HAVE_LCD_COLOR then this func use smooth scaling algorithm
 * - downscaling both way use "Area Sampling"
 *   if IMG_RESIZE_BILINER or IMG_RESIZE_NEAREST is NOT set
 * - otherwise "Bilinear" or "Nearest Neighbour"
 *
 * If !(HAVE_LCD_COLOR) then use simple scaling algorithm "Nearest Neighbour"
 * 
 * return -1 for error
 ****************************************************************/

/* nothing needs the on-stack buffer right now */
#define MAX_SC_STACK_ALLOC 0
#define HAVE_UPSCALER 1

#if defined(CPU_COLDFIRE)
#define SC_NUM 0x80000000U
#define SC_MUL_INIT \
    unsigned long macsr_st = coldfire_get_macsr(); \
    coldfire_set_macsr(EMAC_UNSIGNED);
#define SC_MUL_END coldfire_set_macsr(macsr_st);
#define SC_MUL(x, y) \
({ \
    unsigned long t; \
    asm ("mac.l    %[a], %[b], %%acc0\n\t" \
         "move.l %%accext01, %[t]\n\t" \
         "move.l #0, %%acc0\n\t" \
         : [t] "=r" (t) : [a] "r" (x), [b] "r" (y)); \
    t; \
})
#elif (CONFIG_CPU == SH7034)
/* multiply two unsigned 32 bit values and return the top 32 bit
 * of the 64 bit result */
static inline unsigned sc_mul32(unsigned a, unsigned b)
{
    unsigned r, t1, t2, t3;

    asm (
        "swap.w  %[a], %[t1]     \n" /* t1 = ba */
        "mulu    %[t1], %[b]     \n" /* a * d */
        "swap.w  %[b], %[t3]     \n" /* t3 = dc */
        "sts     macl, %[t2]     \n" /* t2 = a * d */
        "mulu    %[t1], %[t3]    \n" /* a * c */
        "sts     macl, %[r]      \n" /* hi = a * c */
        "mulu    %[a], %[t3]     \n" /* b * c */
        "clrt                    \n"
        "sts     macl, %[t3]     \n" /* t3 = b * c */
        "addc    %[t2], %[t3]    \n" /* t3 += t2, carry -> t2 */
        "movt    %[t2]           \n"
        "mulu    %[a], %[b]      \n" /* b * d */
        "mov     %[t3], %[t1]    \n" /* t1t3 = t2t3 << 16 */
        "xtrct   %[t2], %[t1]    \n"
        "shll16  %[t3]           \n"
        "sts     macl, %[t2]     \n" /* lo = b * d */
        "clrt                    \n" /* hi.lo += t1t3 */
        "addc    %[t3], %[t2]    \n"
        "addc    %[t1], %[r]     \n"
        : /* outputs */
        [r] "=&r"(r),
        [t1]"=&r"(t1),
        [t2]"=&r"(t2),
        [t3]"=&r"(t3)
        : /* inputs */
        [a] "r"  (a),
        [b] "r"  (b)
    );
    return r;
}
#define SC_MUL(x, y) sc_mul32(x, y)
#define SC_MUL_INIT
#define SC_MUL_END
#endif

#ifndef SC_SHIFT
#define SC_SHIFT 32
#endif

#if SC_SHIFT == 24
#define SC_NUM 0x1000000U
#define SC_FIX 0

#ifndef SC_MUL
#define SC_MUL(x, y) ((x) * (y) >> 24)
#define SC_MUL_INIT
#define SC_MUL_END
#endif

#else /* SC_SHIFT == 32 */
#define SC_NUM 0x80000000U
#define SC_FIX 1

#ifndef SC_MUL
#define SC_MUL(x, y) ((x) * (uint64_t)(y) >> 32)
#define SC_MUL_INIT
#define SC_MUL_END
#endif

#endif

struct img_part {
    int len;
#if !defined(HAVE_LCD_COLOR)    
    uint8_t *buf;
#else
    struct uint8_rgb* buf;
#endif
};

#ifdef HAVE_LCD_COLOR
/* intermediate type used by the scaler for color output. greyscale version
   uses uint32_t
*/
struct uint32_rgb {
    uint32_t r;
    uint32_t g;
    uint32_t b;
};
#endif

/* struct which contains various parameters shared between vertical scaler,
   horizontal scaler, and row output
*/
struct scaler_context {
    uint32_t divisor;
    uint32_t round;
    struct bitmap *bm;
    struct dim *src;
    unsigned char *buf;
    bool dither;
    int len;
    void *args;
    struct img_part* (*store_part)(void *);
    void (*output_row)(uint32_t,void*,struct scaler_context*);
    bool (*h_scaler)(void*,struct scaler_context*, bool);
};

struct custom_format {
    void (*output_row)(uint32_t,void*,struct scaler_context*);
    unsigned int (*get_size)(struct bitmap *bm);
};

struct rowset;
int recalc_dimension(struct dim *dst, struct dim *src);

int resize_on_load(struct bitmap *bm, bool dither,
                   struct dim *src, struct rowset *tmp_row,
                   unsigned char *buf, unsigned int len,
                   const struct custom_format *cformat,
                   struct img_part* (*store_part)(void *args),
                   void *args);

#endif /* _RESIZE_H_ */