/ocr/ocrservice/src/com/googlecode/eyesfree/opticflow/TimestampedFrame.java

http://eyes-free.googlecode.com/ · Java · 210 lines · 116 code · 38 blank · 56 comment · 19 complexity · 288cfe683d2292d9377f5eeb4d21a58c MD5 · raw file

  1. /*
  2. * Copyright (C) 2011 Google Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.googlecode.eyesfree.opticflow;
  17. import android.util.Log;
  18. import com.googlecode.eyesfree.env.Size;
  19. import com.googlecode.eyesfree.opticflow.FrameProducer.Frame;
  20. import com.googlecode.leptonica.android.Pix;
  21. import com.googlecode.leptonica.android.Pixa;
  22. import com.googlecode.leptonica.android.ReadFile;
  23. /**
  24. * Class for interfacing efficiently with image data, and keeping track of all
  25. * records associated with a frame.
  26. *
  27. * @author alanv@google.com (Alan Viverette)
  28. */
  29. public class TimestampedFrame {
  30. private static final String TAG = "TimestampedFrame";
  31. private int threadsLeft;
  32. // For caching PIX created from rawFrameData.
  33. private Pix cachedPix;
  34. // Whether this frame is thought to be blurred. May be null.
  35. private Boolean isBlurred;
  36. // Whether this frame was created while focus was occurring. May be null.
  37. private Boolean takenWhileFocusing;
  38. // The results of text detection.
  39. private Pixa detectedText;
  40. // The FDR value of detected text areas.
  41. private float[] textConfidences;
  42. // The estimated angle for text present in this frame.
  43. // TODO(alanv): Make this a per-Pix setting?
  44. private float angle;
  45. private final Frame originalFrame;
  46. // TODO(andrewharp): Create pool of TimestampedFrames so that used frames
  47. // can be recycled.
  48. protected TimestampedFrame(final Frame originalFrame) {
  49. this.originalFrame = originalFrame;
  50. }
  51. public long getTimestamp() {
  52. return originalFrame.timestamp;
  53. }
  54. public Size getSize() {
  55. return new Size(originalFrame.width, originalFrame.height);
  56. }
  57. public int getWidth() {
  58. return originalFrame.width;
  59. }
  60. public int getHeight() {
  61. return originalFrame.height;
  62. }
  63. public void setDetectedText(Pixa detectedText, float[] textAreaQuality, float angle) {
  64. if (detectedText == null) {
  65. throw new IllegalArgumentException("Detected text must be non-null");
  66. }
  67. this.detectedText = detectedText.copy();
  68. this.textConfidences = textAreaQuality;
  69. this.angle = angle;
  70. }
  71. public Pixa getDetectedText() {
  72. if (detectedText != null) {
  73. return detectedText.copy();
  74. } else {
  75. return null;
  76. }
  77. }
  78. public float[] getTextConfidences() {
  79. return textConfidences.clone();
  80. }
  81. public float getAngle() {
  82. return angle;
  83. }
  84. public void recycleDetectedText() {
  85. if (detectedText != null) {
  86. detectedText.recycle();
  87. detectedText = null;
  88. }
  89. }
  90. /**
  91. * @return A Pix containing the data for a PIX representation of this frame.
  92. */
  93. public synchronized Pix getPixData() {
  94. if (cachedPix == null) {
  95. cachedPix = ReadFile.readBytes8(
  96. originalFrame.data, originalFrame.width, originalFrame.height);
  97. }
  98. return cachedPix.clone();
  99. }
  100. /**
  101. * @return Whether or not rawFrameData is null.
  102. */
  103. protected synchronized boolean hasRawData() {
  104. return originalFrame.data != null;
  105. }
  106. /**
  107. * @return The raw frame data. Raw data may have already been released, in
  108. * which case an error is logged.
  109. */
  110. public synchronized byte[] getRawData() {
  111. if (!hasRawData()) {
  112. Log.e(TAG, "Frame data for frame is no longer available.");
  113. }
  114. return originalFrame.data;
  115. }
  116. /**
  117. * Raw frame data is expensive to keep around, so we need to provide a way
  118. * to remove it from this frame after the smaller JPEG is created.
  119. *
  120. * @return The byte[] this frame was holding.
  121. */
  122. protected synchronized byte[] clearRawData() {
  123. final byte[] tmpData = getRawData(); // So we get the implicit check.
  124. originalFrame.recycle();
  125. // Unblock any threads that are wait()ing in releaesBitmap(true).
  126. notify();
  127. return tmpData;
  128. }
  129. public boolean isBlurred() {
  130. if (isBlurred == null) {
  131. Log.w(TAG, "isBlurred() called without value having been set!");
  132. // If focusing we can assume it's blurred, otherwise default to
  133. // unblurred.
  134. return takenWhileFocusing();
  135. }
  136. return isBlurred;
  137. }
  138. public void setBlurred(final boolean blurred) {
  139. if (isBlurred != null) {
  140. Log.w(TAG, "Blurred already set!");
  141. }
  142. isBlurred = blurred;
  143. }
  144. public void setTakenWhileFocusing(final boolean takenWhileFocusing) {
  145. this.takenWhileFocusing = takenWhileFocusing;
  146. }
  147. public boolean takenWhileFocusing() {
  148. if (takenWhileFocusing == null) {
  149. return false;
  150. }
  151. return takenWhileFocusing.booleanValue();
  152. }
  153. /**
  154. * Used by a ProcessingThread to signify that it's done processing this
  155. * frame.
  156. */
  157. public void threadDone() {
  158. --threadsLeft;
  159. if (threadsLeft < 0) {
  160. Log.w(TAG, "Negative number of threads remaining.");
  161. }
  162. }
  163. /**
  164. * @return true iff all threads have finished processing this frame.
  165. */
  166. public boolean allThreadsDone() {
  167. return threadsLeft == 0;
  168. }
  169. public void threadStart() {
  170. ++threadsLeft;
  171. }
  172. }