aboutsummaryrefslogtreecommitdiff
path: root/helium/leptonica.cc
blob: 8c102d0f1ca86e2977d71e0da392894da2b26d3b (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
// Copyright 2006 Google Inc.
// All Rights Reserved.
// Author: <renn@google.com> (Marius Renn)

// Local includes
#include "leptonica.h"
#include "image.h"
#include "graymap.h"
#include "imageenhancer.h"

// C includes
#include <stdlib.h>

using namespace helium;


// TODO: CONVERT IF NECESSARY!!!
Image Leptonica::PixToImage(const Pix* cpix) {
  Pix* pix = const_cast<Pix*>(cpix);
  if (pixGetDepth(pix) == 8) {
    GrayMap gmap = PixToGrayMap(pix);
    return Image::FromGrayMap(gmap);
  }
  // Else must be 32-bit
  ASSERT(pixGetDepth(pix) == 32);
  Image out = Image(pixGetWidth(pix), pixGetHeight(pix));
  memcpy(out.data(), pix->data, out.width() * out.height() * 4);
  return out;
}

Pix* Leptonica::ImageToPix(const Image& image) {
  Pix* pix = reinterpret_cast<Pix*>(calloc(sizeof(Pix), 1));
  pix->w = image.width();
  pix->h = image.height();
  pix->d = 32;
  pix->wpl = image.width();
  pix->data = reinterpret_cast<l_uint32*>(
                malloc(image.width() * image.height() * 4)
              );
  pix->refcount = 1;
  memcpy(pix->data, image.data(), image.width() * image.height() * 4);
  return pix;
}

// TODO: Return pointer to avoid unnecessary copies.
GrayMap Leptonica::PixToGrayMap(const Pix *cpix) {
  Pix* pix = const_cast<Pix*>(cpix);
  ASSERT(pixGetDepth(pix) == 8);
  GrayMap out(pixGetWidth(pix), pixGetHeight(pix));
  uint8 *wpt = out.data();
  for (int y = 0; y < out.height(); ++y) {
    l_uint32* lrpt = pixGetData(pix) + y * pixGetWpl(pix);
    for (int x = 0; x < out.width(); ++x) {
      *wpt++ = static_cast<uint8>(GET_DATA_BYTE(lrpt, x));
    }
  }
  // A direct memcpy does not work
  // memcpy(out.data(), pixGetData(pix), out.width() * out.height());
  return out;
}

Pix* Leptonica::GrayMapToPix(const GrayMap& graymap) {
  Pix* pix = pixCreate(graymap.width(), graymap.height(), 8);
  uint8 *rpt = graymap.data();
  for (int y = 0; y < graymap.height(); ++y) {
    l_uint32 *lwpt = pixGetData(pix) + y * pixGetWpl(pix);
    for (int x = 0; x < graymap.width(); ++x) {
      SET_DATA_BYTE(lwpt, x, *rpt++);
    }
  }
  return pix;
}

Mask* Leptonica::PixToMask(const Pix* cpix) {
  Pix* pix = const_cast<Pix*>(cpix);
  ASSERT(pixGetDepth(pix) == 1);
  Mask* mask = new Mask(pixGetWidth(pix), pixGetHeight(pix));
  bool* mask_ptr = mask->data();
  for (int y = 0; y < mask->height(); ++y) {
    l_uint32 *lrpt = pixGetData(pix) + y * pixGetWpl(pix);
    for (int x = 0; x < mask->width(); ++x) {
      *(mask_ptr++) = GET_DATA_BIT(lrpt, x);
    }
  }
  return mask;
}

Pix* Leptonica::MaskToPix(const Mask& mask) {
  Pix* pix = pixCreate(mask.width(), mask.height(), 1);
  bool* mask_ptr = mask.data();
  for (int y = 0; y < mask.height(); ++y) {
    l_uint32 *lwpt = pixGetData(pix) + y * pixGetWpl(pix);
    for (int x = 0; x < mask.width(); ++x) {
      if (*(mask_ptr++))
        SET_DATA_BIT(lwpt, x);
    }
  }
  return pix;
}

void Leptonica::DisplayImage(const Image& image) {
  Pix *pix = ImageToPix(image);
  pixDisplay(pix, 0, 0);
  pixDestroy(&pix);
}

void Leptonica::DisplayGrayMap(const GrayMap& graymap) {
  DisplayImage(Image::FromGrayMap(graymap));
}

void Leptonica::DisplayMask(const Mask& mask) {
  Pix *pix = MaskToPix(mask);
  pixDisplay(pix, 0, 0);
  pixDestroy(&pix);
}

void Leptonica::SaveImage(const Image& image, const char* filename) {
  Pix *pix = ImageToPix(image);
  pixWrite(filename, pix, IFF_JFIF_JPEG);
  pixDestroy(&pix);
}