1 /*
2 Internal image format.
3 
4 The count of pixelels in a pixel depends on the format type.
5 The engine uses a struct that tells where Pixelels are in an internal Pixel.
6 The internal Pixel aggregates color, mask, and map pixelels; for memory locality.
7 
8   Copyright (C) 2010, 2011  Lloyd Konneker
9 
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2 of the License, or
13   (at your option) any later version.
14 
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19 
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24 
25 // Compiling switch #defines
26 #include "buildSwitches.h"
27 #ifdef SYNTH_USE_GLIB
28   // Use glib via gimp.h
29   #include <libgimp/gimp.h>
30 #else
31   #include "glibProxy.h"
32 #endif
33 
34 #include "imageSynthConstants.h"
35 #include "engineParams.h"
36 #include "imageFormat.h"
37 #include "imageFormatIndicies.h"
38 
39 extern unsigned int
countPixelelsPerPixelForFormat(TImageFormat format)40 countPixelelsPerPixelForFormat(
41   TImageFormat format // IN
42   )
43 {
44 switch (format) {
45   case T_RGB:
46     return 3;
47   case T_RGBA:
48     return 4;
49   case T_Gray:
50     return 1;
51   case T_GrayA:
52     return 2;
53   default:
54     return 0; // Unhandled format type
55   }
56 }
57 
58 
59 /*
60 Generate a TFormatIndices struct from a format code.
61 
62 This is only for adapting to the SimpleAPI.
63 When adapting from Gimp, formatIndices is generated another way.
64 */
65 extern int
prepareImageFormatIndicesFromFormatType(TFormatIndices * formatIndices,TImageFormat format)66 prepareImageFormatIndicesFromFormatType(
67   TFormatIndices* formatIndices,  // OUT
68   TImageFormat format
69   )
70 {
71   switch (format) {
72   case T_RGB:
73     prepareImageFormatIndices( formatIndices,
74       3,    // count color pixelels
75       0,    // no map colors
76       FALSE, // is_alpha_target,
77       FALSE, // is_alpha_source,
78       FALSE // isMap
79       );
80     break;
81   case T_RGBA:
82     prepareImageFormatIndices( formatIndices,
83       3,    // count color pixelels
84       0,    // no map colors
85       TRUE, // is_alpha_target,
86       // Since we are adapting by duplicating, if target has alpha, so does source
87       TRUE, // is_alpha_source,
88       FALSE // isMap
89       );
90     break;
91   case T_Gray:
92     prepareImageFormatIndices( formatIndices,
93       1,    // count color pixelels
94       0,    // no map colors
95       FALSE, // is_alpha_target,
96       FALSE, // is_alpha_source,
97       FALSE // isMap
98       );
99     break;
100   case T_GrayA:
101     prepareImageFormatIndices( formatIndices,
102       1,    // count color pixelels
103       0,    // no map colors
104       TRUE, // is_alpha_target,
105       TRUE, // is_alpha_source,
106       FALSE // isMap
107       );
108     break;
109   default:
110     return IMAGE_SYNTH_ERROR_INVALID_IMAGE_FORMAT;
111   }
112   return 0;
113 }
114 
115 
116 void
prepareImageFormatIndices(TFormatIndices * indices,guint count_color_channels_target,guint count_color_channels_map,gboolean is_alpha_target,gboolean is_alpha_source,gboolean isMap)117 prepareImageFormatIndices(
118   TFormatIndices* indices,  // OUT
119   guint count_color_channels_target,  // Must be same count in source
120   guint count_color_channels_map,
121   gboolean is_alpha_target,
122   gboolean is_alpha_source,
123   gboolean isMap
124   )
125 {
126   /*
127   Dynamic counts and indexes of pixelels.  Depends on the in drawables.
128   !!! These are the same for target and corpus, even if the in drawables differ in alphas.
129   !!! See resynth_types.h.
130   bpp means bytes per pixel
131   bip means byte index in pixel
132   !!! Note the end is not the index of the last, but the index after the last
133 
134   [0]                         mask pixelel
135   [1,colorEndBip)           image color pixelels, up to 3 (RGB)
136   optional alpha byte
137   [map_start_bip, total_bpp)  map color pixelels
138   optional map alpha byte     !!! discard
139   [0, total_bpp)              entire pixel
140 
141   [1, colorEndBip)  color pixelels compared
142   [map_start_bip, map_end_bip)      map pixelels compared
143 
144   Examples:
145   RGBA with RGB maps                RGB with GRAY maps                RGB with no maps
146   0 Mask (selection)                M                                 M
147   1 R FIRST_PIXELEL_INDEX           R FIRST_PIXELEL_INDEX             R
148   2 G                               G                                 G
149   3 B                               B                                 B
150   4 A alpha_bip, colorEndBip      W colorEndBip, map_start_bip   4  color_end, map_start, map_end, total
151   5 R map_start_bip                5  map_end_bip, total_bpp
152   6 G
153   7 B
154   8   map_end_bip, total_bpp
155 
156   !!! alpha_bip is undefined unless is_alpha_corpus or is_alpha_target
157 
158   TODO Possibly pad pixel to size 8 for memory alignment, especially if vectorized.
159   */
160 
161   /* !!! Not drawable->bpp because it includes other channels. */
162   /* Don't compare alpha */
163   //img_match_bpp = count_color_channels_target;
164   indices->img_match_bpp = count_color_channels_target;
165 
166   /* Index of first color pixelel: 1, follows mask, use constant FIRST_PIXELEL_INDEX */
167   guint colorEndBip = FIRST_PIXELEL_INDEX + indices->img_match_bpp;
168   indices->colorEndBip = colorEndBip;
169 
170   if ( is_alpha_target || is_alpha_source )
171   {
172     /* Allocate a pixelel for alpha. */
173     //alpha_bip = colorEndBip;
174     //map_start_bip = 1 + colorEndBip;
175     indices->alpha_bip = colorEndBip;
176     indices->map_start_bip = 1 + colorEndBip;
177   }
178   else
179     /* alpha_bip is undefined. */
180     //map_start_bip = colorEndBip;
181     indices->map_start_bip = colorEndBip;
182 
183   /* Count pixelels to compare in maps. */
184   if ( isMap )
185   {
186     /*
187     Either, none, or both maps can have alpha, but it is discarded.
188     Both maps must have same count color pixelels, checked earlier.
189     */
190     //map_match_bpp = count_color_channels_map;
191     indices->map_match_bpp = count_color_channels_map;
192   }
193   else
194     //map_match_bpp =0;
195     indices->map_match_bpp =0;
196 
197   //map_end_bip   = map_start_bip + map_match_bpp;
198   //total_bpp  = map_end_bip;
199   indices->map_end_bip   = indices->map_start_bip + indices->map_match_bpp;
200   indices->total_bpp  = indices->map_end_bip;
201 
202   indices->isAlphaTarget = is_alpha_target;
203   indices->isAlphaSource = is_alpha_source;
204 
205   // The patch struct has a limit on pixelels per pixel
206   g_assert( indices->total_bpp <= MAX_IMAGE_SYNTH_BPP);
207 }
208 
209 
210 // Test harness setter of pixel indices
211 void
prepareDefaultFormatIndices(TFormatIndices * formatIndices)212 prepareDefaultFormatIndices(
213   TFormatIndices* formatIndices
214   )
215   /*
216   Default is RGBA
217   For testing.
218 
219   Engine internal pixel is:
220   MRGBA
221   012345
222   */
223 {
224 // !!! MASK_PIXELEL_INDEX is a constant (0); mask pixelel is first, always.
225 
226 formatIndices->img_match_bpp = 3;  // Match RGB but not A
227 formatIndices->colorEndBip = 4;  // Pixelels 1-3 (2nd through 4th)
228 formatIndices->alpha_bip = 4;			// Alpha bip must be defined: read but not synthesize
229 formatIndices->map_match_bpp = 0;  // No map pixelels
230 formatIndices->map_start_bip = 5;
231 formatIndices->map_end_bip = 5;
232 
233 formatIndices->total_bpp = 5;
234 
235 formatIndices->isAlphaTarget = TRUE; // Does target have alpha?
236 formatIndices->isAlphaSource = TRUE;
237 
238 // !!! isMap is not a field of format indices, use map_match_bpp
239 }
240 
241 
242