Skip to content

Commit

Permalink
SavePgm() and some encoding procedures
Browse files Browse the repository at this point in the history
  • Loading branch information
baAlex committed Jan 7, 2022
1 parent 2c060e3 commit 6ed60c9
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 221 deletions.
2 changes: 2 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

Checks: "-*, bugprone-*, clang-analyzer-*, cert-*, misc-*, performance-*, portability-*"
16 changes: 1 addition & 15 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
/akoenc
/akodec

/resources/prob

/*.a
/*.so

*.ako
*.pgm
/*.png

/.ninja_log
/.ninja_deps

/build/
/build-debug/
/build-release/
/objects/

/dev/
/.vscode/
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ endif ()

set(AKO_SOURCES
"./library/decode.c"
"./library/developer.c"
"./library/encode.c"
"./library/format.c"
"./library/head.c"
Expand Down
9 changes: 7 additions & 2 deletions library/ako-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
#include "ako.h"


#if (AKO_FREESTANDING == 0)
#include <stdio.h>
#include <stdlib.h>
#define DEV_PRINTF(...) printf(__VA_ARGS__)
#endif


typedef int16_t wavelet_t; // Technically a 'wavelet coefficient'

struct akoTileHead
{
uint16_t unused;
Expand All @@ -22,6 +23,10 @@ struct akoLiftHead
};


// developer.c:

void akoSavePgmI16(size_t width, size_t height, size_t in_stride, const int16_t* in, const char* filename);

// format.c:

void akoFormatToPlanarI16Yuv(int keep_transparent_pixels, enum akoColorspace, size_t channels, size_t width,
Expand Down
2 changes: 2 additions & 0 deletions library/ako.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ void akoDefaultFree(void*);

const char* akoStatusString(enum akoStatus);

void akoSavePgmU8(size_t width, size_t height, size_t in_stride, const uint8_t* in, const char* filename);

int akoVersionMajor();
int akoVersionMinor();
int akoVersionPatch();
Expand Down
20 changes: 15 additions & 5 deletions library/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ uint8_t* akoDecodeExt(const struct akoCallbacks* c, size_t input_size, const voi
size_t image_w;
size_t image_h;

wavelet_t* workarea_a = NULL;
wavelet_t* workarea_b = NULL;
uint8_t* in_cursor = in;

int16_t* workarea_a = NULL;
int16_t* workarea_b = NULL;

// Check callbacks
const struct akoCallbacks checked_c = (c != NULL) ? *c : akoDefaultCallbacks();
Expand Down Expand Up @@ -82,10 +84,18 @@ uint8_t* akoDecodeExt(const struct akoCallbacks* c, size_t input_size, const voi
{
const size_t tile_w = akoTileDimension(tile_x, image_w, s.tiles_dimension);
const size_t tile_h = akoTileDimension(tile_y, image_h, s.tiles_dimension);
const size_t tile_size = akoTileDataSize(tile_w, tile_h) * channels;
const size_t tile_size = (s.wavelet != AKO_WAVELET_NONE)
? (akoTileDataSize(tile_w, tile_h) * channels)
: (tile_w * tile_h * channels * sizeof(int16_t)); // No wavelet is a rare case

DEV_PRINTF("D\tTile %zu at %zu:%zu, %zux%zu px, size: %zu bytes\n", t, tile_x, tile_y, tile_w, tile_h,
tile_size);
// Developers, developers, developers
if (t < 10)
{
DEV_PRINTF("D\tTile %zu at %zu:%zu, %zux%zu px, size: %zu bytes\n", t, tile_x, tile_y, tile_w, tile_h,
tile_size);
}
else if (t == 11)
DEV_PRINTF("D\t...\n");

// Next tile
tile_x += s.tiles_dimension;
Expand Down
144 changes: 25 additions & 119 deletions library/developer.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*-----------------------------
/*
MIT License
Expand All @@ -21,138 +21,44 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

-------------------------------

[developer.c]
- Alexander Brandt 2021
-----------------------------*/
#include "ako-private.h"

#include <assert.h>
#include <stdarg.h>
#include <stdio.h>

#include "ako.h"
#include "developer.h"


#if (AKO_DEV_TINY_BENCHMARK == 1)
inline struct Benchmark DevBenchmarkCreate(const char* name)
{
return (struct Benchmark){.start = 0, .elapsed = 0, .name = name};
}

inline void DevBenchmarkStartResume(struct Benchmark* benchmark)
{
if (benchmark->start == 0)
benchmark->start = clock();
}

inline void DevBenchmarkPause(struct Benchmark* benchmark)
{
if (benchmark->start != 0)
{
benchmark->elapsed = benchmark->elapsed + (clock() - benchmark->start);
benchmark->start = 0;
}
}

inline void DevBenchmarkStop(struct Benchmark* benchmark)
#if (AKO_FREESTANDING == 0)
void akoSavePgmU8(size_t width, size_t height, size_t in_stride, const uint8_t* in, const char* filename)
{
if (benchmark->start != 0)
FILE* fp = fopen(filename, "wb");
if (fp != NULL)
{
benchmark->elapsed = (clock() - benchmark->start);
benchmark->start = 0;
}
}

inline void DevBenchmarkPrint(struct Benchmark* benchmark)
{
DevBenchmarkStop(benchmark);
fprintf(fp, "P5\n%zu\n%zu\n255\n", width, height);

const double ms = (double)benchmark->elapsed / ((double)CLOCKS_PER_SEC / 1000.0f);
const double sec = (double)benchmark->elapsed / (double)CLOCKS_PER_SEC;
for (size_t row = 0; row < height; row++)
fwrite(in + (row * in_stride), 1, width, fp);

if (ms < 1000.0f)
printf("###\t%7.2f ms | %s\n", ms, benchmark->name);
else
printf("###\t%7.2f s | %s\n", sec, benchmark->name);
}
#else
inline struct Benchmark DevBenchmarkCreate(const char* name)
{
(void)name;
return (struct Benchmark){0};
}

inline void DevBenchmarkStartResume(struct Benchmark* benchmark)
{
(void)benchmark;
}

inline void DevBenchmarkPause(struct Benchmark* benchmark)
{
(void)benchmark;
}

inline void DevBenchmarkStop(struct Benchmark* benchmark)
{
(void)benchmark;
}

inline void DevBenchmarkPrint(struct Benchmark* benchmark)
{
(void)benchmark;
fclose(fp);
}
}
#endif


#if (AKO_DEV_SAVE_IMAGES == 1)
void DevSaveGrayPgm(size_t width, size_t height, size_t in_pitch, const int16_t* data, const char* filename_format, ...)
void akoSavePgmI16(size_t width, size_t height, size_t in_stride, const int16_t* in, const char* filename)
{
char filename[256];
va_list args;

va_start(args, filename_format);
vsprintf(filename, filename_format, args);
va_end(args);

FILE* fp = fopen(filename, "wb");
fprintf(fp, "P5\n%zu\n%zu\n255\n", width, height);

for (size_t row = 0; row < height; row++)
for (size_t col = 0; col < width; col++)
{
const int16_t* in = &data[(row * in_pitch) + col];
uint8_t p = (*in > 0) ? (*in < 255) ? (uint8_t)*in : 255 : 0;
fwrite(&p, 1, 1, fp);
}

fclose(fp);
}
#else
void DevSaveGrayPgm(size_t width, size_t height, size_t in_pitch, const int16_t* data, const char* filename_format, ...)
{
(void)width;
(void)height;
(void)in_pitch;
(void)data;
(void)filename_format;
}
#endif
if (fp != NULL)
{
fprintf(fp, "P5\n%zu\n%zu\n255\n", width, height);

for (size_t row = 0; row < height; row++)
for (size_t col = 0; col < width; col++)
{
const int16_t i16 = in[(row * in_stride) + col];
const uint8_t u8 = (i16 > 0) ? (i16 < 255) ? (uint8_t)i16 : 255 : 0;
fwrite(&u8, 1, 1, fp);
}

#if (AKO_DEV_PRINTF_DEBUG == 1)
void DevPrintf(const char* format, ...)
{
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
#else
void DevPrintf(const char* format, ...)
{
(void)format;
fclose(fp);
}
}
#endif
29 changes: 0 additions & 29 deletions library/developer.h

This file was deleted.

66 changes: 56 additions & 10 deletions library/encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,12 @@ size_t akoEncodeExt(const struct akoCallbacks* c, const struct akoSettings* s, s
size_t image_h, const void* in, void** out, enum akoStatus* out_status)
{
enum akoStatus status;
struct akoHead* h;

size_t blob_size = 0;
void* blob = NULL;
uint8_t* blob = NULL;

wavelet_t* workarea_a = NULL;
wavelet_t* workarea_b = NULL;
int16_t* workarea_a = NULL;
int16_t* workarea_b = NULL;

// Check callbacks and settings
const struct akoCallbacks checked_c = (c != NULL) ? *c : akoDefaultCallbacks();
Expand All @@ -60,8 +59,7 @@ size_t akoEncodeExt(const struct akoCallbacks* c, const struct akoSettings* s, s
}

// Write head
h = blob;
if ((status = akoHeadWrite(channels, image_w, image_h, &checked_s, h)) != AKO_OK)
if ((status = akoHeadWrite(channels, image_w, image_h, &checked_s, blob)) != AKO_OK)
goto return_failure;

// Allocate workareas
Expand All @@ -87,12 +85,60 @@ size_t akoEncodeExt(const struct akoCallbacks* c, const struct akoSettings* s, s
{
const size_t tile_w = akoTileDimension(tile_x, image_w, checked_s.tiles_dimension);
const size_t tile_h = akoTileDimension(tile_y, image_h, checked_s.tiles_dimension);
const size_t tile_size = akoTileDataSize(tile_w, tile_h) * channels;
const size_t tile_size =
(checked_s.wavelet != AKO_WAVELET_NONE)
? (akoTileDataSize(tile_w, tile_h) * channels)
: (tile_w * tile_h * channels * sizeof(int16_t)); // No wavelet is a rare case, so those 16 bits
// (format in which following steps operate) are
// a waste of space

// 1. Format
akoFormatToPlanarI16Yuv(checked_s.discard_transparent_pixels, checked_s.colorspace, channels, tile_w, tile_h,
image_w, 0, (const uint8_t*)in + ((image_w * tile_y) + tile_x) * channels, workarea_a);

// 2. Wavelet transform
// if (checked_s.wavelet != AKO_WAVELET_NONE)
{
// TODO
}

// 3. Compression
// if (checked_s.compression == AKO_COMPRESSION_NONE)
{
// Make space
void* updated_blob = checked_c.realloc(blob, blob_size + tile_size);
if (updated_blob == NULL)
{
status = AKO_NO_ENOUGH_MEMORY;
goto return_failure;
}

// Copy as is
blob = updated_blob;
for (size_t i = 0; i < tile_size; i++)
blob[blob_size + i] = ((uint8_t*)workarea_a)[i];

blob_size += tile_size; // Update
}

DEV_PRINTF("E\tTile %zu at %zu:%zu, %zux%zu px, size: %zu bytes\n", t, tile_x, tile_y, tile_w, tile_h,
tile_size);
// 4. Developers, developers, developers
if (t < 10)
{
char filename[64];

DEV_PRINTF("E\tTile %zu at %zu:%zu, %zux%zu px, size: %zu bytes, blob size: %zu bytes\n", t, tile_x, tile_y,
tile_w, tile_h, tile_size, blob_size);

for (size_t ch = 0; ch < channels; ch++)
{
snprintf(filename, 64, "E tile%zu ch%zu.pgm", t, ch);
akoSavePgmI16(tile_w, tile_h, tile_w, workarea_a + (tile_w * tile_h) * ch, filename);
}
}
else if (t == 11)
DEV_PRINTF("E\t...\n");

// Next tile
// 5. Next tile
tile_x += checked_s.tiles_dimension;
if (tile_x >= image_w)
{
Expand Down
Loading

0 comments on commit 6ed60c9

Please sign in to comment.