poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] pickles: Add new pickle for jpeg


From: Jose E. Marchesi
Subject: Re: [PATCH] pickles: Add new pickle for jpeg
Date: Wed, 31 Jan 2024 09:24:45 +0100
User-agent: Gnus/5.13 (Gnus v5.13)

> Hi Andreas.
>
> Thank you for sharing the draft for this pickle.
> Please find the comments below.
>
>
> On Mon, Jan 29, 2024 at 06:19:20PM +0100, Andreas Klinger wrote:
>> 2024-01-29  Andreas Klinger  <ak@it-klinger.de>
>> 
>>         * pickles/jpeg.pk: New pickle for jpeg files
>> ---
>> 
>> This is also a RFC as there is a topic i'm not completely satisfied:
>> 
>> - When uncommenting 
>>     byte[] image
>>   in JPEG_Tag it takes a long time to use the pickle.
>
>
> Yeah, that's a real problem.  One possible answer that we're thinking about
> is "lazy" arrays that will not try to map all the elements of the array and
> only map/poke/peek the content of the array when it is necessary.
>
>>   Maybe there is a better way to define it.
>
>
> The technique is to have some "marker" fields (like
> `uint<8>[0] _marker : some_constraint;') to mark the boundaries and provide
> some functions to get different view to the data when needed.
> Of course, the data format should be "good enough" to enable you to find
> the boundaries easily :)
>
> ELF is an example of a good format that gives you a table in the beginning 
> which
> enables you easily find the boundaries of different entities.
> Please see `Elf64_File' type definition in `elf-64.pk' in poke-elf pickle
> (https://jemarch.net/poke-elf.html).
>
>
> But these are "workarounds" till we implement the lazy arrays (or other
> solutions).
>
>
>> 
>> - For my purposes i don't need the image but when submitting this pickle it
>>   could be relevant to other users.
>> 
>> diff --git a/pickles/jpeg.pk b/pickles/jpeg.pk
>> new file mode 100644
>> index 00000000..ca07bf81
>> --- /dev/null
>> +++ b/pickles/jpeg.pk
>> @@ -0,0 +1,114 @@
>> +/* jpeg.pk - JPEG implementation for GNU poke */
>> +
>> +/* Copyright (C) 2024 Andreas Klinger */
>> +
>> +/* 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 3 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +/* Implemented as specified in
>> + * https://en.wikipedia.org/wiki/JPEG as well as
>> + * https://de.wikipedia.org/wiki/JPEG_File_Interchange_Format  */
>> +
>> +/* Marker of JPEG pictures
>> + * Array id 0 ("SOF0") starts at binary marker value 0xC0:
>> + *   0xC0, 0xC1, ... , 0xC7
>> + *   0xC8, 0xC1, ... , 0xCF
>> + *   0xD0, 0xD1, ... , 0xD7
>> + *   ...
>> + *   0xF8, 0xF1, ... , 0xFF
>> + */
>> +var jpeg_marker =
>> +  ["SOF0", "SOF1", "SOF2", "SOF3", "DHT", "SOF5", "SOF6", "SOF7",
>> +   "JPG", "SOF9", "SOF10", "SOF11", "DAC", "SOF13", "SOF14", "SOF15",
>> +   "-", "-", "-", "-", "-", "-", "-", "-",
>> +   "SOI", "EOI", "SOS", "DQT", "-", "DRI", "-", "-",
>> +   "APP0", "APP1", "APP2", "APP3", "APP4", "APP5", "APP6", "APP7",
>> +   "APP8", "APP9", "APP10", "APP11", "APP12", "APP13", "APP14", "APP15",
>> +   "-", "-", "-", "-", "-", "-", "-", "-",
>> +   "-", "-", "-", "-", "-", "-", "COM", "-"];
>> +
>> +type JPEG_SOI =
>> +  struct
>> +  {
>> +    byte ff = 0xFF;
>> +    byte xx = 0xD8;
>> +    method _print = void:
>> +    {
>> +      printf ("\n#<tag: %u16x\tsymbol: %s>",
>> +                        ff:::xx, jpeg_marker[xx - 0xC0]);
>> +    }
>> +  };
>> +
>> +type JPEG_SOS =
>> +  struct
>> +  {
>> +    byte ff = 0xFF;
>> +    byte xx = 0xDA;
>> +    method _print = void:
>> +    {
>> +      printf ("\n#<tag: %u16x\tsymbol: %s>",
>> +                        ff:::xx, jpeg_marker[xx - 0xC0]);
>> +    }
>> +  };
>> +
>> +type JPEG_EOI =
>> +  struct
>> +  {
>> +    byte ff = 0xFF;
>> +    byte xx = 0xD9;
>> +  };
>> +
>> +type JPEG_Segment =
>> +  struct
>> +  {
>> +    byte ff == 0xFF;
>> +    byte xx : xx != 0xD8 && xx != 0xDA && xx != 0xD9 && xx >= 0xC0 && xx < 
>> 0xFF;
>> +    uint16 size;
>> +    char[size-2] data;
>
>
> `size-2' is not a good idea because you cannot guarantee that `size' is always
> `>= 2' and this happens:
>
> ```
> (poke) var size = 0UH
> (poke) size - 2
> 4294967294U
> ```
>
> which is not easy to debug!

But you can use

  uint16 size : size >= 2;
  char[size >= 2 ? size - 2 : 0] data;

The conditional expression in the array size is to allow non-strict
mappings @!.

> The other thing is all the "standard types" (things like `byte', `uint16', 
> etc.)
> are defined in `std-types.pk'.
> These are very handy while developing/poking from the CLI.  But using them 
> inside
> pickles is not a good idea because loading of `std-types.pk' is optional (by
> initializing the libpoke using
> `pk_compiler_new_with_flags (&term_if, PK_F_NOSTDTYPES);').  Those libpoke
> instances cannot load pickles and a real-world example of such is gdb 
> integration
> of libpoke.
>
> So please use `uint<8>', `uint<16>' instead of `byte' and `uint16'.
>
>
>> +    method _print = void:
>> +    {
>> +      printf ("\n#<tag: %u16x\tsymbol: %s\tsize: %u16d>",
>> +                        ff:::xx, jpeg_marker[xx - 0xC0], size);
>> +    }
>> +  };
>> +
>> +fun JPEG_find_eoi = (byte[] image) int:
>> +  {
>> +    printf ("size: %u32d length: %u32d\n", image'size / 1#B, image'length);
>> +    for (var i = image'length - 1; i > 1; i--)
>> +      {
>> +        var ff = image[i - 1];
>> +        var xx = image[i];
>> +        if (ff == 0xFF && xx == 0xD9)
>> +          {
>> +            return i;
>> +          }
>> +      }
>> +    return 0;
>> +  }
>> +
>> +type JPEG_Tag =
>> +  struct
>> +  {
>> +    JPEG_SOI soi;
>> +    JPEG_Segment[] segments;
>> +    JPEG_SOS sos;
>> +/*    byte[] image; */  /* could take some time for loading */
>> +/*    var image_size = JPEG_find_eoi(image); */
>> +/*    JPEG_EOI eoi; */
>
>
> For a more idiomatic approach you can see `BER_Variable_Contents' type defined
> in `asn1-ber.pk'.  You can find the detailed explanation of the technique
> here: https://pokology.org/tips-and-tricks.html (section "1 Sequence of bytes
> ended by two consecutive zero bytes").
>
>
>
> Happy poking!



reply via email to

[Prev in Thread] Current Thread [Next in Thread]