Skip to main content

xcf_rs/
create.rs

1use std::fs::File;
2use std::io::Write;
3use std::path::PathBuf;
4
5use byteorder::{BigEndian, ByteOrder};
6
7extern crate hex_slice;
8use hex_slice::AsHex;
9
10use crate::data::color::ColorType;
11use crate::data::layer::Layer;
12use crate::data::property::Property;
13use crate::data::property::PropertyPayload;
14use crate::data::xcf::XcfCompression;
15use crate::data::tiles::Tiles;
16use crate::LayerColorValue;
17use crate::PropertyIdentifier;
18use crate::RgbaPixel;
19
20pub struct XcfCreator {
21    pub version: u16,
22    pub data: Vec<u8>,
23    pub index: u64,
24    pub compression: XcfCompression,
25}
26
27//impl Creator for Xcf {
28impl XcfCreator {
29    fn extend_u32(&mut self, value: u32) {
30        let mut width_buf = vec![0; 4];
31        BigEndian::write_u32(&mut width_buf, value);
32        self.data.extend_from_slice(&width_buf);
33        self.index += 4;
34    }
35
36    fn extend_u64(&mut self, value: u64) {
37        let mut width_buf = vec![0; 8];
38        BigEndian::write_u64(&mut width_buf, value);
39        self.data.extend_from_slice(&width_buf);
40        self.index += 8;
41    }
42
43    fn buf_extend_u32(&mut self, data: &mut Vec<u8>, index: &mut u32, value: u32) {
44        let size = 4;
45        let mut width_buf = vec![0; size];
46        BigEndian::write_u32(&mut width_buf, value);
47        data.extend_from_slice(&width_buf);
48        *index += size as u32;
49    }
50
51    fn buf_extend_u64(&mut self, data: &mut Vec<u8>, index: &mut u32, value: u64) {
52        let size = 8;
53        let mut width_buf = vec![0; size];
54        BigEndian::write_u64(&mut width_buf, value);
55        data.extend_from_slice(&mut width_buf);
56        *index += size as u32;
57    }
58
59    fn create_signature(&mut self, gimp_version: u16) {
60        let mut signature = format!("gimp xcf v{:03}\0", gimp_version);
61        if gimp_version == 1 {
62            signature = "gimp xcf file\0".to_string();
63        }
64        self.data.extend_from_slice(signature.as_bytes());
65        self.index += 14;
66    }
67
68    fn v10_gimp_string(&mut self, data: &mut Vec<u8>, index: &mut u32, str: &[u8]) {
69        let str_count = str.len() as u32;
70        self.buf_extend_u32(data, index, str_count + 4);
71        data.extend_from_slice(str);
72        *index += str_count;
73        self.buf_extend_u32(data, index, 0);
74    }
75
76    fn gimp_string(&mut self, data: &mut Vec<u8>, index: &mut u32, str: &[u8]) {
77        let str_count = str.len() as u32 + 1;
78        self.buf_extend_u32(data, index, str_count);
79        data.extend_from_slice(str);
80        data.extend_from_slice(&[0]);
81        *index += str_count;
82    }
83
84    fn parasite_prop(&mut self, data: &mut Vec<u8>, index: &mut u32, parasite_title: &str, parasite_data: &str, flags: u32) {
85        let title_len = parasite_title.len() + 1;
86        self.buf_extend_u32(data, index, title_len as u32);
87        data.extend_from_slice(parasite_title.as_bytes());
88        data.extend_from_slice(&[0]);
89        *index += title_len as u32;
90        self.buf_extend_u32(data, index,flags);
91
92        let data_len = parasite_data.len() + 1;
93        self.buf_extend_u32(data, index,data_len as u32);
94        data.extend_from_slice(parasite_data.as_bytes());
95        data.extend_from_slice(&[0]);
96        *index += data_len as u32;
97    }
98
99    pub fn new(version: u16, width: u32, height: u32, color_type: ColorType) -> Self {
100        let data = vec![];
101        let index = 0;
102
103        let mut _self = XcfCreator {
104            version,
105            data,
106            index,
107            compression: XcfCompression::None,
108        };
109        _self.create_signature(version);
110        _self.extend_u32(width);
111        _self.extend_u32(height);
112        _self.extend_u32(color_type as u32);
113
114        if version >= 4 {
115            _self.extend_u32(150); // 8-bit gamma integer
116        }
117
118        _self
119    }
120
121    fn prop_end(&mut self, data: &mut Vec<u8>, index: &mut u32) {
122        self.buf_extend_u32(data, index, 0);
123        self.buf_extend_u32(data, index, 0);
124        //self.extend_u64(0); // prop : End + size : 0
125    }
126
127    pub fn add_properties(&mut self, properties: &Vec<Property>) {
128        let mut _has_compression = false;
129        for property in properties {
130            self.extend_u32(property.kind as u32);
131            match &property.payload {
132                PropertyPayload::Compression(_value) => {
133                    self.extend_u32(property.length as u32); // size
134
135                    self.data.extend_from_slice(&[_value.to_u8()]);
136                    self.index += 1;
137                    self.compression = _value.clone();
138                    _has_compression = true;
139                }
140                PropertyPayload::ResolutionProperty(_value) => {
141                    self.extend_u32(property.length as u32); // size
142
143                    self.extend_u32(_value.xres.to_bits()); // X resolution in DPI
144                    self.extend_u32(_value.yres.to_bits()); // Y resolution in DPI
145                }
146                PropertyPayload::Tatoo(_value) | PropertyPayload::Unit(_value) => {
147                    self.extend_u32(property.length as u32); // size
148
149                    self.extend_u32(*_value);
150                }
151                PropertyPayload::Parasites(_parasites) => {
152                    let mut parasite_prop_buf = vec![];
153                    let mut parasite_prop_len = 0;
154                    for parasite in _parasites {
155                        self.parasite_prop(
156                            &mut parasite_prop_buf, 
157                            &mut parasite_prop_len, 
158                            &parasite.name,
159                            &parasite.data,
160                            parasite.flags
161                        );
162                    }
163                    self.extend_u32(parasite_prop_len); // size
164                    self.data.extend_from_slice(&parasite_prop_buf);
165                    self.index += parasite_prop_len as u64;
166                }
167                _ => {
168                    self.extend_u32(property.length as u32); // size
169                }
170            }
171        }
172        if self.version > 10 && !_has_compression {
173            self.extend_u32(PropertyIdentifier::PropCompression as u32);
174            self.extend_u32(1); // size
175            self.data.extend_from_slice(&[XcfCompression::Rle as u8]);
176            self.index += 1;
177            self.compression = XcfCompression::Rle;
178
179            // resolution
180            self.extend_u32(PropertyIdentifier::PropResolution as u32);
181            self.extend_u32(8); // size
182            let value: f32 = 300.0;
183            self.extend_u32(value.to_bits()); // X resolution in DPI
184            self.extend_u32(value.to_bits()); // Y resolution in DPI
185
186            // tatoo
187            self.extend_u32(PropertyIdentifier::PropTattoo as u32);
188            self.extend_u32(4); // size
189            self.extend_u32(2);
190
191            // unit
192            self.extend_u32(PropertyIdentifier::PropUnit as u32);
193            self.extend_u32(4); // size
194            self.extend_u32(1);
195
196            // parasites
197            let mut parasite_prop_buf = vec![];
198            let mut parasite_prop_len = 0;
199            self.parasite_prop(
200                &mut parasite_prop_buf, 
201                &mut parasite_prop_len, 
202                "gimp-comment", 
203                //"Created with GIMP",
204                "Test Comment",
205                1
206            );
207            self.parasite_prop(
208                &mut parasite_prop_buf, 
209                &mut parasite_prop_len, 
210                "gimp-image-grid", 
211                "(style solid)\n(fgcolor (color-rgba 0 0 0 1))\n(bgcolor (color-rgba 1 1 1 1))\n(xspacing 10)\n(yspacing 10)\n(spacing-unit inches)\n(xoffset 0)\n(yoffset 0)\n(offset-unit inches)\n",
212                1
213            );
214            self.extend_u32(PropertyIdentifier::PropParasites as u32);
215            self.extend_u32(parasite_prop_len); // size
216            self.data.extend_from_slice(&parasite_prop_buf);
217            self.index += parasite_prop_len as u64;
218        }
219
220        // TODO : replace by : self.propend()
221        self.extend_u32(0);
222        self.extend_u32(0);
223    }
224
225    fn _add_layers_properties(&mut self, data: &mut Vec<u8>, index: &mut u32, layers_properties: &Vec<Property>) {
226        for layer_property in layers_properties {
227            self.buf_extend_u32(data, index, layer_property.kind as u32);
228            self.buf_extend_u32(data, index, layer_property.length as u32); // size
229            match &layer_property.payload {
230                PropertyPayload::Compression(_value) => {
231                    data.extend_from_slice(&[_value.to_u8()]);
232                    *index += 1;
233                }
234                PropertyPayload::OpacityLayer(_value) => {
235                    data
236                        .extend_from_slice(&[_value.r(), _value.g(), _value.b(), _value.a()]);
237                    *index += 4;
238                }
239                PropertyPayload::FloatOpacityLayer() => {
240                    // TODO : à améliorer, ça doit être une valeur en float
241                    let float_slice = [63, 128, 0, 0];
242                    data.extend_from_slice(&float_slice); // prop float opacity value
243                    *index += 4;
244                }
245                PropertyPayload::VisibleLayer() => {
246                    let float_slice = [0, 0, 0, 1];
247                    data.extend_from_slice(&float_slice); // prop visible value
248                    *index += 4;
249                }
250                PropertyPayload::OffsetsLayer(_offset_x, _offset_y) => {
251                    self.buf_extend_u32(data, index, *_offset_x);
252                    self.buf_extend_u32(data, index, *_offset_y);
253                }
254                PropertyPayload::LinkedLayer(_value)
255                | PropertyPayload::ColorTagLayer(_value)
256                | PropertyPayload::LockContentLayer(_value)
257                | PropertyPayload::LockAlphaLayer(_value)
258                | PropertyPayload::LockPositionLayer(_value)
259                | PropertyPayload::ApplyMaskLayer(_value)
260                | PropertyPayload::EditMaskLayer(_value)
261                | PropertyPayload::ShowMaskLayer(_value)
262                | PropertyPayload::ModeLayer(_value)
263                | PropertyPayload::BlendSpaceLayer(_value)
264                | PropertyPayload::CompositeSpaceLayer(_value)
265                | PropertyPayload::CompositeModeLayer(_value)
266                | PropertyPayload::Tatoo(_value) => {
267                    self.buf_extend_u32(data, index, *_value);
268                }
269                _ => {}
270            }
271        }
272        if self.version > 10 && layers_properties.iter().len() == 0 {
273            // active
274            self.buf_extend_u32(data, index, PropertyIdentifier::PropActiveLayer as u32);
275            self.buf_extend_u32(data, index, 0);
276            // opacity
277            self.buf_extend_u32(data, index, PropertyIdentifier::PropOpacity as u32);
278            self.buf_extend_u32(data, index, 4);
279            data.extend_from_slice(&[0, 0, 0, 255]);
280            *index += 4;
281            // float opacity
282            self.buf_extend_u32(data, index, PropertyIdentifier::PropFloatOpacity as u32);
283            self.buf_extend_u32(data, index, 4);
284            let float_slice = [63, 128, 0, 0];
285            data.extend_from_slice(&float_slice); // prop float opacity value
286            *index += 4;
287            // visible
288            self.buf_extend_u32(data, index, PropertyIdentifier::PropVisible as u32);
289            self.buf_extend_u32(data, index, 4);
290            let float_slice = [0, 0, 0, 1];
291            data.extend_from_slice(&float_slice); // prop visible value
292            *index += 4;
293
294            // linked
295            self.buf_extend_u32(data, index, PropertyIdentifier::PropLinked as u32);
296            self.buf_extend_u32(data, index, 4);
297            self.buf_extend_u32(data, index, 0);
298
299            // color tag
300            self.buf_extend_u32(data, index, PropertyIdentifier::PropColorTag as u32);
301            self.buf_extend_u32(data, index, 4);
302            self.buf_extend_u32(data, index, 0);
303
304            // lock content
305            self.buf_extend_u32(data, index, PropertyIdentifier::PropLockContent as u32);
306            self.buf_extend_u32(data, index, 4);
307            self.buf_extend_u32(data, index, 0);
308
309            // lock alpha
310            self.buf_extend_u32(data, index, PropertyIdentifier::PropLockAlpha as u32);
311            self.buf_extend_u32(data, index, 4);
312            self.buf_extend_u32(data, index, 0);
313
314            // lock position
315            self.buf_extend_u32(data, index, PropertyIdentifier::PropLockPosition as u32);
316            self.buf_extend_u32(data, index, 4);
317            self.buf_extend_u32(data, index, 0);
318
319            // apply mask
320            self.buf_extend_u32(data, index, PropertyIdentifier::PropApplyMask as u32);
321            self.buf_extend_u32(data, index, 4);
322            self.buf_extend_u32(data, index, 0);
323
324            // edit mask
325            self.buf_extend_u32(data, index, PropertyIdentifier::PropEditMask as u32);
326            self.buf_extend_u32(data, index, 4);
327            self.buf_extend_u32(data, index, 0);
328
329            // show mask
330            self.buf_extend_u32(data, index, PropertyIdentifier::PropShowMask as u32);
331            self.buf_extend_u32(data, index, 4);
332            self.buf_extend_u32(data, index, 0);
333
334            // offsets
335            self.buf_extend_u32(data, index, PropertyIdentifier::PropOffsets as u32);
336            self.buf_extend_u32(data, index, 8);
337            self.buf_extend_u32(data, index, 0);
338            self.buf_extend_u32(data, index, 0);
339
340            // if version >= 11, than the layer mode must be the new normal mode (not legacy)
341            self.buf_extend_u32(data, index, PropertyIdentifier::PropMode as u32);
342            self.buf_extend_u32(data, index, 4); // size
343            self.buf_extend_u32(data, index, 28); // mode normal after version 10
344
345            // blend space
346            self.buf_extend_u32(data, index, PropertyIdentifier::PropBlendSpace as u32);
347            self.buf_extend_u32(data, index, 4);
348            self.buf_extend_u32(data, index, 0);
349
350            // composite space
351            self.buf_extend_u32(data, index, PropertyIdentifier::PropCompositeSpace as u32);
352            self.buf_extend_u32(data, index, 4);
353            self.buf_extend_u32(data, index, u32::MAX);
354
355            // composite mode
356            self.buf_extend_u32(data, index, PropertyIdentifier::PropCompositeMode as u32);
357            self.buf_extend_u32(data, index, 4);
358            self.buf_extend_u32(data, index, u32::MAX);
359
360            // tatoo
361            self.buf_extend_u32(data, index, PropertyIdentifier::PropTattoo as u32);
362            self.buf_extend_u32(data, index, 4);
363            self.buf_extend_u32(data, index, 2);
364        }
365        self.prop_end(data, index);
366    }
367
368    fn _add_layers_v10(&mut self, _layers: &[Layer]) {
369        let mut intermediate_buf = vec![];
370        let mut layer_offset_zero_index = 0;
371
372        self.buf_extend_u32(&mut intermediate_buf, &mut layer_offset_zero_index, 0); // layer_offset[n] : 0 = end
373        self.buf_extend_u32(&mut intermediate_buf, &mut layer_offset_zero_index, 0); // channel_offset[] = 0 => end
374
375        self.index += layer_offset_zero_index as u64;
376
377        let mut layer_offset_one_buf = vec![];
378        let mut layer_offset_one_index = 0;
379
380        self.buf_extend_u32(
381            &mut layer_offset_one_buf,
382            &mut layer_offset_one_index,
383            self.index as u32 + 4,
384        ); // layer_offset[0] = le pointer du calque
385
386        layer_offset_one_buf.extend_from_slice(&intermediate_buf);
387        self.data.extend_from_slice(&layer_offset_one_buf);
388        self.index += layer_offset_one_index as u64;
389
390        self.extend_u32(1); // layer[0] : width=1
391        self.extend_u32(1); // layer[0] : height=1
392        self.extend_u32(0); // layer[0] : type=RGB
393
394        // layer name :
395        let mut layer_name_data = vec!();
396        let mut layer_name_len = 0;
397        self.v10_gimp_string(&mut layer_name_data, &mut layer_name_len, b"Background");
398        self.data.extend_from_slice(&layer_name_data);
399        self.index += layer_name_len as u64;
400
401        self.extend_u32(PropertyIdentifier::PropActiveLayer as u32); // prop = 2 : active layer
402        self.extend_u32(0);
403
404        self.extend_u32(PropertyIdentifier::PropOpacity as u32); // prop : opacity
405        self.extend_u32(4); // prop opacity size
406        self.extend_u32(RgbaPixel::new(0, 0, 0, 255).to_u32()); // color of opacity = black
407
408        self.extend_u32(PropertyIdentifier::PropMode as u32); // prop : Mode
409        self.extend_u32(4); // prop mode size
410        self.extend_u32(0); // prop mode=normal
411
412        // TODO : à améliorer, ça doit être une valeur en float
413        self.extend_u32(PropertyIdentifier::PropFloatOpacity as u32); // prop : float opacity
414        self.extend_u32(4); // prop float opacity size
415        let float_slice = [63, 128, 0, 0];
416        self.data.extend_from_slice(&float_slice); // prop float opacity value
417        self.index += 4;
418
419        self.extend_u32(PropertyIdentifier::PropVisible as u32); // prop : visible
420        self.extend_u32(4); // prop visible size
421        let float_slice = [0, 0, 0, 1];
422        self.data.extend_from_slice(&float_slice); // prop visible value
423        self.index += 4;
424
425        self.extend_u32(PropertyIdentifier::PropLinked as u32); // prop : linked
426        self.extend_u32(4); // prop linked size
427        self.extend_u32(0); // prop linked value
428
429
430        // TODO : replace by : self.propend()
431        self.extend_u32(0);
432        self.extend_u32(0);
433
434        // hierarchy offset
435        self.extend_u32(self.index as u32 + 8);
436        self.extend_u32(0); // mask offset
437
438        // https://testing.developer.gimp.org/core/standards/xcf/#the-hierarchy-structure
439        self.extend_u32(1); // width=1
440        self.extend_u32(1); // height=1
441        self.extend_u32(3); // bpp=3 : RGB color without alpha in 8-bit precision
442
443        self.extend_u32(self.index as u32 + 8); // offset[0]
444
445        self.extend_u32(0); // offset[n] = 0 => end
446
447        self.extend_u32(1); // level[0] width =1
448        self.extend_u32(1); // level[0] height =1
449        self.extend_u32(self.index as u32 + 8); // offset= le pointer du contenu
450
451        self.extend_u32(0); // data_offset[0] = 0 => end
452
453        //let slice = [00, 158, 00, 36, 00, 222]; // violet r: 158, g: 23, b: 222  with RLE compression
454        let slice = [158, 36, 222]; // violet r: 158, g: 36, b: 222  without compression
455
456        // \0\0\2\xa4\0\0\0\0\0\0\0\0\0\x9e
457        self.data.extend_from_slice(&slice);
458    }
459
460    pub fn add_layers(&mut self, layers: &Vec<Layer>) {
461        if self.version < 11 {
462            self._add_layers_v10(layers);
463            return;
464        }
465        let nb_layers = layers.iter().len();
466
467        let mut layer_data = vec![];
468        let mut layer_index = 0;
469        for layer in layers {
470            layer_index += 1;
471            let mut layer_len = 0;
472
473            let tiles = Tiles::new(layer);
474
475            // Each layers is 8 bits + 8 bits for close layers + 8 bits for close channels
476            let layer_offset = self.index + (nb_layers - layer_index + 1) as u64 * 8 + layer_len as u64 + 16;
477            /*
478            println!(
479                "layer[{}] >>>> self.index : {} ---- layer_index {} ---- nb_layers {} layer_len {} ===> {}",
480                layer_index - 1,
481                self.index,
482                layer_index,
483                nb_layers,
484                layer_len,
485                layer_offset
486            );
487            */
488            self.extend_u64(layer_offset); // layer_offset[index -1]
489            //self.buf_extend_u64(&mut layer_data, &mut layer_len, pos_layer); // layer_offset[index -1]
490
491            self.buf_extend_u32(&mut layer_data, &mut layer_len, layer.width);
492            self.buf_extend_u32(&mut layer_data, &mut layer_len, layer.height);
493            self.buf_extend_u32(&mut layer_data, &mut layer_len, layer.kind.kind.clone() as u32);
494
495            // layer name
496            self.gimp_string(&mut layer_data, &mut layer_len, layer.name.as_bytes());
497
498            // layer properties
499            self._add_layers_properties(&mut layer_data, &mut layer_len, &layer.properties);
500
501            let mut hierarchy_data = vec![];
502            let mut hierarchy_len = 0;
503            // https://testing.developer.gimp.org/core/standards/xcf/#the-hierarchy-structure
504            self.buf_extend_u32(&mut hierarchy_data, &mut hierarchy_len,layer.pixels.width); // width=1
505            self.buf_extend_u32(&mut hierarchy_data, &mut hierarchy_len,layer.pixels.height); // height=1
506
507            let layer_has_alpha = LayerColorValue::has_alpha(layer.kind.kind.clone());
508            if layer_has_alpha {
509                self.buf_extend_u32(&mut hierarchy_data, &mut hierarchy_len, 4); // bpp with alpha
510            } else {
511                self.buf_extend_u32(&mut hierarchy_data, &mut hierarchy_len, 3); // bpp without alpha
512            }
513
514            let mut tiles_headers = vec![];
515            let mut tiles_body = vec![];
516            let mut tiles_pixels: Vec<Vec<RgbaPixel>> = vec![];
517            for _x in 0..tiles.nb {
518                tiles_pixels.push(vec![]);
519            }
520
521            let mut pixel_index = 0;
522            let mut x = 0;
523            let mut y = 1;
524            for pixel in &layer.pixels.pixels {
525                pixel_index += 1;
526                x += 1;
527
528                let tile_x = (x as f32 / 64.0).ceil();
529                let tile_y = (y as f32 / 64.0).ceil();
530
531                //println!("tiles_len : {}, tile_width_nb: {}, y: {}, tile_y: {}, tile_x: {}, i: {}",
532                //    tiles.len(),
533                //    tile_width_nb,
534                //    y,
535                //    tile_y,
536                //    tile_x,
537                //    tile_width_nb as usize * (tile_y as usize - 1) + tile_x as usize - 1
538                //);
539                tiles_pixels[tiles.nb_width as usize * (tile_y as usize - 1) + tile_x as usize - 1].push(*pixel);
540
541                if pixel_index % layer.width == 0 {
542                    y += 1;
543                    x = 0;
544                }
545            }
546
547            /*
548            let mut inc = 0;
549            for _t in &tiles {
550                inc +=1;
551                println!("tile[{}] = length {}", inc, _t.len());
552                if inc == 1 {
553                    println!("tile : \n\n {:?}", tiles[0]);
554                }
555            }
556            */
557
558            if self.compression == XcfCompression::Rle {
559                /*
560                let pixels_index = self.index + layer_index as u64 * 8 + nb_layers as u64 * 8 + layer_len as u64;
561                println!(
562                    "pixels_index : {} = {}",
563                    layer_offset,
564                    pixels_index
565                );
566                */
567                let nb_of_pixels = layer.pixels.pixels.iter().len() as u32;
568                let nb_pixels_of_layers = layer.pixels.width * layer.pixels.height;
569                if nb_pixels_of_layers != nb_of_pixels {
570                    panic!(
571                        "Number of pixels on the layers {} and pixels {} aren't equals",
572                        nb_pixels_of_layers, nb_of_pixels
573                    );
574                }
575
576                //let tile_pointer_size = 8 * nb_of_tiles + 4;
577
578                let mut offset_data = vec![];
579                let mut offset_len = 0;
580                //let hierarchy_ofs = self.index + layer_index as u64 * 8 + nb_layers as u64 * 8 + 8 + layer_len as u64 + 8;
581                let hierarchy_ofs =  layer_offset + layer_len as u64 + 16;
582                //println!(
583                //    "hierarchy_ofs : {} + {} = {}",
584                //    layer_offset,
585                //    layer_len,
586                //    hierarchy_ofs
587                //);
588                self.buf_extend_u32(&mut offset_data, &mut offset_len,layer.pixels.width); // level[0] width
589                self.buf_extend_u32(&mut offset_data, &mut offset_len,layer.pixels.height); // level[0] height
590                self.buf_extend_u32(&mut offset_data, &mut offset_len,0); // ptr : Pointer to tile data
591    
592                let offset_index = hierarchy_ofs + offset_len as u64 + tiles.nb as u64 * 8 + 8;
593                //println!(
594                //    "offset_index : {} + {} + {} + 8 = offset_index = {}",
595                //    hierarchy_ofs,
596                //    offset_len,
597                //    tiles.nb,
598                //    offset_index
599                //);
600                for _tile in &tiles_pixels {
601                    self.buf_extend_u64(&mut hierarchy_data, &mut hierarchy_len, offset_index); // offset[n]
602                }
603                self.buf_extend_u64(&mut hierarchy_data, &mut hierarchy_len, 0); // offset[2]
604
605                let mut tiles_headers_len = 0;
606                for tile in &tiles_pixels {
607                    let tile_index = offset_index as u32 + 16 + tiles.nb * 8 + tiles_body.len() as u32;
608                    //println!("tile_index : {}, offset_index: {}, nb_of_tiles : {}, tiles_len : {}", tile_index, offset_index, nb_of_tiles, tiles_body.len());
609                    self.buf_extend_u32(&mut tiles_headers, &mut tiles_headers_len, tile_index);
610                    self.buf_extend_u32(&mut tiles_headers, &mut tiles_headers_len, 0);
611                    tiles_headers_len = 0;
612
613                    let mut buffer_r = vec![];
614                    let mut buffer_g = vec![];
615                    let mut buffer_b = vec![];
616                    let mut buffer_a = vec![];
617                    for pixel in tile {
618                        buffer_r.push(pixel.r());
619                        buffer_g.push(pixel.g());
620                        buffer_b.push(pixel.b());
621                        if layer_has_alpha {
622                            buffer_a.push(pixel.a());
623                        }
624                    }
625
626                    let rle_r = rle_compress(&buffer_r);
627                    //println!("buffer r : {:?}", buffer_r);
628                    //println!("rle r : {:?}\n\n", rle_r);
629                    tiles_body.extend(rle_r);
630
631                    let rle_g = rle_compress(&buffer_g);
632                    //println!("buffer g : {:?}", buffer_g);
633                    //println!("rle g : {:?}\n\n", rle_g);
634                    tiles_body.extend(rle_g);
635
636                    let  rle_b = rle_compress(&buffer_b);
637                    //println!("buffer b : {:?}", buffer_b);
638                    //println!("rle b : {:?}\n\n", rle_b);
639                    tiles_body.extend(rle_b);
640
641                    if layer_has_alpha {
642                        let rle_a = rle_compress(&buffer_a);
643                        //println!("buffer a : {:?}", buffer_a);
644                        //println!("rle a : {:?}\n\n", rle_a);
645                        tiles_body.extend(rle_a);
646                    }
647                }
648
649                hierarchy_data.extend_from_slice(&offset_data);
650                hierarchy_len += offset_len;
651
652                // hierarchy offset
653                self.buf_extend_u64(&mut layer_data, &mut layer_len, hierarchy_ofs); // hierarchy_ofs=
654                self.buf_extend_u64(&mut layer_data, &mut layer_len,0); // layer mask offset
655
656                layer_data.extend_from_slice(&hierarchy_data);
657                layer_len += hierarchy_len;
658                tiles_headers.extend_from_slice(&[0, 0, 0, 0]);
659
660                layer_data.extend_from_slice(&tiles_headers);
661                layer_data.extend_from_slice(&tiles_body);
662                layer_len += tiles_headers.len() as u32 + tiles_body.len() as u32;
663                self.index += layer_len as u64;
664            } else {
665                panic!("not implemented");
666            }
667        }
668        self.extend_u64(0); // layer_offset[1] = 0
669        self.extend_u64(0); // channel_offset[0] = 0
670        self.data.extend_from_slice(&layer_data);
671    }
672
673    pub fn save(&mut self, path: &PathBuf) -> Result<File, crate::Error> {
674        let mut new_file = File::create(&path)?;
675        new_file.write_all(self.data.as_slice())?;
676        Ok(new_file)
677    }
678}
679
680pub fn short_run_identical(verbatim: &[u8]) -> Vec<u8> {
681    println!("short run identical");
682    if verbatim.len() < 1 {
683        panic!("Wrong verbatim lengh : {}", verbatim.len());
684    }
685    vec![(verbatim.len() - 1) as u8, verbatim[0]]
686}
687
688pub fn long_run_identical(verbatim: &[u8]) -> Vec<u8> {
689    println!("long run identical");
690    if verbatim.len() < 127 {
691        panic!("Wrong verbatim lengh : {}", verbatim.len());
692    }
693    // verbatim_len = p*256+q
694    let p = verbatim.len() / 256;
695    let q = verbatim.len() % 256;
696    vec![127, p as u8, q as u8, verbatim[0]]
697}
698
699pub fn run_identical(verbatim: &[u8]) -> Vec<u8> {
700    if verbatim.len() > 126 {
701        return long_run_identical(&verbatim);
702    }
703    short_run_identical(&verbatim)
704}
705
706pub fn short_run_diff(verbatim: &[u8]) -> Vec<u8> {
707    println!("short run diff");
708    if verbatim.len() < 1 {
709        panic!("Wrong verbatim lengh : {}", verbatim.len());
710    }
711    let mut r = vec![(256 - verbatim.len()) as u8];
712    r.extend_from_slice(verbatim);
713    r
714}
715
716pub fn long_run_diff(verbatim: &[u8]) -> Vec<u8> {
717    println!("long run diff");
718    if verbatim.len() < 127 {
719        panic!("Wrong verbatim lengh : {}", verbatim.len());
720    }
721    // verbatim_len = p*256+q
722    let p = verbatim.len() / 256;
723    let q = verbatim.len() % 256;
724    let mut r = vec![128, p as u8, q as u8];
725    r.extend_from_slice(verbatim);
726    r
727}
728
729pub fn run_diff(verbatim: &[u8]) -> Vec<u8> {
730    if verbatim.len() > 126 {
731        return long_run_diff(&verbatim);
732    }
733    short_run_diff(&verbatim)
734}
735
736pub fn is_identiqual(values: &[u8]) -> bool {
737    if values.len() < 2 {
738        panic!("Wrong values lengh : {}", values.len());
739    }
740    let value = values[0];
741    for v in &values[1..values.len()] {
742        if value != *v {
743            return false;
744        }
745    }
746    return true;
747}
748
749// https://testing.developer.gimp.org/core/standards/xcf/#rle-compressed-tile-data
750pub fn rle_compress(data: &Vec<u8>) -> Vec<u8> {
751    let mut compress_data = vec![];
752    let mut verbatim: Vec<u8> = vec![];
753    let mut i = 0;
754    for byte in data {
755        i += 1;
756        verbatim.push(*byte);
757
758        if i >= data.len() - 1 {
759            break;
760        }
761        let val = *byte;
762        let mut val_last_1 = val;
763        let mut val_last_2 = val;
764        if i > 1 {
765            val_last_1 = data[i - 2];
766        }
767        if i > 2 {
768            val_last_2 = data[i - 3];
769        }
770        let val_1 = data[i];
771        let val_2 = data[i + 1];
772        let mut val_3 = val_2;
773        if i < data.len() - 2 {
774            val_3 = data[i + 2];
775        }
776
777        //println!(
778        //    "i: {}, val-2: {}, val-1: {}, val: {}, val+1: {}, val+2: {}, val+3: {}, v_len: {}",
779        //    i,
780        //    val_last_2,
781        //    val_last_1,
782        //    val,
783        //    val_1,
784        //    val_2,
785        //    val_3,
786        //    verbatim.len()
787        //);
788        if i == 2
789        && val_last_1 == val
790        && val != val_1 {
791            let buffer = short_run_identical(&verbatim);
792            compress_data.extend_from_slice(&buffer);
793            verbatim = vec![];
794            continue;
795        }
796        if i == 1
797        && val != val_1
798        && val_1 == val_2
799        && val_2 == val_3 {
800            let buffer = run_diff(&verbatim);
801            compress_data.extend_from_slice(&buffer);
802            verbatim = vec![];
803            continue;
804        }
805        if i > 2
806        && val_last_2 == val_last_1
807        && val_last_1 == val
808        && val != val_1 {
809            println!("f 2: {:?}", verbatim);
810            let buffer = run_identical(&verbatim);
811            compress_data.extend_from_slice(&buffer);
812            verbatim = vec![];
813            continue;
814        }
815
816        if i > 4  && i < data.len() - 2
817           && is_identiqual(&vec![data[i - 3], data[i - 4], data[i - 5]])
818           && val_last_1 == val
819           && val != val_1
820        {
821            println!("f 3: {:?}", verbatim);
822            let buffer = run_identical(&verbatim);
823            compress_data.extend_from_slice(&buffer);
824            verbatim = vec![];
825            continue;
826        }
827
828        if i < data.len() - 2
829        && val != val_1
830        && val_1 == val_2
831        && val_2 == val_3 {
832            println!("f 4");
833            let buffer = run_diff(&verbatim);
834            compress_data.extend_from_slice(&buffer);
835            verbatim = vec![];
836            continue;
837        }
838    }
839    verbatim.push(data[data.len() - 1]);
840    let val = verbatim[verbatim.len() - 1];
841    let mut val_last_1 = val;
842    let mut val_last_2 = val;
843    let mut val_last_3 = val;
844    if verbatim.len() > 1 {
845        val_last_1 = verbatim[verbatim.len() - 2];
846    }
847    if verbatim.len() > 2 {
848        val_last_2 = verbatim[verbatim.len() - 3];
849    }
850    if verbatim.len() > 3 {
851        val_last_3 = verbatim[verbatim.len() - 4];
852    }
853    let mut buffer;
854
855    if verbatim.len() >= 2 && val == val_last_1 && val_last_1 == val_last_2 {
856        println!("1.");
857        if data.len() == 1 {
858            buffer = vec![0, verbatim[0]];
859        } else {
860            buffer = run_identical(&verbatim);
861        }
862    } else if verbatim.len() >= 2 && val != val_last_1 && val_last_1 == val_last_2 && val_last_2 == val_last_3 {
863        println!("1.1");
864        buffer = run_identical(&verbatim[..verbatim.len() - 1]);
865        buffer.push(0);
866        buffer.push(val);
867    } else if verbatim.len() >= 2 && val == val_last_1 {
868        println!("2.");
869        //println!("2. c: {:?}, v: {:?}", compress_data, verbatim);
870        buffer = run_diff(&verbatim[..verbatim.len() - 2]);
871        buffer.push(1);
872        buffer.push(verbatim[verbatim.len() - 1]);
873    } else {
874        println!("3.");
875        buffer = run_diff(&verbatim);
876    }
877
878    compress_data.extend_from_slice(&buffer);
879    compress_data
880}